14 #include "eckit/config/Configuration.h"
16 #include "ioda/ObsDataVector.h"
17 #include "ioda/ObsSpace.h"
18 #include "oops/util/abor1_cpp.h"
19 #include "oops/util/IntSetParser.h"
20 #include "oops/util/Logger.h"
21 #include "oops/util/missingValues.h"
36 const std::vector<float> & testValues,
39 const bool treatMissingAsOutOfBounds,
40 std::vector<bool> &flagged) {
41 const size_t nlocs = testValues.size();
42 ASSERT(apply.size() ==
nlocs);
43 ASSERT(flagged.size() ==
nlocs);
46 for (
size_t i = 0; i <
nlocs; ++i) {
49 if (minValue !=
missing && testValues[i] < minValue)
54 if (treatMissingAsOutOfBounds)
68 :
FilterBase(obsdb, parameters, flags, obserr), parameters_(parameters)
85 std::vector<std::vector<bool>> & flagged)
const {
96 throw eckit::UserError(
"ObsBoundsCheck: The list of test variables is empty", Here());
99 << testvars << std::endl;
107 const bool flagAllFilterVarsIfAnyTestVarOutOfBounds =
110 testvars.
nvars() == 1);
111 const bool onlyTestGoodFilterVarsForFlagAllFilterVars =
116 if (flagAllFilterVarsIfAnyTestVarOutOfBounds) {
119 if (onlyTestGoodFilterVarsForFlagAllFilterVars && filtervars.
nvars() != testvars.
nvars())
120 throw eckit::UserError(
"The number of 'primitive' (single-channel) test variables must "
121 "match that of 'primitive' filter variables when using the "
122 "'test only filter variables with passed qc when flagging all "
123 "filter variables' option.");
124 ASSERT(filtervars.
nvars() == flagged.size());
127 std::vector<bool> anyTestVarOutOfBounds(
obsdb_.nlocs(),
false);
128 size_t ifiltervar = 0;
130 std::vector<bool> testAtLocations = apply;
131 if (onlyTestGoodFilterVarsForFlagAllFilterVars) {
132 for (
size_t iloc=0; iloc < testAtLocations.size(); iloc++)
135 const std::vector<float> & testValues = singleChannelTestVar.values();
137 anyTestVarOutOfBounds);
141 for (std::vector<bool> &
f : flagged)
142 f = anyTestVarOutOfBounds;
145 throw eckit::UserError(
"The number of 'primitive' (single-channel) test variables must match "
146 "that of 'primitive' filter variables unless the 'flag all filter "
147 "variables if any test variable is out of bounds' option is set");
150 ASSERT(filtervars.
nvars() == flagged.size());
151 size_t ifiltervar = 0;
153 const std::vector<float> & testValues = singleChannelTestVar.values();
155 flagged[ifiltervar++]);
163 os <<
"ObsBoundsCheck: config = " <<
parameters_ << std::endl;
Base class for UFO QC filters.
void applyFilter(const std::vector< bool > &, const Variables &, std::vector< std::vector< bool >> &) const override
ObsBoundsCheck(ioda::ObsSpace &, const Parameters_ &, std::shared_ptr< ioda::ObsDataVector< int > >, std::shared_ptr< ioda::ObsDataVector< float > >)
void print(std::ostream &) const override
Parameters controlling the operation of the ObsBoundsCheck filter.
oops::Parameter< bool > onlyTestGoodFilterVarsForFlagAllFilterVars
oops::OptionalParameter< std::vector< Variable > > testVariables
oops::Parameter< bool > treatMissingAsOutOfBounds
oops::Parameter< bool > flagAllFilterVarsIfAnyTestVarOutOfBounds
oops::OptionalParameter< float > minvalue
Minimum allowed value of the tested variables.
oops::OptionalParameter< float > maxvalue
Maximum allowed value of the tested variables.
std::shared_ptr< ioda::ObsDataVector< int > > flags_
A range covering all "primitive" (single-channel) variables in a Variables object.
size_t nvars() const
Return the number of constituent "primitive" (single-channel) variables.
void flagWhereOutOfBounds(const std::vector< bool > &apply, const std::vector< float > &testValues, const float minValue, const float maxValue, const bool treatMissingAsOutOfBounds, std::vector< bool > &flagged)
Value maxValue(const std::map< Key, Value > &map)
integer function nlocs(this)
Return the number of observational locations in this Locations object.