8 #ifndef TEST_UFO_CONVENTIONALPROFILEPROCESSING_H_
9 #define TEST_UFO_CONVENTIONALPROFILEPROCESSING_H_
18 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
20 #include "eckit/config/LocalConfiguration.h"
21 #include "eckit/testing/Test.h"
22 #include "ioda/ObsDataVector.h"
23 #include "ioda/ObsSpace.h"
24 #include "ioda/ObsVector.h"
25 #include "oops/mpi/mpi.h"
26 #include "oops/runs/Test.h"
27 #include "oops/util/Expect.h"
28 #include "oops/util/FloatCompare.h"
29 #include "test/TestEnvironment.h"
34 #include "ufo/GeoVaLs.h"
35 #include "ufo/ObsDiagnostics.h"
60 util::DateTime bgn(conf.getString(
"window begin"));
61 util::DateTime end(conf.getString(
"window end"));
63 const eckit::LocalConfiguration obsSpaceConf(conf,
"obs space");
64 ioda::ObsTopLevelParameters obsParams;
65 obsParams.validateAndDeserialize(obsSpaceConf);
66 ioda::ObsSpace obsspace(obsParams, oops::mpi::world(), bgn, end, oops::mpi::myself());
72 ioda::ObsVector hofx(obsspace);
74 ioda::ObsVector bias(obsspace);
77 const eckit::LocalConfiguration obsdiagconf(conf,
"obs diagnostics");
78 std::vector<eckit::LocalConfiguration> varconfs;
79 obsdiagconf.get(
"variables", varconfs);
81 const ObsDiagnostics obsdiags(obsdiagconf, obsspace, diagvars.toOopsVariables());
84 obsspace, obsspace.obsvariables(),
"ObsError"));
87 obsspace, obsspace.obsvariables()));
89 const eckit::LocalConfiguration filterConf(conf,
"Conventional Profile Processing");
91 filterParameters.validateAndDeserialize(filterConf);
97 bool expectThrowOnInstantiation = conf.getBool(
"ExpectThrowOnInstantiation",
false);
98 bool expectThrowDuringOperation = conf.getBool(
"ExpectThrowDuringOperation",
false);
100 if (expectThrowOnInstantiation) {
111 const bool ignoreGeoVaLs = conf.getBool(
"IgnoreGeoVaLs",
false);
113 std::unique_ptr <GeoVaLs> geovals;
114 if (!ignoreGeoVaLs && geovars.size() > 0) {
115 const eckit::LocalConfiguration geovalsConf(conf,
"geovals");
116 geovals.reset(
new GeoVaLs(geovalsConf, obsspace, geovars));
118 geovals.reset(
new GeoVaLs(obsspace.distribution(), oops::Variables()));
123 if (expectThrowDuringOperation)
124 EXPECT_THROWS(filter.
postFilter(hofx, bias, obsdiags));
131 const bool bypassMismatchComparison = conf.getBool(
"BypassMismatchComparison",
false);
134 if (!bypassMismatchComparison) {
136 EXPECT_EQUAL(nMM, 0);
142 const bool addDuplicateCheck = conf.getBool(
"AddDuplicateCheck",
false);
143 if (addDuplicateCheck) {
149 const bool getWrongType = conf.getBool(
"GetWrongType",
false);
152 options.deserialize(conf);
159 std::vector<bool> apply(obsspace.nlocs(),
true);
160 std::vector<std::vector<bool>> flagged;
173 const bool ManualFlagModification = conf.getBool(
"ManualFlagModification",
false);
174 if (ManualFlagModification) {
176 options.deserialize(conf);
182 std::vector<bool> apply(obsspace.nlocs(),
true);
183 std::vector<std::vector<bool>> flagged;
197 std::vector <int> &ReportFlags =
199 std::vector <int> &tFlags =
201 std::vector <int> &rhFlags =
203 std::vector <int> &uFlags =
205 std::vector <int> &zFlags =
207 std::vector <int> &timeFlags =
227 profileCheckTime.
runCheck(profileDataHandler);
233 profileCheckBackgroundT.
runCheck(profileDataHandler);
234 profileCheckBackgroundRH.
runCheck(profileDataHandler);
235 profileCheckBackgroundUV.
runCheck(profileDataHandler);
236 profileCheckBackgroundZ.
runCheck(profileDataHandler);
240 const bool testProfileVerticalInterpolation =
241 conf.getBool(
"testProfileVerticalInterpolation",
false);
242 if (testProfileVerticalInterpolation) {
244 options.deserialize(conf);
246 std::vector<bool> apply(obsspace.nlocs(),
true);
247 std::vector<std::vector<bool>> flagged;
255 const auto interpMethodNames = conf.getStringVector(
"interpMethodNames");
256 const auto coordOrderNames = conf.getStringVector(
"coordOrderNames");
257 const auto outOfBoundsNames = conf.getStringVector(
"outOfBoundsNames");
259 for (
size_t jprof = 0; jprof < obsspace.nrecs(); ++jprof) {
262 const std::string interpMethodName = interpMethodNames[jprof];
263 const std::string coordOrderName = coordOrderNames[jprof];
264 const std::string outOfBoundsName = outOfBoundsNames[jprof];
267 std::vector <float> orogGeoVaLs(obsspace.nlocs(), 0.0);
269 std::vector <float> zRhoGeoVaLs;
270 std::vector <float> zThetaGeoVaLs;
277 if (coordOrderName ==
"Descending")
281 std::vector <float> pressureGeoVaLs(obsspace.nlocs(), 0.0);
283 std::vector <float> pressureGeoVaLs_column;
284 for (
int jlev = 0; jlev < gvnlevs; ++jlev) {
286 pressureGeoVaLs_column.push_back(pressureGeoVaLs[0]);
294 if (interpMethodName ==
"LogLinear")
297 if (coordOrderName ==
"Descending")
300 if (outOfBoundsName ==
"SetMissing")
302 if (outOfBoundsName ==
"Extrapolate")
307 pressureGeoVaLs_column,
315 const std::string expectedPressureName =
"OPS_" +
317 const auto &expected_pressures = profileDataHandler.
get<
float>(expectedPressureName);
318 for (
size_t jlev = 0; jlev < pressures.size(); ++jlev)
319 EXPECT(oops::is_close_relative(pressures[jlev], expected_pressures[jlev], 1e-5f));
324 const bool testProfileVerticalAveraging =
325 conf.getBool(
"testProfileVerticalAveraging",
false);
326 if (testProfileVerticalAveraging) {
328 options.deserialize(conf);
330 std::vector<bool> apply(obsspace.nlocs(),
true);
331 std::vector<std::vector<bool>> flagged;
338 for (
size_t jprof = 0; jprof < obsspace.nrecs(); ++jprof) {
345 const auto &coordOut = profileDataHandler.
get<
float>
347 const float DZFrac = 0.5;
351 std::vector <int> flagsOut;
352 std::vector <float> valuesOut;
354 std::vector<float> ZMax;
355 std::vector<float> ZMin;
372 const auto &expected_flagsOut =
373 profileDataHandler.
get<
int>(
"OPS_eastward_wind@ModelLevelsQCFlags");
374 for (
size_t jlev = 0; jlev < flagsOut.size(); ++jlev)
375 EXPECT(flagsOut[jlev] == expected_flagsOut[jlev]);
376 const auto &expected_valuesOut =
377 profileDataHandler.
get<
float>(
"OPS_eastward_wind@ModelLevelsDerivedValue");
378 for (
size_t jlev = 0; jlev < flagsOut.size(); ++jlev)
379 EXPECT(oops::is_close_relative(valuesOut[jlev], expected_valuesOut[jlev], 1e-4f));
380 const auto &expected_ZMin =
381 profileDataHandler.
get<
float>(
"OPS_LogP_u_Min@ModelLevelsDerivedValue");
382 for (
size_t jlev = 0; jlev < ZMin.size(); ++jlev)
383 EXPECT(oops::is_close_relative(ZMin[jlev], expected_ZMin[jlev], 1e-14f));
384 const auto &expected_ZMax =
385 profileDataHandler.
get<
float>(
"OPS_LogP_u_Max@ModelLevelsDerivedValue");
386 for (
size_t jlev = 0; jlev < ZMax.size(); ++jlev)
387 EXPECT(oops::is_close_relative(ZMax[jlev], expected_ZMax[jlev], 1e-14f));
392 const bool testProfileDataHolder =
393 conf.getBool(
"testProfileDataHolder",
false);
394 if (testProfileDataHolder) {
396 options.deserialize(conf);
398 std::vector<bool> apply(obsspace.nlocs(),
true);
399 std::vector<std::vector<bool>> flagged;
423 EXPECT_THROWS(profileDataHolder.
get<
int>(
"wrong@MetaData"));
439 std::vector <int> int1 {1};
440 profileDataHolder.
set<
int>(
"test", std::move(int1));
441 std::vector <int> int2 {1};
442 profileDataHolder.
set<
int>(
"test", std::move(int2));
448 std::string
testid()
const override {
return "ufo::test::ConventionalProfileProcessing";}
451 std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
453 const eckit::LocalConfiguration conf(::test::TestEnvironment::config());
454 for (
const std::string & testCaseName : conf.keys())
456 const eckit::LocalConfiguration testCaseConf(::test::TestEnvironment::config(), testCaseName);
457 ts.emplace_back(
CASE(
"ufo/ConventionalProfileProcessing/" + testCaseName, testCaseConf)
Conventional profile processing.
std::vector< int > getMismatches() const
Options controlling the operation of the ConventionalProfileProcessing filter.
DataHandlerParameters DHParameters
Parameters related to profile data handler.
ModelParameters ModParameters
Parameters related to the model.
Retrieve and store data for entire sample. This class uses lazy loading; vectors of variables are ret...
std::vector< T > & get(const std::string &fullname)
void priorFilter(const GeoVaLs &) override
void postFilter(const ioda::ObsVector &, const ioda::ObsVector &, const ObsDiagnostics &) override
void preProcess() override
oops::Variables requiredVars() const override
Profile QC: compare geopotential height data against model background values using a Bayesian method....
void runCheck(ProfileDataHandler &profileDataHandler) override
Run check.
Profile QC: compare relative humidity data against model background values using a Bayesian method....
void runCheck(ProfileDataHandler &profileDataHandler) override
Run check.
Profile QC: compare temperature data with model background values using a Bayesian method....
void runCheck(ProfileDataHandler &profileDataHandler) override
Run check.
Profile QC: compare wind speed data against model background values using a Bayesian method....
void runCheck(ProfileDataHandler &profileDataHandler) override
Run check.
Profile QC: reject data which are outside the assimilation time window. Also, if requested,...
void runCheck(ProfileDataHandler &profileDataHandler) override
Run check.
Profile QC check validator.
Retrieve and store data for individual profiles. To do this, first the vector of values in the entire...
std::vector< T > & get(const std::string &fullname)
void initialiseNextProfile()
Profile data holder class.
std::vector< float > & getObsDiagVector(const std::string &fullname)
Retrieve an ObsDiag vector if it is present. If not, throw an exception.
std::vector< T > & get(const std::string &fullname)
Retrieve a vector if it is present. If not, throw an exception.
void set(const std::string &fullname, std::vector< T > &&vec_in)
Set values in a vector.
void fill(const std::vector< std::string > &variableNamesInt, const std::vector< std::string > &variableNamesFloat, const std::vector< std::string > &variableNamesString, const std::vector< std::string > &variableNamesGeoVaLs, const std::vector< std::string > &variableNamesObsDiags)
Fill profile with data.
std::vector< float > & getGeoVaLVector(const std::string &fullname)
Retrieve a GeoVaL vector if it is present. If not, throw an exception.
void checkObsSpaceSection(ufo::ObsSpaceSection section)
Check this profile is in the expected ObsSpace section (original or extended).
std::string testid() const override
void register_tests() const override
void clear() const override
@ InterpolationFlag
Interpolation check flag.
@ SuperadiabatFlag
Superadiabatic check flag.
@ HydrostaticFlag
Hydrostatic check flag.
@ PermRejectReport
Blacklisted data.
@ PermRejectFlag
Blacklisted data.
void testConventionalProfileProcessing(const eckit::LocalConfiguration &conf)
ObsPair reverse(const ObsPair &pair)
CASE("ufo/DataExtractor/bilinearinterp/float_linear")
void profileVerticalInterpolation(const std::vector< float > &coordIn, const std::vector< float > &valuesIn, const std::vector< float > &coordOut, std::vector< float > &valuesOut, const ProfileInterpolation::InterpolationMethod interpMethod, const ProfileInterpolation::CoordinateOrder coordOrder, const ProfileInterpolation::OutOfBoundsTreatment outOfBounds)
void calculateVerticalAverage(const std::vector< int > &flagsIn, const std::vector< float > &valuesIn, const std::vector< float > &coordIn, const std::vector< float > &bigGap, const std::vector< float > &coordOut, float DZFrac, ProfileAveraging::Method method, std::vector< int > &flagsOut, std::vector< float > &valuesOut, int &numGaps, std::vector< float > *coordMax, std::vector< float > *coordMin)
Profile vertical averaging onto model levels.
void CalculateModelHeight(const ModelParameters &options, const float orogGeoVaLs, std::vector< float > &zRhoGeoVaLs, std::vector< float > &zThetaGeoVaLs)
Calculate model heights on rho and theta levels. The calculation uses the terrain-following height co...
static constexpr const char *const station_ID
static constexpr const char *const extended_obs_space
static constexpr const char *const qcflags_observation_report
static constexpr const char *const qcflags_eastward_wind
static constexpr const char *const bigPgaps_derived
static constexpr const char *const modellevels_logPWB_rho_derived
static constexpr const char *const qcflags_relative_humidity
static constexpr const char *const geovals_orog
static constexpr const char *const LogP_derived
static constexpr const char *const obs_geopotential_height
static constexpr const char *const obs_eastward_wind
static constexpr const char *const geovals_pressure
static constexpr const char *const qcflags_time
static constexpr const char *const obs_air_pressure
static constexpr const char *const qcflags_air_temperature
static constexpr const char *const bkgerr_air_temperature
static constexpr const char *const qcflags_geopotential_height