diff --git a/parm/atm/atm_obs_list.yaml.j2 b/parm/atm/atm_obs_list.yaml.j2 index 61b483f68..e776bd59e 100644 --- a/parm/atm/atm_obs_list.yaml.j2 +++ b/parm/atm/atm_obs_list.yaml.j2 @@ -31,6 +31,9 @@ observations: ##- cris-fsr_n21 ##- atms_npp - radiance_atms_n20 +##- radiance_mhs_metop-b +##- radiance_mhs_metop-c +##- radiance_mhs_n19 ##- gnssro_cosmic2 ##- gnssro_spire ##- gnssro_s6 diff --git a/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_metop-a.yaml b/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_metop-a.yaml new file mode 100644 index 000000000..1cb844018 --- /dev/null +++ b/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_metop-a.yaml @@ -0,0 +1,26 @@ +# Instrument metadata +# ------------------- +commissioned: 2009-12-15T00:00:00 + +observer_type: satellite # Type of chronicle to use + +# Instrument initial configuration +# -------------------------------- +channel_variables: + simulated: min + active: min + biascorrtd: min + error: max + error_cld: max + ermax: max + var_b: min + var_pg: min + icld_det: min + icloud: min + iaerosol: min +channel_values: + 1: [ 1, -1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 2: [ 1, -1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 3: [ 1, -1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 4: [ 1, -1, 1, 2.00, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 5: [ 1, -1, 1, 2.00, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] diff --git a/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_metop-b.yaml b/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_metop-b.yaml new file mode 100644 index 000000000..7b543da32 --- /dev/null +++ b/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_metop-b.yaml @@ -0,0 +1,26 @@ +# Instrument metadata +# ------------------- +commissioned: 2009-12-15T00:00:00 + +observer_type: satellite # Type of chronicle to use + +# Instrument initial configuration +# -------------------------------- +channel_variables: + simulated: min + active: min + biascorrtd: min + error: max + error_cld: max + ermax: max + var_b: min + var_pg: min + icld_det: min + icloud: min + iaerosol: min +channel_values: + 1: [ 1, 1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 2: [ 1, 1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 3: [ 1, 1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 4: [ 1, 1, 1, 2.00, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 5: [ 1, 1, 1, 2.00, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] diff --git a/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_metop-c.yaml b/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_metop-c.yaml new file mode 100644 index 000000000..86362b31c --- /dev/null +++ b/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_metop-c.yaml @@ -0,0 +1,26 @@ +# Instrument metadata +# ------------------- +commissioned: 2019-10-30T00:00:00 + +observer_type: satellite # Type of chronicle to use + +# Instrument initial configuration +# -------------------------------- +channel_variables: + simulated: min + active: min + biascorrtd: min + error: max + error_cld: max + ermax: max + var_b: min + var_pg: min + icld_det: min + icloud: min + iaerosol: min +channel_values: + 1: [ 1, 1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 2: [ 1, 1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 3: [ 1, 1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 4: [ 1, 1, 1, 2.00, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 5: [ 1, 1, 1, 2.00, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] diff --git a/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_n18.yaml b/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_n18.yaml new file mode 100644 index 000000000..7b543da32 --- /dev/null +++ b/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_n18.yaml @@ -0,0 +1,26 @@ +# Instrument metadata +# ------------------- +commissioned: 2009-12-15T00:00:00 + +observer_type: satellite # Type of chronicle to use + +# Instrument initial configuration +# -------------------------------- +channel_variables: + simulated: min + active: min + biascorrtd: min + error: max + error_cld: max + ermax: max + var_b: min + var_pg: min + icld_det: min + icloud: min + iaerosol: min +channel_values: + 1: [ 1, 1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 2: [ 1, 1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 3: [ 1, 1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 4: [ 1, 1, 1, 2.00, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 5: [ 1, 1, 1, 2.00, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] diff --git a/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_n19.yaml b/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_n19.yaml new file mode 100644 index 000000000..17a85c016 --- /dev/null +++ b/parm/jcb-gdas/observation_chronicle/atmosphere/radiance_mhs_n19.yaml @@ -0,0 +1,26 @@ +# Instrument metadata +# ------------------- +commissioned: 2009-12-15T00:00:00 + +observer_type: satellite # Type of chronicle to use + +# Instrument initial configuration +# -------------------------------- +channel_variables: + simulated: min + active: min + biascorrtd: min + error: max + error_cld: max + ermax: max + var_b: min + var_pg: min + icld_det: min + icloud: min + iaerosol: min +channel_values: + 1: [ 1, 1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 2: [ 1, 1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 3: [ 1, -1, 1, 2.50, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 4: [ 1, 1, 1, 2.00, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] + 5: [ 1, 1, 1, 2.00, 0.00, 6.00, 10.00, 0.00, -2, -1, -1 ] diff --git a/parm/jcb-gdas/observations/atmosphere/radiance_mhs_metop-b.yaml.j2 b/parm/jcb-gdas/observations/atmosphere/radiance_mhs_metop-b.yaml.j2 new file mode 100644 index 000000000..e29118ae6 --- /dev/null +++ b/parm/jcb-gdas/observations/atmosphere/radiance_mhs_metop-b.yaml.j2 @@ -0,0 +1,516 @@ +- + + # Observation Space (I/O) + # ----------------------- + obs space: + name: {{observation_from_jcb}} + obsdatain: + engine: + type: H5File + obsfile: "{{atmosphere_obsdatain_path}}/{{atmosphere_obsdatain_prefix}}{{observation_from_jcb}}{{atmosphere_obsdatain_suffix}}" + missing file action: warn + obsdataout: + engine: + type: H5File + obsfile: "{{atmosphere_obsdataout_path}}/{{atmosphere_obsdataout_prefix}}{{observation_from_jcb}}{{atmosphere_obsdataout_suffix}}" + io pool: + max pool size: 1 + simulated variables: [brightnessTemperature] + channels: &{{observation_from_jcb}}_simulated_channels {{ get_satellite_variable(observation_from_jcb, "simulated") }} + + # Observation Operator + # -------------------- + obs operator: + name: CRTM + Absorbers: [H2O, O3, CO2] + obs options: + Sensor_ID: &{{observation_from_jcb}}_sensor_id mhs_metop-b + EndianType: little_endian + CoefficientPath: "{{crtm_coefficient_path}}" + linear obs operator: + Absorbers: [H2O, O3] + + # Observation Bias Correction (VarBC) + # ----------------------------------- + obs bias: + input file: "{{atmosphere_obsbiasin_path}}/{{atmosphere_obsbiasin_prefix}}{{observation_from_jcb}}{{atmosphere_obsbiasin_suffix}}" + output file: "{{atmosphere_obsbiasout_path}}/{{atmosphere_obsbiasout_prefix}}{{observation_from_jcb}}{{atmosphere_obsbiasout_suffix}}" + variational bc: + predictors: + - name: constant + - name: lapseRate + order: 2 + tlapse: &{{observation_from_jcb}}_tlapse "{{atmosphere_obsbiasin_path}}/{{atmosphere_obstlapsein_prefix}}{{observation_from_jcb}}{{atmosphere_obstlapsein_suffix}}" + - name: lapseRate + tlapse: *{{observation_from_jcb}}_tlapse + - name: emissivityJacobian + - name: sensorScanAngle + order: 4 + - name: sensorScanAngle + order: 3 + - name: sensorScanAngle + order: 2 + - name: sensorScanAngle + covariance: + minimal required obs number: 20 + variance range: [1.0e-6, 10.0] + step size: 1.0e-4 + largest analysis variance: 10000.0 + prior: + input file: "{{atmosphere_obsbiasin_path}}/{{atmosphere_obsbiascovin_prefix}}{{observation_from_jcb}}{{atmosphere_obsbiascovin_suffix}}" + inflation: + ratio: 1.1 + ratio for small dataset: 2.0 + output file: "{{atmosphere_obsbiasout_path}}/{{atmosphere_obsbiascovout_prefix}}{{observation_from_jcb}}{{atmosphere_obsbiascovout_suffix}}" + + # ------------------------ + obs pre filters: + # Remove observations from the Edge of the Scan + - filter: Domain Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + where: + - variable: + name: MetaData/sensorScanPosition + is_in: 10-81 + action: + name: reduce obs space + +# # Data Thinning +# - filter: Gaussian Thinning +# horizontal_mesh: 145 +# use_reduced_horizontal_grid: true +# distance_norm: geodesic +# round_horizontal_bin_count_to_nearest: true +# # partition_longitude_bins_using_mesh: true +# action: +# name: reduce obs space + + # Observation Post Filters (QC) + # ----------------------------- + obs post filters: + # Step A: Conduct observation range sanity check + # Valid range: (50, 550) + - filter: Bounds Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + minvalue: 50.00001 + maxvalue: 549.99999 + action: + name: reject + # Step B: Do initial observation error Assignment + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: assign error + error parameter vector: &{{observation_from_jcb}}_oberr [{{ get_satellite_variable(observation_from_jcb, "error") }}] + # Step C: Assign surface_water_ice_snow = 1 if surface type is sea, ice, or snow. + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/surface_water_ice_snow + type: int + value: 1 + where: + - variable: + name: GeoVaLs/water_area_fraction + minvalue: 0.99 + - variable: + name: GeoVaLs/ice_area_fraction + minvalue: 0.99 + - variable: + name: GeoVaLs/surface_snow_area_fraction + minvalue: 0.99 + where operator: or + # Step C1: Assign surface_water_ice_snow = 0 if surface type is not sea, ice, or snow. + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/surface_water_ice_snow + type: int + value: 0 + where: + - variable: + name: GeoVaLs/water_area_fraction + maxvalue: 0.99 + max_exclusive: true + - variable: + name: GeoVaLs/ice_area_fraction + maxvalue: 0.99 + max_exclusive: true + - variable: + name: GeoVaLs/surface_snow_area_fraction + maxvalue: 0.99 + max_exclusive: true + + # Step D: Get Departure ObsMinusHofx = ObsValue - HofX + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/ObsMinusHofx + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: ObsValue/brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + - name: HofX/brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + coefs: + - 1 + - -1 + # Step E: Get cloud_index ("dsi" in GSI sub "qc_mhs") + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/cloud_index + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/ObsMinusHofx + channels: [1] + - name: DerivedMetaData/ObsMinusHofx + channels: [2] + coefs: + - 0.85 + - -1 + where: + - variable: + name: DerivedMetaData/surface_water_ice_snow + is_in: 0 + # Step E1: Get cloud_index ("dsi" in GSI sub "qc_mhs") + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/cloud_index + type: float + value: 9.0 + where: + - variable: + name: DerivedMetaData/surface_water_ice_snow + is_in: 1 + - variable: + name: ObsValue/brightnessTemperature_2 + minvalue: 300.0 + # Step E2: Define 300-Obs(ch2) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/diff_300_obs2 + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: ObsValue/brightnessTemperature + channels: [2] + coefs: [-1] + intercept: 300.0 + # Step E3: Define "OmF_ch2 / (300 - Obs_ch2)" + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/omf2_diff_300_obs2 + type: float + function: + name: ObsFunction/ElementMultiply + options: + variables: + - name: DerivedMetaData/ObsMinusHofx + channels: [2] + - name: DerivedMetaData/diff_300_obs2 + exponents: [1, -1] + # Step E4: Get final 'cloud_index' ('dsi' in qc_mhs in GSI) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/cloud_index + type: float + # function = 0.13 *(tbc(1)-33.58 *tbc(2)/(h300-tb_obs(2))) in GSI + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/ObsMinusHofx + channels: [1] + - name: DerivedMetaData/omf2_diff_300_obs2 + coefs: [1, -33.58] + total coefficient: 0.13 + where: + - variable: + name: DerivedMetaData/surface_water_ice_snow + is_in: 1 + - variable: + name: ObsValue/brightnessTemperature_2 + maxvalue: 300.0 + max_exclusive: true + # Step E5: Make cloud_index >= 0 + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/cloud_index + type: float + value: 0.0 + where: + - variable: + name: DerivedMetaData/cloud_index + maxvalue: 0.0 + + # Step F: Get tpwc_index =((ObsMinusHofX_1 - 7.5*dsi)/10.0)**2+(dsi)**2 + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/tpwc_indexA + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/ObsMinusHofx + channels: [1] + - name: DerivedMetaData/cloud_index + coefs: [1, -7.5] + total coefficient: 0.1 + # Step F1: Get the final 'tpwc_index' (it is 'fact1' in qc_mhs() in GSI) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/tpwc_index + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/tpwc_indexA + - name: DerivedMetaData/cloud_index + exponents: [2, 2] + # Step H: Assign inflationFactor0 = (1 - tpwc_index^2) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/inflationFactor0 + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/tpwc_index + coefs: [-1] + exponents: [2] + intercept: 1 + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 1.0 + # Step H1: Assign inflationFactor1 = 1.0/(inflationFactor0)^(0.5) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/inflationFactor1 + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/inflationFactor0 + exponents: [-0.5] + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 0.9999999 + # Step H2: Assign inflationFactor1 = 1.0 where tpwc_index >= 1.0 + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/inflationFactor1 + type: float + value: 1.0 + where: + - variable: + name: DerivedMetaData/tpwc_index + minvalue: 1.0 + + # Step J: Initial error inflation by inflationFactor1 + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 1.0 + action: + name: inflate error + inflation variable: + name: DerivedMetaData/inflationFactor1 + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + + # Step J1: Observation error inflation based on topography check + - filter: Variable Assignment + assignments: + - name: ObsErrorFactorTopo@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsErrorFactorTopoRad@ObsFunction + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + channels: *{{observation_from_jcb}}_simulated_channels + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: inflate error + inflation variable: + name: ObsErrorFactorTopo@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 1.0 + + # Step J2: Obs error inflation based on TOA Transmittancec check + - filter: Variable Assignment + assignments: + - name: ObsErrorFactorTransmitTop@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsErrorFactorTransmitTopRad@ObsFunction + channels: *{{observation_from_jcb}}_simulated_channels + options: + channels: *{{observation_from_jcb}}_simulated_channels + + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: inflate error + inflation variable: + name: ObsErrorFactorTransmitTop@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + + # Step K: Find gross error check bounds + # Note, use DerivedMetaData/inflationFactor1 for "obserr_bound_latitude" + - filter: Variable Assignment + assignments: + - name: ObsErrorBound@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsErrorBoundMW@ObsFunction + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + channels: *{{observation_from_jcb}}_simulated_channels + obserr_bound_latitude: + name: DerivedMetaData/inflationFactor1 + obserr_bound_transmittop: + name: ObsErrorFactorTransmitTop@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + options: + channels: *{{observation_from_jcb}}_simulated_channels + obserr_bound_topo: + name: ObsErrorFactorTopo@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + error parameter vector: *{{observation_from_jcb}}_oberr + threshold: 3 + obserr_bound_max: [{{ get_satellite_variable(observation_from_jcb, "ermax") }}] + # Step K1: Gross error check + - filter: Background Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + function absolute threshold: + - name: ObsErrorBound@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: reject + + # Step K2: Toss channel 3-5 data with O-F > 2K + - filter: BlackList + where: + - variable: + name: DerivedMetaData/tpwc_index + minvalue: 1.0 + - filter: Background Check + filter variables: + - name: brightnessTemperature + channels: 3-5 + absolute threshold: 2.0 + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 1.0 + action: + name: reject + + # Step L: Conduct inter-channel check + - filter: Bounds Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + test variables: + - name: ObsFunction/InterChannelConsistencyCheck + channels: *{{observation_from_jcb}}_simulated_channels + options: + channels: *{{observation_from_jcb}}_simulated_channels + sensor: *{{observation_from_jcb}}_sensor_id + use_flag: &{{observation_from_jcb}}_active_channels [{{ get_satellite_variable(observation_from_jcb, "active") }}] + use passive_bc: true + maxvalue: 1.0e-12 + action: + name: reject + + # Step L1: Conduct Useflag check + - filter: Bounds Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + test variables: + - name: ObsFunction/ChannelUseflagCheckRad + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + channels: *{{observation_from_jcb}}_simulated_channels + use_flag: *{{observation_from_jcb}}_active_channels + minvalue: 1.0e-12 + action: + name: reject + + # Step M: Observation error inflation based on surface Jacobian check + - filter: Variable Assignment + assignments: + - name: ObsErrorFactorSurfJacobian@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsErrorFactorSurfJacobianRad@ObsFunction + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + channels: *{{observation_from_jcb}}_simulated_channels + # obserr_demisf: [0.015, 0.030, 0.020, 0.020, 0.250] + # obserr_dtempf: [0.500, 2.000, 1.000, 2.000, 5.000] + # x3 if not sea for MHS + # surface type sea, land, ice, snow, mixed + obserr_demisf: [0.015, 0.090, 0.060, 0.060, 0.750] + obserr_dtempf: [0.500, 6.000, 3.000, 6.000, 15.00] + # Step M1: Inflate observation error + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: inflate error + inflation variable: + name: ObsErrorFactorSurfJacobian@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + + # GeoVaLs for Driving observation Operators (testing mode) + # -------------------------------------------------------- + geovals: + filename: "{{atmosphere_obsdatain_path}}/{{atmosphere_obsdatain_prefix}}{{observation_from_jcb}}_geoval{{atmosphere_obsdatain_suffix}}" + + # Passed benchmark for UFO testing + # -------------------------------- + passedBenchmark: 0 diff --git a/parm/jcb-gdas/observations/atmosphere/radiance_mhs_metop-c.yaml.j2 b/parm/jcb-gdas/observations/atmosphere/radiance_mhs_metop-c.yaml.j2 new file mode 100644 index 000000000..299e0175e --- /dev/null +++ b/parm/jcb-gdas/observations/atmosphere/radiance_mhs_metop-c.yaml.j2 @@ -0,0 +1,516 @@ +- + + # Observation Space (I/O) + # ----------------------- + obs space: + name: {{observation_from_jcb}} + obsdatain: + engine: + type: H5File + obsfile: "{{atmosphere_obsdatain_path}}/{{atmosphere_obsdatain_prefix}}{{observation_from_jcb}}{{atmosphere_obsdatain_suffix}}" + missing file action: warn + obsdataout: + engine: + type: H5File + obsfile: "{{atmosphere_obsdataout_path}}/{{atmosphere_obsdataout_prefix}}{{observation_from_jcb}}{{atmosphere_obsdataout_suffix}}" + io pool: + max pool size: 1 + simulated variables: [brightnessTemperature] + channels: &{{observation_from_jcb}}_simulated_channels {{ get_satellite_variable(observation_from_jcb, "simulated") }} + + # Observation Operator + # -------------------- + obs operator: + name: CRTM + Absorbers: [H2O, O3, CO2] + obs options: + Sensor_ID: &{{observation_from_jcb}}_sensor_id mhs_metop-c + EndianType: little_endian + CoefficientPath: "{{crtm_coefficient_path}}" + linear obs operator: + Absorbers: [H2O, O3] + + # Observation Bias Correction (VarBC) + # ----------------------------------- + obs bias: + input file: "{{atmosphere_obsbiasin_path}}/{{atmosphere_obsbiasin_prefix}}{{observation_from_jcb}}{{atmosphere_obsbiasin_suffix}}" + output file: "{{atmosphere_obsbiasout_path}}/{{atmosphere_obsbiasout_prefix}}{{observation_from_jcb}}{{atmosphere_obsbiasout_suffix}}" + variational bc: + predictors: + - name: constant + - name: lapseRate + order: 2 + tlapse: &{{observation_from_jcb}}_tlapse "{{atmosphere_obsbiasin_path}}/{{atmosphere_obstlapsein_prefix}}{{observation_from_jcb}}{{atmosphere_obstlapsein_suffix}}" + - name: lapseRate + tlapse: *{{observation_from_jcb}}_tlapse + - name: emissivityJacobian + - name: sensorScanAngle + order: 4 + - name: sensorScanAngle + order: 3 + - name: sensorScanAngle + order: 2 + - name: sensorScanAngle + covariance: + minimal required obs number: 20 + variance range: [1.0e-6, 10.0] + step size: 1.0e-4 + largest analysis variance: 10000.0 + prior: + input file: "{{atmosphere_obsbiasin_path}}/{{atmosphere_obsbiascovin_prefix}}{{observation_from_jcb}}{{atmosphere_obsbiascovin_suffix}}" + inflation: + ratio: 1.1 + ratio for small dataset: 2.0 + output file: "{{atmosphere_obsbiasout_path}}/{{atmosphere_obsbiascovout_prefix}}{{observation_from_jcb}}{{atmosphere_obsbiascovout_suffix}}" + + # ------------------------ + obs pre filters: + # Remove observations from the Edge of the Scan + - filter: Domain Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + where: + - variable: + name: MetaData/sensorScanPosition + is_in: 10-81 + action: + name: reduce obs space + +# # Data Thinning +# - filter: Gaussian Thinning +# horizontal_mesh: 145 +# use_reduced_horizontal_grid: true +# distance_norm: geodesic +# round_horizontal_bin_count_to_nearest: true +# # partition_longitude_bins_using_mesh: true +# action: +# name: reduce obs space + + # Observation Post Filters (QC) + # ----------------------------- + obs post filters: + # Step A: Conduct observation range sanity check + # Valid range: (50, 550) + - filter: Bounds Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + minvalue: 50.00001 + maxvalue: 549.99999 + action: + name: reject + # Step B: Do initial observation error Assignment + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: assign error + error parameter vector: &{{observation_from_jcb}}_oberr [{{ get_satellite_variable(observation_from_jcb, "error") }}] + # Step C: Assign surface_water_ice_snow = 1 if surface type is sea, ice, or snow. + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/surface_water_ice_snow + type: int + value: 1 + where: + - variable: + name: GeoVaLs/water_area_fraction + minvalue: 0.99 + - variable: + name: GeoVaLs/ice_area_fraction + minvalue: 0.99 + - variable: + name: GeoVaLs/surface_snow_area_fraction + minvalue: 0.99 + where operator: or + # Step C1: Assign surface_water_ice_snow = 0 if surface type is not sea, ice, or snow. + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/surface_water_ice_snow + type: int + value: 0 + where: + - variable: + name: GeoVaLs/water_area_fraction + maxvalue: 0.99 + max_exclusive: true + - variable: + name: GeoVaLs/ice_area_fraction + maxvalue: 0.99 + max_exclusive: true + - variable: + name: GeoVaLs/surface_snow_area_fraction + maxvalue: 0.99 + max_exclusive: true + + # Step D: Get Departure ObsMinusHofx = ObsValue - HofX + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/ObsMinusHofx + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: ObsValue/brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + - name: HofX/brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + coefs: + - 1 + - -1 + # Step E: Get cloud_index ("dsi" in GSI sub "qc_mhs") + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/cloud_index + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/ObsMinusHofx + channels: [1] + - name: DerivedMetaData/ObsMinusHofx + channels: [2] + coefs: + - 0.85 + - -1 + where: + - variable: + name: DerivedMetaData/surface_water_ice_snow + is_in: 0 + # Step E1: Get cloud_index ("dsi" in GSI sub "qc_mhs") + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/cloud_index + type: float + value: 9.0 + where: + - variable: + name: DerivedMetaData/surface_water_ice_snow + is_in: 1 + - variable: + name: ObsValue/brightnessTemperature_2 + minvalue: 300.0 + # Step E2: Define 300-Obs(ch2) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/diff_300_obs2 + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: ObsValue/brightnessTemperature + channels: [2] + coefs: [-1] + intercept: 300.0 + # Step E3: Define "OmF_ch2 / (300 - Obs_ch2)" + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/omf2_diff_300_obs2 + type: float + function: + name: ObsFunction/ElementMultiply + options: + variables: + - name: DerivedMetaData/ObsMinusHofx + channels: [2] + - name: DerivedMetaData/diff_300_obs2 + exponents: [1, -1] + # Step E4: Get final 'cloud_index' ('dsi' in qc_mhs in GSI) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/cloud_index + type: float + # function = 0.13 *(tbc(1)-33.58 *tbc(2)/(h300-tb_obs(2))) in GSI + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/ObsMinusHofx + channels: [1] + - name: DerivedMetaData/omf2_diff_300_obs2 + coefs: [1, -33.58] + total coefficient: 0.13 + where: + - variable: + name: DerivedMetaData/surface_water_ice_snow + is_in: 1 + - variable: + name: ObsValue/brightnessTemperature_2 + maxvalue: 300.0 + max_exclusive: true + # Step E5: Make cloud_index >= 0 + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/cloud_index + type: float + value: 0.0 + where: + - variable: + name: DerivedMetaData/cloud_index + maxvalue: 0.0 + + # Step F: Get tpwc_index =((ObsMinusHofX_1 - 7.5*dsi)/10.0)**2+(dsi)**2 + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/tpwc_indexA + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/ObsMinusHofx + channels: [1] + - name: DerivedMetaData/cloud_index + coefs: [1, -7.5] + total coefficient: 0.1 + # Step F1: Get the final 'tpwc_index' (it is 'fact1' in qc_mhs() in GSI) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/tpwc_index + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/tpwc_indexA + - name: DerivedMetaData/cloud_index + exponents: [2, 2] + # Step H: Assign inflationFactor0 = (1 - tpwc_index^2) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/inflationFactor0 + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/tpwc_index + coefs: [-1] + exponents: [2] + intercept: 1 + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 1.0 + # Step H1: Assign inflationFactor1 = 1.0/(inflationFactor0)^(0.5) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/inflationFactor1 + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/inflationFactor0 + exponents: [-0.5] + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 0.9999999 + # Step H2: Assign inflationFactor1 = 1.0 where tpwc_index >= 1.0 + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/inflationFactor1 + type: float + value: 1.0 + where: + - variable: + name: DerivedMetaData/tpwc_index + minvalue: 1.0 + + # Step J: Initial error inflation by inflationFactor1 + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 1.0 + action: + name: inflate error + inflation variable: + name: DerivedMetaData/inflationFactor1 + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + + # Step J1: Observation error inflation based on topography check + - filter: Variable Assignment + assignments: + - name: ObsErrorFactorTopo@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsErrorFactorTopoRad@ObsFunction + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + channels: *{{observation_from_jcb}}_simulated_channels + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: inflate error + inflation variable: + name: ObsErrorFactorTopo@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 1.0 + + # Step J2: Obs error inflation based on TOA Transmittancec check + - filter: Variable Assignment + assignments: + - name: ObsErrorFactorTransmitTop@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsErrorFactorTransmitTopRad@ObsFunction + channels: *{{observation_from_jcb}}_simulated_channels + options: + channels: *{{observation_from_jcb}}_simulated_channels + + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: inflate error + inflation variable: + name: ObsErrorFactorTransmitTop@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + + # Step K: Find gross error check bounds + # Note, use DerivedMetaData/inflationFactor1 for "obserr_bound_latitude" + - filter: Variable Assignment + assignments: + - name: ObsErrorBound@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsErrorBoundMW@ObsFunction + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + channels: *{{observation_from_jcb}}_simulated_channels + obserr_bound_latitude: + name: DerivedMetaData/inflationFactor1 + obserr_bound_transmittop: + name: ObsErrorFactorTransmitTop@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + options: + channels: *{{observation_from_jcb}}_simulated_channels + obserr_bound_topo: + name: ObsErrorFactorTopo@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + error parameter vector: *{{observation_from_jcb}}_oberr + threshold: 3 + obserr_bound_max: [{{ get_satellite_variable(observation_from_jcb, "ermax") }}] + # Step K1: Gross error check + - filter: Background Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + function absolute threshold: + - name: ObsErrorBound@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: reject + + # Step K2: Toss channel 3-5 data with O-F > 2K + - filter: BlackList + where: + - variable: + name: DerivedMetaData/tpwc_index + minvalue: 1.0 + - filter: Background Check + filter variables: + - name: brightnessTemperature + channels: 3-5 + absolute threshold: 2.0 + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 1.0 + action: + name: reject + + # Step L: Conduct inter-channel check + - filter: Bounds Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + test variables: + - name: ObsFunction/InterChannelConsistencyCheck + channels: *{{observation_from_jcb}}_simulated_channels + options: + channels: *{{observation_from_jcb}}_simulated_channels + sensor: *{{observation_from_jcb}}_sensor_id + use_flag: &{{observation_from_jcb}}_active_channels [{{ get_satellite_variable(observation_from_jcb, "active") }}] + use passive_bc: true + maxvalue: 1.0e-12 + action: + name: reject + + # Step L1: Conduct Useflag check + - filter: Bounds Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + test variables: + - name: ObsFunction/ChannelUseflagCheckRad + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + channels: *{{observation_from_jcb}}_simulated_channels + use_flag: *{{observation_from_jcb}}_active_channels + minvalue: 1.0e-12 + action: + name: reject + + # Step M: Observation error inflation based on surface Jacobian check + - filter: Variable Assignment + assignments: + - name: ObsErrorFactorSurfJacobian@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsErrorFactorSurfJacobianRad@ObsFunction + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + channels: *{{observation_from_jcb}}_simulated_channels + # obserr_demisf: [0.015, 0.030, 0.020, 0.020, 0.250] + # obserr_dtempf: [0.500, 2.000, 1.000, 2.000, 5.000] + # x3 if not sea for MHS + # surface type sea, land, ice, snow, mixed + obserr_demisf: [0.015, 0.090, 0.060, 0.060, 0.750] + obserr_dtempf: [0.500, 6.000, 3.000, 6.000, 15.00] + # Step M1: Inflate observation error + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: inflate error + inflation variable: + name: ObsErrorFactorSurfJacobian@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + + # GeoVaLs for Driving observation Operators (testing mode) + # -------------------------------------------------------- + geovals: + filename: "{{atmosphere_obsdatain_path}}/{{atmosphere_obsdatain_prefix}}{{observation_from_jcb}}_geoval{{atmosphere_obsdatain_suffix}}" + + # Passed benchmark for UFO testing + # -------------------------------- + passedBenchmark: 0 diff --git a/parm/jcb-gdas/observations/atmosphere/radiance_mhs_n19.yaml.j2 b/parm/jcb-gdas/observations/atmosphere/radiance_mhs_n19.yaml.j2 new file mode 100644 index 000000000..0bf103ec1 --- /dev/null +++ b/parm/jcb-gdas/observations/atmosphere/radiance_mhs_n19.yaml.j2 @@ -0,0 +1,516 @@ +- + + # Observation Space (I/O) + # ----------------------- + obs space: + name: {{observation_from_jcb}} + obsdatain: + engine: + type: H5File + obsfile: "{{atmosphere_obsdatain_path}}/{{atmosphere_obsdatain_prefix}}{{observation_from_jcb}}{{atmosphere_obsdatain_suffix}}" + missing file action: warn + obsdataout: + engine: + type: H5File + obsfile: "{{atmosphere_obsdataout_path}}/{{atmosphere_obsdataout_prefix}}{{observation_from_jcb}}{{atmosphere_obsdataout_suffix}}" + io pool: + max pool size: 1 + simulated variables: [brightnessTemperature] + channels: &{{observation_from_jcb}}_simulated_channels {{ get_satellite_variable(observation_from_jcb, "simulated") }} + + # Observation Operator + # -------------------- + obs operator: + name: CRTM + Absorbers: [H2O, O3, CO2] + obs options: + Sensor_ID: &{{observation_from_jcb}}_sensor_id mhs_n19 + EndianType: little_endian + CoefficientPath: "{{crtm_coefficient_path}}" + linear obs operator: + Absorbers: [H2O, O3] + + # Observation Bias Correction (VarBC) + # ----------------------------------- + obs bias: + input file: "{{atmosphere_obsbiasin_path}}/{{atmosphere_obsbiasin_prefix}}{{observation_from_jcb}}{{atmosphere_obsbiasin_suffix}}" + output file: "{{atmosphere_obsbiasout_path}}/{{atmosphere_obsbiasout_prefix}}{{observation_from_jcb}}{{atmosphere_obsbiasout_suffix}}" + variational bc: + predictors: + - name: constant + - name: lapseRate + order: 2 + tlapse: &{{observation_from_jcb}}_tlapse "{{atmosphere_obsbiasin_path}}/{{atmosphere_obstlapsein_prefix}}{{observation_from_jcb}}{{atmosphere_obstlapsein_suffix}}" + - name: lapseRate + tlapse: *{{observation_from_jcb}}_tlapse + - name: emissivityJacobian + - name: sensorScanAngle + order: 4 + - name: sensorScanAngle + order: 3 + - name: sensorScanAngle + order: 2 + - name: sensorScanAngle + covariance: + minimal required obs number: 20 + variance range: [1.0e-6, 10.0] + step size: 1.0e-4 + largest analysis variance: 10000.0 + prior: + input file: "{{atmosphere_obsbiasin_path}}/{{atmosphere_obsbiascovin_prefix}}{{observation_from_jcb}}{{atmosphere_obsbiascovin_suffix}}" + inflation: + ratio: 1.1 + ratio for small dataset: 2.0 + output file: "{{atmosphere_obsbiasout_path}}/{{atmosphere_obsbiascovout_prefix}}{{observation_from_jcb}}{{atmosphere_obsbiascovout_suffix}}" + + # ------------------------ + obs pre filters: + # Remove observations from the Edge of the Scan + - filter: Domain Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + where: + - variable: + name: MetaData/sensorScanPosition + is_in: 10-81 + action: + name: reduce obs space + +# # Data Thinning +# - filter: Gaussian Thinning +# horizontal_mesh: 145 +# use_reduced_horizontal_grid: true +# distance_norm: geodesic +# round_horizontal_bin_count_to_nearest: true +# # partition_longitude_bins_using_mesh: true +# action: +# name: reduce obs space + + # Observation Post Filters (QC) + # ----------------------------- + obs post filters: + # Step A: Conduct observation range sanity check + # Valid range: (50, 550) + - filter: Bounds Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + minvalue: 50.00001 + maxvalue: 549.99999 + action: + name: reject + # Step B: Do initial observation error Assignment + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: assign error + error parameter vector: &{{observation_from_jcb}}_oberr [{{ get_satellite_variable(observation_from_jcb, "error") }}] + # Step C: Assign surface_water_ice_snow = 1 if surface type is sea, ice, or snow. + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/surface_water_ice_snow + type: int + value: 1 + where: + - variable: + name: GeoVaLs/water_area_fraction + minvalue: 0.99 + - variable: + name: GeoVaLs/ice_area_fraction + minvalue: 0.99 + - variable: + name: GeoVaLs/surface_snow_area_fraction + minvalue: 0.99 + where operator: or + # Step C1: Assign surface_water_ice_snow = 0 if surface type is not sea, ice, or snow. + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/surface_water_ice_snow + type: int + value: 0 + where: + - variable: + name: GeoVaLs/water_area_fraction + maxvalue: 0.99 + max_exclusive: true + - variable: + name: GeoVaLs/ice_area_fraction + maxvalue: 0.99 + max_exclusive: true + - variable: + name: GeoVaLs/surface_snow_area_fraction + maxvalue: 0.99 + max_exclusive: true + + # Step D: Get Departure ObsMinusHofx = ObsValue - HofX + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/ObsMinusHofx + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: ObsValue/brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + - name: HofX/brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + coefs: + - 1 + - -1 + # Step E: Get cloud_index ("dsi" in GSI sub "qc_mhs") + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/cloud_index + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/ObsMinusHofx + channels: [1] + - name: DerivedMetaData/ObsMinusHofx + channels: [2] + coefs: + - 0.85 + - -1 + where: + - variable: + name: DerivedMetaData/surface_water_ice_snow + is_in: 0 + # Step E1: Get cloud_index ("dsi" in GSI sub "qc_mhs") + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/cloud_index + type: float + value: 9.0 + where: + - variable: + name: DerivedMetaData/surface_water_ice_snow + is_in: 1 + - variable: + name: ObsValue/brightnessTemperature_2 + minvalue: 300.0 + # Step E2: Define 300-Obs(ch2) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/diff_300_obs2 + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: ObsValue/brightnessTemperature + channels: [2] + coefs: [-1] + intercept: 300.0 + # Step E3: Define "OmF_ch2 / (300 - Obs_ch2)" + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/omf2_diff_300_obs2 + type: float + function: + name: ObsFunction/ElementMultiply + options: + variables: + - name: DerivedMetaData/ObsMinusHofx + channels: [2] + - name: DerivedMetaData/diff_300_obs2 + exponents: [1, -1] + # Step E4: Get final 'cloud_index' ('dsi' in qc_mhs in GSI) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/cloud_index + type: float + # function = 0.13 *(tbc(1)-33.58 *tbc(2)/(h300-tb_obs(2))) in GSI + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/ObsMinusHofx + channels: [1] + - name: DerivedMetaData/omf2_diff_300_obs2 + coefs: [1, -33.58] + total coefficient: 0.13 + where: + - variable: + name: DerivedMetaData/surface_water_ice_snow + is_in: 1 + - variable: + name: ObsValue/brightnessTemperature_2 + maxvalue: 300.0 + max_exclusive: true + # Step E5: Make cloud_index >= 0 + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/cloud_index + type: float + value: 0.0 + where: + - variable: + name: DerivedMetaData/cloud_index + maxvalue: 0.0 + + # Step F: Get tpwc_index =((ObsMinusHofX_1 - 7.5*dsi)/10.0)**2+(dsi)**2 + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/tpwc_indexA + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/ObsMinusHofx + channels: [1] + - name: DerivedMetaData/cloud_index + coefs: [1, -7.5] + total coefficient: 0.1 + # Step F1: Get the final 'tpwc_index' (it is 'fact1' in qc_mhs() in GSI) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/tpwc_index + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/tpwc_indexA + - name: DerivedMetaData/cloud_index + exponents: [2, 2] + # Step H: Assign inflationFactor0 = (1 - tpwc_index^2) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/inflationFactor0 + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/tpwc_index + coefs: [-1] + exponents: [2] + intercept: 1 + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 1.0 + # Step H1: Assign inflationFactor1 = 1.0/(inflationFactor0)^(0.5) + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/inflationFactor1 + type: float + function: + name: ObsFunction/Arithmetic + options: + variables: + - name: DerivedMetaData/inflationFactor0 + exponents: [-0.5] + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 0.9999999 + # Step H2: Assign inflationFactor1 = 1.0 where tpwc_index >= 1.0 + - filter: Variable Assignment + assignments: + - name: DerivedMetaData/inflationFactor1 + type: float + value: 1.0 + where: + - variable: + name: DerivedMetaData/tpwc_index + minvalue: 1.0 + + # Step J: Initial error inflation by inflationFactor1 + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 1.0 + action: + name: inflate error + inflation variable: + name: DerivedMetaData/inflationFactor1 + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + + # Step J1: Observation error inflation based on topography check + - filter: Variable Assignment + assignments: + - name: ObsErrorFactorTopo@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsErrorFactorTopoRad@ObsFunction + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + channels: *{{observation_from_jcb}}_simulated_channels + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: inflate error + inflation variable: + name: ObsErrorFactorTopo@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 1.0 + + # Step J2: Obs error inflation based on TOA Transmittancec check + - filter: Variable Assignment + assignments: + - name: ObsErrorFactorTransmitTop@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsErrorFactorTransmitTopRad@ObsFunction + channels: *{{observation_from_jcb}}_simulated_channels + options: + channels: *{{observation_from_jcb}}_simulated_channels + + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: inflate error + inflation variable: + name: ObsErrorFactorTransmitTop@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + + # Step K: Find gross error check bounds + # Note, use DerivedMetaData/inflationFactor1 for "obserr_bound_latitude" + - filter: Variable Assignment + assignments: + - name: ObsErrorBound@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsErrorBoundMW@ObsFunction + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + channels: *{{observation_from_jcb}}_simulated_channels + obserr_bound_latitude: + name: DerivedMetaData/inflationFactor1 + obserr_bound_transmittop: + name: ObsErrorFactorTransmitTop@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + options: + channels: *{{observation_from_jcb}}_simulated_channels + obserr_bound_topo: + name: ObsErrorFactorTopo@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + error parameter vector: *{{observation_from_jcb}}_oberr + threshold: 3 + obserr_bound_max: [{{ get_satellite_variable(observation_from_jcb, "ermax") }}] + # Step K1: Gross error check + - filter: Background Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + function absolute threshold: + - name: ObsErrorBound@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: reject + + # Step K2: Toss channel 3-5 data with O-F > 2K + - filter: BlackList + where: + - variable: + name: DerivedMetaData/tpwc_index + minvalue: 1.0 + - filter: Background Check + filter variables: + - name: brightnessTemperature + channels: 3-5 + absolute threshold: 2.0 + where: + - variable: + name: DerivedMetaData/tpwc_index + maxvalue: 1.0 + action: + name: reject + + # Step L: Conduct inter-channel check + - filter: Bounds Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + test variables: + - name: ObsFunction/InterChannelConsistencyCheck + channels: *{{observation_from_jcb}}_simulated_channels + options: + channels: *{{observation_from_jcb}}_simulated_channels + sensor: *{{observation_from_jcb}}_sensor_id + use_flag: &{{observation_from_jcb}}_active_channels [{{ get_satellite_variable(observation_from_jcb, "active") }}] + use passive_bc: true + maxvalue: 1.0e-12 + action: + name: reject + + # Step L1: Conduct Useflag check + - filter: Bounds Check + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + test variables: + - name: ObsFunction/ChannelUseflagCheckRad + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + channels: *{{observation_from_jcb}}_simulated_channels + use_flag: *{{observation_from_jcb}}_active_channels + minvalue: 1.0e-12 + action: + name: reject + + # Step M: Observation error inflation based on surface Jacobian check + - filter: Variable Assignment + assignments: + - name: ObsErrorFactorSurfJacobian@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + type: float + function: + name: ObsErrorFactorSurfJacobianRad@ObsFunction + channels: *{{observation_from_jcb}}_simulated_channels + options: + sensor: *{{observation_from_jcb}}_sensor_id + channels: *{{observation_from_jcb}}_simulated_channels + # obserr_demisf: [0.015, 0.030, 0.020, 0.020, 0.250] + # obserr_dtempf: [0.500, 2.000, 1.000, 2.000, 5.000] + # x3 if not sea for MHS + # surface type sea, land, ice, snow, mixed + obserr_demisf: [0.015, 0.090, 0.060, 0.060, 0.750] + obserr_dtempf: [0.500, 6.000, 3.000, 6.000, 15.00] + # Step M1: Inflate observation error + - filter: Perform Action + filter variables: + - name: brightnessTemperature + channels: *{{observation_from_jcb}}_simulated_channels + action: + name: inflate error + inflation variable: + name: ObsErrorFactorSurfJacobian@DerivedMetaData + channels: *{{observation_from_jcb}}_simulated_channels + + # GeoVaLs for Driving observation Operators (testing mode) + # -------------------------------------------------------- + geovals: + filename: "{{atmosphere_obsdatain_path}}/{{atmosphere_obsdatain_prefix}}{{observation_from_jcb}}_geoval{{atmosphere_obsdatain_suffix}}" + + # Passed benchmark for UFO testing + # -------------------------------- + passedBenchmark: 0