UFO
AssignError.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2019 UCAR
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 <algorithm>
11 #include <set>
12 
13 #include "ioda/ObsDataVector.h"
14 #include "oops/base/Variables.h"
15 #include "oops/util/missingValues.h"
17 #include "ufo/filters/QCflags.h"
18 
19 namespace ufo {
20 
21 // -----------------------------------------------------------------------------
22 
24 
25 // -----------------------------------------------------------------------------
26 
27 void AssignErrorParameters::deserialize(util::CompositePath &path,
28  const eckit::Configuration &config) {
29  oops::Parameters::deserialize(path, config);
30 
31  // These checks should really be done at the validation stage (using JSON Schema),
32  // but this isn't supported yet, so this is better than nothing.
33  if ((errorParameter.value() == boost::none && errorFunction.value() == boost::none) ||
34  (errorParameter.value() != boost::none && errorFunction.value() != boost::none))
35  throw eckit::UserError(path.path() +
36  ": Exactly one of the 'error parameter' and 'error function' "
37  "options must be present");
38 }
39 
40 // -----------------------------------------------------------------------------
41 
43  : allvars_(), parameters_(parameters) {
44  if (parameters_.errorFunction.value() != boost::none) {
46  }
47 }
48 
49 // -----------------------------------------------------------------------------
50 
51 void AssignError::apply(const Variables & vars,
52  const std::vector<std::vector<bool>> &,
53  const ObsFilterData & data,
54  int /*filterQCflag*/,
56  ioda::ObsDataVector<float> & obserr) const {
57  oops::Log::debug() << " AssignError input obserr: " << obserr << std::endl;
58  const float missing = util::missingValue(missing);
59  // If float error is specified
60  if (parameters_.errorParameter.value() != boost::none) {
61  float error = *parameters_.errorParameter.value();
62  for (size_t jv = 0; jv < vars.nvars(); ++jv) {
63  size_t iv = obserr.varnames().find(vars.variable(jv).variable());
64  size_t kv = flags.varnames().find(vars.variable(jv).variable());
65  for (size_t jobs = 0; jobs < obserr.nlocs(); ++jobs) {
66  if (flags[kv][jobs] == QCflags::pass) obserr[iv][jobs] = error;
67  }
68  }
69  // If variable is specified
70  } else if (parameters_.errorFunction.value() != boost::none) {
71  const Variable &errorvar = *parameters_.errorFunction.value();
72  ASSERT(errorvar.size() == 1 || errorvar.size() == vars.nvars());
73  ioda::ObsDataVector<float> errors(data.obsspace(), errorvar.toOopsVariables(),
74  errorvar.group(), false);
75  data.get(errorvar, errors);
76 
77  // if assigned error function is 1D variable, apply the same error to all variables
78  // error_jv = {0, 0, 0, ..., 0} for all nvars
79  std::vector<size_t> error_jv(vars.nvars(), 0);
80  // if multiple variables are in the assigned error function, apply different error to different
81  // variables
82  // error_jv = {0, 1, 2, ..., nvars-1}
83  if (errorvar.size() == vars.nvars()) {
84  std::iota(error_jv.begin(), error_jv.end(), 0);
85  }
86 
87  // loop over all variables to update
88  for (size_t jv = 0; jv < vars.nvars(); ++jv) {
89  // find current variable index in obserr
90  size_t iv = obserr.varnames().find(vars.variable(jv).variable());
91  size_t kv = flags.varnames().find(vars.variable(jv).variable());
92  for (size_t jobs = 0; jobs < obserr.nlocs(); ++jobs) {
93  if (flags[kv][jobs] == QCflags::pass && errors[error_jv[jv]][jobs] != missing)
94  obserr[iv][jobs] = errors[error_jv[jv]][jobs];
95  }
96  }
97  }
98  oops::Log::debug() << " AssignError output obserr: " << obserr << std::endl;
99 }
100 
101 // -----------------------------------------------------------------------------
102 
103 } // namespace ufo
void apply(const Variables &, const std::vector< std::vector< bool >> &, const ObsFilterData &, int, ioda::ObsDataVector< int > &, ioda::ObsDataVector< float > &) const override
Definition: AssignError.cc:51
const Parameters_ parameters_
Definition: AssignError.h:55
Variables allvars_
Definition: AssignError.h:54
AssignError(const Parameters_ &)
Definition: AssignError.cc:42
oops::OptionalParameter< Variable > errorFunction
Definition: AssignError.h:31
void deserialize(util::CompositePath &path, const eckit::Configuration &config) override
Definition: AssignError.cc:27
oops::OptionalParameter< float > errorParameter
Definition: AssignError.h:30
ObsFilterData provides access to all data related to an ObsFilter.
ioda::ObsSpace & obsspace() const
Returns reference to ObsSpace associated with ObsFilterData.
void get(const Variable &varname, std::vector< float > &values) const
Fills a std::vector with values of the specified variable.
const std::string & variable() const
Definition: Variable.cc:99
const std::string & group() const
Definition: Variable.cc:116
oops::Variables toOopsVariables() const
Definition: Variable.cc:139
size_t size() const
Definition: Variable.cc:78
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
constexpr int pass
Definition: QCflags.h:14
constexpr int missing
Definition: QCflags.h:20
Definition: RunCRTM.h:27
static FilterActionMaker< AssignError > makerAssignErr_("assign error")