UFO
BackgroundCheck.cc
Go to the documentation of this file.
1 /* * (C) Copyright 2017-2018 UCAR
2  *
3  * This software is licensed under the terms of the Apache Licence Version 2.0
4  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5  */
6 
8 
9 #include <algorithm>
10 #include <cmath>
11 #include <iomanip>
12 #include <iostream>
13 #include <limits>
14 #include <set>
15 #include <string>
16 #include <vector>
17 
18 #include "eckit/config/Configuration.h"
19 
20 #include "ioda/ObsDataVector.h"
21 #include "ioda/ObsSpace.h"
22 
23 #include "oops/util/abor1_cpp.h"
24 #include "oops/util/IntSetParser.h"
25 #include "oops/util/Logger.h"
26 
28 #include "ufo/filters/QCflags.h"
29 
30 namespace ufo {
31 
32 // -----------------------------------------------------------------------------
33 
34 BackgroundCheck::BackgroundCheck(ioda::ObsSpace & obsdb, const Parameters_ & parameters,
35  std::shared_ptr<ioda::ObsDataVector<int> > flags,
36  std::shared_ptr<ioda::ObsDataVector<float> > obserr)
37  : FilterBase(obsdb, parameters, flags, obserr), parameters_(parameters)
38 {
39  oops::Log::trace() << "BackgroundCheck constructor" << std::endl;
40 
41  // Typical use would be HofX group, but during testing, we include option for GsiHofX
42  std::string test_hofx = parameters_.test_hofx.value();
43 
45  for (const Variable & var : *(parameters_.functionAbsoluteThreshold.value()))
46  allvars_ += var;
47  }
48  allvars_ += Variables(filtervars_, test_hofx);
49  // Add BG error variable if threshold is required wrt BG error:
50  for (size_t jv = 0; jv < filtervars_.size(); ++jv) {
51  if (parameters_.thresholdWrtBGerror.value()) {
53  }
54  }
55  ASSERT(parameters_.threshold.value() ||
59  ASSERT(!parameters_.threshold.value() &&
61  ASSERT(!parameters_.functionAbsoluteThreshold.value()->empty());
62  }
63  if (parameters_.thresholdWrtBGerror.value()) {
64  ASSERT(parameters_.threshold.value());
65  }
66 }
67 
68 // -----------------------------------------------------------------------------
69 
71  oops::Log::trace() << "BackgroundCheck destructed" << std::endl;
72 }
73 
74 // -----------------------------------------------------------------------------
75 /// Return the name of the variable containing the background error estimate of the
76 /// specified filter variable.
77 
79  return Variable(filterVariable.variable() + "_background_error@ObsDiag");
80 }
81 
82 // -----------------------------------------------------------------------------
83 
84 void BackgroundCheck::applyFilter(const std::vector<bool> & apply,
85  const Variables & filtervars,
86  std::vector<std::vector<bool>> & flagged) const {
87  oops::Log::trace() << "BackgroundCheck postFilter" << std::endl;
88  const oops::Variables observed = obsdb_.obsvariables();
89  const float missing = util::missingValue(missing);
90  oops::Log::debug() << "BackgroundCheck obserr: " << *obserr_ << std::endl;
91 
92  ioda::ObsDataVector<float> obs(obsdb_, filtervars.toOopsVariables(), "ObsValue");
93 
94  std::string test_hofx = parameters_.test_hofx.value();
95  Variables varhofx(filtervars_, test_hofx);
96 
97 // Get function absolute threshold
99 // Get function absolute threshold info from configuration
100  const Variable &rtvar = parameters_.functionAbsoluteThreshold.value()->front();
101  ioda::ObsDataVector<float> function_abs_threshold(obsdb_, rtvar.toOopsVariables());
102  data_.get(rtvar, function_abs_threshold);
103 
104  for (size_t jv = 0; jv < filtervars.nvars(); ++jv) {
105  size_t iv = observed.find(filtervars.variable(jv).variable());
106 // H(x)
107  std::vector<float> hofx;
108  data_.get(varhofx.variable(jv), hofx);
109  for (size_t jobs = 0; jobs < obsdb_.nlocs(); ++jobs) {
110  if (apply[jobs] && (*flags_)[iv][jobs] == QCflags::pass &&
111  (*obserr_)[iv][jobs] != util::missingValue((*obserr_)[iv][jobs])) {
112  ASSERT(obs[jv][jobs] != util::missingValue(obs[jv][jobs]));
113  ASSERT(hofx[jobs] != util::missingValue(hofx[jobs]));
114 
115 // Threshold for current observation
116  float zz = function_abs_threshold[jv][jobs];
117 // Check distance from background
118  if (std::abs(static_cast<float>(hofx[jobs]) - obs[jv][jobs]) > zz) {
119  flagged[jv][jobs] = true;
120  }
121  }
122  }
123  }
124  } else {
125  Variables varbias(filtervars_, "ObsBiasData");
126  for (size_t jv = 0; jv < filtervars.nvars(); ++jv) {
127  size_t iv = observed.find(filtervars.variable(jv).variable());
128 // H(x) (including bias correction)
129  std::vector<float> hofx;
130  data_.get(varhofx.variable(jv), hofx);
131 // H(x) error
132  std::vector<float> hofxerr;
133  bool thresholdWrtBGerror = parameters_.thresholdWrtBGerror.value();
134  if (thresholdWrtBGerror) {
135  data_.get(backgrErrVariable(filtervars[jv]), hofxerr);
136  }
137 // Bias correction (only read in if removeBiasCorrection is set to true, otherwise
138 // set to zero).
139  std::vector<float> bias(obsdb_.nlocs(), 0.0);
141  data_.get(varbias.variable(jv), bias);
142  }
143 
144 // Threshold for current variable
145  std::vector<float> abs_thr(obsdb_.nlocs(), std::numeric_limits<float>::max());
146  std::vector<float> thr(obsdb_.nlocs(), std::numeric_limits<float>::max());
147  if (parameters_.absoluteThreshold.value())
149  if (parameters_.threshold.value())
151 
152  for (size_t jobs = 0; jobs < obsdb_.nlocs(); ++jobs) {
153  if (apply[jobs] && (*flags_)[iv][jobs] == QCflags::pass &&
154  (*obserr_)[iv][jobs] != util::missingValue((*obserr_)[iv][jobs])) {
155  ASSERT(obs[jv][jobs] != util::missingValue(obs[jv][jobs]));
156  ASSERT(hofx[jobs] != util::missingValue(hofx[jobs]));
157  ASSERT(bias[jobs] != util::missingValue(bias[jobs]));
158 
159  const std::vector<float> &errorMultiplier = thresholdWrtBGerror ?
160  hofxerr : (*obserr_)[iv];
161 // Threshold for current observation
162  float zz = (thr[jobs] == std::numeric_limits<float>::max()) ? abs_thr[jobs] :
163  std::min(abs_thr[jobs], thr[jobs] * errorMultiplier[jobs]);
164 
165  ASSERT(zz < std::numeric_limits<float>::max() && zz > 0.0);
166 
167 // Check distance from background. hofx includes bias correction.
168 // If removeBiasCorrection is set to true, `bias` contains bias correction, and
169 // it is removed from hofx.
170 // Otherwise, `bias` is set to zero, and bias correction is not removed from hofx.
171  if (std::abs(hofx[jobs] - obs[jv][jobs] - bias[jobs]) > zz) {
172  flagged[jv][jobs] = true;
173  }
174  }
175  }
176  }
177  }
178 }
179 
180 // -----------------------------------------------------------------------------
181 
182 void BackgroundCheck::print(std::ostream & os) const {
183  os << "BackgroundCheck::print not yet implemented ";
184 }
185 
186 // -----------------------------------------------------------------------------
187 
188 } // namespace ufo
void applyFilter(const std::vector< bool > &, const Variables &, std::vector< std::vector< bool >> &) const override
Variable backgrErrVariable(const Variable &filterVariable) const
Return the name of the variable containing the background error estimate of the specified filter vari...
BackgroundCheck(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 BackgroundCheck filter.
oops::OptionalParameter< std::string > absoluteThreshold
oops::Parameter< std::string > test_hofx
Name of the HofX group used to replace the default group (default is HofX)
oops::Parameter< bool > removeBiasCorrection
The filter uses bias-corrected H(x) unless remove bias correction is set to true.
oops::OptionalParameter< std::string > threshold
oops::Parameter< bool > thresholdWrtBGerror
oops::OptionalParameter< std::vector< Variable > > functionAbsoluteThreshold
Base class for UFO QC filters.
Definition: FilterBase.h:45
ufo::Variables filtervars_
Definition: FilterBase.h:60
void get(const Variable &varname, std::vector< float > &values) const
Fills a std::vector with values of the specified variable.
ufo::Variables allvars_
std::shared_ptr< ioda::ObsDataVector< float > > obserr_
ioda::ObsSpace & obsdb_
std::shared_ptr< ioda::ObsDataVector< int > > flags_
const std::string & variable() const
Definition: Variable.cc:99
oops::Variables toOopsVariables() const
Definition: Variable.cc:139
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
oops::Variables toOopsVariables() const
Definition: Variables.cc:156
size_t size() const
Return the number of constituent Variable objects (some of which may contain multiple channels).
Definition: Variables.cc:92
constexpr int pass
Definition: QCflags.h:14
constexpr int missing
Definition: QCflags.h:20
Definition: RunCRTM.h:27
util::Duration abs(const util::Duration &duration)
std::vector< float > getScalarOrFilterData(const std::string &strfactor, const ObsFilterData &data)
Function to fill in a vector with either a scalar or data from ObsFilterData.