Basic functionality of octant package¶
Import the necessary modules
[1]:
from pathlib import Path
from octant.core import TrackRun, OctantTrack, HOUR
Define the common data directory
[2]:
sample_dir = Path(".") / "sample_data"
Data are usually organised in hierarchical directory structure. Here, the relevant parameters are defined.
[3]:
dataset = "era5"
period = "test"
run_id = 0
Construct the full path
[4]:
track_res_dir = sample_dir / dataset / f"run{run_id:03d}" / period
Load the data¶
The standard loading procedure is done during the initialisation of TrackRun by reading text files (output from PMCTRACK) from the given directory.
[5]:
tr = TrackRun(track_res_dir)
[6]:
print(tr)
<octant.core.TrackRun>
[671 tracks]
Data columns:
lon | lat | vo | time | area | vortex_type
Sources:
sample_data/era5/run000/test
The TrackRun object also has an HTML view available in Jupyter Notebooks
[7]:
tr
[7]:
| Cyclone tracking results | ||||||
|---|---|---|---|---|---|---|
| Number of tracks | 671 | |||||
| Data columns | lon, lat, vo, time, area, vortex_type | |||||
| Sources | ||||||
| sample_data/era5/run000/test | ||||||
[8]:
type(tr)
[8]:
octant.core.TrackRun
[9]:
len(tr)
[9]:
671
[10]:
tr.size()
[10]:
671
[11]:
tr.tstep_h
[11]:
1.0
Main data container¶
The main attribute of TrackRun is .data, which has all the tracks stored in one DataFrame-like object.
[12]:
tr.data.head()
[12]:
| lon | lat | vo | time | area | vortex_type | ||
|---|---|---|---|---|---|---|---|
| track_idx | row_idx | ||||||
| 0 | 0 | 9.3 | 79.2 | 0.000345 | 2011-01-01 00:00:00 | 10617.93652 | 0 |
| 1 | 9.3 | 79.2 | 0.000352 | 2011-01-01 01:00:00 | 10154.14648 | 0 | |
| 2 | 9.3 | 79.2 | 0.000362 | 2011-01-01 02:00:00 | 10136.94629 | 0 | |
| 1 | 0 | 20.4 | 70.5 | 0.000317 | 2011-01-01 00:00:00 | 34750.66016 | 1 |
| 1 | 20.7 | 70.5 | 0.000310 | 2011-01-01 01:00:00 | 36727.84375 | 1 |
It always has track_idx level in order to index through individual tracks.
Tracking run configuration¶
If a .conf file is present in the same directory, it is loaded to TrackRun.
[13]:
tr.conf
[13]:
| Tracking algorithm settings (43) | |
|---|---|
| dt_start = | 201101010000 |
| dt_end = | 201101312300 |
| vor_lvl = | 950 |
| steer_lvl_btm = | 1000 |
| steer_lvl_top = | 700 |
| datadir = | ../../reanalysis/era5 |
| outdir = | ../results/test7 |
| vort_name = | vo |
| u_name = | u |
| v_name = | v |
| psea_name = | msl |
| land_name = | lsm |
| prefix_lvl = | era5.an.pl. |
| prefix_sfc = | era5.an.sfc. |
| proj = | 1 |
| vert_grid = | 1 |
| lon1 = | -20 |
| lon2 = | 50 |
| lat1 = | 65 |
| lat2 = | 85 |
| halo_r = | 30.0 |
| smth_type = | 0 |
| nsmth_x = | 10 |
| nsmth_y = | 10 |
| r_smth = | 60.0 |
| zeta_max0 = | 0.0002 |
| zeta_min0 = | 0.00015 |
| int_zeta_min0 = | 2e-06 |
| gamma = | 0.25 |
| d_cf_min = | 400.0 |
| size_synop = | 90000.0 |
| distance_ec = | 300.0 |
| del_psea_min = | 0.5 |
| steering_type = | 2 |
| n_steering_x = | 20 |
| n_steering_y = | 20 |
| r_steering = | 200.0 |
| track_type = | 2 |
| del_lon = | 1.0 |
| del_lat = | 0.8 |
| del_r = | 120.0 |
| merge_opt = | 2 |
| vor_out_on = | 0 |
Other methods of initialisation¶
TrackRun class can be initialised empty:
[14]:
tr_empty = TrackRun()
[15]:
tr_empty
[15]:
| Cyclone tracking results | ||||||
|---|---|---|---|---|---|---|
| Number of tracks | 0 | |||||
| Data columns | lon, lat, vo, time, area, vortex_type | |||||
Concatenate data from several directories¶
TR = TrackRun(one_directory)
TR2 = TrackRun(another_directory)
TR.extend(TR2)
or
TR += TrackRun(another_directory)
Some attributes of TrackRun¶
TrackRun object has a few useful properties
for example, it is possible to access the list of files that the data were loaded from.
[16]:
tr.filelist[:5]
[16]:
[PosixPath('sample_data/era5/run000/test/vortrack_0001_0001.txt'),
PosixPath('sample_data/era5/run000/test/vortrack_0002_0001.txt'),
PosixPath('sample_data/era5/run000/test/vortrack_0003_0001.txt'),
PosixPath('sample_data/era5/run000/test/vortrack_0004_0001.txt'),
PosixPath('sample_data/era5/run000/test/vortrack_0005_0001.txt')]
there is a shortcut to group tracks by their index
[17]:
tr.gb
[17]:
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7fee3dd9f390>
It is equivalent of doing tr.data.groupby("track_idx").
[18]:
for idx, a_track in tr.gb:
print(f"Track with index={idx}")
print(a_track)
break
Track with index=0
lon lat vo time area \
track_idx row_idx
0 0 9.3 79.2 0.000345 2011-01-01 00:00:00 10617.93652
1 9.3 79.2 0.000352 2011-01-01 01:00:00 10154.14648
2 9.3 79.2 0.000362 2011-01-01 02:00:00 10136.94629
vortex_type
track_idx row_idx
0 0 0
1 0
2 0
current
TrackRunis not categorised yet (see “Categorisation” examples), so this attribute is empty:
[19]:
tr.cat_labels
[19]:
[]
Serialising TrackRun¶
TrackRun and all its metadata can be saved to and loaded from an HDF file.
[20]:
tr.to_archive("test.h5")
[21]:
new_tr = TrackRun.from_archive("test.h5")
[22]:
new_tr
[22]:
| Cyclone tracking results | ||||||
|---|---|---|---|---|---|---|
| Number of tracks | 671 | |||||
| Data columns | lon, lat, vo, time, area, vortex_type | |||||
| Sources | ||||||
| sample_data/era5/run000/test | ||||||
Units of TrackRun¶
[23]:
import random
Each cyclone track stored in lists of TrackRun class as a OctantTrack instance
[24]:
ot = random.choice([*tr[:].gb])[1]
It is essentially a sub-class of pandas.DataFrame
[25]:
ot
[25]:
| lon | lat | vo | time | area | vortex_type | ||
|---|---|---|---|---|---|---|---|
| track_idx | row_idx | ||||||
| 124 | 0 | 12.3 | 72.0 | 0.000423 | 2011-01-05 23:00:00 | 7615.17285 | 1 |
| 1 | 10.8 | 72.0 | 0.000393 | 2011-01-06 00:00:00 | 19943.68750 | 1 | |
| 2 | 8.7 | 72.0 | 0.000349 | 2011-01-06 01:00:00 | 18887.55273 | 1 | |
| 3 | -3.6 | 67.2 | 0.000666 | 2011-01-06 02:00:00 | 95968.20312 | 3 |
[26]:
type(ot)
[26]:
octant.core.OctantTrack
It has a few useful properties
[27]:
ot.lifetime_h
[27]:
3.0
[28]:
ot.total_dist_km
[28]:
836.7043121073503
including maximum vorticity in $ s^{-1}$:
[29]:
ot.max_vort
[29]:
0.00066578
[30]:
ot.gen_lys_dist_km
[30]:
810.8722660749592
[31]:
ot.average_speed
[31]:
278.90143736911676
[32]:
ot.lonlat
[32]:
array([[12.3, 72. ],
[10.8, 72. ],
[ 8.7, 72. ],
[-3.6, 67.2]])
Running octant with a progress bar¶
Having either the fastprogress or tqdm module installed allows for running some methods with a bar that shows progress. To enable it, set the attribute of RUNTIME variable to True:
[33]:
import octant
octant.RUNTIME.enable_progress_bar = True
[34]:
conditions = [
("long_lived", [lambda ot: ot.lifetime_h >= 6]),
(
"far_travelled_and_very_long_lived",
[lambda ot: ot.lifetime_h >= 36, lambda ot: ot.gen_lys_dist_km > 300.0],
),
("strong", [lambda x: x.max_vort > 1e-3]),
]
[35]:
tr.classify(conditions)
More classify() examples
octant’s utilities¶
[36]:
from octant.utils import great_circle
[37]:
great_circle(lon1=9.6, lon2=10.2, lat1=76.9, lat2=78.9)
[37]:
222826.50759451024