17 #include "eckit/config/Configuration.h"
18 #include "ioda/ObsDataVector.h"
19 #include "ioda/ObsSpace.h"
20 #include "oops/base/Variables.h"
21 #include "oops/util/DateTime.h"
22 #include "oops/util/Duration.h"
23 #include "oops/util/Logger.h"
24 #include "oops/util/sqr.h"
34 const util::DateTime &time,
float pressure)
35 : obsLocationTime_(latitude, longitude, time), pressure_(pressure),
36 rejectedInPreviousSweep_(false), rejectedBeforePreviousSweep_(false),
44 float referencePressure)
const {
47 this->obsLocationTime_.time());
52 const float conservativeSpeedEstimate =
55 const float maxSpeed = maxValidSpeedAtPressure(referencePressure);
61 const float conservativeClimbRateEstimate =
65 (conservativeClimbRateEstimate <= *options.
maxClimbRate.value());
87 rejectedBeforePreviousSweep_ = rejected();
88 rejectedInPreviousSweep_ = rejectedInSweep;
92 return this->checkCounter_.failedChecksFraction();
113 std::vector<std::vector<bool>> & flagged)
const {
123 std::vector<bool> isRejected(apply.size(),
false);
126 obsPressureLoc, maxSpeedByPressure, isRejected);
130 if (filtervars.
size() != 0) {
131 oops::Log::trace() <<
"TrackCheck: flagged? = " << flagged[0] << std::endl;
140 return obsPressureLoc;
144 const std::map<float, float> &maxSpeedInterpolationPoints =
145 options_->maxSpeedInterpolationPoints.value();
147 std::vector<double> pressures, maxSpeeds;
148 pressures.reserve(maxSpeedInterpolationPoints.size());
149 maxSpeeds.reserve(maxSpeedInterpolationPoints.size());
153 const int metersPerKm = 1000;
154 for (
const auto &pressureAndMaxSpeed : maxSpeedInterpolationPoints) {
155 pressures.push_back(pressureAndMaxSpeed.first);
156 maxSpeeds.push_back(pressureAndMaxSpeed.second / metersPerKm);
163 std::vector<size_t>::const_iterator trackObsIndicesBegin,
164 std::vector<size_t>::const_iterator trackObsIndicesEnd,
165 const std::vector<size_t> &validObsIds,
168 std::vector<bool> &isRejected)
const {
171 trackObsIndicesBegin, trackObsIndicesEnd, validObsIds, obsPressureLoc);
172 std::vector<float> workspace;
180 validObsIds, trackObservations, isRejected);
184 std::vector<size_t>::const_iterator trackObsIndicesBegin,
185 std::vector<size_t>::const_iterator trackObsIndicesEnd,
186 const std::vector<size_t> &validObsIds,
188 std::vector<TrackObservation> trackObservations;
189 trackObservations.reserve(trackObsIndicesEnd - trackObsIndicesBegin);
190 for (std::vector<size_t>::const_iterator it = trackObsIndicesBegin;
191 it != trackObsIndicesEnd; ++it) {
192 const size_t obsId = validObsIds[*it];
198 return trackObservations;
202 std::vector<TrackObservation> &trackObservations,
204 std::vector<float> &workspace)
const {
206 std::vector<float> &failedChecksFraction = workspace;
207 failedChecksFraction.assign(trackObservations.size(), 0.0f);
209 for (
int obsIdx = 0; obsIdx < trackObservations.size(); ++obsIdx) {
216 const int numNeighborsVisitedInPreviousSweep =
218 int numNewDistinctBuddiesToVisit = firstSweep ?
options_->numDistinctBuddiesPerDirection : 0;
220 auto getNthNeighbor = [&trackObservations, obsIdx, dir](
int n) ->
const TrackObservation* {
221 const int neighborObsIdx = obsIdx + (dir ==
FORWARD ? n : -n);
222 if (neighborObsIdx < 0 || neighborObsIdx >= trackObservations.size())
225 return &trackObservations[neighborObsIdx];
228 float minPressureBetween = obs.
pressure();
231 for (; neighborIdx <= numNeighborsVisitedInPreviousSweep && neighborObs !=
nullptr;
232 neighborObs = getNthNeighbor(++neighborIdx)) {
237 minPressureBetween = std::min(minPressureBetween, neighborObs->
pressure());
240 maxValidSpeedAtPressure, minPressureBetween);
244 ++numNewDistinctBuddiesToVisit;
249 for (; numNewDistinctBuddiesToVisit > 0 && neighborObs !=
nullptr;
250 neighborObs = getNthNeighbor(++neighborIdx)) {
251 minPressureBetween = std::min(minPressureBetween, neighborObs->
pressure());
254 maxValidSpeedAtPressure, minPressureBetween);
257 --numNewDistinctBuddiesToVisit;
261 const int numNeighborsVisitedInThisSweep = neighborIdx - 1;
262 assert(numNeighborsVisitedInThisSweep >= numNeighborsVisitedInPreviousSweep);
269 const float maxFailedChecksFraction = *std::max_element(failedChecksFraction.begin(),
270 failedChecksFraction.end());
271 const float failedChecksThreshold =
options_->rejectionThreshold * maxFailedChecksFraction;
272 if (failedChecksThreshold <= 0)
275 for (
int obsIdx = 0; obsIdx < trackObservations.size(); ++obsIdx) {
276 const bool rejected = failedChecksFraction[obsIdx] > failedChecksThreshold;
277 trackObservations[obsIdx].registerSweepOutcome(rejected);
284 std::vector<size_t>::const_iterator trackObsIndicesBegin,
285 std::vector<size_t>::const_iterator trackObsIndicesEnd,
286 const std::vector<size_t> &validObsIds,
287 const std::vector<TrackObservation> &trackObservations,
288 std::vector<bool> &isRejected)
const {
289 auto trackObsIndexIt = trackObsIndicesBegin;
290 auto trackObsIt = trackObservations.begin();
291 for (; trackObsIndexIt != trackObsIndicesEnd; ++trackObsIndexIt, ++trackObsIt)
292 if (trackObsIt->rejected())
293 isRejected[validObsIds[*trackObsIndexIt]] =
true;
297 os <<
"TrackCheck: config = " <<
config_ << std::endl;