18 #include "ioda/ObsDataVector.h"
19 #include "ioda/ObsSpace.h"
21 #include "oops/util/Logger.h"
46 ioda::ObsSpace & obsdb,
50 :
FilterBase(obsdb, parameters, flags, obserr), parameters_(parameters)
52 oops::Log::trace() <<
"ProfileBackgroundCheck constructor" << std::endl;
61 oops::Log::trace() <<
"ProfileBackgroundCheck destructed" << std::endl;
69 std::vector<std::vector<bool>> & flagged)
const {
70 oops::Log::trace() <<
"ProfileBackgroundCheck postFilter" << std::endl;
71 const oops::Variables observed =
obsdb_.obsvariables();
80 const std::vector<size_t> &unique =
obsdb_.recidx_all_recnums();
82 for (
size_t iUnique : unique)
87 std::vector<float> abs_thr(
obsdb_.nlocs(), std::numeric_limits<float>::max());
88 std::vector<float> rel_thr(
obsdb_.nlocs(), std::numeric_limits<float>::max());
95 for (
size_t jv = 0; jv < filtervars.
nvars(); ++jv) {
98 std::vector<float> hofx;
102 for (
const auto& iprofile : unique) {
103 std::vector<size_t> obs_numbers =
obsdb_.recidx_vector(iprofile);
105 double total_diff = 0;
107 bool using_rel_thresh =
false;
108 bool first_ob =
true;
109 float profile_threshold = 0;
115 for (
size_t jobs : obs_numbers) {
117 ASSERT((*
obserr_)[iv][jobs] != util::missingValue((*
obserr_)[iv][jobs]));
118 ASSERT(obs[jv][jobs] != util::missingValue(obs[jv][jobs]));
119 ASSERT(hofx[jobs] != util::missingValue(hofx[jobs]));
122 if (rel_thr[jobs] == std::numeric_limits<float>::max()) {
123 using_rel_thresh =
false;
124 profile_threshold = abs_thr[jobs];
126 using_rel_thresh =
true;
127 profile_threshold = rel_thr[jobs];
130 ASSERT(profile_threshold < std::numeric_limits<float>::max() &&
131 profile_threshold > 0.0f);
135 const float yy = obs[jv][jobs] - bias[jv][jobs];
138 if ((*
obserr_)[iv][jobs] > 0) {
140 if (using_rel_thresh) {
142 total_diff += std::pow((hofx[jobs] - yy) / (*
obserr_)[iv][jobs], 2);
145 total_diff += std::pow(hofx[jobs] - yy, 2);
152 if (total_nobs > 0) {
153 total_diff = std::pow(total_diff / total_nobs, 0.5);
156 " rms diff is " << total_diff << std::endl;
159 for (
size_t jobs : obs_numbers) {
162 if (total_diff >
static_cast<double>(profile_threshold)) flagged[jv][jobs] =
true;
172 os <<
"ProfileBackgroundCheck: config = " <<
parameters_ << std::endl;
Base class for UFO QC filters.
ufo::Variables filtervars_
void get(const Variable &varname, std::vector< float > &values) const
Fills a std::vector with values of the specified variable.
std::shared_ptr< ioda::ObsDataVector< float > > obserr_
std::shared_ptr< ioda::ObsDataVector< int > > flags_
~ProfileBackgroundCheck()
ProfileBackgroundCheck(ioda::ObsSpace &, const Parameters_ &, std::shared_ptr< ioda::ObsDataVector< int > >, std::shared_ptr< ioda::ObsDataVector< float > >)
void print(std::ostream &) const override
void applyFilter(const std::vector< bool > &, const Variables &, std::vector< std::vector< bool >> &) const override
Apply the profile background check filter.
Parameters controlling the operation of the ProfileBackgroundCheck filter.
oops::OptionalParameter< std::string > relativeThreshold
oops::OptionalParameter< std::string > absoluteThreshold
const std::string & variable() const
size_t nvars() const
Return the number of constituent "primitive" (single-channel) variables.
Variable variable(const size_t) const
Return a given constituent "primitive" (single-channel) variable.
oops::Variables toOopsVariables() const
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.