UFO
QCmanager.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2018-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 <string>
11 #include <vector>
12 
13 #include "eckit/config/Configuration.h"
14 
15 #include "ioda/ObsDataVector.h"
16 #include "ioda/ObsSpace.h"
17 #include "ioda/ObsVector.h"
18 #include "oops/base/Variables.h"
19 #include "oops/interface/ObsFilter.h"
20 #include "oops/util/Logger.h"
21 #include "oops/util/missingValues.h"
22 #include "ufo/filters/QCflags.h"
23 
24 namespace ufo {
25 
26 // Presets for QC filters could be performed in a function outside of any class.
27 // We keep them as a filter for now. The main reason for this is to be able to use
28 // the factory for models not in UFO/IODA.
29 
30 // -----------------------------------------------------------------------------
31 
32 QCmanager::QCmanager(ioda::ObsSpace & obsdb, const eckit::Configuration & config,
33  std::shared_ptr<ioda::ObsDataVector<int> > qcflags,
34  std::shared_ptr<ioda::ObsDataVector<float> > obserr)
35  : obsdb_(obsdb), config_(config), nogeovals_(), nodiags_(), flags_(qcflags),
36  observed_(obsdb.obsvariables())
37 {
38  oops::Log::trace() << "QCmanager::QCmanager starting " << config_ << std::endl;
39 
40  ASSERT(qcflags);
41  ASSERT(obserr);
42 
43  ASSERT(flags_->nvars() == observed_.size());
44  ASSERT(flags_->nlocs() == obsdb_.nlocs());
45  ASSERT(obserr->nvars() == observed_.size());
46  ASSERT(obserr->nlocs() == obsdb_.nlocs());
47 
48  const float rmiss = util::missingValue(rmiss);
49  const int imiss = util::missingValue(imiss);
50 
51  const ioda::ObsDataVector<float> obs(obsdb, observed_, "ObsValue");
52 
53  for (size_t jv = 0; jv < observed_.size(); ++jv) {
54  for (size_t jobs = 0; jobs < obsdb_.nlocs(); ++jobs) {
55  if ((*flags_)[jv][jobs] == imiss || obs[jv][jobs] == rmiss || (*obserr)[jv][jobs] == rmiss) {
56  (*flags_)[jv][jobs] = QCflags::missing;
57  }
58  }
59  }
60 
61  oops::Log::trace() << "QCmanager::QCmanager done" << std::endl;
62 }
63 
64 // -----------------------------------------------------------------------------
65 
66 void QCmanager::postFilter(const ioda::ObsVector & hofx, const ObsDiagnostics &) const {
67  oops::Log::trace() << "QCmanager postFilter" << std::endl;
68 
69  const double missing = util::missingValue(missing);
70 
71  for (size_t jv = 0; jv < observed_.size(); ++jv) {
72  for (size_t jobs = 0; jobs < obsdb_.nlocs(); ++jobs) {
73  size_t iobs = observed_.size() * jobs + jv;
74  if ((*flags_)[jv][jobs] == 0 && hofx[iobs] == missing) {
75  (*flags_)[jv][jobs] = QCflags::Hfailed;
76  }
77  }
78  }
79  oops::Log::trace() << "QCmanager postFilter done" << std::endl;
80 }
81 
82 // -----------------------------------------------------------------------------
83 
85  oops::Log::trace() << "QCmanager::~QCmanager starting" << std::endl;
86  oops::Log::info() << *this;
87  oops::Log::trace() << "QCmanager::~QCmanager done" << std::endl;
88 }
89 
90 // -----------------------------------------------------------------------------
91 
92 void QCmanager::print(std::ostream & os) const {
93  for (size_t jj = 0; jj < observed_.size(); ++jj) {
94  size_t iobs = obsdb_.nlocs();
95  size_t ipass = 0;
96  size_t imiss = 0;
97  size_t ipreq = 0;
98  size_t ibnds = 0;
99  size_t iwhit = 0;
100  size_t iblck = 0;
101  size_t iherr = 0;
102  size_t ifgss = 0;
103  size_t ignss = 0;
104  size_t ithin = 0;
105  size_t idydx = 0;
106  size_t iclw = 0;
107  size_t iprof = 0;
108  size_t idiffref = 0;
109  size_t iseaice = 0;
110  size_t itrack = 0;
111  size_t ibuddy = 0;
112 
113  for (size_t jobs = 0; jobs < iobs; ++jobs) {
114  if ((*flags_)[jj][jobs] == QCflags::pass) ++ipass;
115  if ((*flags_)[jj][jobs] == QCflags::missing) ++imiss;
116  if ((*flags_)[jj][jobs] == QCflags::preQC) ++ipreq;
117  if ((*flags_)[jj][jobs] == QCflags::bounds) ++ibnds;
118  if ((*flags_)[jj][jobs] == QCflags::domain) ++iwhit;
119  if ((*flags_)[jj][jobs] == QCflags::black) ++iblck;
120  if ((*flags_)[jj][jobs] == QCflags::Hfailed) ++iherr;
121  if ((*flags_)[jj][jobs] == QCflags::fguess) ++ifgss;
122  if ((*flags_)[jj][jobs] == QCflags::thinned) ++ithin;
123  if ((*flags_)[jj][jobs] == QCflags::clw) ++iclw;
124  if ((*flags_)[jj][jobs] == QCflags::profile) ++iprof;
125  if ((*flags_)[jj][jobs] == QCflags::diffref) ++idiffref;
126  if ((*flags_)[jj][jobs] == QCflags::seaice) ++iseaice;
127  if ((*flags_)[jj][jobs] == 76 || (*flags_)[jj][jobs] == 77) ++ignss;
128  if ((*flags_)[jj][jobs] == QCflags::track) ++itrack;
129  if ((*flags_)[jj][jobs] == QCflags::buddy) ++ibuddy;
130  if ((*flags_)[jj][jobs] == QCflags::derivative) ++idydx;
131  }
132 
133  if (obsdb_.isDistributed()) {
134  obsdb_.comm().allReduceInPlace(iobs, eckit::mpi::sum());
135  obsdb_.comm().allReduceInPlace(ipass, eckit::mpi::sum());
136  obsdb_.comm().allReduceInPlace(imiss, eckit::mpi::sum());
137  obsdb_.comm().allReduceInPlace(ipreq, eckit::mpi::sum());
138  obsdb_.comm().allReduceInPlace(ibnds, eckit::mpi::sum());
139  obsdb_.comm().allReduceInPlace(iwhit, eckit::mpi::sum());
140  obsdb_.comm().allReduceInPlace(iblck, eckit::mpi::sum());
141  obsdb_.comm().allReduceInPlace(iherr, eckit::mpi::sum());
142  obsdb_.comm().allReduceInPlace(ifgss, eckit::mpi::sum());
143  obsdb_.comm().allReduceInPlace(iclw, eckit::mpi::sum());
144  obsdb_.comm().allReduceInPlace(iprof, eckit::mpi::sum());
145  obsdb_.comm().allReduceInPlace(ignss, eckit::mpi::sum());
146  obsdb_.comm().allReduceInPlace(ithin, eckit::mpi::sum());
147  obsdb_.comm().allReduceInPlace(idiffref, eckit::mpi::sum());
148  obsdb_.comm().allReduceInPlace(iseaice, eckit::mpi::sum());
149  obsdb_.comm().allReduceInPlace(itrack, eckit::mpi::sum());
150  obsdb_.comm().allReduceInPlace(ibuddy, eckit::mpi::sum());
151  obsdb_.comm().allReduceInPlace(idydx, eckit::mpi::sum());
152  }
153 
154  if (obsdb_.comm().rank() == 0) {
155  const std::string info = "QC " + flags_->obstype() + " " + observed_[jj] + ": ";
156  if (imiss > 0) os << info << imiss << " missing values." << std::endl;
157  if (ipreq > 0) os << info << ipreq << " rejected by pre QC." << std::endl;
158  if (ibnds > 0) os << info << ibnds << " out of bounds." << std::endl;
159  if (iwhit > 0) os << info << iwhit << " out of domain of use." << std::endl;
160  if (iblck > 0) os << info << iblck << " black-listed." << std::endl;
161  if (iherr > 0) os << info << iherr << " H(x) failed." << std::endl;
162  if (ithin > 0) os << info << ithin << " removed by thinning." << std::endl;
163  if (idydx > 0) os << info << idydx << " dy/dx out of valid range." << std::endl;
164  if (iclw > 0) os << info << iclw << " removed by cloud liquid water check." << std::endl;
165  if (iprof > 0) os << info << iprof << " removed by profile consistency check." << std::endl;
166  if (ifgss > 0) os << info << ifgss << " rejected by first-guess check." << std::endl;
167  if (ignss > 0) os << info << ignss << " rejected by GNSSRO reality check." << std::endl;
168  if (idiffref > 0) os << info << idiffref << " rejected by difference check." << std::endl;
169  if (iseaice > 0) os << info << iseaice << " removed by sea ice check." << std::endl;
170  if (itrack > 0) os << info << itrack << " removed by track check." << std::endl;
171  if (ibuddy > 0) os << info << ibuddy << " removed by buddy check." << std::endl;
172 
173  os << info << ipass << " passed out of " << iobs << " observations." << std::endl;
174  }
175 
176  ASSERT(ipass + imiss + ipreq + ibnds + iwhit + iblck + iherr + ithin + iclw + iprof + ifgss + \
177  ignss + idiffref + iseaice + itrack + ibuddy + idydx == iobs);
178  }
179 }
180 
181 // -----------------------------------------------------------------------------
182 
183 } // namespace ufo
ufo::QCmanager::print
void print(std::ostream &) const
Definition: QCmanager.cc:92
ufo::QCflags::pass
constexpr int pass
Definition: QCflags.h:14
ufo::QCmanager::config_
const eckit::LocalConfiguration config_
Definition: QCmanager.h:47
ufo::QCmanager::obsdb_
ioda::ObsSpace & obsdb_
Definition: QCmanager.h:46
ufo::QCflags::black
constexpr int black
Definition: QCflags.h:19
ufo::QCmanager::~QCmanager
~QCmanager()
Definition: QCmanager.cc:84
ufo::QCmanager::observed_
const oops::Variables & observed_
Definition: QCmanager.h:52
ufo::QCflags::Hfailed
constexpr int Hfailed
Definition: QCflags.h:20
ufo::QCflags::seaice
constexpr int seaice
Definition: QCflags.h:25
ufo::QCflags::domain
constexpr int domain
Definition: QCflags.h:18
ufo
Definition: RunCRTM.h:27
ufo::QCmanager::postFilter
void postFilter(const ioda::ObsVector &, const ObsDiagnostics &) const
Definition: QCmanager.cc:66
ufo::QCflags::preQC
constexpr int preQC
Definition: QCflags.h:16
ufo::QCflags::buddy
constexpr int buddy
Definition: QCflags.h:27
ufo::QCflags::fguess
constexpr int fguess
Definition: QCflags.h:24
ufo::QCflags::track
constexpr int track
Definition: QCflags.h:26
ufo::QCflags::missing
constexpr int missing
Definition: QCflags.h:15
ufo::ObsDiagnostics
Definition: src/ufo/ObsDiagnostics.h:35
ufo::QCflags::derivative
constexpr int derivative
Definition: QCflags.h:28
QCflags.h
QCmanager.h
ufo_radiancerttov_utils_mod::iprof
integer iprof
Definition: ufo_radiancerttov_utils_mod.F90:102
ufo::QCflags::clw
constexpr int clw
Definition: QCflags.h:23
ufo::QCmanager::QCmanager
QCmanager(ioda::ObsSpace &, const eckit::Configuration &, std::shared_ptr< ioda::ObsDataVector< int > >, std::shared_ptr< ioda::ObsDataVector< float > >)
Definition: QCmanager.cc:32
ufo::QCflags::thinned
constexpr int thinned
Definition: QCflags.h:21
ioda::ObsDataVector< int >
ufo::QCflags::profile
constexpr int profile
Definition: QCflags.h:29
ufo::QCflags::diffref
constexpr int diffref
Definition: QCflags.h:22
ufo::QCmanager::flags_
std::shared_ptr< ioda::ObsDataVector< int > > flags_
Definition: QCmanager.h:50
ufo::QCflags::bounds
constexpr int bounds
Definition: QCflags.h:17