<jupyter_start><jupyter_text>Retrieve and plot European air quality forecast data from the Atmosphere Data Store  This notebook demonstrates how to retrieve NetCDF data from the Atmosphere Data Store (https://ads.atmosphere.copernicus.eu/) (ADS) and create time series plots and maps using xarray and Cartopy libraries. First, let's define some general purpose variables<jupyter_code>DATADIR = '../data/'
DATE = "2020-11-09"
hours = [str(h) for h in range(97)]
models = [ 'chimere', 'dehm', 'emep', 'ensemble', 'euradim', 'gemaq', 'lotos', 'match', 'mocage', 'silam']<jupyter_output><empty_output><jupyter_text>Next, we will retrieve the data from the ADS by using the cdsapi Python library. https://ads.atmosphere.copernicus.eu/api-how-to **To be able to run the data retrieval example below you will need to register on the Atmosphere Data Store (https://ads.atmosphere.copernicus.eu/) and then visit this page: https://ads.atmosphere.copernicus.eu/api-how-to to obtain the API authentication key.**If you want to speed up the process, you can use the files which are already available on the LTPY training platform.<jupyter_code>DOWNLOAD = False

if DOWNLOAD:

    import cdsapi
    # to suppress SSL warnings
    import urllib3
    urllib3.disable_warnings()
    
    # enter your ADS authentication key
    URL = "https://ads.atmosphere.copernicus.eu/api/v2"
    KEY = "<KEY>"
    c = cdsapi.Client(url=URL, key=KEY)

    for model in models:  
        c.retrieve(
    'cams-europe-air-quality-forecasts',
    {
        'model': model,
        'date': DATE,
        'format': 'netcdf',
        'variable': 'nitrogen_dioxide',
        'type': 'forecast',
        'time': '00:00',
        'leadtime_hour': hours,
        'level': '0',
    },
    f'{DATADIR}/air_quality_{model}_{DATE}.nc')<jupyter_output><empty_output><jupyter_text>Let's inspect one file<jupyter_code>import xarray as xr

dset = xr.open_dataset(f'{DATADIR}/air_quality_ensemble_{DATE}.nc')
print(dset)
import matplotlib.pyplot as plt

import cartopy
import cartopy.crs as ccrs

param = "NO2"
lat = 45.47
lon = 9.19

fig = plt.figure(figsize=(16,8))
ax = fig.subplots()

for model in models:
    dset = xr.open_dataset(f'{DATADIR}/air_quality_{model}_{DATE}.nc')
# print(dset)
    dd = dset["no2_conc"].interp(latitude=45.3, longitude=9.35).to_dataframe()
    dd.no2_conc.plot(ax=ax, label=model.upper())

plt.grid()
plt.legend()
plt.title(f"CAMS air quality {param} forecast BASETIME={DATE} LAT={lat} LON={lon}")
BORDER_COLOUR = "#cccccc"
NCOLS = 3
NROWS = len(models) // NCOLS + 1

fig, axes = plt.subplots(nrows=NROWS, ncols=NCOLS, figsize=(16,12), subplot_kw={'projection': ccrs.PlateCarree()})

for ii, model in enumerate(models):
    dset = xr.open_dataset(f'{DATADIR}/air_quality_{model}_{DATE}.nc')
    dset = dset.assign_coords(longitude=(((dset.longitude + 180) % 360) - 180)).sortby('longitude')    

    # x and y indices of the subplot to use for this model
    iy = ii // NCOLS
    ix = ii % NCOLS
    # show the colorbar only in the last column
    show_cbar = NCOLS - ix == 1
    p = dset["no2_conc"][13][0].plot.pcolormesh(ax=axes[iy, ix], vmin=10, vmax=100., 
                                                add_colorbar=show_cbar, extend='both', cmap='Reds', 
                                                transform=ccrs.PlateCarree())
    axes[iy, ix].set_title(model.upper())
    axes[iy, ix].xaxis.set_label_text("")
    axes[iy, ix].yaxis.set_label_text("")
    axes[iy, ix].set_extent([-5, 15, 40, 55])
    axes[iy, ix].add_feature(cartopy.feature.BORDERS, color=BORDER_COLOUR)
    axes[iy, ix].coastlines(color=BORDER_COLOUR)
    
# let's remove axes on the empty subplots
for iix in range(ix + 1, NROWS - 1):
    axes[iy, iix].axis('off')

# plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
plt.subplots_adjust(wspace=.0, hspace=0.2)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13883196721311475, 'fraction_numerical': 0.018954918032786885, 'mean_word_length': 3.7448359659781287, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 14, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '366979', 'license': 'MIT', 'n_tokens_mistral': 1482, 'n_tokens_neox': 1382, 'n_words': 340, 'path': '90_workshops/202011_ac_training_school/3_overview_cams_data/3.2_CAMSDataAccess_ADS_EuropeanAirQuality.ipynb', 'repo_name': 'trivedi-c/atm_Practical3', 'size': '3942'}