15 #include "eckit/config/Configuration.h"
17 #include "ioda/distribution/Accumulator.h"
18 #include "ioda/ObsDataVector.h"
19 #include "ioda/ObsSpace.h"
20 #include "ioda/ObsVector.h"
21 #include "oops/base/Variables.h"
22 #include "oops/util/Logger.h"
23 #include "oops/util/missingValues.h"
36 void updateQCFlags(
const std::vector<float> *obsValues, std::vector<int>& qcflags) {
37 const float rmiss = util::missingValue(rmiss);
38 const int imiss = util::missingValue(imiss);
39 for (
size_t jobs = 0; jobs < qcflags.size(); ++jobs) {
40 if (qcflags[jobs] == imiss || !obsValues || (*obsValues)[jobs] == rmiss) {
53 : obsdb_(obsdb), nogeovals_(), nodiags_(), flags_(qcflags)
55 oops::Log::trace() <<
"QCmanager::QCmanager starting" << std::endl;
59 const oops::Variables &allSimulatedVars = obsdb.obsvariables();
60 const oops::Variables &initialSimulatedVars = obsdb.initial_obsvariables();
61 const oops::Variables &derivedSimulatedVars = obsdb.derived_obsvariables();
63 ASSERT(allSimulatedVars.size() == initialSimulatedVars.size() + derivedSimulatedVars.size());
64 ASSERT(
flags_->nvars() == allSimulatedVars.size());
67 const float rmiss = util::missingValue(rmiss);
68 const int imiss = util::missingValue(imiss);
73 for (
size_t jv = 0; jv < initialSimulatedVars.size(); ++jv) {
74 const ioda::ObsDataRow<float> ¤tObsValues = obs[jv];
75 ioda::ObsDataRow<int> ¤tQCFlags = (*qcflags)[obs.varnames()[jv]];
81 for (
size_t jv = 0; jv < derivedSimulatedVars.size(); ++jv) {
82 ioda::ObsDataRow<int> ¤tQCFlags = (*qcflags)[derivedSimulatedVars[jv]];
83 if (!obsdb.has(
"ObsValue", derivedSimulatedVars[jv])) {
86 std::vector<float> currentObsValues(
obsdb_.nlocs());
87 obsdb_.get_db(
"ObsValue", derivedSimulatedVars[jv], currentObsValues);
92 oops::Log::trace() <<
"QCmanager::QCmanager done" << std::endl;
98 const ioda::ObsVector & ,
100 oops::Log::trace() <<
"QCmanager postFilter" << std::endl;
103 const oops::Variables &allSimulatedVars =
obsdb_.obsvariables();
105 for (
size_t jv = 0; jv < allSimulatedVars.size(); ++jv) {
106 for (
size_t jobs = 0; jobs <
obsdb_.nlocs(); ++jobs) {
107 size_t iobs = allSimulatedVars.size() * jobs + jv;
113 oops::Log::trace() <<
"QCmanager postFilter done" << std::endl;
119 oops::Log::trace() <<
"QCmanager::~QCmanager starting" << std::endl;
120 oops::Log::info() << *
this;
121 oops::Log::trace() <<
"QCmanager::~QCmanager done" << std::endl;
127 const std::vector<std::pair<int, const char*>> cases{
154 const size_t numSpecialCases = 3;
157 const size_t gnlocs =
obsdb_.globalNumLocs();
159 const oops::Variables &allSimulatedVars =
obsdb_.obsvariables();
161 for (
size_t jvar = 0; jvar < allSimulatedVars.size(); ++jvar) {
162 std::unique_ptr<ioda::Accumulator<std::vector<size_t>>> accumulator =
163 obsdb_.distribution()->createAccumulator<
size_t>(cases.size());
165 for (
size_t jobs = 0; jobs <
nlocs; ++jobs) {
166 const int actualFlag = (*flags_)[jvar][jobs];
167 for (
size_t jcase = 0; jcase < cases.size(); ++jcase)
168 if (actualFlag == cases[jcase].first)
169 accumulator->addTerm(jobs, jcase, 1);
171 const std::vector<std::size_t> counts = accumulator->computeResult();
173 if (
obsdb_.comm().rank() == 0) {
174 const std::string info =
"QC " +
flags_->obstype() +
" " + allSimulatedVars[jvar] +
": ";
177 for (
size_t i = numSpecialCases; i < counts.size(); ++i)
179 os << info << counts[i] <<
" " << cases[i].second <<
"." << std::endl;
182 const size_t nGNSSRO = counts[1] + counts[2];
184 os << info << nGNSSRO <<
" rejected by GNSSRO reality check." << std::endl;
187 const size_t npass = counts[0];
188 os << info << npass <<
" passed out of " << gnlocs <<
" observations." << std::endl;
191 const size_t numRecognizedFlags = std::accumulate(counts.begin(), counts.end(), 0);
192 ASSERT(numRecognizedFlags == gnlocs);
std::shared_ptr< ioda::ObsDataVector< int > > flags_
void postFilter(const ioda::ObsVector &, const ioda::ObsVector &, const ObsDiagnostics &) override
QCmanager(ioda::ObsSpace &, const eckit::Configuration &, std::shared_ptr< ioda::ObsDataVector< int > >, std::shared_ptr< ioda::ObsDataVector< float > >)
void print(std::ostream &) const override
constexpr int modelobthresh
void updateQCFlags(const std::vector< float > *obsValues, std::vector< int > &qcflags)
integer function nlocs(this)
Return the number of observational locations in this Locations object.