Tutorial: The Ocean Module

Note

You can download an executable version (Jupyter Notebook) of this tutorial here.

ocean_module_tutorial

Kadlu's Ocean Module

The ocean module is an abstraction of Kadlu's loading and interpolation functions, which provides a unified interface to quickly load and interpolate many different environmental variables. In this tutorial, we will take a closer look at the key functionalities of the ocean module.

We begin by importing the necessary modules, functions, etc.

In [1]:
import numpy as np
from datetime import datetime

from kadlu import source_map
from kadlu.geospatial.ocean import Ocean

The geographical and temporal boundaries are specified as python dictionary, to be passed to the plotting function later. In this example, we are concerned with a rectangular area in the Gulf of St. Lawrence, which extends from $47.8^o$N to $48.8^o$N and $-63.4^o$W to $-61.8^o$W, as shown on the map below. Note, also, that we are only loading data for the first 100 m of the water column (bottom=100, top=0) on the first 12 hours of January 9, 2015.

In [2]:
# ocean boundaries:
bounds = dict(
        start=datetime(2015, 1, 9), end=datetime(2015, 1, 9, 12),
        south=47.8, west=-63.4, 
        north=48.8, east=-61.8, 
        top=0, bottom=100
    )

Selected region

Initialization and querying

The ocean module can be instatiated without specifying any data sources. This is the simplest way of instantiating the ocean module and result in an ocean with null data everywere.

In [3]:
o = Ocean(**bounds) # instantiate ocean with null values

The ocean module has a bunch of methods for querying various environmental data. For a full list, see the ocean module's documentation page. For example, bathymetric data can be queried with the bathy method as follows,

In [4]:
o.bathy(lat=[48.5, 48.1], lon=[-63, -62.5]) # query bathymetric interpolator for values at given coordinates
Out[4]:
array([0., 0.])

To query using planar coordinates, use the bathy_xy method instead,

In [5]:
o.bathy_xy(x=[-2000, 3500], y=[10000, 15000]) # query bathymetric interpolator for values at given displacements
Out[5]:
array([0., 0.])

Here, x and y are the horizontal (W-E) and vertical (S-N) displacements in meters, respectively, in a planar coordinate system centered at the mid-point of the geographical region under consideration.

Automatic loading of data

In order to use Kadlu's automated data loading functionalities, you simply have to specify one (or several) of the data sources listed in the source_map. For example,

In [6]:
o = Ocean(load_salinity='hycom', **bounds)                     # instantiate interpolator with HYCOM salinity data
o.salinity(lat=[48.5, 48.1], lon=[-64, -62.5], depth=[0, 10])  # query interpolator for values at given coordinates
2020-06-15 02:46:23  HYCOM 2015-01-09 downloading 424320 salinity values in region 46.00°N,64.00°W,0m:48.00°N,62.00°W,5000m...
2020-06-15 02:46:47  HYCOM 2015-01-09 salinity: downloaded 430 Kb in 21.800s. parsed and inserted 121544 rows in 2.218s. 302776 null values removed, 0 duplicates ignored
2020-06-15 02:46:47  HYCOM 2015-01-09 downloading 424320 salinity values in region 48.00°N,64.00°W,0m:50.00°N,62.00°W,5000m...
2020-06-15 02:47:07  HYCOM 2015-01-09 salinity: downloaded 426 Kb in 17.170s. parsed and inserted 172832 rows in 2.712s. 247992 null values removed, 3496 duplicates ignored
2020-06-15 02:47:07  HYCOM 2015-01-09 downloading 424320 salinity values in region 46.00°N,62.00°W,0m:48.00°N,60.00°W,5000m...
2020-06-15 02:47:09  HYCOM 2015-01-09 salinity: downloaded 430 Kb in 0.886s. parsed and inserted 129080 rows in 1.966s. 290400 null values removed, 4840 duplicates ignored
2020-06-15 02:47:09  HYCOM 2015-01-09 downloading 424320 salinity values in region 48.00°N,62.00°W,0m:50.00°N,60.00°W,5000m...
2020-06-15 02:47:20  HYCOM 2015-01-09 salinity: downloaded 418 Kb in 6.768s. parsed and inserted 227952 rows in 3.331s. 184584 null values removed, 11784 duplicates ignored
Out[6]:
array([31.29669351, 31.44977994])
In [7]:
o.waveheight(lat=[48.5, 48.1], lon=[-64, -62.5]) # query waveheight interpolator: values remain null
Out[7]:
array([0., 0.])

Kadlu can check for missing data and prepare interpolators for many variables at the same time

In [9]:
# source strings passed as load arguments tells the ocean module where to source the data
sources = dict(
        load_bathymetry='gebco',
        load_temp='hycom',
        load_salinity='hycom',
        load_wavedir='era5',
        load_waveheight='era5',
        load_waveperiod='era5',
        load_wavedirection='era5',
        load_windspeed='era5'
    )

