Minimal example#

[This notebook is distributed as part of OceanTracker’s source code oceantracker/tutorials_how_to/]

Running a simulation generally follows three steps:

  1. Define model parameters

  2. Pass these parameters to OceanTracker and running the model

  3. Visualize the results

This example uses OceanTracker’s “helper functions” - a set of python methods - to configure and run OceanTracker. You can also run OceanTracker from the command line uns using json or yaml input files. See tutorial E: using parameter dictionaries for more info on that.

# 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 download 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
import os  # used here exclusively to make platform (win/mac/linux) dependent paths
from oceantracker.main import OceanTracker
prelim:     Starting package set up
# minimal_example.py using class helper method
# ------------------------------------------------

# create an oceantracker instance that we can then configure step by step
ot = OceanTracker()

# ot.settings method use to set basic settings
ot.settings(
    run_output_dir=os.path.join("output", "minimal_example"),
    time_step=120,  #  2 min time step as seconds
)

# the different functionality is contained in "classes"
# here we add the 'reader' to read the hydrodynamical hindcasts
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",
)

# next we add "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
ot.add_class(
    "release_groups",
    points=[
        [1595000, 5482600],  # [x,y] pairs of release locations
        [1599000, 5486200],
    ],  # must be an N by 2 or 3 or list, convertible to a numpy array
    release_interval=3600,  # seconds between releasing particles
    pulse_size=10,  # number of particles released each release_interval
)

