Machine Learning
The machine learning (ML) tracker detects tropical cyclones using a U-Net segmentation model, and then links the detections into trajectories. The model weights are downloaded from a HuggingFace Hub repository (or supplied locally) rather than wrapping an external executable.
The model and its training pipeline are described in the reference cyclone-track-ml repository.
For an overview of the functionalities, installation, and usage see the Machine Learning section of the documentation.
- class tctrack.machine_learning.MLTracker(parameters, stitch_parameters=None)[source]
Bases:
TCMLTrackerClass used to run the machine-learning cyclone tracking algorithm.
The model weights are loaded from a HuggingFace Hub repository on first use and cached locally by
huggingface_hub.- parameters
Class containing the parameters for the tracking algorithm.
- Type:
- stitch_parameters
Class containing the parameters for the stitching step.
- Type:
- model
The loaded TorchScript model in evaluation mode.
- Type:
torch.jit.ScriptModule
Examples
>>> params = MLParameters(input_file="era5_2020.nc") >>> tracker = MLTracker(params) >>> tracker.run_tracker("trajectories.nc")
- read_trajectories()[source]
Parse tracker outputs into a list of
tctrack.core.Trajectory.- Returns:
A list of
tctrack.core.Trajectoryobjects.- Return type:
list[Trajectory]
- property global_metadata: dict
Read-only property containing metadata for tctrack / tracker instance.
- Raises:
AttributeError – If _global_metadata has not been initialized.
- Type:
dict
- run_tracker_subprocess(command_name, command_list, input_file=None, input_str=None, cwd=None, verbosity=1)
Run a subprocess command for a cyclone tracking algorithm.
- Parameters:
command_name (
str) – The name of the command, used in logging and error messages.command_list (
list[str]) – The command and its arguments to execute.input_file (
str | None) – Path to a file to pass to the process via stdin (e.g. a namelist). Cannot be used together with input_str. Defaults to None.input_str (
str | None) – A string to pass to the process via stdin (e.g. interactive inputs). Cannot be used together with input_file. Defaults to None.cwd (
str | None) – Working directory in which to execute the command. Defaults to None.verbosity (
int) – Controls how much output is shown: 0 = No output gets printed. 1 = summary, first and last 12 lines printed (default). 2 = Entire output is streamed in real-time. Defaults to 1.
- Returns:
Dictionary of subprocess output to ‘stdout’, ‘stderr’, and ‘returncode’.
- Return type:
dict- Raises:
ValueError – If both input_file and input_str are provided simultaneously.
ValueError – If verbosity is not 0, 1, or 2.
- set_metadata()
Initialise the metadata attributes used in the CF-netcdf output.
This is called from the
to_netcdf()method.This sets the
_global_metadataattribute with the TCTrack parameters and name of the tracker. It then calls the subclass-specific_set_metadata()to set_variable_metadataand_time_metadata.- Return type:
None
- property time_metadata: TCTrackerTimeMetadata
Read-only property containing time metadata for this Tracker run.
- Raises:
AttributeError – If _time_metadata has not been initialized.
- Type:
dict
- to_netcdf(output_file, trajectories=None)
Write track trajectories to CF-compliant NetCDF trajectory file.
Reads in trajectories based on the parameters set for a specific implementation of the class and writes them to a CF-Conventions compliant NetCDF trajectory file using cf-python. Trajectories are assumed to contain as a minimum data for
lat,lon, andtimestep.An ancillary field variable is added to the output file indicating any tracks that start/end within 1 day of the input dataset boundaries.
- Parameters:
output_file (
str) – filename for the output netCDF file Note: This will be placed in the local directory unless a full path is giventrajectories (
list[Trajectory] | None) – An optional list of trajectories to write. If the tracking algorithm produces an intermediate output file then this can be skipped as it will instead read from there.
- Return type:
None
Warning
- UserWarning
If there are no trajectories read in from the tracker outputs by
read_trajectories()meaning no NetCDF output file can be written.
References
CF-Conventions v1.1 - H.4. Trajectory Data cf-python documentation
Examples
Instantiate a
TCTrackersubclass instance with appropriate parameters, run the relevant methods to generate cyclone track trajectories, and then save the results to a CF-compliant trajectory file:>>> my_tracker = TCTracker(...) >>> ... >>> my_tracker.to_netcdf("my_netcdf_file.nc")
- property variable_metadata: dict
Read-only property containing NetCDF metadata for variables.
- Raises:
AttributeError – If _variable_metadata has not been initialized.
- Type:
dict
- preprocess()[source]
Build the model input tensor from the configured ERA5 variables.
Reproduces the channel layout the model was trained on: each of parameters.pressure_variables at each of parameters.pressure_levels, followed by a land/sea mask, followed by sea surface temperature gap-filled with 2-metre temperature over land. Channels are then normalised using _load_normalisation_stats.
- Returns:
Tensor of shape
(channel, time, lat, lon), normalised.- Return type:
torch.Tensor- Raises:
ValueError – If a configured variable cannot be found in the input file.
- detect()[source]
Run the U-Net over the grid and locate the tropical cyclones in it.
For each timestep the model is run, its per-pixel class probabilities are thresholded, and the surviving pixels are grouped into discrete candidate storms (see
_cluster_candidates()and_merge_nearby_candidates()). The result is a list of TC locations on_candidates, whichstitch()then links into trajectories - mirroring how the other TCTrack trackers split the work, where detection emits candidate points and stitching consumes them.The full per-pixel probabilities are also kept on
_scores, which retains the per-class detail that thresholding discards (useful for evaluation, e.g. one-vs-rest ROC per lifecycle class).- Raises:
ValueError – If the model’s output spatial shape doesn’t match the input file’s latitude/longitude grid, it would indicate a bug.
- Return type:
None
- stitch()[source]
Link the TC locations found by
detect()into trajectories.Consumes the candidates on
_candidates, working through the timesteps in order and, at each one, extending existing tracks with a nearby candidate, retiring tracks that have gone unmatched for too long, and starting new tracks from whatever is left over.The result is also stored on
_trajectories, so thatread_trajectories()- and thereforeto_netcdf()- can reach it.- Returns:
One
Trajectoryper track with at leaststitch_parameters.min_lengthobservations.- Return type:
list[Trajectory]
- detections_to_netcdf(output_file)[source]
Write the detected TC locations to a CF-compliant NetCDF point file.
The detections from
detect()are a set of independent points - each a storm location at one time, with the input variables sampled there - rather than connected tracks. They are therefore written withfeatureType = "point"over a singleobservationdimension, instead of the trajectory layoutto_netcdf()produces.- Parameters:
output_file (
str) – Filename for the output NetCDF file. Placed in the working directory unless a full path is given.- Warns:
UserWarning – If
detect()found no candidates, in which case no file is written.- Return type:
None
References
- run_tracker(output_file)[source]
Run the tracker to obtain the tropical cyclone trajectories.
Runs
detect()to locate the cyclones at each timestep - which reads and prepares the input itself, viapreprocess()- then links those detections into tracks withstitch(), and finally writes the tracks out withto_netcdf().The detections behind those tracks can be saved separately, as CF point data, with
detections_to_netcdf().- Parameters:
output_file (
str) – Filename to which the tropical cyclone track trajectories are saved.- Return type:
None
Examples
To set the parameters, instantiate a
MLTrackerinstance and run the algorithm to generate trajectories:>>> params = MLParameters(...) >>> tracker = MLTracker(params) >>> tracker.run_tracker("trajectories.nc")
- class tctrack.machine_learning.MLParameters(model_path=None, hf_repo_id='surbhigoel456/cyclone-TC-ML', hf_token=None, device='cpu', threshold=0.5, input_file='', pressure_variables=('relative_humidity', 'air_temperature', 'eastward_wind', 'northward_wind', 'atmosphere_relative_vorticity'), pressure_levels=(1000, 750, 500), sst_variable='ncvar%sst', t2m_variable='ncvar%t2m', normalisation_stats_path=None, merge_distance_deg=2.0)[source]
Bases:
TCMLParametersDataclass containing values for parameters used by MLTracker.
Extends
TCMLParameterswith the input file path and sets the default HuggingFace repository for this model.See also
MLTrackerThe tracker class that uses these parameters.
-
input_file:
str= '' CF-NetCDF file containing the input variables for the model.
-
hf_repo_id:
str= 'surbhigoel456/cyclone-TC-ML' HuggingFace Hub repository ID for the cyclone detection model.
-
pressure_variables:
Sequence[str] = ('relative_humidity', 'air_temperature', 'eastward_wind', 'northward_wind', 'atmosphere_relative_vorticity') CF identities of the pressure-level input variables, in model channel order.
Correspond to
pressure_var_codesin the reference training pipeline (cyclone-track-ml), but given as the actual CFstandard_nameeach variable is converted to (via cfgrib) in ERA5 output, which differs from the CDS API request name used there for several variables (e.g."temperature"in the reference pipeline is"air_temperature"here).
-
pressure_levels:
Sequence[float] = (1000, 750, 500) Pressure levels (hPa) to extract for each of
pressure_variables.
-
sst_variable:
str= 'ncvar%sst' CF identity of the sea surface temperature variable.
ERA5 sea surface temperature has no
standard_name(cfgrib leaves it"unknown"), so it must be selected by NetCDF variable name instead.
-
t2m_variable:
str= 'ncvar%t2m' CF identity of the 2-metre temperature, used to gap-fill SST over land.
-
normalisation_stats_path:
str|None= None Path to a
.ncfile with per-channelmeanandrangevariables (each shape(channel,), ordered as inMLTracker.preprocess()), used to normalise input as(x - mean) / range.These must be the statistics computed over the model’s training set; they cannot be recomputed from a single inference file. Matches the
data/normalisation_parameters.ncfile saved bycompiler.pyin the reference training pipeline. IfNone, the statistics bundled with this package - computed over the default model’s training set - are used instead.
-
merge_distance_deg:
float= 2.0 Distance (degrees lat/lon) within which candidates in the same timestep are merged, keeping only the highest-scoring one.
The model often splits a single storm into several adjacent clusters - either side of a lifecycle-class boundary, or where confidence dips below
thresholdmid-storm - which would otherwise each become a separate track. Mirrorsmerge_distin TempestExtremes’DetectNodes, which resolves the same problem for its own candidates. Set to0to disable merging.
-
device:
str= 'cpu' PyTorch device to run inference (e.g.
"cpu"or"cuda").
-
hf_token:
str|None= None HuggingFace access token for the model repository. If
None, the value of theHF_TOKENenvironment variable is used instead.
-
model_path:
str|None= None Local path to the
.ptmodel file. IfNone, the model is downloaded from the HuggingFace Hub repository given byhf_repo_id.
-
threshold:
float= 0.5 Confidence threshold for retaining detections. Candidates with a model score below this value are discarded.
- class tctrack.machine_learning.MLStitchParameters(max_distance_deg=3.0, max_gap=1, min_length=2)[source]
Bases:
TCTrackerParametersDataclass containing values used by
MLTracker.stitch().See also
MLTrackerThe tracker class that uses these parameters.
-
max_distance_deg:
float= 3.0 Maximum distance (degrees lat/lon) between a track’s last point and a candidate in the next timestep for them to be linked as the same storm.
Not part of the reference training pipeline, which only trains per-pixel classification and has no timestep-to-timestep linking step. The default assumes 6-hourly input (as used for training) and typical cyclone translation speeds; reduce for higher-frequency input.
-
max_gap:
int= 1 Number of consecutive timesteps a track may go unmatched before it is closed, tolerating brief drops below
threshold.
-
min_length:
int= 2 Minimum number of observations a track must have to be kept, filtering out single-timestep detections likely to be noise.
The classes below are base classes for adding other machine learning tracking algorithms to TCTrack. They are not intended to be used directly.
- class tctrack.core.ml_tracker.TCMLParameters(model_path=None, hf_repo_id='', hf_token=None, device='cpu', threshold=0.5)[source]
Bases:
TCTrackerParametersBase dataclass for parameters common to all ML-based trackers.
-
model_path:
str|None= None Local path to the
.ptmodel file. IfNone, the model is downloaded from the HuggingFace Hub repository given byhf_repo_id.
-
hf_repo_id:
str= '' HuggingFace Hub repository ID from which the model is downloaded.
-
hf_token:
str|None= None HuggingFace access token for the model repository. If
None, the value of theHF_TOKENenvironment variable is used instead.
-
device:
str= 'cpu' PyTorch device to run inference (e.g.
"cpu"or"cuda").
-
threshold:
float= 0.5 Confidence threshold for retaining detections. Candidates with a model score below this value are discarded.
-
model_path:
- class tctrack.core.ml_tracker.TCMLTracker[source]
Bases:
TCTrackerAbstract base class for ML-based tropical cyclone trackers.
Extends TCTracker functionality common to all ML-based trackers e.g. loading a TorchScript model from HuggingFace Hub repository, and the detect step.
- model
The loaded TorchScript model in evaluation mode.
- Type:
torch.jit.ScriptModule