UFO
ProfileCheckSign.cc
Go to the documentation of this file.
1 /*
2  * (C) Crown copyright 2020, Met Office
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 
10 
11 namespace ufo {
12 
14 
16  : ProfileCheckBase(options)
17  {}
18 
20  {
21  oops::Log::debug() << " Sign check/correction" << std::endl;
22 
23  const int numProfileLevels = profileDataHandler.getNumProfileLevels();
24 
25  const std::vector <float> &pressures =
26  profileDataHandler.get<float>(ufo::VariableNames::obs_air_pressure);
27  const std::vector <float> &tObs =
28  profileDataHandler.get<float>(ufo::VariableNames::obs_air_temperature);
29  const std::vector <float> &tBkg =
30  profileDataHandler.get<float>(ufo::VariableNames::hofx_air_temperature);
31  std::vector <int> &tFlags =
32  profileDataHandler.get<int>(ufo::VariableNames::qcflags_air_temperature);
33  std::vector <int> &NumAnyErrors =
34  profileDataHandler.get<int>(ufo::VariableNames::counter_NumAnyErrors);
35  std::vector <int> &NumSignChange =
36  profileDataHandler.get<int>(ufo::VariableNames::counter_NumSignChange);
37  std::vector <float> &tObsCorrection =
38  profileDataHandler.get<float>(ufo::VariableNames::obscorrection_air_temperature);
39 
40  if (!oops::allVectorsSameNonZeroSize(pressures, tObs, tBkg,
41  tFlags, tObsCorrection)) {
42  oops::Log::warning() << "At least one vector is the wrong size. "
43  << "Check will not be performed." << std::endl;
44  oops::Log::warning() << "Vector sizes: "
45  << oops::listOfVectorSizes(pressures, tObs, tBkg,
46  tFlags, tObsCorrection)
47  << std::endl;
48  return;
49  }
50 
51  // Obtain air pressure GeoVals.
52  const std::vector <float> &pressureGeoVaLs =
54  if (pressureGeoVaLs.empty())
55  throw eckit::BadValue("Air pressure GeoVaLs vector is empty.", Here());
56 
57  // Pstar is the pressure at the bottom of the upper-air column (following the OPS code).
58  const float Pstar = pressureGeoVaLs[0];
59 
60  for (int jlev = 0; jlev < numProfileLevels; ++jlev) {
61  // Ignore this level if it has been flagged as rejected.
62  if (tFlags[jlev] & ufo::MetOfficeQCFlags::Elem::FinalRejectFlag) continue;
63  if (pressures[jlev] <= Pstar - options_.SCheck_PstarThresh.value() &&
64  tObs[jlev] != missingValueFloat &&
65  std::abs(tObs[jlev] - tBkg[jlev]) >= options_.SCheck_tObstBkgThresh.value()) {
66  // Change sign of tObs in C and compare to tBkg (also in C)
67  if (std::abs(2.0 * ufo::Constants::t0c - tObs[jlev] - tBkg[jlev]) <
69  NumAnyErrors[0]++;
70  NumSignChange[0]++;
71 
73 
74  oops::Log::debug() << " -> Failed sign check for level " << jlev << std::endl;
75  oops::Log::debug() << " -> P = " << pressures[jlev] * 0.01 << "hPa, tObs = "
76  << ufo::Constants::t0c - tObs[jlev] << "C, tBkg = "
77  << tBkg[jlev] - ufo::Constants::t0c << "C" << std::endl;
78 
79  if (options_.SCheck_CorrectT.value()) {
80  // Corrected T is 2 * t0c - T (all quantities in K).
81  // The correction is 2 * (t0c - T).
82  tObsCorrection[jlev] = 2.0 * (ufo::Constants::t0c - tObs[jlev]);
83 
84  oops::Log::debug() << " -> Uncorrected tObs: " << tObs[jlev] << "C" << std::endl;
85  oops::Log::debug() << " tObs correction: "
86  << tObsCorrection[jlev] << "C" << std::endl;
87  oops::Log::debug() << " Corrected tObs: "
88  << tObs[jlev] + tObsCorrection[jlev] << "C" << std::endl;
89  } else {
90  // Observation is rejected
92  }
93  } else if (pressures[jlev] > options_.SCheck_PrintLargeTThresh.value()) {
94  // Print out information on other large T differences
95  oops::Log::debug() << " -> Passed test but have large T difference for level "
96  << jlev << ": "
97  << "P = " << pressures[jlev] * 0.01 << "hPa, tObs = "
98  << tObs[jlev] - ufo::Constants::t0c << "C, tBkg = "
99  << tBkg[jlev] - ufo::Constants::t0c << "C" << std::endl;
100  }
101  }
102  }
103  }
104 } // namespace ufo
105 
Options controlling the operation of the ConventionalProfileProcessing filter.
oops::Parameter< float > SCheck_tObstBkgThresh
Threshold used for |tObs - tBkg| in sign check (K)
oops::Parameter< float > SCheck_PrintLargeTThresh
P threshold over which to print large T differences (Pa)
oops::Parameter< float > SCheck_ProfileSignTol
Tolerance used for sign check (K)
oops::Parameter< float > SCheck_PstarThresh
Threshold used for Pstar difference in sign check (Pa)
oops::Parameter< bool > SCheck_CorrectT
Correct tObs in the sign check?
Profile QC checker base class.
const float missingValueFloat
Missing value (float)
const ConventionalProfileProcessingParameters & options_
Configurable parameters.
ProfileCheckSign(const ConventionalProfileProcessingParameters &options)
void runCheck(ProfileDataHandler &profileDataHandler) override
Run check.
Retrieve and store data for individual profiles. To do this, first the vector of values in the entire...
std::vector< T > & get(const std::string &fullname)
std::vector< float > & getGeoVaLVector(const std::string &variableName)
Get GeoVaLs for a particular profile.
int getNumProfileLevels() const
Return number of levels to which QC checks should be applied.
@ FinalRejectFlag
Final QC flag.
@ DataCorrectFlag
Eg sign correction.
Definition: RunCRTM.h:27
static ProfileCheckMaker< ProfileCheckSign > makerProfileCheckSign_("Sign")
util::Duration abs(const util::Duration &duration)
static constexpr double t0c
Definition: Constants.h:24
static constexpr const char *const hofx_air_temperature
Definition: VariableNames.h:38
static constexpr const char *const obs_air_temperature
Definition: VariableNames.h:19
static constexpr const char *const counter_NumAnyErrors
static constexpr const char *const geovals_pressure
static constexpr const char *const counter_NumSignChange
static constexpr const char *const obs_air_pressure
Definition: VariableNames.h:18
static constexpr const char *const qcflags_air_temperature
Definition: VariableNames.h:99
static constexpr const char *const obscorrection_air_temperature