# we can already run this minimal setup
case_info_file_name = ot.run()
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/minimal_example"
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,      0.983 sec
helper:       - Built OceanTracker sort name map,     0.000 sec
helper:   - Done package set up to setup ClassImporter,       0.983 sec
setup: ----------------------------------------------------------------------
setup:  OceanTracker version 0.5.2.55
setup:     Starting user param. runner at 2026-01-21T17:42:26.986541
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.887 sec
setup:     - built triangle adjacency matrix,         0.191 sec
setup:     - found boundary triangles,        0.000 sec
setup:     - built domain and island outlines,        1.085 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.340 sec
setup:   - Loading reader fields ['water_depth', 'tide', 'water_velocity']
setup:   - Finished field group manager and readers setup,    4.769 sec
setup: ----------------------------------------------------------------------
setup:   - Added 1 release group(s) and found run start and end times,        1.878 sec
setup:   - Starting initial setup of all classes
setup:     - Done initial setup of all classes,       0.004 sec
setup: ----------------------------------------------------------------------
setup:   - Starting "minimal_example",  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.129 sec
S: 0000: 00%:H0000b00-01 Day +00 00:00 2017-01-01 00:30:00: Rel:20   : Active:20     Move:20     Bottom:0     Strand:0      Dead:0     Out:   0 Buffer: 4%  step time = 9516.9 ms
S: 0030: 04%:H0001b01-02 Day +00 01:00 2017-01-01 01:30:00: Rel:40   : Active:40     Move:40     Bottom:0     Strand:0      Dead:0     Out:   0 Buffer: 8%  step time =  5.2 ms
S: 0060: 09%:H0002b02-03 Day +00 02:00 2017-01-01 02:30:00: Rel:60   : Active:60     Move:60     Bottom:0     Strand:0      Dead:0     Out:   0 Buffer:12%  step time =  5.2 ms
S: 0090: 13%:H0003b03-04 Day +00 03:00 2017-01-01 03:30:00: Rel:70   : Active:70     Move:60     Bottom:0     Strand:10     Dead:0     Out:   0 Buffer:14%  step time =  7.6 ms
S: 0120: 17%:H0004b04-05 Day +00 04:00 2017-01-01 04:30:00: Rel:80   : Active:80     Move:70     Bottom:0     Strand:10     Dead:0     Out:   0 Buffer:16%  step time =  7.6 ms
S: 0150: 22%:H0005b05-06 Day +00 05:00 2017-01-01 05:30:00: Rel:90   : Active:90     Move:80     Bottom:0     Strand:10     Dead:0     Out:   0 Buffer:18%  step time =  7.4 ms
S: 0180: 26%:H0006b06-07 Day +00 06:00 2017-01-01 06:30:00: Rel:100  : Active:100    Move:90     Bottom:0     Strand:10     Dead:0     Out:   0 Buffer:20%  step time =  6.7 ms
S: 0210: 30%:H0007b07-08 Day +00 07:00 2017-01-01 07:30:00: Rel:110  : Active:110    Move:100    Bottom:0     Strand:10     Dead:0     Out:   0 Buffer:22%  step time =  7.3 ms
S: 0240: 35%:H0008b08-09 Day +00 08:00 2017-01-01 08:30:00: Rel:120  : Active:120    Move:110    Bottom:0     Strand:10     Dead:0     Out:   0 Buffer:25%  step time =  5.5 ms
S: 0270: 39%:H0009b09-10 Day +00 09:00 2017-01-01 09:30:00: Rel:140  : Active:140    Move:140    Bottom:0     Strand:0      Dead:0     Out:   0 Buffer:29%  step time = 10.6 ms
S: 0300: 43%:H0010b10-11 Day +00 10:00 2017-01-01 10:30:00: Rel:160  : Active:160    Move:160    Bottom:0     Strand:0      Dead:0     Out:   0 Buffer:33%  step time =  7.4 ms
S: 0330: 48%:H0011b11-12 Day +00 11:00 2017-01-01 11:30:00: Rel:180  : Active:180    Move:180    Bottom:0     Strand:0      Dead:0     Out:   0 Buffer:37%  step time =  7.3 ms
S: 0360: 52%:H0012b12-13 Day +00 12:00 2017-01-01 12:30:00: Rel:200  : Active:200    Move:200    Bottom:0     Strand:0      Dead:0     Out:   0 Buffer:41%  step time = 14.1 ms
S: 0390: 57%:H0013b13-14 Day +00 13:00 2017-01-01 13:30:00: Rel:220  : Active:220    Move:205    Bottom:0     Strand:15     Dead:0     Out:   0 Buffer:45%  step time =  8.0 ms
S: 0420: 61%:H0014b14-15 Day +00 14:00 2017-01-01 14:30:00: Rel:240  : Active:240    Move:221    Bottom:0     Strand:19     Dead:0     Out:   0 Buffer:50%  step time =  7.9 ms
S: 0450: 65%:H0015b15-16 Day +00 15:00 2017-01-01 15:30:00: Rel:250  : Active:250    Move:192    Bottom:0     Strand:58     Dead:0     Out:   0 Buffer:52%  step time =  8.5 ms
S: 0480: 70%:H0016b16-17 Day +00 16:00 2017-01-01 16:30:00: Rel:260  : Active:260    Move:193    Bottom:0     Strand:67     Dead:0     Out:   0 Buffer:54%  step time =  9.1 ms
S: 0510: 74%:H0017b17-18 Day +00 17:00 2017-01-01 17:30:00: Rel:270  : Active:270    Move:195    Bottom:0     Strand:75     Dead:0     Out:   0 Buffer:56%  step time =  7.8 ms
S: 0540: 78%:H0018b18-19 Day +00 18:00 2017-01-01 18:30:00: Rel:280  : Active:280    Move:205    Bottom:0     Strand:75     Dead:0     Out:   0 Buffer:58%  step time =  8.8 ms
S: 0570: 83%:H0019b19-20 Day +00 19:00 2017-01-01 19:30:00: Rel:290  : Active:290    Move:217    Bottom:0     Strand:73     Dead:0     Out:   0 Buffer:60%  step time = 10.2 ms
S: 0600: 87%:H0020b20-21 Day +00 20:00 2017-01-01 20:30:00: Rel:300  : Active:300    Move:236    Bottom:0     Strand:64     Dead:0     Out:   0 Buffer:62%  step time =  7.5 ms
S: 0630: 91%:H0021b21-22 Day +00 21:00 2017-01-01 21:30:00: Rel:320  : Active:320    Move:301    Bottom:0     Strand:19     Dead:0     Out:   0 Buffer:66%  step time = 10.3 ms
S: 0660: 96%:H0022b22-23 Day +00 22:00 2017-01-01 22:30:00: Rel:340  : Active:340    Move:325    Bottom:0     Strand:15     Dead:0     Out:   0 Buffer:70%  step time =  8.3 ms
S: 0690: 100%:H0022b22-23 Day +00 23:00 2017-01-01 23:30:00: Rel:360  : Active:360    Move:360    Bottom:0     Strand:0      Dead:0     Out:   0 Buffer:75%  step time =  8.4 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/minimal_example
S:     - Finished "tracks_rectangular_000.nc",        0.091 sec
S:     - Conversion complete,         0.091 sec
S: Removing compact track files output after conversion
end: ----------------------------------------------------------------------
end: Finished "minimal_example"
end:     Timings: total =  29.0 sec
end:         Setup                          1.20 s    4.1%
end:         Find initial horizontal cell   1.57 s    5.4%
end:         Reading hindcast               1.21 s    4.2%
end:         Find horizontal cell           2.49 s    8.6%
end:         Find vertical cell             1.53 s    5.3%
end:         Interpolate fields             1.47 s    5.1%
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.46 s    1.6%
end:         Releasing particles            0.05 s    0.2%
end:         Close down                     3.83 s   13.2%
end:         resuspension                   0.40 s    1.4%
end:         dispersion                     0.54 s    1.9%
end:         tracks_writer                  0.07 s    0.2%
end: ----------------------------------------------------------------------
end: Finished "minimal_example",  started: 2026-01-21 17:42:25.788022, ended: 2026-01-21 17:42:54.817729
end:       Computational time = 0:00:29.029719
end:       Max. memory used 111.27 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/minimal_example" --------
/home/ls/projects/oceantracker_dev/oceantracker/tutorials_how_to/output/minimal_example/caseInfo.json
../../_images/A_minimal_example_3_1.png
# case_info file name contains the path to "head" model output, located in the run_output_dir
# its a json file that contains e.g. model statistics and model output file names
# which is handy for post-processing
print(case_info_file_name)
/home/ls/projects/oceantracker_dev/oceantracker/tutorials_how_to/output/minimal_example/caseInfo.json

