UFO
test/ufo/ProfileConsistencyChecks.h
Go to the documentation of this file.
1 /*
2  * (C) Crown copyright 2020, Met Office
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  */
7 
8 #ifndef TEST_UFO_PROFILECONSISTENCYCHECKS_H_
9 #define TEST_UFO_PROFILECONSISTENCYCHECKS_H_
10 
11 #include <iomanip>
12 #include <memory>
13 #include <string>
14 #include <vector>
15 
16 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
17 
18 #include "eckit/config/LocalConfiguration.h"
19 #include "eckit/testing/Test.h"
20 #include "ioda/ObsSpace.h"
21 #include "ioda/ObsVector.h"
22 #include "oops/mpi/mpi.h"
23 #include "oops/runs/Test.h"
24 #include "oops/util/Expect.h"
25 #include "test/TestEnvironment.h"
28 #include "ufo/filters/Variables.h"
29 #include "ufo/ObsDiagnostics.h"
30 
41 
43 
44 namespace ufo {
45 namespace test {
46 
47 void testProfileConsistencyChecks(const eckit::LocalConfiguration &conf) {
48  util::DateTime bgn(conf.getString("window begin"));
49  util::DateTime end(conf.getString("window end"));
50 
51  const eckit::LocalConfiguration obsSpaceConf(conf, "obs space");
52  ioda::ObsSpace obsspace(obsSpaceConf, oops::mpi::world(), bgn, end, oops::mpi::myself());
53 
54  ioda::ObsVector hofx(obsspace);
55 
56  const eckit::LocalConfiguration obsdiagconf(conf, "obs diagnostics");
57  std::vector<eckit::LocalConfiguration> varconfs;
58  obsdiagconf.get("variables", varconfs);
59  const Variables diagvars(varconfs);
60  const ObsDiagnostics obsdiags(obsdiagconf, obsspace, diagvars.toOopsVariables());
61 
62  std::shared_ptr<ioda::ObsDataVector<float>> obserr(new ioda::ObsDataVector<float>(
63  obsspace, obsspace.obsvariables(), "ObsError"));
64 
65  std::shared_ptr<ioda::ObsDataVector<int>> qcflags(new ioda::ObsDataVector<int>(
66  obsspace, obsspace.obsvariables()));
67 
68  const eckit::LocalConfiguration filterConf(conf, "ProfileConsistencyChecks");
69 
70  // Determine whether an exception is expected to be thrown.
71  // Exceptions can be thrown in two places: on instantiation of the filter,
72  // and during the operation of the filter.
73  bool expectThrowOnInstantiation = conf.getBool("ExpectThrowOnInstantiation", false);
74  bool expectThrowDuringOperation = conf.getBool("ExpectThrowDuringOperation", false);
75 
76  if (expectThrowOnInstantiation) {
77  EXPECT_THROWS(ufo::ProfileConsistencyChecks filterThrow(obsspace, filterConf, qcflags, obserr));
78  // Do not proceed further in this case.
79  return;
80  }
81 
82  ufo::ProfileConsistencyChecks filter(obsspace, filterConf, qcflags, obserr);
83  filter.preProcess();
84 
85  if (expectThrowDuringOperation)
86  EXPECT_THROWS(filter.postFilter(hofx, obsdiags));
87  else
88  filter.postFilter(hofx, obsdiags);
89 
90  // Determine whether the mismatch check should be bypassed or not.
91  // It might be necessary to disable the mismatch check in tests which are
92  // designed to reach code paths that would normally result in failure.
93  bool bypassMismatchComparison = conf.getBool("BypassMismatchComparison", false);
94 
95  // Check there are no mismatches between the values produced by this code and the OPS equivalents
96  if (!bypassMismatchComparison) {
97  for (auto nMM : filter.getMismatches())
98  EXPECT_EQUAL(nMM, 0);
99  }
100 
101  // === Additional tests of exceptions === //
102 
103  // Test whether adding the same check twice throws an exception.
104  bool addDuplicateCheck = conf.getBool("AddDuplicateCheck", false);
105  if (addDuplicateCheck) {
106  static ProfileCheckMaker<ProfileCheckUInterp> makerDuplicate1_("duplicate");
107  EXPECT_THROWS(static ProfileCheckMaker<ProfileCheckUInterp> makerDuplicate2_("duplicate"));
108  }
109 
110  // Test whether using the get function with the wrong type throws an exception.
111  bool getWrongType = conf.getBool("GetWrongType", false);
112  if (getWrongType) {
113  std::unique_ptr <ProfileConsistencyCheckParameters> options_;
114  options_.reset(new ProfileConsistencyCheckParameters());
115  options_->deserialize(conf);
116  EntireSampleDataHandler entireSampleDataHandler(obsspace,
117  *options_);
118  // Load data from obsspace
119  entireSampleDataHandler.get<float>(ufo::VariableNames::obs_air_pressure);
120  // Attempt to access data with incorrect type
121  EXPECT_THROWS(entireSampleDataHandler.get<int>(ufo::VariableNames::obs_air_pressure));
122  std::vector<bool> apply(obsspace.nlocs(), true);
123  ProfileIndices profileIndices(obsspace,
124  *options_,
125  apply);
126  ProfileDataHandler profileDataHandler(obsspace,
127  *options_,
128  entireSampleDataHandler,
129  profileIndices);
130  // Obtain profile data
131  profileDataHandler.get<float>(ufo::VariableNames::obs_air_pressure);
132  // Attempt to access data with incorrect type
133  EXPECT_THROWS(profileDataHandler.get<int>(ufo::VariableNames::obs_air_pressure));
134  }
135 
136  // Manually modify QC flags in order to cover rare code paths.
137  bool ManualFlagModification = conf.getBool("ManualFlagModification", false);
138  if (ManualFlagModification) {
139  std::unique_ptr <ProfileConsistencyCheckParameters> options_;
140  options_.reset(new ProfileConsistencyCheckParameters());
141  options_->deserialize(conf);
142  EntireSampleDataHandler entireSampleDataHandler(obsspace,
143  *options_);
144  // Load data from obsspace
145  entireSampleDataHandler.get<float>(ufo::VariableNames::obs_air_pressure);
146  entireSampleDataHandler.get<int>(ufo::VariableNames::qcflags_air_temperature);
147  std::vector<bool> apply(obsspace.nlocs(), true);
148  ProfileIndices profileIndices(obsspace,
149  *options_,
150  apply);
151  ProfileDataHandler profileDataHandler(obsspace,
152  *options_,
153  entireSampleDataHandler,
154  profileIndices);
155  ProfileCheckValidator profileCheckValidator(*options_,
156  profileDataHandler);
157 
158  profileIndices.determineProfileIndices();
159  profileDataHandler.reset();
160 
161  // Obtain profile data
162  profileDataHandler.get<float>(ufo::VariableNames::obs_air_pressure);
163 
164  // Modify flags
165  std::vector <int> &ReportFlags =
166  profileDataHandler.get<int>(ufo::VariableNames::qcflags_observation_report);
167  std::vector <int> &tFlags =
168  profileDataHandler.get<int>(ufo::VariableNames::qcflags_air_temperature);
169  std::vector <int> &rhFlags =
170  profileDataHandler.get<int>(ufo::VariableNames::qcflags_relative_humidity);
171  std::vector <int> &uFlags =
172  profileDataHandler.get<int>(ufo::VariableNames::qcflags_eastward_wind);
173  std::vector <int> &zFlags =
174  profileDataHandler.get<int>(ufo::VariableNames::qcflags_geopotential_height);
175  std::vector <int> &timeFlags =
176  profileDataHandler.get<int>(ufo::VariableNames::qcflags_time);
177 
186 
187  // Create checks
188  ProfileCheckTime profileCheckTime(*options_,
189  profileIndices,
190  profileDataHandler,
191  profileCheckValidator);
192  ProfileCheckBackgroundTemperature profileCheckBackgroundT(*options_,
193  profileIndices,
194  profileDataHandler,
195  profileCheckValidator);
196  ProfileCheckBackgroundRelativeHumidity profileCheckBackgroundRH(*options_,
197  profileIndices,
198  profileDataHandler,
199  profileCheckValidator);
200  ProfileCheckBackgroundWindSpeed profileCheckBackgroundUV(*options_,
201  profileIndices,
202  profileDataHandler,
203  profileCheckValidator);
204  ProfileCheckBackgroundGeopotentialHeight profileCheckBackgroundZ(*options_,
205  profileIndices,
206  profileDataHandler,
207  profileCheckValidator);
208 
209  // Run time check
210  profileCheckTime.runCheck();
211 
212  // Modify time flag
213  timeFlags[0] = true;
214 
215  // Run remaining checks
216  profileCheckBackgroundT.runCheck();
217  profileCheckBackgroundRH.runCheck();
218  profileCheckBackgroundUV.runCheck();
219  profileCheckBackgroundZ.runCheck();
220  }
221 }
222 
223 class ProfileConsistencyChecks : public oops::Test {
224  private:
225  std::string testid() const override {return "ufo::test::ProfileConsistencyChecks";}
226 
227  void register_tests() const override {
228  std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
229 
230  const eckit::LocalConfiguration conf(::test::TestEnvironment::config());
231  for (const std::string & testCaseName : conf.keys())
232  {
233  const eckit::LocalConfiguration testCaseConf(::test::TestEnvironment::config(), testCaseName);
234  ts.emplace_back(CASE("ufo/ProfileConsistencyChecks/" + testCaseName, testCaseConf)
235  {
236  testProfileConsistencyChecks(testCaseConf);
237  });
238  }
239  }
240 
241  void clear() const override {}
242 };
243 
244 } // namespace test
245 } // namespace ufo
246 
247 #endif // TEST_UFO_PROFILECONSISTENCYCHECKS_H_
ProfileCheckBackgroundTemperature.h
ufo::ProfileDataHandler
Retrieve and store data for individual profiles. To do this, first the vector of values in the entire...
Definition: ProfileDataHandler.h:40
MetOfficeQCFlags.h
ProfileCheckBackgroundRelativeHumidity.h
ufo::MetOfficeQCFlags::PermRejectFlag
@ PermRejectFlag
Blacklisted data.
Definition: MetOfficeQCFlags.h:57
ufo::ProfileIndices
Determine indices of observations making up individual profiles. The indices are computed with respec...
Definition: ProfileIndices.h:39
ufo::ProfileCheckBackgroundTemperature::runCheck
void runCheck() override
Run check.
Definition: ProfileCheckBackgroundTemperature.cc:23
ufo::test::CASE
CASE("ufo/MetOfficeBuddyPairFinder/" "Duplicates, constraints on buddy counts, legacy pair collector")
Definition: test/ufo/MetOfficeBuddyPairFinder.h:171
ufo::ProfileCheckBackgroundGeopotentialHeight
Profile QC: compare geopotential height data against model background values using a Bayesian method....
Definition: ProfileCheckBackgroundGeopotentialHeight.h:38
ufo::ProfileConsistencyChecks
Profile QC checks.
Definition: src/ufo/filters/ProfileConsistencyChecks.h:81
ufo::ProfileConsistencyChecks::getMismatches
std::vector< int > getMismatches() const
Definition: src/ufo/filters/ProfileConsistencyChecks.h:95
ufo::FilterBase::preProcess
void preProcess()
Definition: FilterBase.cc:66
ufo::ProfileCheckValidator
Profile QC check validator.
Definition: ProfileCheckValidator.h:27
ufo::VariableNames::qcflags_eastward_wind
static constexpr const char *const qcflags_eastward_wind
Definition: VariableNames.h:95
ufo::VariableNames::qcflags_observation_report
static constexpr const char *const qcflags_observation_report
Definition: VariableNames.h:91
ufo::ProfileCheckBackgroundRelativeHumidity
Profile QC: compare relative humidity data against model background values using a Bayesian method....
Definition: ProfileCheckBackgroundRelativeHumidity.h:38
ProfileConsistencyCheckParameters.h
ufo::test::ProfileConsistencyChecks
Definition: test/ufo/ProfileConsistencyChecks.h:223
ufo::VariableNames::qcflags_relative_humidity
static constexpr const char *const qcflags_relative_humidity
Definition: VariableNames.h:93
ProfileCheckUInterp.h
ufo::ProfileCheckMaker
Definition: ProfileCheckBase.h:113
ufo::VariableNames::qcflags_geopotential_height
static constexpr const char *const qcflags_geopotential_height
Definition: VariableNames.h:94
ufo
Definition: RunCRTM.h:27
ProfileCheckBackgroundGeopotentialHeight.h
ufo::ProfileCheckTime::runCheck
void runCheck() override
Run check.
Definition: ProfileCheckTime.cc:23
ufo::MetOfficeQCFlags::SuperadiabatFlag
@ SuperadiabatFlag
Superadiabatic check flag.
Definition: MetOfficeQCFlags.h:88
ProfileCheckBackgroundWindSpeed.h
ufo::test::ProfileConsistencyChecks::testid
std::string testid() const override
Definition: test/ufo/ProfileConsistencyChecks.h:225
Variables.h
ufo::ProfileIndices::determineProfileIndices
void determineProfileIndices()
Determine indices in entire sample for this profile.
Definition: ProfileIndices.cc:40
ProfileDataHandler.h
ufo::VariableNames::obs_air_pressure
static constexpr const char *const obs_air_pressure
Definition: VariableNames.h:18
EntireSampleDataHandler.h
ufo::ProfileCheckBackgroundRelativeHumidity::runCheck
void runCheck() override
Run check.
Definition: ProfileCheckBackgroundRelativeHumidity.cc:23
ufo::EntireSampleDataHandler
Retrieve and store data for entire sample. This class uses lazy loading; vectors of variables are ret...
Definition: EntireSampleDataHandler.h:42
ufo::MetOfficeQCFlags::PermRejectReport
@ PermRejectReport
Blacklisted data.
Definition: MetOfficeQCFlags.h:27
ufo::ProfileCheckBackgroundGeopotentialHeight::runCheck
void runCheck() override
Run check.
Definition: ProfileCheckBackgroundGeopotentialHeight.cc:23
ufo::test::ProfileConsistencyChecks::clear
void clear() const override
Definition: test/ufo/ProfileConsistencyChecks.h:241
ufo::VariableNames::qcflags_time
static constexpr const char *const qcflags_time
Definition: VariableNames.h:97
ufo::ProfileConsistencyCheckParameters
Options controlling the operation of the ProfileConsistencyChecks filter.
Definition: ProfileConsistencyCheckParameters.h:33
ufo::FilterBase::postFilter
void postFilter(const ioda::ObsVector &, const ObsDiagnostics &)
Definition: FilterBase.cc:94
ProfileCheckBase.h
ioda::ObsDataVector
Definition: BackgroundCheck.h:26
ProfileCheckTime.h
ufo::MetOfficeQCFlags::HydrostaticFlag
@ HydrostaticFlag
Hydrostatic check flag.
Definition: MetOfficeQCFlags.h:86
ufo::VariableNames::qcflags_air_temperature
static constexpr const char *const qcflags_air_temperature
Definition: VariableNames.h:92
ufo::ProfileCheckBackgroundWindSpeed::runCheck
void runCheck() override
Run check.
Definition: ProfileCheckBackgroundWindSpeed.cc:23
ufo::test::testProfileConsistencyChecks
void testProfileConsistencyChecks(const eckit::LocalConfiguration &conf)
Definition: test/ufo/ProfileConsistencyChecks.h:47
ProfileConsistencyChecks.h
ufo::test::ProfileConsistencyChecks::register_tests
void register_tests() const override
Definition: test/ufo/ProfileConsistencyChecks.h:227
ufo::MetOfficeQCFlags::InterpolationFlag
@ InterpolationFlag
Interpolation check flag.
Definition: MetOfficeQCFlags.h:87
VariableNames.h
ufo::ProfileCheckTime
Profile QC: reject data which are outside the assimilation time window. Also, if requested,...
Definition: ProfileCheckTime.h:34
ufo::test::ObsDiagnostics
Definition: test/ufo/ObsDiagnostics.h:102
ufo::ProfileCheckBackgroundWindSpeed
Profile QC: compare wind speed data against model background values using a Bayesian method....
Definition: ProfileCheckBackgroundWindSpeed.h:38
ufo::EntireSampleDataHandler::get
std::vector< T > & get(const std::string &fullname)
Definition: EntireSampleDataHandler.h:56
ufo::ProfileDataHandler::get
std::vector< T > & get(const std::string &fullname)
Definition: ProfileDataHandler.h:53
ufo::test::Variables
Definition: test/ufo/Variables.h:118
ufo::ProfileCheckBackgroundTemperature
Profile QC: compare temperature data with model background values using a Bayesian method....
Definition: ProfileCheckBackgroundTemperature.h:38
conf
Definition: conf.py:1
ufo::ProfileDataHandler::reset
void reset()
Definition: ProfileDataHandler.cc:22