Running with helper class#

[This note-book is in oceantracker/tutorials_how_to/]

Oceantracker is designed so that both coders and non-coders can get almost the same level of adaptability to their specific needs. Also to streamline running many cases across distributed computers, along with enabling online particle tracking as a service.

To achieve these capabilities, it uses parameters to both change the settings to meet the users needs, but also to build the computational pipeline for the users specific needs. This flexibility in the computational pipeline is achieved using “class” parameters.

Classes perform specific roles in the pipeline. Parameters tell Oceantracker which version of core classes the user wants to use for each role, or add optional classes. Eg. add multiple “release_groups” classes, which may release particles at points, or within a polygon, at different times, rates and locations, all within the same computational run.

Simply by changing the parameters, users can load their own version of a class, including the “solver” class which orchestrates the time stepping and operations by other classes. There are base classes for all the major roles within the computational pipeline. Classes can be adapted by inheriting the bases class, or one of its children, and overwriting some of the methods to alter how the class performs its role.

To make the ideas of settings and classes easier to adopt, the below uses methods of a helper class to add settings and classes to the pipeline. The notebook E_run_using_parameter_dictionaries.ipynb, shows how run directly from parameter dictionaries, which are built in code or read from a json or yaml file.

Parameters using helper#

There are two types of parameters:

  1. Settings parameters

These are set with one or more calls to helper method, ot.setting(…), where … are keyword arguments. eg “time_step”, the model time step in seconds is set using, time_step= 1800.

There are default values for most settings. A full list off the existing options and their defaults can be found in “top level settings”

  1. Class role parameters

Classes add specific tasks to the computational pipeline, eg. how to release particles, write output, particle suspension etc. These are added using helper method ot.add_class(class_role, ….). The first argument is a “class_role”. Each class has its own specific settings, which are set using keyword arguments of helper method. Eg. ot.add_class(‘reader’, input_dir= ‘my_hindcast_dir’, ….) adds a reader class and tells is it which folder contains the hindcast files.

A full list the existing classes and their default settings is located in the “parameter reference” of the documentation

Normally there must be a keyword argument “class_name” setting. This is used to import the required class into the computational pipeline, with its specific settings. This “class_name” is a string, used to import the class at setup (so is the same as that used to import any python class within a module).

The “class_name” setting is normally required. A few class_roles have a default class_name, eg. in minimal_example “release_groups” assumes a point_release, and the reader’s “class_name” is chosen by looking at variable names within the hindcast’s netcdf file.

There are two types of “class_role”.

When

  1. Only a single class is required, these have singular “class_role”, eg.”reader” and “solver”.

  2. One or more classes can be added. These have plural “class_role” (eg. can add multiple “release_groups”). Users must give a unique name to each one.

Documentation for all parameters/settings and their default values.

Add link here

Extend the minimal example#

The below extends the minimal_example, it adds:

  • release at random locations within a polygon, at random water depths (the default)

  • a particle fall velocity

  • particles on the bottom are re-suspended if friction velocity exceeds a critical value.

# Notes for debugging if the scripts below fail:
# * These scripts assume that you already installed oceantracker. If you didn't take a look at https://oceantracker.github.io/oceantracker/_build/html/info/installing.html
# * Paths in this directory are relative to the location of the ipython notebook.
#   I.e. On Linux or Mac, running a cell with "!ls" should return a list containing the notebook you are running.

# Checks if the hindcast data is available and downloads them if not
from oceantracker.util.download_data import download_hindcast_data_for_tutorials
download_hindcast_data_for_tutorials()
Hindcast data found locally at ./demo_hindcast
# build parameters using helper class
from oceantracker.main import OceanTracker
import os

ot = OceanTracker()  # make an instance of the helper class

# one or more settings can be set by calls to os.settings
ot.settings(
    run_output_dir=os.path.join("output", "param_test1"),
)

# ot.settings can be used more than once to add more settings
ot.settings(time_step=120)  #  2 min model time step as seconds

# add a compulsory reader class
# in most cases you won't need to specify which reader to use
# as the type of hindcast is autodetected
ot.add_class(
    "reader",
    # folder to search for hindcast files, sub-dirs will, by default, also be searched
    input_dir="./demo_hindcast/schsim3D",
    # hindcast file mask - only read files that follow this pattern
    file_mask="demo_hindcast_schisim3D*.nc",
)