Read and plot output#

from oceantracker.read_output.python import load_output_files
from oceantracker.plot_output import plot_tracks
# oceantracker has some build in plotting tools that we frequently use to
# take a quick look at the model output

# first we need to read particle track data
tracks = load_output_files.load_track_data(case_info_file_name)
Merging rectangular track files
     Reading rectangular track file "tracks_rectangular_000.nc"
# the have a quick look at what variables are available you can call
_ = [print(item) for item in tracks.keys()]  # show what is in tracks dictionary holds
particles_written_per_time_step
time_step_range
time
num_part_released_so_far
x
x0
status
status_last_good
age
ID
IDrelease_group
user_release_groupID
IDpulse
hydro_model_gridID
time_released
water_depth
tide
dry_cell_index
grid
particle_status_flags
particle_release_groups
axis_lim
plot_tracks.plot_tracks(
    tracks, axis_lims=[1591000, 1601500, 5479500, 5491000], show_grid=True
)
../../_images/A_minimal_example_9_0.png

Add aminations#

In animation, sand colored area shows dry cells, blue particles are moving, green are stranded by the tide in dry cells, gray are on the sea bed, from which they resupend in this example.

By default particles are blocked from moving from a wet cell to a dry cell and will not be released if the release location lies within a dry cell.

from oceantracker.plot_output import plot_tracks
from IPython.display import HTML

# animate particles
anim = plot_tracks.animate_particles(
    tracks,
    axis_lims=[1591000, 1601500, 5479500, 5491000],
    interval=100, # milliseconds between frames
    show_dry_cells=True,
    show_grid=True,
    show=False, # we'll use the ipythons HTML function to show it
)

# this line only used in note books, in python scripts use show = True above
HTML(anim.to_html5_video())
../../_images/A_minimal_example_11_1.png