...
The tables below show the mapping. Below that is some example Python code showing how this information can be used with ecCodes to identify the model and variable of each field in a GRIB file.
Model | centre | subCentre |
---|---|---|
CHIMERE | 85 | 200 |
DEHM | 85 | 203 |
EMEP | 88 | 0 |
Ensemble median | 85 | 2 |
EURAD-IM | 85 | 201 |
GEM-AQ | 85 | 204 |
LOTOS-EUROS | 99 | 0 |
MATCH | 82 | 98 |
MOCAGE | 85 | 1 |
SILAM | 86 | 0 |
Variable | parameterNumber | constituentType |
---|---|---|
Alder pollen | 59 | 62100 |
Ammonia | 0 | 9 |
Birch pollen | 59 | 62101 |
Carbon monoxide | 0 | 4 |
Dust | 0 | 62001 |
Grass pollen | 59 | 62300 |
Nitrogen dioxide | 0 | 5 |
Nitrogen monoxide | 0 | 11 |
Non-methane VOCs | 0 | 60013 |
Olive pollen | 59 | 64002 |
Ozone | 0 | 0 |
Particulate matter < 10um (PM10) | 0 | 40008 |
Particulate matter < 2.5um (PM2.5) | 0 | 40009 |
Peroxyacyl nitrates (PANs) | 0 | 60018 |
PM10 from wildfires | 0 | 62096 |
Ragweed pollen | 59 | 62200 |
Secondary inorganic aerosol (SIA) | 0 | 62099 |
Sulphur dioxide | 0 | 8 |
Code Block |
---|
from eccodes import codes_grib_new_from_file, codes_get, codes_release
grib_file = 'cams_AQ_forecast.grib'
# Dictionary matching ADS API key/value pairs to grib key/value pairs
definitions = {
'variable': {
'ozone': {
'parameterNumber': 0, # Mass density kg/m3
'constituentType': 0},
'carbon_monoxide': {
'parameterNumber': 0,
'constituentType': 4},
'ammonia': {
'parameterNumber': 0,
'constituentType': 9},
'non_methane_vocs': {
'parameterNumber': 0,
'constituentType': 60013},
'nitrogen_monoxide': {
'parameterNumber': 0,
'constituentType': 11},
'nitrogen_dioxide': {
'parameterNumber': 0,
'constituentType': 5},
'peroxyacyl_nitrates': {
'parameterNumber': 0,
'constituentType': 60018},
'particulate_matter_10um': {
'parameterNumber': 0,
'constituentType': 40008},
'particulate_matter_2.5um': {
'parameterNumber': 0,
'constituentType': 40009},
'pm10_wildfires': {
'parameterNumber': 0,
'constituentType': 62096},
'sulphur_dioxide': {
'parameterNumber': 0,
'constituentType': 8},
'birch_pollen': {
'parameterNumber': 59, # Number Concentration (1/m3)
'constituentType': 62101},
'grass_pollen': {
'parameterNumber': 59,
'constituentType': 62300},
'olive_pollen': {
'parameterNumber': 59,
'constituentType': 64002},
'ragweed_pollen': {
'parameterNumber': 59,
'constituentType': 62200},
'alder_pollen': {
'parameterNumber': 59,
'constituentType': 62100},
'dust': {
'parameterNumber': 0, # Mass density kg/m3
'constituentType': 62001},
'secondary_inorganic_aerosol': {
'parameterNumber': 0,
'constituentType': 62099}
},
'model': {
'chimere': {
'centre': 85, # France
'subCentre': 200},
'emep': {
'centre': 88, # Oslo
'subCentre': 0},
'ensemble': {
'centre': 85, # France
'subCentre': 2},
'euradim': {
'centre': 85, # France
'subCentre': 201},
'match': {
'centre': 82, # Norrkoping
'subCentre': 98},
'mocage': {
'centre': 85, # Meteo France
'subCentre': 1},
'silam': {
'centre': 86, # Helsinki
'subCentre': 0},
'lotos': {
'centre': 99,
'subCentre': 0},
'gemaq': {
'centre': 85,
'subCentre': 204},
'dehm': {
'centre': 85,
'subCentre': 203}
}
}
def identify_field(msg):
"""Return a dict identifying the input grib message"""
field = {}
for api_key, value_to_grib in definitions.items():
for api_value, grib_defn in value_to_grib.items():
# Does this message match the key/value pairs in grib_defn?
match = True
for grib_key, grib_value in grib_defn.items():
msg_value = codes_get(msg, grib_key,
ktype=type(grib_value))
if msg_value != grib_value:
match = False
break
if match:
field[api_key] = api_value
if api_key not in field:
raise Exception('Unrecognised field')
return field
# Loop over messages in a grib file, identifying all fields
count = 0
with open(grib_file) as f:
while True:
msg = codes_grib_new_from_file(f)
if msg is None:
break
count += 1
try:
field = identify_field(msg)
finally:
codes_release(msg)
print('Field ' + str(count) + ' is: ' + repr(field))
|
...