13 #include "eckit/exception/Exceptions.h"
14 #include "eckit/geometry/Point2.h"
15 #include "eckit/geometry/Point3.h"
16 #include "eckit/geometry/Sphere.h"
17 #include "ioda/ObsDataVector.h"
18 #include "ioda/ObsSpace.h"
19 #include "oops/util/DateTime.h"
20 #include "oops/util/sqr.h"
32 for (
size_t i = 0; i < a.size(); ++i)
33 sum += util::sqr(a[i] - b[i]);
41 eckit::geometry::Point3 eckitPoint;
42 eckit::geometry::Sphere::convertSphericalToCartesian(
43 meanEarthRadius, eckit::geometry::Point2(longitude, latitude), eckitPoint);
45 std::copy(eckitPoint.begin(), eckitPoint.end(),
Point.begin());
58 const std::vector<size_t> validObsIds) {
59 std::vector<T> validObsCategories(validObsIds.size());
60 for (
size_t validObsIndex = 0; validObsIndex < validObsIds.size(); ++validObsIndex) {
61 validObsCategories[validObsIndex] = categories[validObsIds[validObsIndex]];
63 return validObsCategories;
68 std::vector<size_t> validObsIds;
69 for (
size_t obsId = 0; obsId < apply.size(); ++obsId)
71 validObsIds.push_back(obsId);
77 const eckit::Configuration &config,
78 const ioda::ObsSpace &obsdb) {
79 std::unique_ptr<TrackCheckUtilsParameters> baseOptions_;
81 baseOptions_->deserialize(config);
82 if (baseOptions_->stationIdVariable.value() == boost::none) {
83 if (obsdb.obs_group_var().empty()) {
92 validObsIds, splitter, obsdb);
97 const ioda::ObsSpace &obsdb) {
98 const std::vector<size_t> &obsCategories = obsdb.recnum();
100 obsCategories, validObsIds);
101 splitter.
groupBy(validObsCategories);
105 const std::vector<size_t> &validObsIds,
107 const ioda::ObsSpace &obsdb) {
108 switch (obsdb.dtype(variable.
group(), variable.
variable())) {
109 case ioda::ObsDtype::Integer:
110 groupObservationsByTypedVariable<int>(variable, validObsIds, splitter, obsdb);
113 case ioda::ObsDtype::String:
114 groupObservationsByTypedVariable<std::string>(variable, validObsIds, splitter, obsdb);
118 throw eckit::UserError(
119 "Only integer and string variables may be used as station IDs", Here());
122 template <
typename VariableType>
124 const std::vector<size_t> &validObsIds,
126 const ioda::ObsSpace &obsdb) {
127 std::vector<VariableType> obsCategories(obsdb.nlocs());
128 obsdb.get_db(variable.
group(), variable.
variable(), obsCategories);
130 obsCategories, validObsIds);
132 splitter.
groupBy(validObsCategories);
137 const ioda::ObsSpace &obsdb) {
138 std::vector<util::DateTime> times(obsdb.nlocs());
139 obsdb.get_db(
"MetaData",
"datetime", times);
140 splitter.
sortGroupsBy([×, &validObsIds](
size_t obsIndexA,
size_t obsIndexB)
141 {
return times[validObsIds[obsIndexA]] < times[validObsIds[obsIndexB]]; });
148 locationTimes.
latitudes.resize(obsdb.nlocs());
149 obsdb.get_db(
"MetaData",
"latitude", locationTimes.
latitudes);
151 locationTimes.
longitudes.resize(obsdb.nlocs());
152 obsdb.get_db(
"MetaData",
"longitude", locationTimes.
longitudes);
154 locationTimes.
datetimes.resize(obsdb.nlocs());
155 obsdb.get_db(
"MetaData",
"datetime", locationTimes.
datetimes);
157 return locationTimes;
161 std::vector<std::vector<bool> >
163 for (std::vector<bool> & variableFlagged : flagged)
164 for (
size_t obsId = 0; obsId < isRejected.size(); ++obsId)
165 if (isRejected[obsId])
166 variableFlagged[obsId] =
true;
170 const util::DateTime &time)
175 return numChecks_ != 0 ?
static_cast<float>(numFailedChecks_) / numChecks_ : 0.0f;
178 : numFailedChecks_(0), numChecks_(0)
185 assert(numChecks_ >= 0);
186 assert(numFailedChecks_ >= 0);
187 assert(numFailedChecks_ <= numChecks_);
195 assert(numChecks_ >= 0);
196 assert(numFailedChecks_ >= 0);
197 assert(numFailedChecks_ <= numChecks_);