UFO
test/ufo/MetOfficeBuddyCheck.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2020 Met Office UK
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_METOFFICEBUDDYCHECK_H_
9 #define TEST_UFO_METOFFICEBUDDYCHECK_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"
27 #include "ufo/filters/Variables.h"
28 #include "ufo/Locations.h"
29 #include "ufo/ObsDiagnostics.h"
30 #include "ufo/utils/StringUtils.h"
31 
32 namespace ufo {
33 namespace test {
34 
35 void testMetOfficeBuddyCheck(const eckit::LocalConfiguration &conf) {
36  util::DateTime bgn(conf.getString("window begin"));
37  util::DateTime end(conf.getString("window end"));
38 
39  const eckit::LocalConfiguration obsSpaceConf(conf, "obs space");
40  ioda::ObsTopLevelParameters obsParams;
41  obsParams.validateAndDeserialize(obsSpaceConf);
42  ioda::ObsSpace obsSpace(obsParams, oops::mpi::world(), bgn, end, oops::mpi::myself());
43 
44  const eckit::LocalConfiguration floatVarInitConf(conf, "FloatVariables");
45  for (const std::string & varNameGroup : floatVarInitConf.keys()) {
46  std::string varName, varGroup;
47  ufo::splitVarGroup(varNameGroup, varName, varGroup);
48  const std::vector<float> values = floatVarInitConf.getFloatVector(varNameGroup);
49  obsSpace.put_db(varGroup, varName, values);
50  }
51 
52  const eckit::LocalConfiguration intVarInitConf(conf, "IntVariables");
53  for (const std::string & varNameGroup : intVarInitConf.keys()) {
54  std::string varName, varGroup;
55  ufo::splitVarGroup(varNameGroup, varName, varGroup);
56  const std::vector<int> values = intVarInitConf.getIntVector(varNameGroup);
57  obsSpace.put_db(varGroup, varName, values);
58  }
59 
60  std::shared_ptr<ioda::ObsDataVector<float>> obserr(new ioda::ObsDataVector<float>(
61  obsSpace, obsSpace.obsvariables(), "ObsError"));
62  std::shared_ptr<ioda::ObsDataVector<int>> qcflags(new ioda::ObsDataVector<int>(
63  obsSpace, obsSpace.obsvariables()));
64 
65  eckit::LocalConfiguration filterConf(conf, "Met Office Buddy Check");
66  ufo::MetOfficeBuddyCheckParameters filterParameters;
67  filterParameters.validateAndDeserialize(filterConf);
68  ufo::MetOfficeBuddyCheck filter(obsSpace, filterParameters, qcflags, obserr);
69  filter.preProcess();
70 
71  ioda::ObsVector hofx(obsSpace, "HofX");
72 
73  ioda::ObsVector bias(obsSpace);
74  bias.zero();
75 
76  ufo::Locations locations(conf, obsSpace.comm());
77  const eckit::LocalConfiguration diagConf = conf.getSubConfiguration("obs diagnostics");
78  oops::Variables diagVars;
79  for (const std::string &name : diagConf.keys())
80  diagVars.push_back(name);
81  ufo::ObsDiagnostics obsDiags(obsSpace, locations, diagVars);
82  obsDiags.allocate(1, diagVars);
83  for (const std::string &name : diagConf.keys()) {
84  const std::vector<double> diag = diagConf.getDoubleVector(name);
85  obsDiags.save(diag, name, 0);
86  }
87 
88  filter.postFilter(hofx, bias, obsDiags);
89 
90  const eckit::LocalConfiguration pgeConf(conf, "ExpectedGrossErrorProbabilities");
91  for (const std::string & varNameGroup : pgeConf.keys()) {
92  std::string varName, varGroup;
93  ufo::splitVarGroup(varNameGroup, varName, varGroup);
94  const std::vector<float> expectedPges = pgeConf.getFloatVector(varNameGroup);
95  std::vector<float> actualPges(obsSpace.nlocs());
96  obsSpace.get_db(varGroup, varName, actualPges);
97  EXPECT(oops::are_all_close_absolute(actualPges, expectedPges, 1e-6f));
98  }
99 }
100 
101 class MetOfficeBuddyCheck : public oops::Test {
102  private:
103  std::string testid() const override {return "ufo::test::MetOfficeBuddyCheck";}
104 
105  void register_tests() const override {
106  std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
107 
108  const eckit::LocalConfiguration conf(::test::TestEnvironment::config());
109  for (const std::string & testCaseName : conf.keys())
110  {
111  const eckit::LocalConfiguration testCaseConf(::test::TestEnvironment::config(), testCaseName);
112  ts.emplace_back(CASE("ufo/MetOfficeBuddyCheck/" + testCaseName, testCaseConf)
113  {
114  testMetOfficeBuddyCheck(testCaseConf);
115  });
116  }
117  }
118 
119  void clear() const override {}
120 };
121 
122 } // namespace test
123 } // namespace ufo
124 
125 #endif // TEST_UFO_METOFFICEBUDDYCHECK_H_
Locations class to handle simple lat-lon-time locations.
Met Office's implementation of the buddy check.
Options controlling the operation of the MetOfficeBuddyCheck filter.
void allocate(const int nlev, const oops::Variables &vars)
Allocate diagnostics for variables vars with nlev number of levels.
void save(const std::vector< double > &, const std::string &, const int)
void postFilter(const ioda::ObsVector &, const ioda::ObsVector &, const ObsDiagnostics &) override
void preProcess() override
CASE("ufo/DataExtractor/bilinearinterp/float_linear")
void testMetOfficeBuddyCheck(const eckit::LocalConfiguration &conf)
Definition: RunCRTM.h:27
void splitVarGroup(const std::string &vargrp, std::string &var, std::string &grp)
Definition: StringUtils.cc:27