o = Ocean(**sources, **bounds)
2020-06-15 02:47:34  HYCOM 2015-01-09 downloading 424320 water_temp values in region 46.00°N,64.00°W,0m:48.00°N,62.00°W,5000m...
2020-06-15 02:47:54  HYCOM 2015-01-09 water_temp: downloaded 448 Kb in 16.295s. parsed and inserted 121544 rows in 3.303s. 302776 null values removed, 0 duplicates ignored
2020-06-15 02:47:54  HYCOM 2015-01-09 downloading 424320 water_temp values in region 48.00°N,64.00°W,0m:50.00°N,62.00°W,5000m...
2020-06-15 02:48:08  HYCOM 2015-01-09 water_temp: downloaded 448 Kb in 11.152s. parsed and inserted 172832 rows in 2.751s. 247992 null values removed, 3496 duplicates ignored
2020-06-15 02:48:08  HYCOM 2015-01-09 downloading 424320 water_temp values in region 46.00°N,62.00°W,0m:48.00°N,60.00°W,5000m...
2020-06-15 02:48:14  HYCOM 2015-01-09 water_temp: downloaded 448 Kb in 4.961s. parsed and inserted 129080 rows in 1.845s. 290400 null values removed, 4840 duplicates ignored
2020-06-15 02:48:14  HYCOM 2015-01-09 downloading 424320 water_temp values in region 48.00°N,62.00°W,0m:50.00°N,60.00°W,5000m...
2020-06-15 02:48:28  HYCOM 2015-01-09 water_temp: downloaded 448 Kb in 10.328s. parsed and inserted 227952 rows in 3.152s. 184584 null values removed, 11784 duplicates ignored
2020-06-15 02:48:31  ERA5 2015-01-09 mean_wave_direction: processed and inserted 529 rows in region 46.00°N,64.00°W,0m:48.00°N,62.00°W,5000m. 0 duplicates ignored
2020-06-15 02:48:33  ERA5 2015-01-09 mean_wave_direction: processed and inserted 414 rows in region 48.00°N,64.00°W,0m:50.00°N,62.00°W,5000m. 115 duplicates ignored
2020-06-15 02:48:36  ERA5 2015-01-09 mean_wave_direction: processed and inserted 368 rows in region 46.00°N,62.00°W,0m:48.00°N,60.00°W,5000m. 115 duplicates ignored
2020-06-15 02:48:38  ERA5 2015-01-09 mean_wave_direction: processed and inserted 368 rows in region 48.00°N,62.00°W,0m:50.00°N,60.00°W,5000m. 207 duplicates ignored
2020-06-15 02:48:50  ERA5 2015-01-09 significant_height_of_combined_wind_waves_and_swell: processed and inserted 529 rows in region 46.00°N,64.00°W,0m:48.00°N,62.00°W,5000m. 0 duplicates ignored
2020-06-15 02:48:52  ERA5 2015-01-09 significant_height_of_combined_wind_waves_and_swell: processed and inserted 414 rows in region 48.00°N,64.00°W,0m:50.00°N,62.00°W,5000m. 115 duplicates ignored
2020-06-15 02:48:55  ERA5 2015-01-09 significant_height_of_combined_wind_waves_and_swell: processed and inserted 368 rows in region 46.00°N,62.00°W,0m:48.00°N,60.00°W,5000m. 115 duplicates ignored
2020-06-15 02:48:58  ERA5 2015-01-09 significant_height_of_combined_wind_waves_and_swell: processed and inserted 368 rows in region 48.00°N,62.00°W,0m:50.00°N,60.00°W,5000m. 207 duplicates ignored
2020-06-15 02:49:01  ERA5 2015-01-09 mean_wave_period: processed and inserted 529 rows in region 46.00°N,64.00°W,0m:48.00°N,62.00°W,5000m. 0 duplicates ignored
2020-06-15 02:49:04  ERA5 2015-01-09 mean_wave_period: processed and inserted 414 rows in region 48.00°N,64.00°W,0m:50.00°N,62.00°W,5000m. 115 duplicates ignored
2020-06-15 02:49:07  ERA5 2015-01-09 mean_wave_period: processed and inserted 368 rows in region 46.00°N,62.00°W,0m:48.00°N,60.00°W,5000m. 115 duplicates ignored
2020-06-15 02:49:09  ERA5 2015-01-09 mean_wave_period: processed and inserted 368 rows in region 48.00°N,62.00°W,0m:50.00°N,60.00°W,5000m. 207 duplicates ignored
2020-06-15 02:49:09  loading elevation from The GEBCO_2020 Grid - a continuous terrain model for oceans and land at 15 arc-second intervals

Now we can query any of the loaded variable at any set of coordinates, e.g., wave height:

In [10]:
o.waveheight(lat=[48.5, 48.1], lon=[-64, -62.5])  # query waveheight interpolator
Out[10]:
array([2.13783391, 2.17374152])

Manual loading of data

Kadlu also supports ocean interpolation using arbitrary environmental data. An ocean can be initialized by passing a float or array of floats to the load_variable keyword argument. Arrays must be ordered by [values, lat, lon] for 2D data, or [values, lat, lon, depth] for 3D data.

When a float value is used, a uniform "interpolation" of that value will be returned for every coordinate location

In [11]:
bathy_arr = np.array((
        np.random.rand(100) * 500.,  # array of length 100 with random values in the range 0-500.
        bounds['south'] + np.random.rand(100) * (bounds['north'] - bounds['south']),  # latitudes
        bounds['west'] + np.random.rand(100) * (bounds['east'] - bounds['west'])  # longitudes
    ))
temp_float = 10
salinity_float = 35

o = Ocean(load_bathymetry=bathy_arr, load_temp=temp_float, load_salinity=salinity_float, **bounds)
In [12]:
print('bathymetry:\t',  o.bathy(   lat=[47.5, 48.1], lon=[-64, -62.5]))
print('temperature:\t', o.temp(    lat=[47.5, 48.1], lon=[-64, -62.5], depth=[0, 50]))
print('salinity:\t',    o.salinity(lat=[47.5, 48.1], lon=[-64, -62.5], depth=[0, 50]))

for a list of possible strings accepted as input for the load_variable arguments, choose one of the sources listed in the source_map that supports that variable:

In [16]:
print(source_map)