from eccodes import (
codes_grib_new_from_file, codes_get, codes_release
grib_file = 'cams_AQ_forecast.grib', codes_write)
# Dictionary matching ADS API key/value pairs to grib key/value pairs
definitions = {
'variable': {
'ammonia': {
'parameterNumber': 0,
# Mass density (kg/m3)
'constituentType': 9},
'carbon_monoxide': {
'parameterNumber': 0,
'constituentType': 4},
'dust': {
'parameterNumber': 0, # Mass density kg/m3
'constituentType': 62001}, # Dust dry
'non_methane_vocsformaldehyde': {
'parameterNumber': 0,
'constituentType': 600137},
'nitrogen_monoxideglyoxal': {
'parameterNumber': 0,
'constituentType': 1110038},
'nitrogennon_methane_dioxidevocs': {
'parameterNumber': 0,
'constituentType': 560013},
'ozonenitrogen_monoxide': {
'parameterNumber': 0, # Mass density kg/m3
'constituentType': 011},
'peroxyacylnitrogen_nitratesdioxide': {
'parameterNumber': 0,
'constituentType': 600185},
'particulate_matter_10umozone': {
'parameterNumber': 0,
'constituentType': 400080},
'particulate_matter_2.5umperoxyacyl_nitrates': {
'parameterNumber': 0,
'constituentType': 4000960018},
'pm2.5_anthropogenic_wood_burning_carbonparticulate_matter_10um': {
'parameterNumber': 0,
'constituentType': 6209840008},
'pm2.5particulate_anthropogenic_fossil_fuel_carbonmatter_2.5um': {
'parameterNumber': 0,
'constituentType': 6209740009},
'pm10_wildfirespm2.5_anthropogenic_wood_burning_carbon': {
'parameterNumber': 0,
'constituentType': 6209662098},
'residential_elementarypm2.5_anthropogenic_fossil_fuel_carbon': {
'parameterNumber': 0,
'constituentType': 6209462097},
'secondary_inorganic_aerosol'pm2.5_total_organic_matter': {
'parameterNumber': 0,
'constituentType': 6209962010},
'sulphur_dioxide'pm10_sea_salt_dry': {
'parameterNumber': 0,
'constituentType': 862008},
'totalpm10_elementary_carbonwildfires': {
'parameterNumber': 0,
'constituentType': 6209562096},
'alderresidential_elementary_pollencarbon': {
'parameterNumber': 59, # Number Concentration (1/m3)0,
'constituentType': 6210062094},
'birchsecondary_inorganic_pollenaerosol': {
'parameterNumber': 590,
'constituentType': 6210162099},
'grasssulphur_pollendioxide': {
'parameterNumber': 590,
'constituentType': 623008},
'mugworttotal_elementary_pollencarbon': {
'parameterNumber': 590,
'constituentType': 6220162095},
'olivealder_pollen': {
'parameterNumber': 59,
# Number Concentration (1/m3)
'constituentType': 6400262100},
'ragweedbirch_pollen': {
'parameterNumber': 59,
'constituentType': 62200}
}62101},
'model': {
'chimere'grass_pollen': {
'centreparameterNumber': 85, # France59,
'subCentreconstituentType': 20062300},
'dehmmugwort_pollen': {
'centreparameterNumber': 8559,
'subCentreconstituentType': 20362201},
'emepolive_pollen': {
'centreparameterNumber': 88, # Oslo59,
'subCentreconstituentType': 064002},
'ensembleragweed_pollen': {
'centreparameterNumber': 8559,
# France
'constituentType': 62200}
},
'subCentremodel': 2},{
'euradimchimere': {
'centre': 85, # France
'subCentre': 201200},
'gemaqdehm': {
'centre': 85,
'subCentre': 204203},
'lotosemep': {
'centre': 99,88, # Oslo
'subCentre': 0},
'matchensemble': {
'centre': 8285, # NorrkopingFrance
'subCentre': 982},
'mocageeuradim': {
'centre': 85, # Meteo France
'subCentre': 1201},
'silamgemaq': {
'centre': 8685,
# Helsinki
'subCentre': 204},
'subCentrelotos': 0}{
}
}
def identify_field(msg): 'centre': 99,
"""Return a dict identifying the input grib message"""
'subCentre': 0},
field ='match': {}
for api_key, value_to_grib in definitions.items():
'centre': 82, for api_value, grib_defn in value_to_grib.items():
# Norrkoping
# Does this message match the key/value pairs in grib_defn?'subCentre': 98},
'mocage': {
match = True
'centre': 85, # Meteo France
for grib_key, grib_value in grib_defn.items(): 'subCentre': 1},
'silam': {
msg_value = codes_get(msg, grib_key,
'centre': 86, # Helsinki
'subCentre': 0},
'minni': {
ktype=type(grib_value))
'centre': 85,
if msg_value != grib_value: 'subCentre': 205},
'monarch': {
match = False'centre': 85,
'subCentre': 206}
break}
}
def identify_field(msg):
"""Return a dict identifying the input if match:grib message"""
field = {}
field[for api_key] = api_value
, value_to_grib in definitions.items():
iffor api_key notvalue, grib_defn in field:
value_to_grib.items():
# raise Exception('Unrecognised field')
return field
# Loop over messages in a grib file, identifying all fields
count = 0
with open(grib_file) as f:Does this message match the key/value pairs in grib_defn?
match = True
while True:
msg = codes_grib_new_from_file(f)for grib_key, grib_value in grib_defn.items():
if msg is None:
msg_value = codes_get(msg, grib_key,
break
count += 1
try:
field = identify_field(msg)
ktype=type(grib_value))
finally:
if codes_release(msg)
msg_value != grib_value:
print('Field ' + str(count) + ' is: 'match + repr(field))
= False
break
if match:
field[api_key] = api_value
if api_key not in field:
raise Exception('Unrecognised field')
return field
def main(grib_file, output_filename_template=None):
"""Read all fields in the GRIB file, identify the model and variable of
each, and optionally write them to output files, split by model or
variable or both.
Any instance of "<model>" or "<variable>" in output_filename_template
will be replaced by the associated model or variable string for the
field, e.g. output_filename_template='<model>.<variable>.grib'
"""
fields_written = {}
# Loop over messages in a grib file, identifying all fields
count = 0
with open(grib_file) as fin:
while True:
msg = codes_grib_new_from_file(fin)
if msg is None:
break
count += 1
try:
field = identify_field(msg)
print('Field ' + str(count) + ' is: ' + repr(field))
# Write the field to an output file?
if output_filename_template:
name = output_filename_template
for k, v in field.items():
name = name.replace(f'<{k}>', v)
if name not in fields_written:
fields_written[name] = 0
mode = 'w'
else:
mode = 'a'
with open(name, mode + 'b') as fout:
codes_write(msg, fout)
fields_written[name] += 1
finally:
codes_release(msg)
for name, n in fields_written.items():
print(f'Wrote {n} fields to {name}')
if __name__ == '__main__':
main('mydata.grib',
output_filename_template='<model>.<variable>.grib') |