16 #include <boost/none.hpp>
17 #include "eckit/config/Configuration.h"
18 #include "ioda/ObsDataVector.h"
19 #include "ioda/ObsSpace.h"
20 #include "oops/base/Variables.h"
21 #include "oops/util/DateTime.h"
22 #include "oops/util/Duration.h"
23 #include "oops/util/Logger.h"
34 :
FilterBase(obsdb, parameters, flags, obserr), options_(parameters)
51 std::vector<std::vector<bool>> & flagged)
const {
55 "MetaData",
"datetime");
60 std::vector<bool> isRejected(validObsIds.size(),
false);
61 std::vector<std::string> filterVariables = filtervars.
toOopsVariables().variables();
63 for (std::string
const& variable : filterVariables) {
64 size_t stationNumber = 0;
65 if (!
obsdb_.has(
"ObsValue", variable)) {
66 std::string errorMessage =
67 "StuckCheck Error: ObsValue vector for " + variable +
" not found.\n";
68 throw std::invalid_argument(errorMessage);
71 "ObsValue", variable);
73 std::string stationId = std::to_string(stationNumber);
75 station.begin(), station.end(), validObsIds, variableValues);
77 float previousObservationValue;
78 float currentObservationValue;
79 size_t firstSameValueIndex = 0;
80 for (
size_t observationIndex = 0; observationIndex < variableDataStation.size();
82 currentObservationValue = variableDataStation.at(observationIndex);
83 if (observationIndex == 0) {
84 previousObservationValue = currentObservationValue;
86 if (currentObservationValue == previousObservationValue) {
89 if (observationIndex == variableDataStation.size() - 1) {
103 observationIndex - 1,
107 firstSameValueIndex = observationIndex;
108 previousObservationValue = currentObservationValue;
119 os <<
"StuckCheck: config = " <<
config_ <<
'\n';
125 std::vector<size_t>::const_iterator stationObsIndicesBegin,
126 std::vector<size_t>::const_iterator stationObsIndicesEnd,
127 const std::vector<size_t> &validObsIds,
128 const std::vector<float> &globalData)
const {
129 std::vector<float> stationData;
130 stationData.reserve(stationObsIndicesEnd - stationObsIndicesBegin);
131 size_t observationNumber = 0;
132 for (std::vector<size_t>::const_iterator it = stationObsIndicesBegin;
133 it != stationObsIndicesEnd; ++it) {
134 const size_t obsId = validObsIds.at(*it);
135 stationData.push_back(globalData[obsId]);
142 std::vector<size_t>::const_iterator stationIndicesBegin,
143 std::vector<size_t>::const_iterator stationIndicesEnd,
144 const std::vector<size_t> &validObsIds,
145 size_t startOfStreakIndex,
146 size_t endOfStreakIndex,
147 std::vector<bool> &isRejected,
148 std::string stationId =
"")
const {
150 auto getObservationTime = [
this, &stationIndicesBegin, &validObsIds] (
151 size_t offsetFromBeginning)->util::DateTime{
152 const size_t obsIndex = validObsIds.at(*(stationIndicesBegin + offsetFromBeginning));
156 auto rejectObservation = [&validObsIds, &isRejected, &stationIndicesBegin, &stationId](
157 size_t observationIndex) {
158 const size_t obsIndex = validObsIds.at(*(stationIndicesBegin + observationIndex));
159 isRejected[obsIndex] =
true;
162 size_t streakLength = endOfStreakIndex - startOfStreakIndex + 1;
167 size_t stationLength = stationIndicesEnd - stationIndicesBegin;
169 if (streakLength < stationLength) {
170 util::DateTime firstStreakObservationTime = getObservationTime(startOfStreakIndex);
171 util::DateTime lastStreakObservationTime = getObservationTime(endOfStreakIndex);
172 util::Duration streakDuration = lastStreakObservationTime - firstStreakObservationTime;
178 for (
size_t indexToReject = startOfStreakIndex;
179 indexToReject <= endOfStreakIndex;
181 rejectObservation(indexToReject);
Base class for UFO QC filters.
const eckit::LocalConfiguration config_
This class provides access to observations that may be held on multiple MPI ranks.
RecursiveSplitter splitObservationsIntoIndependentGroups(const std::vector< size_t > &validObsIds, bool opsCompatibilityMode=false) const
std::vector< size_t > getValidObservationIds(const std::vector< bool > &apply, const ioda::ObsDataVector< int > &flags, const Variables &filtervars, bool validIfAnyFilterVariablePassedQC=true) const
Return the IDs of observation locations that should be treated as valid by a filter.
std::vector< float > getFloatVariableFromObsSpace(const std::string &group, const std::string &variable) const
std::vector< util::DateTime > getDateTimeVariableFromObsSpace(const std::string &group, const std::string &variable) const
void flagRejectedObservations(const std::vector< bool > &isRejected, std::vector< std::vector< bool > > &flagged) const
Update flags of observations held on the current MPI rank.
Partitions an array into groups of elements equivalent according to certain criteria.
MultiElementGroupRange multiElementGroups() const
Return the range of equivalence classes consisting of more than one element.
oops::RequiredParameter< util::Duration > timeStuckTolerance
oops::RequiredParameter< size_t > numberStuckTolerance
std::unique_ptr< std::vector< util::DateTime > > obsGroupDateTimes_
StuckCheck(ioda::ObsSpace &obsdb, const Parameters_ ¶meters, std::shared_ptr< ioda::ObsDataVector< int > > flags, std::shared_ptr< ioda::ObsDataVector< float > > obserr)
std::vector< float > collectStationVariableData(std::vector< size_t >::const_iterator stationObsIndicesBegin, std::vector< size_t >::const_iterator stationObsIndicesEnd, const std::vector< size_t > &validObsIds, const std::vector< float > &globalData) const
void potentiallyRejectStreak(std::vector< size_t >::const_iterator stationIndicesBegin, std::vector< size_t >::const_iterator stationIndicesEnd, const std::vector< size_t > &validObsIds, size_t startOfStreakIndex, size_t endOfStreakIndex, std::vector< bool > &isRejected, std::string stationId) const
void applyFilter(const std::vector< bool > &, const Variables &, std::vector< std::vector< bool >> &) const override
void print(std::ostream &) const override
Options controlling the operation of stuck check filter.
StuckCheckCoreParameters core
oops::OptionalParameter< Variable > stationIdVariable
oops::Variables toOopsVariables() const
ObsAccessor createObsAccessor(const boost::optional< Variable > &stationIdVariable, const ioda::ObsSpace &obsdb)
Create an ObsAccessor object providing access to observations that need to be checked by the current ...
void sortTracksChronologically(const std::vector< size_t > &validObsIds, const ObsAccessor &obsAccessor, RecursiveSplitter &splitter)