Exercise of Data Visualization#

Download the example data (Optional)#

In this practice, we can choose to use the European air quality forecast dataset from CAMS (Copernicus Atmosphere Monitoring Service). You can download this CAMS 2.0 Product Portfolio to see more information on the products. You can follow the instructions below to download the example dataset using python.

Prepare before download#

To download the data, we will use CDS API. The Copernicus website has provided a practical instruction, please follow the steps.

The steps are also described below:

  1. Register an account in ADS here.

  2. Login to the ADS using your account.

  3. Copy the code displayed after login (refresh the page may help) and paste to th file ~/.cdsapirc

  4. Install

A quick fix if you fail to download#

If you fail to download the data or you don’t want to spend time to figure out how to download yourself. We have a already downloaded dataset for you to start the next part.

Read the data#

The file is in netcdf format. We will use xarray package to read the file.

Import the necessary packages:

import xarray as xr
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
ds = xr.open_dataset('../CAMS_ensemble_20240110.nc')
print(ds)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
File ~/miniconda3/envs/pybook/lib/python3.10/site-packages/xarray/backends/file_manager.py:211, in CachingFileManager._acquire_with_cache_info(self, needs_lock)
    210 try:
--> 211     file = self._cache[self._key]
    212 except KeyError:

File ~/miniconda3/envs/pybook/lib/python3.10/site-packages/xarray/backends/lru_cache.py:56, in LRUCache.__getitem__(self, key)
     55 with self._lock:
---> 56     value = self._cache[key]
     57     self._cache.move_to_end(key)

KeyError: [<class 'netCDF4._netCDF4.Dataset'>, ('/Users/zhuyunye/projects/python/python_tutorial/python_book/CAMS_ensemble_20240110.nc',), 'r', (('clobber', True), ('diskless', False), ('format', 'NETCDF4'), ('persist', False)), '43dfbd6b-b901-4230-aa73-06997f7c8028']

During handling of the above exception, another exception occurred:

FileNotFoundError                         Traceback (most recent call last)
Cell In[2], line 1
----> 1 ds = xr.open_dataset('../CAMS_ensemble_20240110.nc')
      2 print(ds)

File ~/miniconda3/envs/pybook/lib/python3.10/site-packages/xarray/backends/api.py:572, in open_dataset(filename_or_obj, engine, chunks, cache, decode_cf, mask_and_scale, decode_times, decode_timedelta, use_cftime, concat_characters, decode_coords, drop_variables, inline_array, chunked_array_type, from_array_kwargs, backend_kwargs, **kwargs)
    560 decoders = _resolve_decoders_kwargs(
    561     decode_cf,
    562     open_backend_dataset_parameters=backend.open_dataset_parameters,
   (...)
    568     decode_coords=decode_coords,
    569 )
    571 overwrite_encoded_chunks = kwargs.pop("overwrite_encoded_chunks", None)
--> 572 backend_ds = backend.open_dataset(
    573     filename_or_obj,
    574     drop_variables=drop_variables,
    575     **decoders,
    576     **kwargs,
    577 )
    578 ds = _dataset_from_backend_dataset(
    579     backend_ds,
    580     filename_or_obj,
   (...)
    590     **kwargs,
    591 )
    592 return ds

File ~/miniconda3/envs/pybook/lib/python3.10/site-packages/xarray/backends/netCDF4_.py:593, in NetCDF4BackendEntrypoint.open_dataset(self, filename_or_obj, mask_and_scale, decode_times, concat_characters, decode_coords, drop_variables, use_cftime, decode_timedelta, group, mode, format, clobber, diskless, persist, lock, autoclose)
    572 def open_dataset(  # type: ignore[override]  # allow LSP violation, not supporting **kwargs
    573     self,
    574     filename_or_obj: str | os.PathLike[Any] | BufferedIOBase | AbstractDataStore,
   (...)
    590     autoclose=False,
    591 ) -> Dataset:
    592     filename_or_obj = _normalize_path(filename_or_obj)