# Adding "release groups" to define where, when and how particles are released
# you can multiple release groups for different kinds of releases (point or polygon)
# or to keep them apart in the results.
# There must be at least one release group

# add  release locations from two points,
ot.add_class(
    "release_groups",  #  class_role is release_groups
    # no class_name setting, so default is a point release
    name="my_release_points1",
    # the required name setting, is used to refer to this release group internally anf in post-processing
    # must be an N by 2 or 3 or list, convertible to a numpy array
    points=[
        [1595000, 5482600],
        [1599000, 5486200],
    ],
    release_interval=3600,  # seconds between releasing particles
    pulse_size=10,  # number of particles released each release_interval
)

# add a second release group, which release particles randomly within a polygon
ot.add_class(
    "release_groups",
    name="my_polygon_release1",
    class_name="PolygonRelease",  # use a polygon release
    # this time is a polygon , so below points are polygon cords
    points=[
        [1597682.1237, 5489972.7479],
        [1598604.1667, 5490275.5488],
        [1598886.4247, 5489464.0424],
        [1597917.3387, 5489000],
        [1597300, 5489000],
        [1597682.1237, 5489972.7479],
    ],
    release_interval=7200,  # seconds between releasing particles
    pulse_size=20,  # number of particles released each release_interval
)

# alter default re-suspension class's default settings
# only re-suspend particles if friction velocity exceeds this value
ot.add_class(
    "resuspension", critical_friction_velocity=0.005
)

# velocity_modifiers are a set of velocities added on top of the water velocity given in the hydrodynamic model's
# here we add a class to modify the particle buoyancy expressed a terminal-(falling)-velocity
ot.add_class(
    #  class_role is velocity_modifiers
    "velocity_modifiers",
    name="my_fall_velocity",
    class_name="TerminalVelocity",
    value=-0.001,  # mean terminal vel < 0 for falling
    # optionally variance can also be use to give each particle its own fall velocity
)


