Visualise seasonal weather forecasts with Python and Climate Data Store

Expand your Data Analysis skills more with free datasets from European Union

Lubomir Franko
5 min readMay 3, 2022
Forecasted 10 metre wind speed anomaly for May 2022, forecast from 15th of April 2022 (source: ECMWF, Image by Author)

Weather affects each of us in our everyday life. However, it also affects decision making of many large companies.

Imagine you own a company which produces electricity generated from wind to thousands of customers in the world. If you want to sell this energy, you must plan ahead and sell your production in advance to secure even more contracts.

But how will you know how much energy will your wind farms produce compared to long-term normal? In this article, we will discover datasets, that are available in Climate Data Store by Copernicus. To use the datasets, you will need to register on CDS webpage. Registration and all the data is provided for free.

Set up CDS Python API

At first, we should start with Python environment creation. We will use Anaconda and some python libraries to process the data and create map with the data. To create virtual environment using Anaconda, simply type:

conda create -n weather python=3.8 pandas scipy cartopy cdsapi xarray cfgrib

Then activate virtual environment:

conda activate weather

The next step is to set up cdsapi client according to the documentation.

Now let’s test if our cdsapi is set up correctly.

import cdsapic = cdsapi.Client()

If this part of a code runs successfully, you have your CDS python API client ready.

Get data from Climate Data Store

My folder structure looks like this:

weather
├── raw_data
├── extracted_data
├── output
└── download_cds.ipynb

To retrieve data, we first need to explore CDS Datasets. For this demonstration, we will use Seasonal forecast anomalies on single levels dataset. There are many options and many sections. In this article we will use:

  • Originating centre: ECMWF,
  • System: 5,
  • Variable: 10m wind speed anomaly,
  • Product type:
    - Ensemble: Ensemble mean
    - Individual members: Monthly mean,
  • Year: 2022,
  • Month: April,
  • Leadtime month: 1, 2.

Do you find this amount of items chaotic? It indeed is. That’s why creators of CDS created Python API. Inside the Python code, we can specify all these items in config json. Then, we specify output directory, where the data should be stored.

You can either click on Show API Request at the bottom of the page, where we set the dataset up, or you can manually edit the code to get the data that you need.

Click “Show API request” button to show python code needed to download data (Image by Author)

Let’s copy this part of a code and place it into our Jupyter notebook. Running this notebook cell will download the data. Note that we will change download.grib to specific location to fit our needs.

First change directory to our weather folder:

cd <put your path here>/weather

Now we download the data. Please, note that this might take several
minutes to download, since the data request will be queried against CDS server.

import cdsapic = cdsapi.Client()c.retrieve(
'seasonal-postprocessed-single-levels',
{
'format': 'grib',
'originating_centre': 'ecmwf',
'system': '5',
'variable': '10m_wind_speed_anomaly',
'product_type': [
'ensemble_mean', 'monthly_mean',
],
'year': '2022',
'month': '04',
'leadtime_month': [
'1', '2',
],
},
'raw_data/download.grib')
Messages from CDS should look like this (Image by Author)

Explore the dataset

We will use xarray library to explore the dataset and to perform basic operations like subsetting and plotting over cartopy map. Note that we used filter_by_keys attribute to filter only ensemble_mean from our data.

import xarray as xrds = xr.open_dataset(
"raw_data/download.grib",
filter_by_keys={'dataType': 'em'}
)
ds

I recognise output from xarray as very informative. We can see all the necessary information that we need, plus we can interactively play with the interface and show additional info.

Plot the data

Now let’s plot the data. We will use cartopy library to do this. Cartopy is great library that provides us with many cartographic projections and coordinate systems. It provides you with features like borders and coastlines, which are important part of maps.

At first, we will create map object, then we will set up extent of a map by specifying canvas in degrees. Then we will continue with plotting of data, setting the title and plotting colorbar.

Note that we need to create 2d lat/lon grid from 1d arrays, using numpy.

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import numpy as np
import cartopy.feature as cf
# We want forecast for month ahead, we chose first element of our dataset
import pandas as pd
first_month = ds["ua10"][0]# Create plot and set up basemap
plt.figure(dpi=250)
ax = plt.axes(projection=ccrs.Mercator(), frameon=True)
# Set coordinate system of data and change extent of a map
data_crs = ccrs.PlateCarree()
ax.set_extent([-24, 45, 33, 61], crs=data_crs)
# Load values and latitude and longitude
values = first_month.values
ax.add_feature(cf.COASTLINE.with_scale("50m"), lw=0.5) # Add borderlines
ax.add_feature(cf.BORDERS.with_scale("50m"), lw=0.3) # Add coastlines
lonsi, latsi = np.meshgrid(first_month["longitude"], first_month["latitude"]) # Create grid from latitude and longitude# Plot the data as filled contour
cs = ax.contourf(lonsi, latsi, values, transform=data_crs, levels=30, cmap="seismic", vmin=-2, vmax=2)
# Get attributes needed for title
name = first_month.attrs["GRIB_name"]
units = first_month.attrs["GRIB_units"]
valid_date = first_month.valid_time.values
valid_date = pd.to_datetime(valid_date)
valid_date = valid_date.strftime("%B %Y")
plt.title(f"{name} ({units}) {valid_date}")
plt.colorbar(cs,orientation="horizontal",ax=ax,
pad=0,
aspect=50)
10 metre wind speed anomaly predicted for May 2022, forecast from April 2022 (source: ECMWF, Image by Author)

You can spot some inconveniences on the map. For example the white line on 0° longitude. This line is present due to data being stored with longitudes ranging not from -180 to 180 degrees, but from 0 to 360 degrees.

This interpretation tells us that we must expect stronger than usual winds in most of the Europe during May. Weaker than usual winds are expected in southeastern parts of Europe and in Nordic countries. If there is stronger than usual wind, we know that we will produce more electricity from wind turbines than we usually do.

Although this map looks trustworthy, we cannot make decisions from one model only. Since there is no single truth in weather forecasts, best practice is to explore models from multiple providers and statistically estimate possible scenarios. In this article we used data from ECMWF, but there are many other available in CDS.

Conclusion

In this article we learned how to visualise climate data from Climate Data Store using Python and geospatial libraries. You can further enhance maps according to your needs. There are no limits to your imagination.

In following articles, we will discuss on how to extract the data by latitude and longitude, but also how to perform zonal statistics.

If you liked this article, don’t hesitate to follow my account. Any comments are welcomed and I’d be glad to answer any of your questions. Thank you for your attention and I look forward to explore more data with you.

Stay Connected

--

--

Lubomir Franko

Experienced Data Engineer writing about Python, Spark and Geospatial Analysis