Skip to content

Commit

Permalink
Add CX and varobs for Surfacecloud (#175)
Browse files Browse the repository at this point in the history
* Added namelist files for SurfaceCloud to both varobs and cx, and added varobs writer functionality to provide obs value and relevant obs error

* Changes for SurfaceCloud. Updated python script and run it for the new settings. Added Varfield 15 (cloud) and have needed to add Cx field cloud_layer too. Added first attempt at cxwriter and varobswriter yaml files for SurfaceCloud.

* Remove files that should not have been changed, and some tweaks to the python script for SurfaceCloud tests

* Add files created by running python code

* Added yaml files and relevant namelist files for testing

* Change list of simulated and observed variables in surfacecloud varobswriter

* Changed obs error for cloud fraction column to be in DerivedObsError/CloudError

* Added missing ObsValue/stationPressure field to varobs netCDF for surfacecloud

* Added Cloud as derived variable

* Update to CMakeLists to include tests for varfield 15 and cx upper air field 15

* Small change to CMakeLists in etc directory to change order of namelists

* Correction to varobs 15 setup

* Change to PLevels

* Update cloud_layer in cxfields mod file

* Change VarField 15 (cloud) to have use_chans instead of use_levels in unit test

* New netCDF file for VarField 15 (cloud)

* Fix for the varobswriter for varfield cloud

* Updates to cx and varobs writer ctest yamls

* Updates to ctest yaml files

* Updates for ctest yamls

* Update to ctest varobswriter yaml

* added derived obs

* update 015_VarField_cloud.yaml (issue with missing data in ob value)

* Cloud update

* working for test_opsinputs_varobswriter_015_VarField_cloud

* not sure if any better, but needed to checkout dev

* include yaml change (missing in previous commit)

* change to surfacecloud namelist for Cx ctest

* add to cmakelist

* set CXX17 standard

* change cloud to cloudAmount

* switch off cxx extensions

* change name

* change in src/opsinputs/opsinputs_varobswriter_mod.F90

* fixed varobswriter_ukvnamelist_surfacecloud

---------

Co-authored-by: fabien-mo <[email protected]>
Co-authored-by: Yaswant Pradhan <[email protected]>
  • Loading branch information
3 people authored Aug 16, 2023
1 parent d0a04be commit 65e4e93
Show file tree
Hide file tree
Showing 18 changed files with 260 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Varfields.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
| 10 | `VarField_britemp` | `CorBriTemp(:,:)` | bias-corrected brightness temperatures | `BiasCorrObsValue/brightnessTemperature` | |
| 11 | `VarField_tskin` | `Tskin(:)` | skin temperature | `OneDVar/skinTemperature` | |
| 12 | `VarField_gpstzdelay` | `gpstzdelay(:)`| Ground based GNSS Total Zenith Delay | `BiasCorrObsValue/zenithTotalDelay` | |
| 15 | `VarField_cloud` | | | | Implement |
| 15 | `VarField_cloud` | `cloud(:,:)` | cloud fraction | `DerivedObsValue/cloudAmount`| |
| 16 | `VarField_rainrate` | | | | Implement |
| 17 | `VarField_mwemiss` | `Emissivity(:,:)` | surface emissivity | `Emiss/emissivity` | |
| 18 | `VarField_tcozone` | `TCozone(:)` | total column ozone (Du) | `MetaData/ozoneTotal` | |
Expand Down
2 changes: 1 addition & 1 deletion deps/ops/code/OpsMod_Varobs/Ops_SetupVarArray.inc
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ DO Ivar = 1, NumValidVarFields
RArrVrbl1d => Ob % AMSUb_Temp
CASE (VarField_cloud)
ObHdrVrbl = Ob % header % Cloud
ObVrblMulti => Ob % Cloud
ObVrblMulti => Ob % Cloud(:,:)
Pge_2D => Pge % Cloud
CASE (VarField_rainrate)
ObHdrVrbl = Ob % header % Rainrate
Expand Down
8 changes: 8 additions & 0 deletions etc/ukv/cx/SurfaceCloud.nl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
&CXControlNL
! Quantities for which H(x) is not calculated so GeoVaLs are used to produced CX columns.
! - multi-level
! 4 = theta, 10 = q, 12 = qcf, 254 = qcl, 407 = p, 9201 = cloud_layer
! - single-level
! 1 = pstar, 31 = seaice, 33 = orog, 9217 = CloudAmount
CxFields=1,4,10,12,31,33,254,407,9201,9217
/
3 changes: 3 additions & 0 deletions etc/ukv/varobs/SurfaceCloud.nl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
&VarobsControlNL
Varfields=15
/
2 changes: 1 addition & 1 deletion src/opsinputs/opsinputs_cxfields_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ module opsinputs_cxfields_mod
character(len=*), parameter, public :: opsinputs_cxfields_RainRate_layer = opsinputs_cxfields_unknown
character(len=*), parameter, public :: opsinputs_cxfields_cloud_conv = opsinputs_cxfields_unknown
character(len=*), parameter, public :: opsinputs_cxfields_qc_conv = opsinputs_cxfields_unknown
character(len=*), parameter, public :: opsinputs_cxfields_cloud_layer = opsinputs_cxfields_unknown
character(len=*), parameter, public :: opsinputs_cxfields_cloud_layer = "cloud_layer"
character(len=*), parameter, public :: opsinputs_cxfields_ozone = opsinputs_cxfields_unknown
character(len=*), parameter, public :: opsinputs_cxfields_qcf = var_cli
character(len=*), parameter, public :: opsinputs_cxfields_qcl = var_clw
Expand Down
4 changes: 4 additions & 0 deletions src/opsinputs/opsinputs_varobswriter_mod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,10 @@ subroutine opsinputs_varobswriter_populateobservations( &
! TODO(someone): handle this varfield
! call Ops_Alloc(Ob % Header % AMSUb_Temp, "AMSUb_Temp", Ob % Header % NumObsLocal, Ob % AMSUb_Temp)
case (VarField_cloud)
call opsinputs_fill_fillelementtype2dfromnormalvariablewithlevels( &
Ob % Header % Cloud, "Cloud", Ob % Header % NumObsLocal, Ob % Cloud, &
ObsSpace, self % modlevs, "cloudAmount_", "DerivedObsValue", self % GeoVaLsAreTopToBottom, &
"cloudAmount_", "DerivedObsError")
! TODO(someone): handle this varfield
! call Ops_Alloc(Ob % Header % Cloud, "Cloud", Ob % Header % NumObsLocal, Ob % Cloud)
case (VarField_rainrate)
Expand Down
15 changes: 15 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ ADD_WRITER_TEST(NAME varobswriter_011_VarField_tskin
ADD_WRITER_TEST(NAME varobswriter_012_VarField_gpstzdelay
YAML 012_VarField_gpstzdelay.yaml
DATA 012_VarField_gpstzdelay.nc4)
ADD_WRITER_TEST(NAME varobswriter_015_VarField_cloud
YAML 015_VarField_cloud.yaml
DATA 015_VarField_cloud.nc4)
ADD_WRITER_TEST(NAME varobswriter_017_VarField_mwemiss
YAML 017_VarField_mwemiss.yaml
NAMELIST VarObsWriterNamelists_017_VarField_mwemiss/AMSUB.nl
Expand Down Expand Up @@ -347,6 +350,10 @@ ADD_WRITER_TEST(NAME varobswriter_ukvnamelist_sonde
YAML varobswriter_ukvnamelist_sonde.yaml
NAMELIST ../../etc/ukv/varobs/Sonde.nl
DATA varobs_ukvnamelist_sonde.nc4)
ADD_WRITER_TEST(NAME varobswriter_ukvnamelist_surfacecloud
YAML varobswriter_ukvnamelist_surfacecloud.yaml
NAMELIST ../../etc/ukv/varobs/SurfaceCloud.nl
DATA varobs_ukvnamelist_surfacecloud.nc4)

### CxWriter tests

Expand Down Expand Up @@ -429,6 +436,10 @@ ADD_WRITER_TEST(NAME cxwriter_011_UpperAirCxField_P
YAML 011_UpperAirCxField_P.yaml
NAMELIST CxWriterNamelists_011_UpperAirCxField_P/AMSUB.nl
DATA 011_UpperAirCxField_P.nc4 dummy.nc4)
ADD_WRITER_TEST(NAME cxwriter_015_UpperAirCxField_cloud_layer
YAML 015_UpperAirCxField_cloud_layer.yaml
NAMELIST CxWriterNamelists_015_UpperAirCxField_cloud_layer/SurfaceCloud.nl
DATA 015_UpperAirCxField_cloud_layer.nc4 dummy.nc4)
ADD_WRITER_TEST(NAME cxwriter_029_UpperAirCxField_qcf
YAML 029_UpperAirCxField_qcf.yaml
NAMELIST CxWriterNamelists_029_UpperAirCxField_qcf/AMSUB.nl
Expand Down Expand Up @@ -618,6 +629,10 @@ ADD_WRITER_TEST(NAME cxwriter_ukvnamelist_sonde
YAML cxwriter_ukvnamelist_sonde.yaml
NAMELIST ../../etc/ukv/cx/Sonde.nl
DATA cx_ukvnamelist_sonde.nc4 dummy.nc4)
ADD_WRITER_TEST(NAME cxwriter_ukvnamelist_surfacecloud
YAML cxwriter_ukvnamelist_surfacecloud.yaml
NAMELIST ../../etc/ukv/cx/SurfaceCloud.nl
DATA cx_ukvnamelist_surfacecloud.nc4 dummy.nc4)

### Tests of auxiliary classes

Expand Down
21 changes: 20 additions & 1 deletion test/generate_unittest_netcdfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,7 @@ def copy_var_to_var(Group, invarname, outvarname, filename):
output_1d_simulated_var_to_netcdf('precipitableWater', 'testinput/007_VarField_tcwv.nc4')
output_2d_simulated_var_to_netcdf('brightnessTemperature', 'testinput/010_VarField_britemp.nc4', with_bias=True)
output_1d_normal_var_to_netcdf ('skinTemperature', 'OneDVar', 'testinput/011_VarField_tskin.nc4')
output_2d_normal_var_to_netcdf ('cloudAmount', 'DerivedObsValue', 'testinput/015_VarField_cloud.nc4', use_chans=True)
output_2d_normal_var_to_netcdf ('emissivity', 'Emiss', 'testinput/017_VarField_mwemiss.nc4', use_chans=True)
output_1d_normal_var_to_netcdf ('ozoneTotal', 'MetaData', 'testinput/018_VarField_tcozone.nc4')
output_1d_normal_var_to_netcdf ('sensorZenithAngle', 'MetaData', 'testinput/019_VarField_satzenith.nc4')
Expand Down Expand Up @@ -765,6 +766,13 @@ def copy_var_to_var(Group, invarname, outvarname, filename):
copy_var_to_var('ObsValue', 'potentialTemperature', 'airTemperature', 'testinput/varobs_ukvnamelist_sonde.nc4')
copy_var_to_var('ObsError', 'potentialTemperature', 'airTemperature', 'testinput/varobs_ukvnamelist_sonde.nc4')

# SurfaceCloud - UKV
output_full_varobs_to_netcdf(['MetaData/latitude',
'MetaData/longitude'],
['ObsValue/cloud_layer', 'DerivedObsValue/cloudAmount', 'DerivedObsError/cloudAmount'],
[],
'testinput/varobs_ukvnamelist_surfacecloud.nc4')

# Scatwind
output_full_varobs_to_netcdf(['MetaData/latitude', 'MetaData/longitude'],
['ObsValue/windEastward', 'ObsError/windEastward', 'GrossErrorProbability/windEastward',
Expand Down Expand Up @@ -830,6 +838,7 @@ def copy_var_to_var(Group, invarname, outvarname, filename):
output_2d_geoval_to_netcdf ('specific_humidity', 'testinput/005_UpperAirCxField_q.nc4')
output_2d_geoval_to_netcdf ('air_pressure', 'testinput/033_UpperAirCxField_p_bar.nc4')
output_2d_geoval_to_netcdf ('air_pressure_levels', 'testinput/011_UpperAirCxField_P.nc4')
output_2d_geoval_to_netcdf ('cloud_layer', 'testinput/015_UpperAirCxField_cloud_layer.nc4')
output_2d_geoval_to_netcdf ('mass_content_of_cloud_ice_in_atmosphere_layer', 'testinput/029_UpperAirCxField_qcf.nc4')
output_2d_geoval_to_netcdf ('mass_content_of_cloud_liquid_water_in_atmosphere_layer', 'testinput/030_UpperAirCxField_qcl.nc4')
output_2d_geoval_to_netcdf ('cloud_volume_fraction_in_atmosphere_layer', 'testinput/031_UpperAirCxField_cloud_bulk.nc4')
Expand Down Expand Up @@ -904,7 +913,7 @@ def copy_var_to_var(Group, invarname, outvarname, filename):
'mass_content_of_cloud_liquid_water_in_atmosphere_layer', 'air_pressure_levels',
'cloud_volume_fraction_in_atmosphere_layer', 'liquid_cloud_volume_fraction_in_atmosphere_layer', 'ice_cloud_volume_fraction_in_atmosphere_layer'],
'testinput/cx_globalnamelist_ssmis.nc4')
# MWSFY3
output_full_cx_to_netcdf(['skin_temperature','ice_area_fraction','surface_altitude','surface_pressure','uwind_at_10m',
'vwind_at_10m','surface_temperature','relative_humidity_2m','surface_pressure_at_mean_sea_level'],
Expand Down Expand Up @@ -947,6 +956,16 @@ def copy_var_to_var(Group, invarname, outvarname, filename):
'ice_cloud_volume_fraction_in_atmosphere_layer'],
'testinput/cx_ukvnamelist_sonde.nc4')

# SurfaceCloud - UKV
output_full_cx_to_netcdf(['surface_altitude',
'surface_pressure',
'ice_area_fraction',
'total_cloud_amount'],
['potential_temperature', 'specific_humidity', 'air_pressure_levels', 'cloud_layer',
'mass_content_of_cloud_ice_in_atmosphere_layer',
'mass_content_of_cloud_liquid_water_in_atmosphere_layer'],
'testinput/cx_ukvnamelist_surfacecloud.nc4')

# SatTCWV
output_full_cx_to_netcdf(['surface_altitude', 'surface_pressure', 'ice_area_fraction', 'total_cloud_amount'],
['potential_temperature', 'specific_humidity', 'air_pressure_levels', 'mass_content_of_cloud_ice_in_atmosphere_layer',
Expand Down
Binary file not shown.
40 changes: 40 additions & 0 deletions test/testinput/015_UpperAirCxField_cloud_layer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
window begin: 2018-01-01T00:00:00Z
window end: 2018-01-01T01:00:00Z

observations:
- obs space:
name: SurfaceCloud
obsdatain:
engine:
type: H5File
obsfile: Data/dummy.nc4
simulated variables: [dummy]
geovals:
filename: Data/015_UpperAirCxField_cloud_layer.nc4
obs filters:
# Set the flag of observations with missing values to "pass": we want to check if these
# values are encoded correctly in the Cx file.
- filter: Reset Flags to Pass
flags_to_reset: [10, 15] # missing, Hfailed
# Reject observation 3: we want to check if it is omitted from the Cx file, as expected.
- filter: Domain Check
where:
- variable:
name: MetaData/latitude
minvalue: 0.0
- filter: Cx Writer
namelist_directory: testinput/CxWriterNamelists_015_UpperAirCxField_cloud_layer
reject_obs_with_any_variable_failing_qc: true
general_mode: debug
IC_PLevels: 5
- filter: Cx Checker
expected_surface_variables: []
expected_upper_air_variables: ["15"] # IndexCxcloud_layer
expected_main_table_columns:
- # batch 1
- ["1.10", "1.20", "1.30"] # column 1
- ["2.10", "**********", "2.30"] # column 2 (the asterisks represent a missing float)
- ["4.10", "4.20", "4.30"] # column 3
HofX: ObsValue # just a placeholder -- not used, but needed to force calls to postFilter.
benchmarkFlag: 1000 # just to keep the ObsFilters test happy
flaggedBenchmark: 0
Binary file added test/testinput/015_VarField_cloud.nc4
Binary file not shown.
58 changes: 58 additions & 0 deletions test/testinput/015_VarField_cloud.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
window begin: 2018-01-01T00:00:00Z
window end: 2018-01-01T02:00:00Z

observations:
- obs space:
name: SurfaceCloud
obsdatain:
engine:
type: H5File
obsfile: Data/015_VarField_cloud.nc4
simulated variables: [dummy]
channels: 1-3
obs filters:
# Set the flag of observations with missing values to "pass": we want to check if these
# values are encoded correctly in the VarObsFile.
- filter: Reset Flags to Pass
flags_to_reset: [10, 15] # missing, Hfailed
# Reject observation 3: we want to check if it is omitted from the VarObs file, as expected.
- filter: Domain Check
where:
- variable:
name: MetaData/latitude
minvalue: 0.0
- filter: VarObs Writer
namelist_directory: ../etc/ukv/varobs
general_mode: debug
IC_PLevels: 3
geovals_are_top_to_bottom: false
- filter: VarObs Checker
expected_main_table_columns:
# In the arrays below, rows denote locations and columns channels.
field: ["15", "15", "15",
"15", "15", "15",
"15", "15", "15",
"15", "15", "15"]
ob value: ["4.10000" ,"5.10000","6.10000",
"-1073741824.00000","5.20000","6.20000",
"4.30000" ,"5.30000","6.30000",
"4.40000" ,"5.40000","6.40000"]
lat: ["21.00000", "21.00000", "21.00000",
"22.00000", "22.00000", "22.00000",
"-23.00000", "-23.00000", "-23.00000",
"24.00000", "24.00000", "24.00000"]
lon: ["31.00000", "31.00000", "31.00000",
"32.00000", "32.00000", "32.00000",
"33.00000", "33.00000", "33.00000",
"34.00000", "34.00000", "34.00000"]
time: ["-3540.00000", "-3540.00000", "-3540.00000",
"-3480.00000", "-3480.00000", "-3480.00000",
"-3420.00000", "-3420.00000", "-3420.00000",
"-3360.00000", "-3360.00000", "-3360.00000"]
Callsign: ["station_1", "station_1", "station_1",
"station_2", "station_2", "station_2",
"station_3", "station_3", "station_3",
"station_4", "station_4", "station_4"]
HofX: ObsValue # just a placeholder -- not used, but needed to force calls to postFilter.
benchmarkFlag: 1000 # just to keep the ObsFilters test happy
flaggedBenchmark: 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
&CXControlNL
CxFields=9201
/
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
&VarobsControlNL
Varfields=15
/
Binary file added test/testinput/cx_ukvnamelist_surfacecloud.nc4
Binary file not shown.
46 changes: 46 additions & 0 deletions test/testinput/cxwriter_ukvnamelist_surfacecloud.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
window begin: 2018-01-01T00:00:00Z
window end: 2018-01-01T01:00:00Z

observations:
- obs space:
name: SurfaceCloud
obsdatain:
engine:
type: H5File
obsfile: Data/dummy.nc4
simulated variables: [dummy]
geovals:
filename: Data/cx_ukvnamelist_surfacecloud.nc4
obs filters:
# Set the flag of observations with missing values to "pass": we want to check if these
# values are encoded correctly in the Cx file.
- filter: Reset Flags to Pass
flags_to_reset: [10] # missing
# Reject observation 3: we want to check if it is omitted from the Cx file, as expected.
- filter: Domain Check
where:
- variable:
name: MetaData/latitude
minvalue: 0.0
- filter: Cx Writer
namelist_directory: ../etc/ukv/cx
reject_obs_with_any_variable_failing_qc: true
general_mode: debug
geovals_are_top_to_bottom: false
- filter: Cx Checker
expected_surface_variables: ["1","2","17","24"]
expected_upper_air_variables: ["1","5","11","15","29","30"]
expected_main_table_columns:
- # observation 3 is rejected by the tests above hence only 3 (1,2,4) columns
- ["7.10","17.10","27.10","37.10","1.30","1.20","1.10","11.30",
"11.20","11.10","21.30","21.20","21.10","31.30","31.20","31.10",
"41.30","41.20","41.10","51.30","51.20","51.10"]
- ["**********","**********","**********","**********","2.30","**********","2.10","12.30",
"**********","12.10","22.30","**********","22.10","32.30","**********","32.10","42.30",
"**********","42.10","52.30","**********","52.10"]
- ["7.40","17.40","27.40","37.40","4.30","4.20","4.10","14.30",
"14.20","14.10","24.30","24.20","24.10","34.30","34.20","34.10",
"44.30","44.20","44.10","54.30","54.20","54.10"]
HofX: ObsValue # just a placeholder -- not used""but needed to force calls to postFilter.
benchmarkFlag: 1000 # just to keep the ObsFilters test happy
flaggedBenchmark: 0
Binary file not shown.
57 changes: 57 additions & 0 deletions test/testinput/varobswriter_ukvnamelist_surfacecloud.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
window begin: 2018-01-01T00:00:00Z
window end: 2018-01-01T02:00:00Z

observations:
- obs space:
name: SurfaceCloud
obsdatain:
engine:
type: H5File
obsfile: Data/varobs_ukvnamelist_surfacecloud.nc4
simulated variables: [cloud_layer, cloudAmount]
observed variables: []
derived variables: [cloud_layer, cloudAmount]
channels: 1-3
obs filters:
# Set the flag of observations with missing values to "pass": we want to check if these
# values are encoded correctly in the VarObsFile.
- filter: Reset Flags to Pass
flags_to_reset: [10] # missing
# Blacklist all missing entries in the original profiles (i.e. observation 2)
# This must be run after the Reset Flags to Pass filter,
# which sets the flags of any missing values in the original profiles
# to 'pass'. Therefore this filter is run with the 'defer to post' option set to true.
- filter: BlackList
where:
- variable:
name: MetaData/latitude
is_not_defined:
defer to post: true
- filter: VarObs Writer
namelist_directory: ../etc/ukv/varobs
general_mode: debug
IC_PLevels: 3
reject_obs_with_all_variables_failing_qc: true
- filter: VarObs Checker
expected_main_table_columns:
# Rows are locations, columns are filter variables
# The blacklist prevents the missing ob from being written out
field: [15,15,15,
15,15,15,
15,15,15,
15,15,15]
ob value: ["11.30000","11.20000","11.10000",
"12.30000","-1073741824.00000","12.10000",
"13.30000","13.20000","13.10000",
"14.30000","14.20000","14.10000"]
lat: ["7.10000","7.10000","7.10000",
"-1073741824.00000","-1073741824.00000","-1073741824.00000",
"7.30000","7.30000","7.30000",
"7.40000","7.40000","7.40000"]
lon: ["17.10000","17.10000","17.10000",
"-1073741824.00000","-1073741824.00000","-1073741824.00000",
"17.30000","17.30000","17.30000",
"17.40000","17.40000","17.40000"]
HofX: ObsValue # just a placeholder -- not used, but needed to force calls to postFilter.
benchmarkFlag: 1000 # just to keep the ObsFilters test happy
flaggedBenchmark: 0

0 comments on commit 65e4e93

Please sign in to comment.