Gulf Stream Currents
Overview
An example that uses ipyleaflet
to reproduce style of visualization used in the New York Times article
In the Atlantic Ocean, Subtle Shifts Hint at Dramatic Dangers (March 2, 20121).
Open an Intake catalogue reference Sea Surface Height data
Make a geographic map of the data using ipyleaflet
Prerequisites
Concepts |
Importance |
Notes |
---|---|---|
Helpful |
||
Helpful |
||
Helpful |
||
Helpful |
Time to learn: 15 minutes
Imports
from ipyleaflet import Map, TileLayer, basemaps
from ipyleaflet.velocity import Velocity
from intake import open_catalog
Load Data
The Copernicus Monitoring Environment Marine Service (CMEMS) is a large repository of ocean products including in-situ observations, satellite based remote sensing data, and numerical model output.
We want to look at altimeter satellite data to show the Sea Level Anomalies (SLA) for the global ocean. The particular data product is called Global Ocean Gridded L4 Sea Surface Heights and Derived Variables Reprocessed (1993-Ongoing) (SEALEVEL_GLO_PHY_L4_MY_008_047).
This dataset is available as an analysis-ready on the Pangeo Cloud Data Catalog
cat = open_catalog("https://raw.githubusercontent.com/pangeo-data/pangeo-datastore/master/intake-catalogs/ocean.yaml")
cat["sea_surface_height"]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[2], line 2
1 cat = open_catalog("https://raw.githubusercontent.com/pangeo-data/pangeo-datastore/master/intake-catalogs/ocean.yaml")
----> 2 cat["sea_surface_height"]
File ~/miniconda3/envs/po-cookbook-dev/lib/python3.10/site-packages/intake/catalog/base.py:472, in Catalog.__getitem__(self, key)
463 """Return a catalog entry by name.
464
465 Can also use attribute syntax, like ``cat.entry_name``, or
(...)
468 cat['name1', 'name2']
469 """
470 if not isinstance(key, list) and key in self:
471 # triggers reload_on_change
--> 472 s = self._get_entry(key)
473 if s.container == "catalog":
474 s.name = key
File ~/miniconda3/envs/po-cookbook-dev/lib/python3.10/site-packages/intake/catalog/utils.py:43, in reload_on_change.<locals>.wrapper(self, *args, **kwargs)
40 @functools.wraps(f)
41 def wrapper(self, *args, **kwargs):
42 self.reload()
---> 43 return f(self, *args, **kwargs)
File ~/miniconda3/envs/po-cookbook-dev/lib/python3.10/site-packages/intake/catalog/base.py:355, in Catalog._get_entry(self, name)
353 ups = [up for name, up in self.user_parameters.items() if name not in up_names]
354 entry._user_parameters = ups + (entry._user_parameters or [])
--> 355 return entry()
File ~/miniconda3/envs/po-cookbook-dev/lib/python3.10/site-packages/intake/catalog/entry.py:60, in CatalogEntry.__call__(self, persist, **kwargs)
58 def __call__(self, persist=None, **kwargs):
59 """Instantiate DataSource with given user arguments"""
---> 60 s = self.get(**kwargs)
61 s._entry = self
62 s._passed_kwargs = list(kwargs)
File ~/miniconda3/envs/po-cookbook-dev/lib/python3.10/site-packages/intake/catalog/local.py:313, in LocalCatalogEntry.get(self, **user_parameters)
310 return self._default_source
312 plugin, open_args = self._create_open_args(user_parameters)
--> 313 data_source = plugin(**open_args)
314 data_source.catalog_object = self._catalog
315 data_source.name = self.name
TypeError: ZarrArraySource.__init__() got an unexpected keyword argument 'consolidated'
This dataset is marked “requester pays” which means we have do an addtional step if we are not already on Pangeo Hub on the Google Cloud Platform.
Working with requester pays data
Several of the datasets within the Pangeo cloud data catalog are contained in requester pays storage buckets. This means that a user requesting data must provide their own billing project (created and authenticated through Google Cloud Platform) to be billed for the charges associated with accessing a dataset. To set up an GCP billing project and use it for authentication in applications:
Create a project on GCP; if this is the first time using GCP, a prompt will appear to choose a Google account to link to all GCP-related activities.
Create a Cloud Billing account associated with the project and enable billing for the project through this account.
Using Google Cloud IAM, add the Service Usage Consumer role to your account, which enables it to make billed requests on the behalf of the project. Through command line, install the Google Cloud SDK; this can be done using conda:
conda install -c conda-forge google-cloud-sdk
Initialize the
gcloud
command line interface, logging into the account used to create the aforementioned project and selecting it as the default project; this will allow the project to be used for requester pays access through the command line:
gcloud init```
Finally, use
gcloud
to establish application default credentials; this will allow the project to be used for requester pays access through applications:gcloud auth application-default login
ds = cat["sea_surface_height"].to_dask()
ds
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[3], line 1
----> 1 ds = cat["sea_surface_height"].to_dask()
2 ds
File ~/miniconda3/envs/po-cookbook-dev/lib/python3.10/site-packages/intake/catalog/base.py:472, in Catalog.__getitem__(self, key)
463 """Return a catalog entry by name.
464
465 Can also use attribute syntax, like ``cat.entry_name``, or
(...)
468 cat['name1', 'name2']
469 """
470 if not isinstance(key, list) and key in self:
471 # triggers reload_on_change
--> 472 s = self._get_entry(key)
473 if s.container == "catalog":
474 s.name = key
File ~/miniconda3/envs/po-cookbook-dev/lib/python3.10/site-packages/intake/catalog/utils.py:43, in reload_on_change.<locals>.wrapper(self, *args, **kwargs)
40 @functools.wraps(f)
41 def wrapper(self, *args, **kwargs):
42 self.reload()
---> 43 return f(self, *args, **kwargs)
File ~/miniconda3/envs/po-cookbook-dev/lib/python3.10/site-packages/intake/catalog/base.py:355, in Catalog._get_entry(self, name)
353 ups = [up for name, up in self.user_parameters.items() if name not in up_names]
354 entry._user_parameters = ups + (entry._user_parameters or [])
--> 355 return entry()
File ~/miniconda3/envs/po-cookbook-dev/lib/python3.10/site-packages/intake/catalog/entry.py:60, in CatalogEntry.__call__(self, persist, **kwargs)
58 def __call__(self, persist=None, **kwargs):
59 """Instantiate DataSource with given user arguments"""
---> 60 s = self.get(**kwargs)
61 s._entry = self
62 s._passed_kwargs = list(kwargs)
File ~/miniconda3/envs/po-cookbook-dev/lib/python3.10/site-packages/intake/catalog/local.py:313, in LocalCatalogEntry.get(self, **user_parameters)
310 return self._default_source
312 plugin, open_args = self._create_open_args(user_parameters)
--> 313 data_source = plugin(**open_args)
314 data_source.catalog_object = self._catalog
315 data_source.name = self.name
TypeError: ZarrArraySource.__init__() got an unexpected keyword argument 'consolidated'
Make a Map
center = [35, -50]
zoom = 4
m = Map(center=center, zoom=zoom, interpolation='nearest', basemap=basemaps.Gaode.Satellite)
display_options = {
'velocityType': 'Global Wind',
'displayPosition': 'bottomleft',
'displayEmptyString': 'No wind data'
}
wind = Velocity(
data=ds.isel(time=-1),
zonal_speed='ugos', meridional_speed='vgos',
latitude_dimension='latitude', longitude_dimension='longitude',
velocity_scale=0.2, max_velocity=1,
display_options=display_options
)
m.add_layer(wind)
m
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[4], line 12
3 m = Map(center=center, zoom=zoom, interpolation='nearest', basemap=basemaps.Gaode.Satellite)
5 display_options = {
6 'velocityType': 'Global Wind',
7 'displayPosition': 'bottomleft',
8 'displayEmptyString': 'No wind data'
9 }
11 wind = Velocity(
---> 12 data=ds.isel(time=-1),
13 zonal_speed='ugos', meridional_speed='vgos',
14 latitude_dimension='latitude', longitude_dimension='longitude',
15 velocity_scale=0.2, max_velocity=1,
16 display_options=display_options
17 )
19 m.add_layer(wind)
21 m
NameError: name 'ds' is not defined
Summary
In this example we loaded sea level data from an analysis-ready cloud based dataset and made a visualization of that data using mapping library.
Resources and references
This notebook is based on the Pangeo physical oceanography gallery example: https://gallery.pangeo.io/repos/pangeo-gallery/physical-oceanography/05_gulf_stream_currents.html