--> 593     store = NetCDF4DataStore.open(
    594         filename_or_obj,
    595         mode=mode,
    596         format=format,
    597         group=group,
    598         clobber=clobber,
    599         diskless=diskless,
    600         persist=persist,
    601         lock=lock,
    602         autoclose=autoclose,
    603     )
    605     store_entrypoint = StoreBackendEntrypoint()
    606     with close_on_error(store):

File ~/miniconda3/envs/pybook/lib/python3.10/site-packages/xarray/backends/netCDF4_.py:400, in NetCDF4DataStore.open(cls, filename, mode, format, group, clobber, diskless, persist, lock, lock_maker, autoclose)
    394 kwargs = dict(
    395     clobber=clobber, diskless=diskless, persist=persist, format=format
    396 )
    397 manager = CachingFileManager(
    398     netCDF4.Dataset, filename, mode=mode, kwargs=kwargs
    399 )
--> 400 return cls(manager, group=group, mode=mode, lock=lock, autoclose=autoclose)

File ~/miniconda3/envs/pybook/lib/python3.10/site-packages/xarray/backends/netCDF4_.py:347, in NetCDF4DataStore.__init__(self, manager, group, mode, lock, autoclose)
    345 self._group = group
    346 self._mode = mode
--> 347 self.format = self.ds.data_model
    348 self._filename = self.ds.filepath()
    349 self.is_remote = is_remote_uri(self._filename)

File ~/miniconda3/envs/pybook/lib/python3.10/site-packages/xarray/backends/netCDF4_.py:409, in NetCDF4DataStore.ds(self)
    407 @property
    408 def ds(self):
--> 409     return self._acquire()

File ~/miniconda3/envs/pybook/lib/python3.10/site-packages/xarray/backends/netCDF4_.py:403, in NetCDF4DataStore._acquire(self, needs_lock)
    402 def _acquire(self, needs_lock=True):
--> 403     with self._manager.acquire_context(needs_lock) as root:
    404         ds = _nc4_require_group(root, self._group, self._mode)
    405     return ds

File ~/miniconda3/envs/pybook/lib/python3.10/contextlib.py:135, in _GeneratorContextManager.__enter__(self)
    133 del self.args, self.kwds, self.func
    134 try:
--> 135     return next(self.gen)
    136 except StopIteration:
    137     raise RuntimeError("generator didn't yield") from None

File ~/miniconda3/envs/pybook/lib/python3.10/site-packages/xarray/backends/file_manager.py:199, in CachingFileManager.acquire_context(self, needs_lock)
    196 @contextlib.contextmanager
    197 def acquire_context(self, needs_lock=True):
    198     """Context manager for acquiring a file."""
--> 199     file, cached = self._acquire_with_cache_info(needs_lock)
    200     try:
    201         yield file

File ~/miniconda3/envs/pybook/lib/python3.10/site-packages/xarray/backends/file_manager.py:217, in CachingFileManager._acquire_with_cache_info(self, needs_lock)
    215     kwargs = kwargs.copy()
    216     kwargs["mode"] = self._mode
--> 217 file = self._opener(*self._args, **kwargs)
    218 if self._mode == "w":
    219     # ensure file doesn't get overridden when opened again
    220     self._mode = "a"

File src/netCDF4/_netCDF4.pyx:2463, in netCDF4._netCDF4.Dataset.__init__()

File src/netCDF4/_netCDF4.pyx:2026, in netCDF4._netCDF4._ensure_nc_success()

FileNotFoundError: [Errno 2] No such file or directory: b'/Users/zhuyunye/projects/python/python_tutorial/python_book/CAMS_ensemble_20240110.nc'
# plot the data in map
fig = plt.figure(figsize=(10, 5))
ax = plt.axes(projection=ccrs.PlateCarree())  # create a GeoAxes object with Plate Carree projection
qm = ds['co_conc'].isel(time=0).plot(ax=ax, transform=ccrs.PlateCarree(),cmap='jet')  # plot the data on the GeoAxes object
qm.colorbar.set_label('CO Concentration (\u03bcg/m3)')
ax.coastlines()  # add coastlines
plt.show()
../_images/e53fafa555010746904a4d68f43c10fa4dded957a604ddb7bc859b55218865c9.png