After this introduction, you will know how to:
GriddedData
and UngriddedData
)ColocatedData
)pandas
or xarray
import pyaerocom as pya
import matplotlib.pyplot as plt
pya.change_verbosity('critical', log=pya.const.print_log) # don't output warnings
pya.__version__
'0.8.1.dev1'
Please make sure to use version 0.8.1.dev1. If you have an earlier version, follow these instructions in order to update your installation.
import socket
if socket.gethostname() == 'pc4971':
print('I am on Jonas PC')
DATA_BASEDIR = '/home/jonasg/MyPyaerocom/pyaerocom-testdata'
else:
print('I assume I am on the Abisko Jupyter hub')
DATA_BASEDIR = '/home/notebook/shared-ns1000k/inputs/pyaerocom-testdata/'
I am on Jonas PC
pya.const.BASEDIR = DATA_BASEDIR
browse_database
)¶pya.browse_database('*TM5*')
Pyaerocom ReadGridded --------------------- Data ID: TM5_AP3-CTRL2919 Data directory: /home/jonasg/MyPyaerocom/pyaerocom-testdata/modeldata/TM5_AP3-CTRL2919/renamed Available experiments: ['AP3-CTRL2019'] Available years: [2010] Available frequencies ['monthly'] Available variables: ['abs350aer', 'abs440aer', 'abs440dryaer', 'abs550aer', 'abs550dryaer', 'abs550drylt1aer', 'abs870aer', 'abs870dryaer', 'airmass', 'asyaer', 'asydryaer', 'depbc', 'depdms', 'depdust', 'dephno3', 'depmsa', 'depn', 'depnh3', 'depnh4', 'depnhx', 'depno2', 'depno3', 'depnoy', 'depo3', 'depoa', 'deps', 'depso2', 'depso4', 'depss', 'dh', 'drybc', 'drydms', 'drydust', 'dryhno3', 'drynh3', 'dryno2', 'dryno3', 'drynoy', 'dryo3', 'dryoa', 'dryso2', 'dryso4', 'dryss', 'ec440dryaer', 'ec550aer', 'ec550dryaer', 'ec550drylt1aer', 'ec870dryaer', 'emibc', 'emico', 'emidms', 'emidust', 'emiisop', 'emin', 'eminh3', 'eminox', 'emioa', 'emis', 'emiso2', 'emiso4', 'emiss', 'emiterp', 'emivoc', 'hus', 'loadbc', 'loaddust', 'loadno3', 'loadoa', 'loadso4', 'loadss', 'od350aer', 'od440aer', 'od550aer', 'od550aerh2o', 'od550bc', 'od550dust', 'od550lt1aer', 'od550lt1dust', 'od550lt1ss', 'od550no3', 'od550oa', 'od550so4', 'od550ss', 'od870aer', 'pr', 'sconcbc', 'sconcdust', 'sconcmsa', 'sconcnh4', 'sconcno3', 'sconcoa', 'sconcso4', 'sconcss', 'ta', 'temp', 'vmrch4', 'vmrco', 'vmrno', 'vmrno2', 'vmro3', 'vmroh', 'wetbc', 'wetdms', 'wetdust', 'wethno3', 'wetmsa', 'wetnh3', 'wetnh4', 'wetno3', 'wetnoy', 'wetoa', 'wetso2', 'wetso4', 'wetss']
You can use the Data ID or the Data directory to read this dataset (next step)
ReadGridded
class)¶DATA_ID = 'TM5_AP3-CTRL2919'
reader = pya.io.ReadGridded(DATA_ID)
print(reader)
Pyaerocom ReadGridded --------------------- Data ID: TM5_AP3-CTRL2919 Data directory: /home/jonasg/MyPyaerocom/pyaerocom-testdata/modeldata/TM5_AP3-CTRL2919/renamed Available experiments: ['AP3-CTRL2019'] Available years: [2010] Available frequencies ['monthly'] Available variables: ['abs350aer', 'abs440aer', 'abs440dryaer', 'abs550aer', 'abs550dryaer', 'abs550drylt1aer', 'abs870aer', 'abs870dryaer', 'airmass', 'asyaer', 'asydryaer', 'depbc', 'depdms', 'depdust', 'dephno3', 'depmsa', 'depn', 'depnh3', 'depnh4', 'depnhx', 'depno2', 'depno3', 'depnoy', 'depo3', 'depoa', 'deps', 'depso2', 'depso4', 'depss', 'dh', 'drybc', 'drydms', 'drydust', 'dryhno3', 'drynh3', 'dryno2', 'dryno3', 'drynoy', 'dryo3', 'dryoa', 'dryso2', 'dryso4', 'dryss', 'ec440dryaer', 'ec550aer', 'ec550dryaer', 'ec550drylt1aer', 'ec870dryaer', 'emibc', 'emico', 'emidms', 'emidust', 'emiisop', 'emin', 'eminh3', 'eminox', 'emioa', 'emis', 'emiso2', 'emiso4', 'emiss', 'emiterp', 'emivoc', 'hus', 'loadbc', 'loaddust', 'loadno3', 'loadoa', 'loadso4', 'loadss', 'od350aer', 'od440aer', 'od550aer', 'od550aerh2o', 'od550bc', 'od550dust', 'od550lt1aer', 'od550lt1dust', 'od550lt1ss', 'od550no3', 'od550oa', 'od550so4', 'od550ss', 'od870aer', 'pr', 'sconcbc', 'sconcdust', 'sconcmsa', 'sconcnh4', 'sconcno3', 'sconcoa', 'sconcso4', 'sconcss', 'ta', 'temp', 'vmrch4', 'vmrco', 'vmrno', 'vmrno2', 'vmro3', 'vmroh', 'wetbc', 'wetdms', 'wetdust', 'wethno3', 'wetmsa', 'wetnh3', 'wetnh4', 'wetno3', 'wetnoy', 'wetoa', 'wetso2', 'wetso4', 'wetss']
pya.get_variable('od550aer')
od550aer standard_name: atmosphere_optical_thickness_due_to_ambient_aerosol_particles; Unit: 1
model_data = reader.read_var('od550aer', start=2010)
type(model_data)
pyaerocom.griddeddata.GriddedData
GriddedData
object¶model_data.ts_type # temporal resolution
'monthly'
model_data.quickplot_map('June 2010');
GriddedData
to iris.Cube
or xarray.DataArray
¶Actually, the GriddedData
object is based on the iris.Cube
object which can be accessed via the cube
attr:
cube = model_data.cube
type(cube)
iris.cube.Cube
cube
Atmosphere Optical Thickness Due To Ambient Aerosol (1) | time | latitude | longitude |
---|---|---|---|
Shape | 12 | 90 | 120 |
Dimension coordinates | |||
time | x | - | - |
latitude | - | x | - |
longitude | - | - | x |
Attributes | |||
Conventions | CF-1.6 | ||
computed | False | ||
concatenated | False | ||
contact | Twan van Noije (noije@knmi.nl) | ||
data_id | TM5_AP3-CTRL2919 | ||
experiment_id | AP3-CTRL2019 | ||
from_files | ['/home/jonasg/MyPyaerocom/pyaerocom-testdata/modeldata/TM5_AP3-CTRL29... | ||
institute_id | KNMI | ||
institution | Royal Netherlands Meteorological Institute, De Bilt, The Netherlands | ||
model_id | TM5 | ||
outliers_removed | False | ||
project_id | AeroCom Phase 3 | ||
reader | None | ||
references | Van Noije, T.P.C., et al. (Geosci. Model Dev., 7, 2435-2475, 2014); Bergman,... | ||
region | None | ||
regridded | False | ||
source | TM5-mp, r1058: CTM ERA-Interim 3x2 34L | ||
title | TM5 model output prepared for AeroCom Phase 3 | ||
ts_type | monthly | ||
var_name_read | n/d | ||
Cell methods | |||
point | longitude, latitude | ||
mean | time |
try: # pyaerocom >= 0.8.1
data_arr = model_data.to_xarray()
except: # pyaerocom < 0.8.1
print('Coming soon in pyaerocom v0.8.1')
import xarray as xarr
data_arr = xarr.DataArray.from_iris(model_data.cube)
data_arr
<xarray.DataArray 'od550aer' (time: 12, lat: 90, lon: 120)> dask.array<shape=(12, 90, 120), dtype=float32, chunksize=(12, 90, 61)> Coordinates: * time (time) object 2010-01-15 12:00:00 ... 2010-12-15 12:00:00 * lat (lat) float64 -89.0 -87.0 -85.0 -83.0 -81.0 ... 83.0 85.0 87.0 89.0 * lon (lon) float64 -181.5 -178.5 -175.5 -172.5 ... 169.5 172.5 175.5 Attributes: standard_name: atmosphere_optical_thickness_due_to_ambient_aerosol long_name: Ambient Aerosol Optical Thickness at 550 nm institution: Royal Netherlands Meteorological Institute, De Bilt, T... institute_id: KNMI source: TM5-mp, r1058: CTM ERA-Interim 3x2 34L model_id: TM5 references: Van Noije, T.P.C., et al. (Geosci. Model Dev., 7, 2435... experiment_id: AP3-CTRL2019 project_id: AeroCom Phase 3 title: TM5 model output prepared for AeroCom Phase 3 Conventions: CF-1.6 contact: Twan van Noije (noije@knmi.nl) from_files: ['/home/jonasg/MyPyaerocom/pyaerocom-testdata/modeldat... data_id: TM5_AP3-CTRL2919 var_name_read: n/d ts_type: monthly regridded: False outliers_removed: False computed: False concatenated: False cell_methods: longitude: latitude: point time: mean
GriddedData
object that may be useful¶LON_ABISKO = 18.8312 #° E
LAT_ABISKO = 68.3495 #° N
subset_abisko = model_data.sel(longitude=LON_ABISKO, latitude=LAT_ABISKO)
try: # pyaerocom >= 0.8.1
subset_abisko.to_xarray().plot();
except: # pyaerocom < 0.8.1
print('Coming soon in pyaerocom v0.8.1')
import xarray as xarr
data_arr = xarr.DataArray.from_iris(subset_abisko.cube).plot()
ReadUngridded
class)¶pya.browse_database('Aeronet*V3*Lev2*')
Dataset name: AeronetSunV3Lev2.daily Data directory: /home/jonasg/MyPyaerocom/pyaerocom-testdata/obsdata/AeronetSunV3Lev2.0.daily/renamed Supported variables: ['od340aer', 'od440aer', 'od500aer', 'od870aer', 'ang4487aer', 'ang4487aer_calc', 'od550aer'] Last revision: 20190920 Reading failed for AeronetSunV3Lev2.AP. Error: OSError('Data directory /home/jonasg/MyPyaerocom/pyaerocom-testdata/obsdata/AeronetSunV3Lev2.0.AP/renamed of observation network AeronetSunV3Lev2.AP does not exists') Reading failed for AeronetSDAV3Lev2.daily. Error: OSError('Data directory /home/jonasg/MyPyaerocom/pyaerocom-testdata/obsdata/Aeronet.SDA.V3L2.0.daily/renamed of observation network AeronetSDAV3Lev2.daily does not exists') Reading failed for AeronetSDAV3Lev2.AP. Error: NetworkNotImplemented('No reading class available yet for dataset AeronetSDAV3Lev2.AP') Reading failed for AeronetInvV3Lev2.daily. Error: OSError('Data directory /home/jonasg/MyPyaerocom/pyaerocom-testdata/obsdata/Aeronet.Inv.V3L2.0.daily/renamed of observation network AeronetInvV3Lev2.daily does not exists') Reading failed for AeronetSunV3Lev2.0.daily. Error: AttributeError("'NoneType' object has no attribute 'experiment'")
OBS_ID = 'AeronetSunV3Lev2.daily'
obs_reader = pya.io.ReadUngridded(OBS_ID)
print(obs_reader)
Dataset name: AeronetSunV3Lev2.daily Data directory: /home/jonasg/MyPyaerocom/pyaerocom-testdata/obsdata/AeronetSunV3Lev2.0.daily/renamed Supported variables: ['od340aer', 'od440aer', 'od500aer', 'od870aer', 'ang4487aer', 'ang4487aer_calc', 'od550aer'] Last revision: 20190920
obs_data = obs_reader.read(vars_to_retrieve='od550aer')
obs_data
UngriddedData <networks: ['AeronetSunV3Lev2.daily']; vars: ['od550aer']; instruments: ['sun_photometer'];No. of stations: 1230
UngriddedData
object¶ax = obs_data.plot_station_coordinates(markersize=16)
ax = obs_data.plot_station_coordinates(var_name='od550aer',
start=2008, stop=2012,
markersize=12, color='lime', ax=ax)
len(obs_data.metadata)
1230
e.g. metadata of first file:
obs_data.metadata[0]
OrderedDict([('var_info', OrderedDict([('od550aer', OrderedDict([('units', '1')]))])), ('latitude', 45.3139), ('longitude', 12.508299999999998), ('altitude', 10.0), ('station_name', 'AAOT'), ('PI', 'Brent_Holben'), ('ts_type', 'daily'), ('data_id', 'AeronetSunV3Lev2.daily'), ('variables', ['od550aer']), ('instrument_name', 'sun_photometer'), ('data_revision', '20190920')])
obs_arctic = obs_data.apply_filters(latitude=[70, 90])
obs_arctic.plot_station_coordinates(markersize=40, marker='x', color='r');
lille_data = obs_data.to_station_data('*Lille*')
type(lille_data)
pyaerocom.stationdata.StationData
StationData
¶.
and []
to access and assign attributes)pandas.Series
lille_data.keys()
odict_keys(['dtime', 'var_info', 'station_coords', 'data_err', 'overlap', 'data_flagged', 'filename', 'station_id', 'station_name', 'instrument_name', 'PI', 'country', 'ts_type', 'latitude', 'longitude', 'altitude', 'data_id', 'dataset_name', 'data_product', 'data_version', 'data_level', 'revision_date', 'website', 'ts_type_src', 'stat_merge_pref_attr', 'data_revision', 'od550aer'])
lille_data.longitude
3.1416669999999987
lille_data.latitude
50.611667000000004
pandas.Series
simply by using the variable name¶lille_data.od550aer # THIS is exactly equivalent to the command lille_data['od550aer']
1995-06-30 12:00:00 0.403992 1995-07-01 12:00:00 0.695444 1995-07-04 12:00:00 0.213412 1995-07-07 12:00:00 0.757272 1995-07-08 12:00:00 1.072732 ... 2019-06-16 12:00:00 0.061789 2019-06-17 12:00:00 0.100830 2019-06-18 12:00:00 0.130222 2019-06-20 12:00:00 0.046714 2019-06-21 12:00:00 0.074854 Length: 3399, dtype: float64
ax = lille_data.plot_timeseries(var_name='od550aer', marker='x', linestyle='none')
ax = lille_data.plot_timeseries(var_name='od550aer', ts_type='monthly', linestyle='-', lw=3, ax=ax)
col_data = pya.colocation.colocate_gridded_ungridded(model_data,
obs_data,
ts_type='monthly',
start=2010)
col_data
<xarray.DataArray 'od550aer' (data_source: 2, time: 12, station_name: 290)> array([[[ nan, 0.117588, ..., nan, 0.222138], [ nan, 0.132128, ..., nan, 0.429762], ..., [0.132236, 0.195057, ..., nan, 0.261765], [ nan, nan, ..., nan, 0.37905 ]], [[0.149478, 0.146562, ..., 0.037668, 0.230157], [0.145884, 0.286354, ..., 0.06611 , 0.464022], ..., [0.164331, 0.199312, ..., 0.035466, 0.405731], [0.104762, 0.138498, ..., 0.040375, 0.455539]]]) Coordinates: * data_source (data_source) <U22 'AeronetSunV3Lev2.daily' 'TM5_AP3-CTRL2919' var_name (data_source) <U8 'od550aer' 'od550aer' var_units (data_source) <U1 '1' '1' ts_type_src (data_source) <U7 'daily' 'monthly' * time (time) datetime64[ns] 2010-01-01 2010-02-01 ... 2010-12-01 * station_name (station_name) <U19 'ARM_Darwin' ... 'Zinder_Airport' latitude (station_name) float64 -12.43 37.97 15.35 ... 62.45 13.78 longitude (station_name) float64 130.9 23.72 -1.479 ... -114.4 8.99 altitude (station_name) float64 29.9 130.0 305.0 ... 300.0 220.8 456.0 Attributes: data_source: ['AeronetSunV3Lev2.daily', 'TM5_AP3-CTRL2919'] var_name: ['od550aer', 'od550aer'] ts_type: monthly filter_name: WORLD-wMOUNTAINS ts_type_src: ['daily', 'monthly'] start_str: 20100101 stop_str: 20101231 var_units: ['1', '1'] vert_scheme: None data_level: 3 revision_ref: 20190920 from_files: ['aerocom3_TM5_AP3-CTRL2019_od550aer_Column_2010_mont... from_files_ref: None stations_ignored: None colocate_time: False apply_constraints: True min_num_obs: {'yearly': {'monthly': 3}, 'monthly': {'daily': 7}, '... outliers_removed: True region: WORLD lon_range: [-180, 180] lat_range: [-90, 90] alt_range: None
col_data.plot_scatter(marker='o', color='blue', alpha=0.1);
xarray.DataArray
object can be simply accessed via¶col_data.data
<xarray.DataArray 'od550aer' (data_source: 2, time: 12, station_name: 290)> array([[[ nan, 0.117588, ..., nan, 0.222138], [ nan, 0.132128, ..., nan, 0.429762], ..., [0.132236, 0.195057, ..., nan, 0.261765], [ nan, nan, ..., nan, 0.37905 ]], [[0.149478, 0.146562, ..., 0.037668, 0.230157], [0.145884, 0.286354, ..., 0.06611 , 0.464022], ..., [0.164331, 0.199312, ..., 0.035466, 0.405731], [0.104762, 0.138498, ..., 0.040375, 0.455539]]]) Coordinates: * data_source (data_source) <U22 'AeronetSunV3Lev2.daily' 'TM5_AP3-CTRL2919' var_name (data_source) <U8 'od550aer' 'od550aer' var_units (data_source) <U1 '1' '1' ts_type_src (data_source) <U7 'daily' 'monthly' * time (time) datetime64[ns] 2010-01-01 2010-02-01 ... 2010-12-01 * station_name (station_name) <U19 'ARM_Darwin' ... 'Zinder_Airport' latitude (station_name) float64 -12.43 37.97 15.35 ... 62.45 13.78 longitude (station_name) float64 130.9 23.72 -1.479 ... -114.4 8.99 altitude (station_name) float64 29.9 130.0 305.0 ... 300.0 220.8 456.0 Attributes: data_source: ['AeronetSunV3Lev2.daily', 'TM5_AP3-CTRL2919'] var_name: ['od550aer', 'od550aer'] ts_type: monthly filter_name: WORLD-wMOUNTAINS ts_type_src: ['daily', 'monthly'] start_str: 20100101 stop_str: 20101231 var_units: ['1', '1'] vert_scheme: None data_level: 3 revision_ref: 20190920 from_files: ['aerocom3_TM5_AP3-CTRL2019_od550aer_Column_2010_mont... from_files_ref: None stations_ignored: None colocate_time: False apply_constraints: True min_num_obs: {'yearly': {'monthly': 3}, 'monthly': {'daily': 7}, '... outliers_removed: True region: WORLD lon_range: [-180, 180] lat_range: [-90, 90] alt_range: None
ColocatedData
object to NetCDF¶col_data.savename_aerocom
'od550aer_REF-AeronetSunV3Lev2.daily_MOD-TM5_AP3-CTRL2919_20100101_20101231_monthly_WORLD-wMOUNTAINS'
col_data.to_netcdf('.')
The example above did essentially the following steps:
GriddedData
and UngriddedData
, respectivelyColocatedData
objectAll these steps can be done with a one-liner in pyaerocom using the Colocator
class
Colocate the same model and observation network but now use the Angstrom exponent (ang4487aer) instead of the AOD:
colocator = pya.Colocator(model_id=DATA_ID,
obs_id=OBS_ID,
obs_vars='ang4487aer',
ts_type='monthly',
start=2010,
basedir_coldata='.',
reanalyse_existing=True,
save_coldata=True)
colocator.run()
The Colocator
objects stores all ColocatedData
objects that were created in it's data
attribute, which is a nested dictionary, organised via model_id
and var_name
:
colocator.data
{'TM5_AP3-CTRL2919': {'ang4487aer': <xarray.DataArray 'ang4487aer' (data_source: 2, time: 12, station_name: 264)> array([[[ nan, 1.128966, ..., nan, 0.259995], [ nan, 0.890816, ..., nan, 0.305093], ..., [1.346214, 0.934353, ..., nan, 0.494529], [ nan, nan, ..., nan, 0.489275]], [[0.867116, 0.737737, ..., 1.355472, 0.622317], [0.9829 , 0.305702, ..., 1.235905, 0.443166], ..., [1.284731, 0.657773, ..., 1.386418, 0.62829 ], [1.142794, 0.750162, ..., 1.374116, 0.413073]]]) Coordinates: * data_source (data_source) <U22 'AeronetSunV3Lev2.daily' 'TM5_AP3-CTRL2919' var_name (data_source) <U10 'ang4487aer' 'ang4487aer' var_units (data_source) <U1 '1' '1' ts_type_src (data_source) <U7 'daily' 'monthly' * time (time) datetime64[ns] 2010-01-01 2010-02-01 ... 2010-12-01 * station_name (station_name) <U19 'ARM_Darwin' ... 'Zinder_Airport' latitude (station_name) float64 -12.43 37.97 15.35 ... 62.45 13.78 longitude (station_name) float64 130.9 23.72 -1.479 ... -114.4 8.99 altitude (station_name) float64 29.9 130.0 305.0 ... 300.0 220.8 456.0 Attributes: data_source: ['AeronetSunV3Lev2.daily', 'TM5_AP3-CTRL2919'] var_name: ['ang4487aer', 'ang4487aer'] ts_type: monthly filter_name: WORLD-noMOUNTAINS ts_type_src: ['daily', 'monthly'] start_str: 20100101 stop_str: 20101231 var_units: ['1', '1'] vert_scheme: None data_level: 3 revision_ref: 20190920 from_files: ['aerocom3_TM5_AP3-CTRL2019_od440aer_Column_2010_mont... from_files_ref: None stations_ignored: None colocate_time: 0 apply_constraints: 1 outliers_removed: 1 region: WORLD lon_range: [-180, 180] lat_range: [-90, 90] alt_range: [-1000000.0, 1000.0] _min_num_obs: yearly,monthly,3;monthly,daily,7;daily,hourly,6;hourl...}}
colocator.data[DATA_ID]['ang4487aer'].plot_scatter(marker='o', alpha=0.1, color='g');
pya.browse_database('*CAM*')
Pyaerocom ReadGridded --------------------- Data ID: CAM53-Oslo_7310_MG15CLM45_5feb2017IHK_53OSLO_PD_UNTUNED Data directory: /home/jonasg/MyPyaerocom/pyaerocom-testdata/modeldata/CAM53-Oslo_7310_MG15CLM45_5feb2017IHK_53OSLO_PD_UNTUNED/renamed Available experiments: ['UNTUNED'] Available years: [2008, 2009, 2010] Available frequencies ['monthly'] Available variables: ['abs550aer', 'abs550aercs', 'ang4487aer', 'ang4487csaer', 'od550aer', 'od550csaer', 'od550lt1aer']
colocator.run(model_id=ANOTHER_MODEL_ID)
colocator.data.keys()
dict_keys(['TM5_AP3-CTRL2919', 'CAM53-Oslo_7310_MG15CLM45_5feb2017IHK_53OSLO_PD_UNTUNED'])
colocator.data[ANOTHER_MODEL_ID]['ang4487aer'].plot_scatter(marker='o', alpha=0.1, color='g');
_arr = col_data.data
mean_bias = ((_arr[1] - _arr[0])/_arr[0]).mean('time') * 100 #%
mean_bias
<xarray.DataArray 'od550aer' (station_name: 290)> array([ 32.791464, 44.197759, -23.840775, ..., 19.99503 , 36.219445, 14.187602]) Coordinates: var_name <U8 'od550aer' var_units <U1 '1' * station_name (station_name) <U19 'ARM_Darwin' ... 'Zinder_Airport' latitude (station_name) float64 -12.43 37.97 15.35 ... 62.45 13.78 longitude (station_name) float64 130.9 23.72 -1.479 ... -114.4 8.99 altitude (station_name) float64 29.9 130.0 305.0 ... 300.0 220.8 456.0 data_source <U22 'AeronetSunV3Lev2.daily' ts_type_src <U7 'daily'
ax = pya.plot.mapping.init_map()
_sc = ax.scatter(mean_bias.longitude, mean_bias.latitude, marker='o', c=mean_bias.data, cmap='bwr',
vmin=-100, vmax=100, s=80)
cb = plt.colorbar(_sc)
cb.ax.set_ylabel('Normalised mean bias [%]');
https://aerocom-evaluation.met.no/overall.php?project=aerocom&exp=PIII-optics2019