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 TrackRun is 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)
100.00% [671/671 00:02<00:00]

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