# now run oceantracker
# as "ot" has been set to the parameters above, simply run it
case_info_file_name = ot.run()
prelim:     Starting package set up
helper: ----------------------------------------------------------------------
helper: Starting OceanTracker helper class,  version 0.5.2.55
helper:      Python version: 3.11.14 | packaged by conda-forge | (main, Oct 22 2025, 22:46:25) [GCC 14.3.0]
helper: ----------------------------------------------------------------------
helper: OceanTracker version 0.5.2.55  starting setup helper "main.py":
helper: Started
helper: Output is in dir "/home/ls/projects/oceantracker_dev/oceantracker/tutorials_how_to/output/param_test1"
helper:     hint: see for copies of screen output and user supplied parameters, plus all other output
helper:     >>> Note: to help with debugging, parameters as given by user  are in "raw_user_params.json"
helper: ----------------------------------------------------------------------
helper: Numba setup: applied settings, max threads = 32, physical cores = 32
helper:     hint:  cache code = False, fastmath= False
helper: ----------------------------------------------------------------------
loading oceantracker read files
helper:       - Built OceanTracker package tree,      1.020 sec
helper:       - Built OceanTracker sort name map,     0.000 sec
helper:   - Done package set up to setup ClassImporter,       1.020 sec
setup: ----------------------------------------------------------------------
setup:  OceanTracker version 0.5.2.55
setup:     Starting user param. runner at 2026-01-21T17:38:06.499417
setup: ----------------------------------------------------------------------
setup:   - Start  field group manager and readers setup
setup:   - Found input dir "./demo_hindcast/schsim3D"
setup:   - Detected reader class_name = "oceantracker.reader.SCHISM_reader.SCHISMreader"
setup:   - Starting grid setup
setup:     - built node to triangles map,     0.867 sec
setup:     - built triangle adjacency matrix,         0.196 sec
setup:     - found boundary triangles,        0.000 sec
setup:     - built domain and island outlines,        1.133 sec
setup:     - calculated triangle areas,       0.000 sec
setup:   - Finished grid setup
setup: --- Hindcast info ----------------------------------------------------
setup:     Hydro-model is "3D", type "SCHISMreader"
setup:         hint: Files found in dir and sub-dirs of "./demo_hindcast/schsim3D"
setup:         Geographic coords = "False"
setup:         Hindcast start: 2017-01-01T00:30:00  end:  2017-01-01T23:30:00
setup:           time step = 0 days 1 hrs 0 min 0 sec, number of time steps= 24
setup:           grid bounding box = [1589789.000 5479437.000] to [1603398.000 5501640.000]
setup:           has:  A_Z profile=True,  bottom stress=False, regrid to sigma=True
setup:           vertical grid type = "LSC", using vertical grid  "Sigma"
setup: ----------------------------------------------------------------------
setup:   - Built barycentric-transform matrix,        0.309 sec
setup:   - Loading reader fields ['water_depth', 'water_velocity', 'tide']
setup:   - Finished field group manager and readers setup,    4.759 sec
setup: ----------------------------------------------------------------------
setup:   - Added 2 release group(s) and found run start and end times,        4.690 sec
setup:   - Starting initial setup of all classes
setup:     - Done initial setup of all classes,       0.004 sec
setup: ----------------------------------------------------------------------
setup:   - Starting "param_test1",  duration: 0 days 23 hrs 0 min 0 sec
setup:       From 2017-01-01T00:30:00 to  2017-01-01T23:30:00
setup:       Time step 120.0 sec
setup:         using: A_Z_profile = False, bottom_stress = False
setup: ----------------------------------------------------------------------
setup:   -  Reading 24 time steps,  for hindcast time steps 00:23 into ring buffer offsets 000:023 ,  for run "None"
setup:       -  read  24 time steps in  1.2 sec, from ./demo_hindcast/schsim3D
setup:   - Starting time stepping: 2017-01-01T00:30:00 to 2017-01-01T23:30:00
setup:     duration  0 days 23 hrs 0 min 0 sec, time step=  0 days 0 hrs 2 min 0 sec
S:   - Opened tracks output and done written first time step in: "tracks_compact_000.nc",     0.143 sec
S: 0000: 00%:H0000b00-01 Day +00 00:00 2017-01-01 00:30:00: Rel:40   : Active:40     Move:40     Bottom:0     Strand:0      Dead:0     Out:   0 Buffer: 5%  step time = 10006.3 ms
S: 0030: 04%:H0001b01-02 Day +00 01:00 2017-01-01 01:30:00: Rel:60   : Active:60     Move:60     Bottom:0     Strand:0      Dead:0     Out:   0 Buffer: 8%  step time =  8.1 ms
S: 0060: 09%:H0002b02-03 Day +00 02:00 2017-01-01 02:30:00: Rel:100  : Active:100    Move:98     Bottom:2     Strand:0      Dead:0     Out:   0 Buffer:13%  step time = 10.3 ms
S: 0090: 13%:H0003b03-04 Day +00 03:00 2017-01-01 03:30:00: Rel:110  : Active:110    Move:93     Bottom:7     Strand:10     Dead:0     Out:   0 Buffer:15%  step time =  7.4 ms
S: 0120: 17%:H0004b04-05 Day +00 04:00 2017-01-01 04:30:00: Rel:140  : Active:140    Move:116    Bottom:14    Strand:10     Dead:0     Out:   0 Buffer:19%  step time = 15.2 ms
S: 0150: 22%:H0005b05-06 Day +00 05:00 2017-01-01 05:30:00: Rel:150  : Active:150    Move:117    Bottom:22    Strand:11     Dead:0     Out:   0 Buffer:20%  step time =  8.4 ms
S: 0180: 26%:H0006b06-07 Day +00 06:00 2017-01-01 06:30:00: Rel:180  : Active:180    Move:150    Bottom:19    Strand:11     Dead:0     Out:   0 Buffer:25%  step time =  7.7 ms
S: 0210: 30%:H0007b07-08 Day +00 07:00 2017-01-01 07:30:00: Rel:190  : Active:190    Move:160    Bottom:20    Strand:10     Dead:0     Out:   0 Buffer:26%  step time = 13.3 ms
S: 0240: 35%:H0008b08-09 Day +00 08:00 2017-01-01 08:30:00: Rel:220  : Active:220    Move:190    Bottom:20    Strand:10     Dead:0     Out:   0 Buffer:30%  step time =  8.5 ms
S: 0270: 39%:H0009b09-10 Day +00 09:00 2017-01-01 09:30:00: Rel:240  : Active:240    Move:219    Bottom:21    Strand:0      Dead:0     Out:   0 Buffer:33%  step time =  9.7 ms
S: 0300: 43%:H0010b10-11 Day +00 10:00 2017-01-01 10:30:00: Rel:280  : Active:280    Move:227    Bottom:53    Strand:0      Dead:0     Out:   0 Buffer:38%  step time = 10.2 ms
S: 0330: 48%:H0011b11-12 Day +00 11:00 2017-01-01 11:30:00: Rel:300  : Active:300    Move:215    Bottom:85    Strand:0      Dead:0     Out:   0 Buffer:41%  step time =  8.6 ms
S: 0360: 52%:H0012b12-13 Day +00 12:00 2017-01-01 12:30:00: Rel:340  : Active:340    Move:217    Bottom:123   Strand:0      Dead:0     Out:   0 Buffer:47%  step time =  9.7 ms
S: 0390: 57%:H0013b13-14 Day +00 13:00 2017-01-01 13:30:00: Rel:360  : Active:360    Move:350    Bottom:10    Strand:0      Dead:0     Out:   0 Buffer:50%  step time =  9.0 ms
S: 0420: 61%:H0014b14-15 Day +00 14:00 2017-01-01 14:30:00: Rel:400  : Active:400    Move:392    Bottom:8     Strand:0      Dead:0     Out:   0 Buffer:55%  step time =  9.0 ms
S: 0450: 65%:H0015b15-16 Day +00 15:00 2017-01-01 15:30:00: Rel:410  : Active:410    Move:331    Bottom:13    Strand:66     Dead:0     Out:   0 Buffer:56%  step time =  7.5 ms
S: 0480: 70%:H0016b16-17 Day +00 16:00 2017-01-01 16:30:00: Rel:440  : Active:440    Move:294    Bottom:80    Strand:66     Dead:0     Out:   0 Buffer:61%  step time = 12.6 ms
S: 0510: 74%:H0017b17-18 Day +00 17:00 2017-01-01 17:30:00: Rel:450  : Active:450    Move:198    Bottom:182   Strand:70     Dead:0     Out:   0 Buffer:62%  step time =  9.6 ms
S: 0540: 78%:H0018b18-19 Day +00 18:00 2017-01-01 18:30:00: Rel:480  : Active:480    Move:371    Bottom:39    Strand:70     Dead:0     Out:   0 Buffer:66%  step time =  9.3 ms
S: 0570: 83%:H0019b19-20 Day +00 19:00 2017-01-01 19:30:00: Rel:490  : Active:490    Move:406    Bottom:14    Strand:70     Dead:0     Out:   0 Buffer:68%  step time =  9.9 ms
S: 0600: 87%:H0020b20-21 Day +00 20:00 2017-01-01 20:30:00: Rel:520  : Active:520    Move:433    Bottom:17    Strand:70     Dead:0     Out:   0 Buffer:72%  step time =  9.0 ms
S: 0630: 91%:H0021b21-22 Day +00 21:00 2017-01-01 21:30:00: Rel:540  : Active:540    Move:512    Bottom:28    Strand:0      Dead:0     Out:   0 Buffer:75%  step time = 15.9 ms
S: 0660: 96%:H0022b22-23 Day +00 22:00 2017-01-01 22:30:00: Rel:580  : Active:580    Move:440    Bottom:140   Strand:0      Dead:0     Out:   0 Buffer:80%  step time =  8.3 ms
S: 0690: 100%:H0022b22-23 Day +00 23:00 2017-01-01 23:30:00: Rel:600  : Active:600    Move:342    Bottom:258   Strand:0      Dead:0     Out:   0 Buffer:83%  step time =  9.1 ms
S: --- Closing all classes ----------------------------------------------
S: Converting compact track files to rectangular format (to disable set reader param convert=False)
S:     hint: reading from dir /home/ls/projects/oceantracker_dev/oceantracker/tutorials_how_to/output/param_test1
S:     - Finished "tracks_rectangular_000.nc",        0.107 sec
S:     - Conversion complete,         0.107 sec
S: Removing compact track files output after conversion
end: ----------------------------------------------------------------------
end: Finished "param_test1"
end:     Timings: total =  32.9 sec
end:         Setup                          1.19 s    3.6%
end:         Find initial horizontal cell   1.57 s    4.8%
end:         Reading hindcast               1.19 s    3.6%
end:         Find horizontal cell           2.30 s    7.0%
end:         Find vertical cell             1.71 s    5.2%
end:         Interpolate fields             1.88 s    5.7%
end:         Update custom particle prop.   0.00 s    0.0%
end:         Update statistics              0.00 s    0.0%
end:         Update event loggers           0.00 s    0.0%
end:         RK integration                 0.47 s    1.4%
end:         Releasing particles            0.07 s    0.2%
end:         Close down                     4.19 s   12.7%
end:         resuspension                   0.41 s    1.3%
end:         dispersion                     0.55 s    1.7%
end:         tracks_writer                  0.08 s    0.2%
end: ----------------------------------------------------------------------
end: Finished "param_test1",  started: 2026-01-21 17:38:05.311720, ended: 2026-01-21 17:38:38.234940
end:       Computational time = 0:00:32.923232
end:       Max. memory used 110.55 GB
end: --- Issues    (check above,  any errors repeated below) --------------
end:     0 errors,    0 strong warnings,   0 warnings,   1 notes
end: --- Successful completion: output in "output/param_test1" ------------
../../_images/B_running_with_helper_class_2_1.png
# and again, the model output and its case_info file are in
print("case file name=", case_info_file_name)
case file name= /home/ls/projects/oceantracker_dev/oceantracker/tutorials_how_to/output/param_test1/caseInfo.json
# model parameters are stored in a python dictionary,
# which can be shown as a json
import json
print(json.dumps(ot.params, indent=4))
{
    "run_output_dir": "output/param_test1",
    "time_step": 120,
    "reader": {
        "input_dir": "./demo_hindcast/schsim3D",
        "file_mask": "demo_hindcast_schisim3D*.nc"
    },
    "release_groups": [
        {
            "points": [
                [
                    1595000,
                    5482600
                ],
                [
                    1599000,
                    5486200
                ]
            ],
            "release_interval": 3600,
            "pulse_size": 10,
            "name": "my_release_points1"
        },
        {
            "points": [
                [
                    1597682.1237,
                    5489972.7479
                ],
                [
                    1598604.1667,
                    5490275.5488
                ],
                [
                    1598886.4247,
                    5489464.0424
                ],
                [
                    1597917.3387,
                    5489000
                ],
                [
                    1597300,
                    5489000
                ],
                [
                    1597682.1237,
                    5489972.7479
                ]
            ],
            "release_interval": 7200,
            "pulse_size": 20,
            "class_name": "PolygonRelease",
            "name": "my_polygon_release1"
        }
    ],
    "resuspension": {
        "critical_friction_velocity": 0.005
    },
    "velocity_modifiers": [
        {
            "value": -0.001,
            "class_name": "TerminalVelocity",
            "name": "my_fall_velocity"
        }
    ]
}
# plot animation of results
from oceantracker.plot_output import plot_tracks
from oceantracker.read_output.python import load_output_files
from IPython.display import HTML  # show animation in note book

# read particle track data into a dictionary using case_info_file_name
tracks = load_output_files.load_track_data(case_info_file_name)

ax = [1591000, 1601500, 5479500, 5491000]  # area to plot
# animate particles
anim = plot_tracks.animate_particles(
    tracks,
    axis_lims=ax,
    title="Fall vel.+  re-sus., grey part. are on bottom when flows too weak to resuspend",
    show_dry_cells=True,
    show_grid=True,
    # use ipython to show video, rather than matplotlib plt.show()
    show=False,
)

# this line only used in note books, in python scripts use show = True above
HTML(anim.to_html5_video())
Merging rectangular track files
     Reading rectangular track file "tracks_rectangular_000.nc"
../../_images/B_running_with_helper_class_5_2.png