track.py


Bingwei Ling, Jian Cui, and Jim Manning
Version 1.0 Summer 2015
Note: We have a web utility that runs most of the code described below here.

Objective:

This code plots observed drifter tracks with those derived from multiple models.

At this time, the only two model fields are selectable:

Both grids cover most of the Northeast Continental Shelf where there are over 1000 observed drifter tracks to examine.

Modules and files needed other than the main routine track.py:

All of files are available on GITHUB Particles-in-the-Coastal-Ocean

Install Anaconda

Running this program need supported by python condition. Anaconda is one of the best python application, here below are steps to install Anaconda.

  1. Download Anaconda from here.
  2. Installation.
  3. Install Module "netCDF4". You may not need.

How to run the main program:

This routine can plot both the observed and modeled drifter tracks. It has four options to start track.

  1. Drifter Track
  2. In this option, the plot of result will be show one day's drifter track and a few days forecast track(depends on the parameter 'track_days'). The forecast track starts at the last point of the drifter. What you need do is give Drifter ID, Files-name, track_days and decide what kind of plot you want, png or gif. You can also turn streamline on. See the sample(image_style=animation). Run this program with the steps below:

    Tips: How to find "ID" of drifters to test:

  3. Grid or Transect of start points
  4. This option allow us enter one or two points and specify numbers between two points as start points, then forecast or hindcast(depends on parameter 'track_way',forward or backward) a few days. You can also choose 'track_way=both' to track both forward and backward at the same time. There are optional features available, like boundary_switch, streamline, etc. Here is a sample of "streamline=ON" case.Run this program with the steps below:

  5. Click on map for points
  6. This option generates a simulation may of Cape Cod Bay first, you click on the map to add points where you want track. and the features are same to option 2. Sample here is an animation of three points forecast one day. Run this program with the steps below:

  7. Star or Random of points
  8. In this option, Specify a point, radius, a number(kind of density), you will got a box contains a certain amount of points that is the start points we will track. The features are available same to other options. See the sample (image_style=animation),click here. Run this program with the steps below:

Example run w/plots:

SET:

RUN:
try "run track.py" in ipython

Description on Classes:

  1. Class track

    Base class of "get_roms" and "get_fvcom" to write common methods.
    • method get_data(self, url)

    • method bbox2ij(self, lons, lats, bbox)

      Return tuple of indices of points that are completely covered by the specific boundary box.
      lon,lat = 2D arrays that are the target of the subset, type: np.ndarray
      bbox = list containing the bounding box: [lon_min, lon_max, lat_min, lat_max]
      Example:
      • i0,i1,j0,j1 = bbox2ij(lat_rho,lon_rho,[-71, -63., 39., 46])
      • h_subset = nc.variables['h'][j0:j1,i0:i1]
    • method nearest_point_index(self, lon, lat, lons, lats, length=(1, 1))

      Return the index of the nearest rho point.
      • lon, lat: the coordinate of start point, float
      • lons, lats: the coordinates of points to be calculated
      • length: side length of boundary box
  2. Class get_roms(track)

    Calculate the nodes of model ROMs.
    Data is hourly from 2013.05.18 to present
    • method get_url(self, starttime, endtime)

      Return specific url according to starttime and endtime.
    • method get_data(self, url)

      Return a dict that contains 'lon_rho', 'lat_rho', 'mask_rho', 'u', 'v'
    • method get_track(self, lon, lat, depth, url)

      Return a dict including 'lon' and 'lat'.
      A shell of method "__waternode"
    • method __get_track(self, lon, lat, depth, url)

      Return a dict including 'lon' and 'lat'
  3. Class get_fvcom

    Calculate the nodes of model FVCOM. There are 3 submodels in FVCOM, '30yr', 'massbay', and 'GOM3'.
    '30yr' is the submodel we use here which contain the data hourly from 1978. to present.
    'massbay' and 'GOM3' are for forecasting.
    • method get_url(self, starttime, endtime)

      Return urls based on starttime and endtime.
      Judge which version url the endtime is in, then pass it to method "__temp".
    • method __temp(self, starttime, endtime, time1, time2)

      Judge which version url the starttime is in. If both starttime and endtime are in the same version url, pass it to method "__url". If not pass (starttime, the time of the end of specific version url before the version url that endtime is in.) to method "get_url", and pass (the time of the start of the version url that endtime is in, endtime) to method "__url".
    • method __url(self, year, month, start_daytime, end_daytime)

      Return the url of the specific month of same version.
      start_daytime, end_daytime: [day, hour]
    • method get_data(self, url)

      Return a dict including 'lon', 'lat', 'latc', 'lonc', 'u', 'v', 'siglay', 'h'
    • method get_track(self, lon, lat, depth, url)

      Return a dict including 'lon' and 'lat'.
      Shell of "__waternode()"

      url: string or list of string.
    • method __get_track(self, lon, lat, depth, url)

      Return a dict including 'lon' and 'lat'.

      url: string
  4. Class get_drifter()

    Return a dict including 'lon', 'lat'.
    • method get_track(self, starttime=None, days=None)

      Return a dict of 'lon', 'lat', 'time'
      If starttime is given, return data starting from starttime.
      If both starttime and days are given, return data starting from 'starttime' in 'days' days.
    • method __cmptime(self, time, times)

      Return indices of the nearest time in "times" which is the nearest to "time"
  5. Class get_roms_rk4()

    Subclass of "get_roms", rewrite method "get_track" and "__get_track". Almost the same, but using Runge Kutta Method to calculate the velocity.
    • method get_track(self, lon, lat, depth, url)

      Return a dictionary of nodes coordinates, using __waternode.
    • method __get_track(self, lon, lat, depth, url)

      Return a dictionary of nodes coordinates, using RungeKutta4_lonlat
    • method polygonal_bartcentric_coordinates(self, xp, yp, xv, yv)

      Return the weights.
    • method VelInterp_lonlat(self, lonp, latp, lons, lats, u, v)

      Return u, v based on method polygonal_bartcentric_coordinates.
    • method RungeKutta4_lonlat(self, lon, lat, lons, lats, u, v, tau)

      Return lon, lat, u, v. RungeKutta4 methods.
    • Function draw_basemap(fig, ax, lonsize, latsize, interval_lon=0.5, interval_lat=0.5)

      Draw basemap for the map. lonsize and latsize determine the size of basemap.

      lonsize = [6, 56]
      latsize = [5, 61]

Description of the class inheritance:

For both Class water_fvcom and water_roms, if you want to get the specific nodes, just need 3 steps:

  1. Create the instance of Class:

    water = Class()
    ("Class" equals "water_fvcom" or "water_roms" or "water_roms_rk4")
  2. Get url that needed:

    url = water.get_url(starttime, endtime)
  3. Get data:

    nodes = water.waternode(lon, lat, depth, url)

Future plans:

  1. add various forms of RungeKutta
    generate at least three examples of the difference in tracks
  2. post to Github
  3. add cookbook to download Python distribution for teachers
  4. add more selectable model fields
    • FVCOM MASSBAY
    • HOPS
    • Nikitas