<jupyter_start><jupyter_text>Copernicus Climate Data Store (CDS) access using xcube This notebook walks provides a walk-through demonstrating how to use xcube and the xcube Climate Data Store (CDS) plugin to read and explore temperature data from the CDS. Before using this notebook, ensure that you have set up xcube, the CDS plugin, and Jupyter Lab as described in the [Ex0-CDS-store-Setup](./Ex0-CDS-store-setup.ipynb) notebook. First, we import some necessary libraries.<jupyter_code># xcube and xcube_cds imports
import xcube
from xcube_cds.store import CDSDataStore

# Various utilities
import shapely.geometry
import IPython.display

# For the orthographic map projection
import matplotlib as mpl
import matplotlib.pyplot as plt<jupyter_output><empty_output><jupyter_text>Configure matplotlib to display graphs inline directly in the notebook and set a sensible default figure size.<jupyter_code>%matplotlib inline
plt.rcParams["figure.figsize"] = 16,12<jupyter_output><empty_output><jupyter_text>Create a CDS data store object. The optional `normalize_names` parameter specifies that variable names in returned data cubes will be converted to legal Python identifiers, if required.<jupyter_code>cds_store = CDSDataStore(normalize_names=True)<jupyter_output><empty_output><jupyter_text>Find out which datasets are available from this store. We get a list of tuples; the first member of each tuple is the data ID, and the second member is a short description of the dataset. We pick ‘ERA5 monthly averaged data on single levels – Monthly averaged reanalysis’.<jupyter_code>data_ids = list(cds_store.get_data_ids())
data_ids
data_id = 'reanalysis-era5-single-levels-monthly-means:monthly_averaged_reanalysis'<jupyter_output><empty_output><jupyter_text>Let's see what parameters we can specify when opening the dataset. Four are listed as required parameters: `time_range`, `spatial_res`, `bbox`, and `variable_names`. The enumeration in `properties → variable_names → items` lists 260 variables we can request. We can request any number of variables, but for this example we will just look at `2m_temperature`.<jupyter_code>cds_store.get_open_data_params_schema(data_id)
variable_names = ['2m_temperature']<jupyter_output><empty_output><jupyter_text>Define the bounding box for the area of interest. For this example, we will be using the mid-latitudes of Europe.<jupyter_code>w = -10  # degree
s = 45   # degree
e = 40   # degree
n = 65   # degree

bbox = [w, s, e, n]<jupyter_output><empty_output><jupyter_text>Plot the bounding box on a map to check that we have the correct area.<jupyter_code>IPython.display.GeoJSON(shapely.geometry.box(*bbox).__geo_interface__)<jupyter_output><empty_output><jupyter_text>Define the desired spatial resolution. ERA5 data are available at a maximum resolution of 0.25°, so this is what we specify.<jupyter_code>spatial_res = 0.25<jupyter_output><empty_output><jupyter_text>For the time range, we select the years 2001 to 2010. The dates are specified in ISO-8601 format.<jupyter_code>time_range=['2001-01-01', '2010-12-31']<jupyter_output><empty_output><jupyter_text>List the available opener IDs for this data store. There is only one, `dataset:netcdf:cds`, which opens a dataset constructed from a NetCDF file returned from the CDS API, so we use this one.<jupyter_code>openers = cds_store.get_data_opener_ids()

openers
opener = openers[0]<jupyter_output><empty_output><jupyter_text>Open the data cube from the store. It may take one or two minutes for the CDS servers to process the request.<jupyter_code>cube = cds_store.open_data(data_id,
                           opener,
                           variable_names=variable_names,
                           bbox=bbox,
                           spatial_res=spatial_res,
                           time_range=time_range)<jupyter_output>2021-01-27 12:59:04,151 INFO Welcome to the CDS
