UFO
test/ufo/TrackCheckShip.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_TRACKCHECKSHIP_H_
9 #define TEST_UFO_TRACKCHECKSHIP_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 "oops/util/FloatCompare.h"
26 #include "test/TestEnvironment.h"
29 #include "ufo/filters/Variables.h"
30 
31 namespace ufo {
32 namespace test {
33 
34 const ufo::TrackCheckShipDiagnostics setupRunFilter(const eckit::LocalConfiguration &conf) {
35  util::DateTime bgn(conf.getString("window begin"));
36  util::DateTime end(conf.getString("window end"));
37 
38  const eckit::LocalConfiguration obsSpaceConf(conf, "obs space");
39  ioda::ObsSpace obsspace(obsSpaceConf, oops::mpi::world(), bgn, end, oops::mpi::myself());
40 
41  if (conf.has("station_ids")) {
42  const std::vector<int> stationIds = conf.getIntVector("station_ids");
43  obsspace.put_db("MetaData", "station_id", stationIds);
44  }
45 
46  std::shared_ptr<ioda::ObsDataVector<float>> obserr(new ioda::ObsDataVector<float>(
47  obsspace, obsspace.obsvariables(), "ObsError"));
48  std::shared_ptr<ioda::ObsDataVector<int>> qcflags(new ioda::ObsDataVector<int>(
49  obsspace, obsspace.obsvariables()));
50 
51  const eckit::LocalConfiguration filterConf(conf, "Ship Track Check");
52  ufo::TrackCheckShip filter(obsspace, filterConf, qcflags, obserr);
53  filter.preProcess();
54  return *filter.diagnostics();
55 }
56 
57 void testTrackCheckShipInitialCalculations(const eckit::LocalConfiguration &conf) {
58  auto diagnostics = setupRunFilter(conf);
59  const std::vector<double> expectedDistances = conf.getDoubleVector("expected distance");
60  const std::vector<double> expectedSpeeds = conf.getDoubleVector("expected speed");
61  const std::vector<double> expectedDistancesAveraged =
62  conf.getDoubleVector("expected distance averaged");
63  const std::vector<double> expectedSpeedsAveraged =
64  conf.getDoubleVector("expected speed averaged");
65  const std::vector<float> expectedAngles = conf.getFloatVector("expected angle");
66  const std::vector<int> expectedShort = conf.getIntVector("expected short");
67  const std::vector<int> expectedFast = conf.getIntVector("expected fast");
68  const std::vector<int> expectedBends = conf.getIntVector("expected bends");
69  const std::vector<int> expectedDist0 = conf.getIntVector("expected dist0");
70  const std::vector<int> expectedSimultaneous = conf.getIntVector("expected simultaneous");
71  const std::vector<double> expectedSumSpeeds = conf.getDoubleVector("expected sum speed");
72  const std::vector<double> expectedMeanSpeeds = conf.getDoubleVector("expected mean speed");
73  std::vector<double> calculatedDistances, calculatedSpeeds, calculatedDistancesAveraged,
74  calculatedSpeedsAveraged, calculatedSumSpeeds, calculatedMeanSpeeds;
75  std::vector<float> calculatedAngles;
76  std::vector<int> calculatedShort, calculatedFast, calculatedBends,
77  calculatedDist0, calculatedSimultaneous;
78  for (auto const& tracks : diagnostics.getInitialCalculationResults()) {
79  for (auto const& obsStats : tracks.first) {
80  calculatedDistances.push_back(obsStats.distance);
81  calculatedSpeeds.push_back(obsStats.speed);
82  calculatedDistancesAveraged.push_back(obsStats.distanceAveraged);
83  calculatedSpeedsAveraged.push_back(obsStats.speedAveraged);
84  calculatedAngles.push_back(obsStats.angle);
85  }
86  calculatedShort.push_back(tracks.second.numShort_);
87  calculatedFast.push_back(tracks.second.numFast_);
88  calculatedBends.push_back(tracks.second.numBends_);
89  calculatedDist0.push_back(tracks.second.numDist0_);
90  calculatedSimultaneous.push_back(tracks.second.numSimultaneous_);
91  calculatedSumSpeeds.push_back(tracks.second.sumSpeed_);
92  calculatedMeanSpeeds.push_back(tracks.second.meanSpeed_);
93  }
94  EXPECT(oops::are_all_close_relative(calculatedDistances, expectedDistances,
95  .05));
96  EXPECT(oops::are_all_close_relative(calculatedSpeeds, expectedSpeeds,
97  .05));
98  EXPECT(oops::are_all_close_relative(
99  calculatedDistancesAveraged, expectedDistancesAveraged,
100  .05));
101  EXPECT(oops::are_all_close_relative(
102  calculatedSpeedsAveraged, expectedSpeedsAveraged,
103  .05));
104  EXPECT(oops::are_all_close_absolute(
105  calculatedAngles, expectedAngles,
106  5.0f));
107  EXPECT_EQUAL(calculatedShort, expectedShort);
108  EXPECT_EQUAL(calculatedFast, expectedFast);
109  EXPECT_EQUAL(calculatedBends, expectedBends);
110  EXPECT_EQUAL(calculatedDist0, expectedDist0);
111  EXPECT_EQUAL(calculatedSimultaneous, expectedSimultaneous);
112  EXPECT(oops::are_all_close_relative(
113  calculatedSumSpeeds, expectedSumSpeeds,
114  .05));
115  EXPECT(oops::are_all_close_relative
116  (calculatedMeanSpeeds, expectedMeanSpeeds,
117  .05));
118 }
119 
120 void testEarlyBreakCondition(const eckit::LocalConfiguration &conf) {
121  const eckit::LocalConfiguration filterConf(conf, "Ship Track Check");
122  if (!filterConf.getBool("early break check", true)) {
123  return;
124  }
125 
126  auto diagnostics = setupRunFilter(conf);
127 
128  std::vector<int> expectedEarlyBreaks(conf.getIntVector("expected early breaks"));
129  std::vector<int> calculatedEarlyBreaks;
130 
131  for (auto const& earlyBreakResults : diagnostics.getEarlyBreaks()) {
132  calculatedEarlyBreaks.push_back(earlyBreakResults);
133  }
134  EXPECT_EQUAL(expectedEarlyBreaks, calculatedEarlyBreaks);
135 }
136 
137 void testDeferSimultaneous(const eckit::LocalConfiguration &conf) {
138  const eckit::LocalConfiguration filterConf(conf, "Ship Track Check");
139  if (!filterConf.getBool("deferred check simultaneous", false)) {
140  return;
141  }
142 
143  auto diagnostics = setupRunFilter(conf);
144 
145  const std::vector<double> expectedDistancesDeferred = conf.getDoubleVector(
146  "expected deferred distance");
147  const std::vector<double> expectedSpeedsDeferred = conf.getDoubleVector(
148  "expected deferred speed");
149  const std::vector<double> expectedDistancesAveragedDeferred =
150  conf.getDoubleVector("expected deferred distance averaged");
151  const std::vector<double> expectedSpeedsAveragedDeferred =
152  conf.getDoubleVector("expected deferred speed averaged");
153  const std::vector<float> expectedAnglesDeferred = conf.getFloatVector("expected deferred angle");
154  std::vector<double> calculatedDistancesDeferred, calculatedSpeedsDeferred,
155  calculatedDistancesAveragedDeferred,
156  calculatedSpeedsAveragedDeferred;
157  std::vector<float> calculatedAnglesDeferred;
158  for (auto const& recalcIteration : (diagnostics.getCalculatedResultsSimultaneousDeferred())) {
159  for (auto const& obs : recalcIteration) {
160  calculatedAnglesDeferred.push_back(obs.angle);
161  calculatedDistancesDeferred.push_back(obs.distance);
162  calculatedSpeedsDeferred.push_back(obs.speed);
163  calculatedDistancesAveragedDeferred.push_back(obs.distanceAveraged);
164  calculatedSpeedsAveragedDeferred.push_back(obs.speedAveraged);
165  }
166  }
167  EXPECT(oops::are_all_close_relative(calculatedDistancesDeferred, expectedDistancesDeferred,
168  .05));
169  EXPECT(oops::are_all_close_relative(calculatedSpeedsDeferred, expectedSpeedsDeferred,
170  .05));
171  EXPECT(oops::are_all_close_relative(
172  calculatedDistancesAveragedDeferred, expectedDistancesAveragedDeferred,
173  .05));
174  EXPECT(oops::are_all_close_relative(
175  calculatedSpeedsAveragedDeferred, expectedSpeedsAveragedDeferred,
176  .05));
177  EXPECT(oops::are_all_close_absolute(
178  calculatedAnglesDeferred, expectedAnglesDeferred,
179  5.0f));
180 }
181 
182 class TrackCheckShip : public oops::Test {
183  private:
184  std::string testid() const override {return "ufo::test::TrackCheckShip";}
185 
186  void register_tests() const override {
187  std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
188 
189  const eckit::LocalConfiguration conf(::test::TestEnvironment::config());
190  for (const std::string & testCaseName : conf.keys())
191  {
192  const eckit::LocalConfiguration testCaseConf(::test::TestEnvironment::config(), testCaseName);
193  ts.emplace_back(CASE("ufo/TrackCheckShip/" + testCaseName, testCaseConf)
194  {
196  testEarlyBreakCondition(testCaseConf);
197  testDeferSimultaneous(testCaseConf);
198  });
199  }
200  }
201 
202  void clear() const override {}
203 };
204 
205 } // namespace test
206 } // namespace ufo
207 
208 #endif // TEST_UFO_TRACKCHECKSHIP_H_
ufo::TrackCheckShipDiagnostics
Definition: TrackCheckShipDiagnostics.h:17
ufo::test::TrackCheckShip::clear
void clear() const override
Definition: test/ufo/TrackCheckShip.h:202
ufo::test::CASE
CASE("ufo/MetOfficeBuddyPairFinder/" "Duplicates, constraints on buddy counts, legacy pair collector")
Definition: test/ufo/MetOfficeBuddyPairFinder.h:171
ufo::test::TrackCheckShip::register_tests
void register_tests() const override
Definition: test/ufo/TrackCheckShip.h:186
ufo::FilterBase::preProcess
void preProcess()
Definition: FilterBase.cc:66
ufo::test::testEarlyBreakCondition
void testEarlyBreakCondition(const eckit::LocalConfiguration &conf)
Definition: test/ufo/TrackCheckShip.h:120
ufo::TrackCheckShip::diagnostics
const TrackCheckShipDiagnostics * diagnostics() const
Definition: TrackCheckShip.cc:86
TrackCheckShip.h
ufo
Definition: RunCRTM.h:27
Variables.h
ufo::test::testDeferSimultaneous
void testDeferSimultaneous(const eckit::LocalConfiguration &conf)
Definition: test/ufo/TrackCheckShip.h:137
TrackCheckShipDiagnostics.h
ufo::test::testTrackCheckShipInitialCalculations
void testTrackCheckShipInitialCalculations(const eckit::LocalConfiguration &conf)
Definition: test/ufo/TrackCheckShip.h:57
ufo::test::TrackCheckShip
Definition: test/ufo/TrackCheckShip.h:182
ioda::ObsDataVector
Definition: BackgroundCheck.h:26
ufo::TrackCheckShip
Checks tracks of ships and buoys, rejecting observations whose locations and timestamps make them inc...
Definition: src/ufo/filters/TrackCheckShip.h:59
ufo::test::setupRunFilter
const ufo::TrackCheckShipDiagnostics setupRunFilter(const eckit::LocalConfiguration &conf)
Definition: test/ufo/TrackCheckShip.h:34
ufo::test::TrackCheckShip::testid
std::string testid() const override
Definition: test/ufo/TrackCheckShip.h:184
conf
Definition: conf.py:1