13 #include "eckit/config/Configuration.h"
15 #include "ioda/ObsDataVector.h"
16 #include "ioda/ObsSpace.h"
18 #include "oops/util/FloatCompare.h"
19 #include "oops/util/Logger.h"
31 :
FilterBase(obsdb, parameters, flags, obserr),
32 parameters_(parameters)
34 oops::Log::trace() <<
"ProbabilityGrossErrorWholeReport contructor starting" << std::endl;
40 oops::Log::trace() <<
"ProbabilityGrossErrorWholeReport destructed" << std::endl;
47 std::vector<std::vector<bool>> & flagged)
const {
48 oops::Log::trace() <<
"ProbabilityGrossErrorWholeReport preProcess" << std::endl;
50 const float missingValueFloat = util::missingValue(missingValueFloat);
53 const size_t nvars = filtervars.
nvars();
55 const float PGEMDI = 1.111f;
57 const float PGEMult = 1000.0;
62 std::vector<float> PBadRep(
nlocs);
64 std::vector<float> PdReport(
nlocs, 1.0f);
66 std::vector<float> PdBad(nvars);
68 std::vector<float> PdBad_synop(nvars);
70 std::vector<float> PdBad_bogus(nvars);
72 std::vector<std::vector<float>> PdBad_used(nvars, std::vector<float>(
nlocs));
74 std::vector<bool> notUsed(nvars);
76 std::vector<std::string> varname(nvars);
78 std::vector<std::vector<float>> varPGEBd(nvars, std::vector<float>(
nlocs));
80 std::vector<std::vector<float>> varPGE(nvars, std::vector<float>(
nlocs));
82 std::vector<std::vector<float>> varPGEFinal(nvars, std::vector<float>(
nlocs));
84 std::vector<std::vector<int>> varQCflags(nvars, std::vector<int>(
nlocs));
86 for (
size_t ivar = 0; ivar < filtervars.
nvars(); ++ivar) {
89 if (
obsdb_.has(
"GrossErrorProbability", varname[ivar]) &&
90 obsdb_.has(
"GrossErrorProbabilityTotal", varname[ivar]) &&
91 obsdb_.has(
"GrossErrorProbabilityFinal", varname[ivar]) &&
92 obsdb_.has(
"QCFlags", varname[ivar])) {
93 obsdb_.get_db(
"GrossErrorProbability", varname[ivar], varPGEBd[ivar]);
94 obsdb_.get_db(
"GrossErrorProbabilityTotal", varname[ivar], varPGE[ivar]);
95 obsdb_.get_db(
"GrossErrorProbabilityFinal", varname[ivar], varPGEFinal[ivar]);
96 obsdb_.get_db(
"QCFlags", varname[ivar], varQCflags[ivar]);
98 std::stringstream errormessage;
99 errormessage <<
"GrossErrorProbability/" + varname[ivar] +
", "
100 <<
"GrossErrorProbabilityTotal/" + varname[ivar] +
", "
101 <<
"GrossErrorProbabilityFinal/" + varname[ivar] +
", and "
102 <<
"QCFlags/" + varname[ivar] +
" must all be present"
104 throw eckit::BadValue(errormessage.str(), Here());
107 PdBad[ivar] = filtervars[ivar].options().getFloat(
"probability_density_bad", 0.1f);
108 if (filtervars[ivar].options().has(
"synop_probability_density_bad")) {
109 PdBad_synop[ivar] = filtervars[ivar].options().getFloat(
"synop_probability_density_bad");
111 PdBad_synop[ivar] = PdBad[ivar];
113 if (filtervars[ivar].options().has(
"bogus_probability_density_bad")) {
114 PdBad_bogus[ivar] = filtervars[ivar].options().getFloat(
"bogus_probability_density_bad");
116 PdBad_bogus[ivar] = PdBad[ivar];
119 notUsed[ivar] = filtervars[ivar].options().getBool(
"not_used_in_whole_report",
false);
122 std::vector<float> ReportPGE(
nlocs);
123 if (
obsdb_.has(
"MetaData",
"GrossErrorProbabilityReport")) {
124 obsdb_.get_db(
"MetaData",
"GrossErrorProbabilityReport", ReportPGE);
126 throw eckit::BadValue(
"MetaData/GrossErrorProbabilityReport not present", Here());
129 std::vector<int> ObsType(
nlocs);
130 if (
obsdb_.has(
"MetaData",
"ObsType")) {
131 obsdb_.get_db(
"MetaData",
"ObsType", ObsType);
133 throw eckit::BadValue(
"MetaData/ObsType not present", Here());
137 for (
size_t jobs = 0; jobs <
nlocs; ++jobs) {
138 if (apply[jobs] && (ReportPGE[jobs] > 0)) {
140 float PdBadRep = 1.0f;
141 for (
size_t ivar = 0; ivar < filtervars.
nvars(); ++ivar) {
142 if (!notUsed[ivar]) {
143 PdReport[jobs] *= varPGE[ivar][jobs];
145 PdBad_used[ivar][jobs] = PdBad_bogus[ivar];
153 PdBad_used[ivar][jobs] = PdBad_synop[ivar];
155 PdBad_used[ivar][jobs] = PdBad[ivar];
157 PdBadRep *= PdBad_used[ivar][jobs];
160 PBadRep[jobs] = ReportPGE[jobs];
161 PdBadRep *= PBadRep[jobs];
162 PdReport[jobs] = PdBadRep + ((1.0f - PBadRep[jobs]) * PdReport[jobs]);
163 if (PdReport[jobs] > 0.0f) {
164 ReportPGE[jobs] = PdBadRep / PdReport[jobs];
171 bool secondComponentOfTwo =
false;
172 for (
size_t ivar = 0; ivar < filtervars.
nvars(); ++ivar) {
173 secondComponentOfTwo = filtervars[ivar].options().getBool(
"second_component_of_two",
false);
174 if (secondComponentOfTwo) {
175 varPGEBd[ivar] = varPGEBd[ivar - 1];
176 varPGEFinal[ivar] = varPGEFinal[ivar - 1];
177 varQCflags[ivar] = varQCflags[ivar - 1];
178 flagged[ivar] = flagged[ivar - 1];
180 for (
size_t jobs = 0; jobs <
nlocs; ++jobs) {
181 if (apply[jobs] && (ReportPGE[jobs] > 0) && (PdReport[jobs] > 0)) {
182 if (varPGEFinal[ivar][jobs] < PGEMult) {
185 float const PGE0 = std::modf(varPGEFinal[ivar][jobs], &intpart);
186 float PdProduct = 1.0f;
187 for (
size_t jvar = 0; jvar < filtervars.
nvars(); ++jvar) {
188 if ((jvar != ivar) && !notUsed[jvar]) {
189 PdProduct *= varPGE[jvar][jobs];
195 PGE1 = ReportPGE[jobs] + varPGEBd[ivar][jobs] -
196 ReportPGE[jobs] * varPGEBd[ivar][jobs];
198 PGE1 = ReportPGE[jobs] + (PdBad_used[ivar][jobs] * PdProduct) * PGE0 *
199 (1.0f - PBadRep[jobs])/PdReport[jobs];
201 varPGEFinal[ivar][jobs] = floor(PGE1 * PGEMult) + PGE0;
202 if (PGE1 >= PGECrit) {
204 flagged[ivar][jobs] =
true;
206 if (
std::abs(varPGEBd[ivar][jobs] - PGEMDI) > 0.001f) {
207 varPGEBd[ivar][jobs] = PGE1;
214 obsdb_.put_db(
"GrossErrorProbability", varname[ivar], varPGEBd[ivar]);
215 obsdb_.put_db(
"GrossErrorProbabilityFinal", varname[ivar], varPGEFinal[ivar]);
216 obsdb_.put_db(
"QCFlags", varname[ivar], varQCflags[ivar]);
218 obsdb_.put_db(
"MetaData",
"GrossErrorProbabilityReport", ReportPGE);
224 os <<
"ProbabilityGrossErrorWholeReport: config = " <<
parameters_ << std::endl;
Base class for UFO QC filters.
ProbabilityGrossErrorWholeReport(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
~ProbabilityGrossErrorWholeReport()
Parameters controlling the operation of the ProbabilityGrossErrorWholeReport filter.
ProbabilityOfGrossErrorParameters PGEParameters
oops::Parameter< float > PGE_PGECrit
PGE rejection limit.
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.
@ MetarAuto
automatic metar
@ MetarManual
non-automatic metar
@ SynopManual
non-automatic synop
@ SynopAuto
automatic synop
@ BackRejectFlag
PGE>0.5 after backgr check.
integer function nlocs(this)
Return the number of observational locations in this Locations object.
util::Duration abs(const util::Duration &duration)