-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Icon support #11
Icon support #11
Changes from 3 commits
2fadef5
6840518
b95e4d9
32e3804
9cdaa9c
f255df7
9afd616
72dd884
d38fa5e
1d0eaa7
a46d1d4
d213dd8
4834117
23dd1b3
f8d4f0f
a5e37aa
bbb4869
5d0c9c9
5b38dfe
96df752
0342316
f7e4ffe
8381959
848fd8f
51d97a5
efab2b0
e54cb60
2a1d4d6
7b694ef
dfd57ba
81ebcb7
1a63380
31ef83f
1222b27
4d52ffe
7fd1801
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, it is uncommon to upload large data files directly to git repos. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dito |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here on the other hand you are directly linking your scratch, this might not work for other users (is this a problem?). Having all required data in one common place might be benefitial for future users to understand the data-IO better. Updated external fields would always be available in that place (e.g. git lfs). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done. There are no links any more. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/scratch/mch/paa/wd/23042500_icon_BETU_POAC_testchain/lm_coarse/iaf2023042500 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/oprusers/osm/opr.aare/data/ICON_INPUT/ICON-CH1-EPS/lfff00000000c |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,28 +7,139 @@ | |
"""A module for the update of the pollen start and end of season in real time.""" | ||
|
||
# Third-party | ||
import cfgrib # type: ignore | ||
import numpy as np | ||
import xarray as xr | ||
from datetime import datetime | ||
from eccodes import ( | ||
codes_get, | ||
codes_get_array, | ||
codes_grib_new_from_file, | ||
codes_release, | ||
codes_set_array, | ||
codes_write, | ||
) | ||
|
||
# First-party | ||
from realtime_pollen_calibration import utils | ||
|
||
|
||
def update_phenology_realtime(file_obs, file_in, file_out, verbose=False): | ||
def update_phenology_realtime(file_obs, file_POV, file_T_2M, file_Const, file_out, verbose=False): | ||
"""Advance the temperature threshold fields by one hour. | ||
|
||
Args: | ||
file_obs: Location of ATAB file containing the pollen | ||
concentration information at the stations. | ||
file_in: Location of GRIB2 file containing the following fields: | ||
'T_2M', 'tthrs', 'tthre' (for POAC, 'saisl' instead), | ||
file_POV: Location of ICON GRIB2 file containing the pollen fields: | ||
'tthrs', 'tthre' (for POAC, 'saisl' instead), | ||
'saisn' and 'ctsum'. Lat-lon information of the grid must be | ||
present in the file. | ||
file_T_2M: Location of GRIB2 file containing T_2M. | ||
file_Const: Location of GRIB2 file containing Longitudes and Latitudes of the | ||
unstructured ICON grid. | ||
file_out: Location of the desired output file. | ||
verbose: Optional additional debug prints. | ||
|
||
""" | ||
ds = cfgrib.open_dataset(file_in, encode_cf=("time", "geography", "vertical")) | ||
|
||
#file_POV = "data/grib2_files_ICON-CH1/ART_POV_iconR19B08-grid_0001_all_specs_values" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove comments if not required There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
#file_obs= "data/atabs/alnu_pollen_measured_values_2022021314.atab" | ||
|
||
fh_POV = open(file_POV, "rb") | ||
fh_Const = open(file_Const, "rb") | ||
fh_T_2M = open(file_T_2M, "rb") | ||
|
||
# read CLON, CLAT | ||
while True: | ||
# Get the next message | ||
recConst = codes_grib_new_from_file(fh_Const) | ||
if recConst is None: | ||
break | ||
|
||
# Get the short name of the current field | ||
short_name = codes_get(recConst, "shortName") | ||
|
||
# Extract longitude and latitude of the ICON grid | ||
if short_name == "CLON": | ||
CLON = codes_get_array(recConst, "values") | ||
if short_name == "CLAT": | ||
CLAT = codes_get_array(recConst, "values") | ||
|
||
# Delete the message | ||
codes_release(recConst) | ||
|
||
# Close the GRIB file | ||
fh_Const.close() | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. these can be considered user input parameters and you might want to write them in a seperate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. Now there is a config.yaml. |
||
# read POV and extract available fields | ||
specs = ["ALNU", "BETU", "POAC", "CORY"] | ||
fields= ["tthrs", "tthre", "saisn", "ctsum"] | ||
pol_fields = [x + y for x in specs for y in fields] | ||
pol_fields[9] = "POACsaisl" | ||
|
||
calFields = {} | ||
while True: | ||
# Get the next message | ||
recPOV = codes_grib_new_from_file(fh_POV) | ||
if recPOV is None: | ||
break | ||
|
||
# Get the short name of the current field | ||
short_name = codes_get(recPOV, "shortName") | ||
|
||
# Extract and alter fields if they present | ||
for pol_field in pol_fields: | ||
if short_name == pol_field: | ||
calFields[pol_field] = codes_get_array(recPOV, "values") | ||
|
||
# Delete the message | ||
codes_release(recPOV) | ||
|
||
# Close the GRIB files | ||
fh_POV.close() | ||
|
||
|
||
# Read T_2M | ||
while True: | ||
# Get the next message | ||
recX = codes_grib_new_from_file(fh_T_2M) | ||
if recX is None: | ||
break | ||
|
||
# Get the short name of the current field | ||
short_name = codes_get(recX, "shortName") | ||
|
||
if short_name == "T_2M": | ||
calFields["T_2M"] = codes_get_array(recX, "values") | ||
|
||
# timestamp is needed. Take it from the T_2M field | ||
dataDate = str(codes_get(recX, "dataDate")) | ||
dataTime = str(str(codes_get(recX, "dataTime")).zfill(2)) | ||
dataDateTime = dataDate + dataTime | ||
|
||
# Convert the string to a datetime object | ||
date_obj = datetime.strptime(dataDateTime, '%Y%m%d%H') | ||
date_obj_fmt = date_obj.strftime('%Y-%m-%dT%H:00:00.000000000') | ||
time_values = np.datetime64(date_obj_fmt) | ||
|
||
codes_release(recX) | ||
|
||
# Close the GRIB files | ||
fh_T_2M.close() | ||
|
||
# Dictionary to hold DataArrays for each variable | ||
calFields_arrays = {} | ||
|
||
# Loop through variables to create DataArrays | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here you might consider using earthkit's .to_xarray() method for conversion to a hypercube. @clairemerker what is the latest guideline on using eccodes/cfgrib/earthkit? also consider a short discussion with Petra on this matter. I am not sure, earthkit makes the code easier but also adds one dependency. |
||
for var_name, data in calFields.items(): | ||
data_array = xr.DataArray(data, coords={'index': np.arange(len(data))}, dims=['index']) | ||
data_array.coords['latitude'] = (('index'), CLAT) | ||
data_array.coords['longitude'] = (('index'), CLON) | ||
data_array.coords['time'] = time_values | ||
calFields_arrays[var_name] = data_array | ||
|
||
# Create an xarray Dataset with the DataArrays | ||
ds = xr.Dataset(calFields_arrays) | ||
|
||
ptype_present = utils.get_pollen_type(ds) | ||
if verbose: | ||
print(f"Detected pollen types in the DataSet provided: {ptype_present}") | ||
|
@@ -55,4 +166,4 @@ def update_phenology_realtime(file_obs, file_in, file_out, verbose=False): | |
obs_mod_data.coord_stns, | ||
method="sum", | ||
) | ||
utils.to_grib(file_in, file_out, dict_fields) | ||
utils.to_grib(file_POV, file_out, dict_fields) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ | |
thr_con_24 = {"ALNU": 240, "BETU": 240, "POAC": 72, "CORY": 240} | ||
thr_con_120 = {"ALNU": 720, "BETU": 720, "POAC": 216, "CORY": 720} | ||
failsafe = {"ALNU": 1000, "BETU": 2500, "POAC": 6000, "CORY": 2500} | ||
jul_days_excl = {"ALNU": 14, "BETU": 40, "POAC": 3, "CORY": 46} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider moving these user defined value into a config.yaml file There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These values should not be changed by users. Hence I would leave them there There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fine to leave it here! Could you provide a comment documenting the meaning of those values? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
jul_days_excl = {"ALNU": 14, "BETU": 40, "POAC": 46, "CORY": 3} | ||
|
||
|
||
def count_to_log_level(count: int) -> int: | ||
|
@@ -414,15 +414,15 @@ def get_change_phenol( # pylint: disable=R0912,R0914,R0915 | |
f"and last 120H {sum_obs}", | ||
) | ||
print( | ||
f"Cumulative temperature sum {ctsum_stns.values[0][0]} ", | ||
f"and threshold (start): {tthrs_stns.values[0][0]}", | ||
f" and saisn: {saisn_stns.values[0][0]}", | ||
f"Cumulative temperature sum {ctsum_stns.values[0]} ", | ||
f"and threshold (start): {tthrs_stns.values[0]}", | ||
f" and saisn: {saisn_stns.values[0]}", | ||
) | ||
if pollen_type != "POAC": | ||
print(f"Cumsum temp threshold end: {tthre_stns.values[0][0]}") | ||
print(f"Cumsum temp threshold end: {tthre_stns.values[0]}") | ||
else: | ||
print(f"Saisl: {saisl_stns.values[0][0]}") | ||
print(f"Temperature at station {t_2m_stns.values[0][0]}, " f"date: {date}") | ||
print(f"Saisl: {saisl_stns.values[0]}") | ||
print(f"Temperature at station {t_2m_stns.values[0]}, " f"date: {date}") | ||
print("-----------------------------------------") | ||
# ADJUSTMENT OF SEASON START AND END AT THE BEGINNING OF THE SEASON | ||
if ( | ||
|
@@ -545,15 +545,20 @@ def to_grib(inp: str, outp: str, dict_fields: dict) -> None: | |
break | ||
# clone record | ||
clone_id = eccodes.codes_clone(gid) | ||
# get short_name | ||
|
||
# get short_name | ||
short_name = eccodes.codes_get_string(clone_id, "shortName") | ||
|
||
# read values | ||
values = eccodes.codes_get_values(clone_id) | ||
eccodes.codes_set( | ||
clone_id, "dataTime", eccodes.codes_get(clone_id, "dataTime") + 100 | ||
) | ||
if short_name in dict_fields: | ||
|
||
#set values in dict_fields[short_name] to zero where values is zero (edge values) | ||
#This is because COSMO-1E was slightly smaller than ICON-CH1 | ||
dict_fields[short_name][values == 0] = 0 | ||
eccodes.codes_set_values(clone_id, dict_fields[short_name].flatten()) | ||
else: | ||
eccodes.codes_set_values(clone_id, values) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this file is quite large to upload to git. Maybe consider using git lfs (large file storage)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test data is not part of the repo any more. It will be available from a location defined by osm.