UFO
BayesianBackgroundQCFlags.cc
Go to the documentation of this file.
1 /*
2  * (C) Crown Copyright 2021 Met Office
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 
9 
10 #include <iomanip>
11 #include <iostream>
12 #include <sstream>
13 #include <vector>
14 
15 #include "ioda/ObsDataVector.h"
16 #include "ioda/ObsSpace.h"
17 
18 #include "oops/util/Logger.h"
19 #include "ufo/filters/QCflags.h"
21 
22 namespace ufo {
23 
25 (ioda::ObsSpace & obsdb,
26  const Parameters_ & parameters,
27  std::shared_ptr<ioda::ObsDataVector<int> > flags,
28  std::shared_ptr<ioda::ObsDataVector<float> > obserr)
29  : FilterBase(obsdb, parameters, flags, obserr), parameters_(parameters)
30 {
31  oops::Log::trace() << "BayesianBackgroundQCFlags constructor" << std::endl;
32 }
33 
35  oops::Log::trace() << "BayesianBackgroundQCFlags destructor" << std::endl;
36 }
37 
38 std::string BayesianBackgroundQCFlags::getPGEsubstituteName(const std::string &varname) const {
39  const auto PGEsubstituteNames = parameters_.PGEsubstituteNames.value();
40  const auto it = PGEsubstituteNames.find(varname);
41  if (it != PGEsubstituteNames.end())
42  return it->second;
43  else
44  return varname;
45 }
46 
47 void BayesianBackgroundQCFlags::setFlags(const std::string& varname,
48  const std::vector<bool>& apply,
49  std::vector<bool>& flagged) const {
50  const float missingValueFloat = util::missingValue(missingValueFloat);
51  const int missingValueInt = util::missingValue(missingValueInt);
52  const size_t nlocs = obsdb_.nlocs();
53  // PGE multiplication factor used to store PGE values for later use.
54  const float PGEMult = 1000.0;
55  // Missing data indicator for packed PGEs (for compatibility with OPS).
56  const float PGEMDI = 1.111;
57  // PGE rejection limit.
58  const float PGECrit = parameters_.PGEParameters.PGE_PGECrit.value();
59  // Packed PGE rejection limit.
60  const float packedPGECrit = PGEMult * PGECrit;
61 
62  // Sometimes the PGE of one variable is used to set the QC flags of another;
63  // this happens for (e.g.) wind u and v components.
64  // By default varPGE = varname.
65  const std::string varPGE = getPGEsubstituteName(varname);
66 
67  // Get QC flags.
68  std::vector <int> QCflags(nlocs, missingValueInt);
69  if (obsdb_.has("QCFlags", varname))
70  obsdb_.get_db("QCFlags", varname, QCflags);
71  else
72  throw eckit::BadValue(varname + "@QCFlags not present", Here());
73 
74  // Get the PGE values that each observation had after
75  // the Bayesian background and buddy checks were applied.
76  // If the checks were not applied, default to using
77  // the existing PGE values.
78  if (obsdb_.has("GrossErrorProbabilityBuddyCheck", varPGE)) {
79  // Buddy check was applied.
80  std::vector <float> buddyCheckPGEs(nlocs, missingValueFloat);
81  obsdb_.get_db("GrossErrorProbabilityBuddyCheck", varPGE, buddyCheckPGEs);
82  for (size_t iloc = 0; iloc < nlocs; ++iloc) {
83  if (!apply[iloc]) continue;
84  if (buddyCheckPGEs[iloc] == PGEMDI) {
86  flagged[iloc] = true;
87  } else if (buddyCheckPGEs[iloc] >= PGECrit) {
90  flagged[iloc] = true;
91  }
92  }
93  } else if (obsdb_.has("GrossErrorProbability", varPGE)) {
94  // Get the PGE values that each observation had before
95  // the Bayesian background and buddy checks were applied.
96  std::vector <float> PGEs(nlocs, missingValueFloat);
97  obsdb_.get_db("GrossErrorProbability", varPGE, PGEs);
98  // Buddy check was not applied.
99  for (size_t iloc = 0; iloc < nlocs; ++iloc) {
100  if (apply[iloc] && PGEs[iloc] >= packedPGECrit) {
102  flagged[iloc] = true;
103  }
104  }
105  } else {
106  std::stringstream errormessage;
107  errormessage << "At least one of "
108  << varname + "@GrossErrorProbability or "
109  << varname + "@GrossErrorProbabilityBuddyCheck must be present"
110  << std::endl;
111  throw eckit::BadValue(errormessage.str(), Here());
112  }
113 
114  // Save modified flags.
115  obsdb_.put_db("QCFlags", varname, QCflags);
116 }
117 
118 void BayesianBackgroundQCFlags::applyFilter(const std::vector<bool> & apply,
119  const Variables & filtervars,
120  std::vector<std::vector<bool>> & flagged) const {
121  print(oops::Log::trace());
122 
123  for (size_t ivar = 0; ivar < filtervars.nvars(); ++ivar) {
124  const std::string varname = filtervars.variable(ivar).variable();
125  setFlags(varname, apply, flagged[ivar]);
126  }
127 }
128 
129 void BayesianBackgroundQCFlags::print(std::ostream & os) const {
130  os << "BayesianBackgroundQCFlags: config = " << parameters_ << std::endl;
131 }
132 
133 } // namespace ufo
Parameters_ parameters_
Parameters used in this filter.
std::string getPGEsubstituteName(const std::string &varname) const
void print(std::ostream &) const override
void setFlags(const std::string &varname, const std::vector< bool > &apply, std::vector< bool > &flagged) const
void applyFilter(const std::vector< bool > &, const Variables &, std::vector< std::vector< bool >> &) const override
BayesianBackgroundQCFlags(ioda::ObsSpace &, const Parameters_ &, std::shared_ptr< ioda::ObsDataVector< int > >, std::shared_ptr< ioda::ObsDataVector< float > >)
Parameters controlling the operation of the BayesianBackgroundQCFlags filter.
ProbabilityOfGrossErrorParameters PGEParameters
oops::Parameter< std::map< std::string, std::string > > PGEsubstituteNames
Base class for UFO QC filters.
Definition: FilterBase.h:45
ioda::ObsSpace & obsdb_
oops::Parameter< float > PGE_PGECrit
PGE rejection limit.
const std::string & variable() const
Definition: Variable.cc:99
size_t nvars() const
Return the number of constituent "primitive" (single-channel) variables.
Definition: Variables.cc:104
Variable variable(const size_t) const
Return a given constituent "primitive" (single-channel) variable.
Definition: Variables.cc:114
@ FinalRejectFlag
Final QC flag.
@ BuddyRejectFlag
PGE>0.5 after buddy check.
integer function nlocs(this)
Return the number of observational locations in this Locations object.
Definition: RunCRTM.h:27