diff --git a/parm/snow/obs/config/bufr_sfcsno_mapping.yaml b/parm/snow/obs/config/bufr_sfcsno_mapping.yaml index 00ab1bc7d..2fe12f39c 100644 --- a/parm/snow/obs/config/bufr_sfcsno_mapping.yaml +++ b/parm/snow/obs/config/bufr_sfcsno_mapping.yaml @@ -17,7 +17,6 @@ bufr: query: "[*/CLON, */CLONH]" stationIdentification: query: "*/RPID" - stationElevation: query: "[*/SELV, */HSMSL]" @@ -26,11 +25,8 @@ bufr: query: "[*/SNWSQ1/TOSD, */MTRMSC/TOSD, */STGDSNDM/TOSD]" transforms: - scale: 1000.0 - filters: - - bounding: - variable: totalSnowDepth - lowerBound: 0 - upperBound: 10000000 + groundState: + query: "[*/GRDSQ1/SOGR, */STGDSNDM/SOGR]" encoder: variables: @@ -65,7 +61,7 @@ encoder: coordinates: "longitude latitude" source: variables/stationIdentification longName: "Identification of Observing Location" - units: "m" + units: "index" # ObsValue - name: "ObsValue/totalSnowDepth" @@ -73,3 +69,10 @@ encoder: source: variables/totalSnowDepth longName: "Total Snow Depth" units: "mm" + + - name: "ObsValue/groundState" + coordinates: "longitude latitude" + source: variables/groundState + longName: "STATE OF THE GROUND" + units: "index" + diff --git a/parm/snow/obs/config/sfcsno_snow.yaml.j2 b/parm/snow/obs/config/sfcsno_snow.yaml.j2 index 960ea8f64..d17d3e9b0 100644 --- a/parm/snow/obs/config/sfcsno_snow.yaml.j2 +++ b/parm/snow/obs/config/sfcsno_snow.yaml.j2 @@ -5,9 +5,11 @@ halo size: 250e3 obsdatain: engine: - type: bufr + type: script + script file: "{{ USHgfs }}/bufr2ioda_sfcsno_bufr_encoder.py" + args: + input_path: '{{ DATA }}/obs/{{ OPREFIX }}sfcsno.tm00.bufr_d' obsfile: '{{ DATA }}/obs/{{ OPREFIX }}sfcsno.tm00.bufr_d' - mapping file: '{{ DATA }}/obs/bufr_sfcsno_mapping.yaml' obsdataout: engine: type: H5File diff --git a/sorc/bufr-query b/sorc/bufr-query index 97367fcd5..8bc28860d 160000 --- a/sorc/bufr-query +++ b/sorc/bufr-query @@ -1 +1 @@ -Subproject commit 97367fcd59adf4863aba1a52189e20f9f66451af +Subproject commit 8bc28860d562f9a53ffa86e7c5c5ae05c2c4e09f diff --git a/ush/ioda/bufr2ioda/bufr2ioda_sfcsno_bufr_encoder.py b/ush/ioda/bufr2ioda/bufr2ioda_sfcsno_bufr_encoder.py new file mode 100644 index 000000000..16a648acd --- /dev/null +++ b/ush/ioda/bufr2ioda/bufr2ioda_sfcsno_bufr_encoder.py @@ -0,0 +1,43 @@ +import numpy as np +import bufr +from pyioda.ioda.Engines.Bufr import Encoder + + +def mask_container(container, mask): + new_container = bufr.DataContainer() + for var_name in container.list(): + var = container.get(var_name) + paths = container.get_paths(var_name) + new_container.add(var_name, var[mask], paths) + + return new_container + + +def create_obs_group(input_path): + """Create the ioda snow observations + This method: + - reads state of ground (sogr) and snow depth (snod) + - applys sogr conditions to the missing snod values + - removes the filled/missing snow values and creates the masked container + - encoders the new container. + + Parameters + ---------- + input_path + The input bufr file + """ + + YAML_PATH = "./obs/bufr_sfcsno_mapping.yaml" + container = bufr.Parser(input_path, YAML_PATH).parse() + + sogr = container.get('variables/groundState') + snod = container.get('variables/totalSnowDepth') + snod[(sogr <= 11.0) & snod.mask] = 0.0 + snod[(sogr == 15.0) & snod.mask] = 0.0 + container.replace('variables/totalSnowDepth', snod) + + masked_container = mask_container(container, (~snod.mask)) + + data = next(iter(Encoder(YAML_PATH).encode(masked_container).values())) + + return data