2021-01-27 12:59:04,153 INFO Sending request to https://cds.climate.copernicus.eu/api/v2/resources/reanalysis-era5-single-levels-monthly-means
2021-01-27 12:59:04,544 INFO Request is completed
2021-01-27 12:59:04,546 INFO Downloading https://download-0015.copernicus-climate.eu/cache-compute-0015/cache/data6/adaptor.mars.internal-1611746330.497521-22565-27-1d4b91bc-c72b-4ffc-956c-12f84946d2bd.nc to /tmp/tmphqdnh25w/tmpoqinkf99/data (3.7M)
2021-01-27 12:59:17,857 INFO Download rate 281.9K/s<jupyter_text>Plot the differences between successive time points in the dataset. We can see that the times are monotonically increasing (all the difference values are positive), but not equally spaced, since months are not all of the same length. The lowest values correspond to February; the four-year leap year cycle can also be discerned.<jupyter_code>cube.time.diff(dim='time').plot.line(figsize=(20, 4))<jupyter_output><empty_output><jupyter_text>We can explore these data by plotting a temperature map for selected time points. First, we select January 2001. Land areas – and mountain ranges in particular – show up on the map as colder regions.<jupyter_code>t2m_2001_jan = cube.t2m.sel(time='2001-01-01 00:00:00', method='nearest')
t2m_2001_jan.plot.imshow(vmin=260, vmax=300, figsize=(14, 8))<jupyter_output><empty_output><jupyter_text>For convenience, we define a custom map plotting function.<jupyter_code>def plot_map(data_array, colour_scale=(None, None), cmap=None):
    data_array.plot.imshow(vmin=colour_scale[0], vmax=colour_scale[1], figsize=(14,8), cmap=cmap)

common_scale = (260, 300)
plot_map(t2m_2001_jan, common_scale)<jupyter_output><empty_output><jupyter_text>We can compare this with a plot for July of the same year using the same colour scale for temperature. As would be expected, the land/sea temperature difference is reversed, but mountainous regions are still colder than surrounding lowlands.<jupyter_code>t2m_2001_jul = cube.t2m.sel(time='2001-07-01 00:00:00', method='nearest')
plot_map(t2m_2001_jul, common_scale)<jupyter_output><empty_output><jupyter_text>We can also subtract January from July to produce a map showing which regions have the greatest differences between summer and winter temperatures:<jupyter_code>plot_map(t2m_2001_jul - t2m_2001_jan)<jupyter_output><empty_output><jupyter_text>We can make use of the 10-year time series to examine longer-term trends. First, we calculate the mean January and July temperature maps separately for the first and second halves of the dataset (i.e. for 2001-2005 and 2006-2010).<jupyter_code>jan_2001_2005 = cube.t2m[0:60:12].mean(axis=0)
jan_2006_2010 = cube.t2m[60::12].mean(axis=0)
jul_2001_2005 = cube.t2m[6:60:12].mean(axis=0)
jul_2006_2010 = cube.t2m[66::12].mean(axis=0)<jupyter_output><empty_output><jupyter_text>Now we can use these means to look at geographical variation in temperature differences between these two timespans and times of year. A plot of the difference in January temperatures shows marked rises in the Gulf of Finland, the Gulf of Bothnia, the Alps, and the Carpathians. Meanwhile, temperatures in the eastern plains have dropped.<jupyter_code>plot_map(jan_2006_2010 - jan_2001_2005, (-2, 2), 'coolwarm')<jupyter_output><empty_output><jupyter_text>For July temperatures, the pattern is quite different: the greatest temperature increase is seen in Germany and adjacent areas, while a cooling trend is evident in Finland, the Baltics, and western Russia.<jupyter_code>plot_map(jul_2006_2010 - jul_2001_2005, (-2, 2), 'coolwarm')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08387010198604401, 'fraction_numerical': 0.05475040257648953, 'mean_word_length': 5.775454545454545, 'pattern_counts': {'":': 0, '<': 76, '<?xml version=': 0, '>': 76, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '19', 'dir': 'jupyter-structured-clean-dedup', 'id': '87125', 'license': 'MIT', 'n_tokens_mistral': 2662, 'n_tokens_neox': 2350, 'n_words': 749, 'path': 'examples/notebooks/Ex1-CDS-store-ERA5.ipynb', 'repo_name': 'dcs4cop/xcube-cds', 'size': '7452'}