19 #include "ioda/ObsDataVector.h"
20 #include "oops/util/IntSetParser.h"
40 std::copy(channelset.begin(), channelset.end(), std::back_inserter(
channels_));
89 int ich238 = 0, ich314 = 1, ich503 = 2, ich528 = 4, ich536 = 5;
90 int ich544 = 6, ich549 = 7, ich890 = 15;
93 int ich1650 = 16, ich1830a = 17, ich1830b = 18, ich1830c = 19, ich1830d = 20, ich1830e = 21;
104 std::vector<float> water_frac(
nlocs);
105 in.
get(
Variable(
"water_area_fraction@GeoVaLs"), water_frac);
107 std::vector<float> land_frac(
nlocs);
108 in.
get(
Variable(
"land_area_fraction@GeoVaLs"), land_frac);
110 std::vector<float> lat(
nlocs);
113 std::vector<float> lon(
nlocs);
117 std::vector<std::vector<float>> dbtde(nchans, std::vector<float>(
nlocs));
118 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
119 in.
get(
Variable(
"brightness_temperature_jacobian_surface_emissivity@ObsDiag",
channels_)[ichan],
124 std::vector<float> hofxclr536(
nlocs);
129 std::vector<float> hofxclr890(
nlocs);
134 std::vector<float> hofxclr1650(
nlocs);
139 std::vector<float> bias_const238(
nlocs);
144 std::vector<float> values(
nlocs);
145 std::vector<std::string> scanterms(nangs);
146 std::vector<float> bias_scanang238(
nlocs);
147 scanterms[0] =
"scan_angle_order_4@"+biastermgrp;
148 scanterms[1] =
"scan_angle_order_3@"+biastermgrp;
149 scanterms[2] =
"scan_angle_order_2@"+biastermgrp;
150 scanterms[3] =
"scan_angle@"+biastermgrp;
151 for (
size_t iang = 0; iang < nangs; ++iang) {
153 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
154 bias_scanang238[iloc] = bias_scanang238[iloc] + values[iloc];
159 std::vector<std::vector<float>> btobs(nchans, std::vector<float>(
nlocs));
161 std::vector<std::vector<float>> bias(nchans, std::vector<float>(
nlocs));
162 std::vector<std::vector<float>> innov(nchans, std::vector<float>(
nlocs));
163 std::vector<float> hofx(
nlocs);
164 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
168 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
169 innov[ichan][iloc] = btobs[ichan][iloc] - hofx[iloc];
176 in.
get(obserrvar, obserr);
181 in.
get(clwretvar, clwobs);
184 float w1f6 = 1.0/10.0, w2f6 = 1.0/0.80;
185 float w1f4 = 1.0/0.30, w2f4 = 1.0/1.80;
187 std::vector<std::vector<int>> affected_channels(nchans, std::vector<int>(
nlocs));
190 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
192 bool luse = (water_frac[iloc] > 0.99 || land_frac[iloc] > 0.99);
195 for (
size_t ich = 0; ich < nchans; ++ich) {
196 affected_channels[ich][iloc] = 0;
200 float cldeff_obs536 = 0.0;
201 if (water_frac[iloc] > 0.99) {
202 cldeff_obs536 = btobs[ich536][iloc] - hofxclr536[iloc] - bias[ich536][iloc];
206 float cldeff_obs890 = 0.0;
207 if (water_frac[iloc] > 0.99) {
208 cldeff_obs890 = btobs[ich890][iloc] - hofxclr890[iloc] - bias[ich890][iloc];
212 float cldeff_obs1650 = 0.0;
213 if (water_frac[iloc] > 0.99) {
214 cldeff_obs1650 = btobs[ich1650][iloc] - hofxclr1650[iloc] - bias[ich1650][iloc];
218 std::vector<float> factch4(
nlocs);
219 std::vector<float> factch6(
nlocs);
220 float btobsbc238 = btobs[ich238][iloc] - bias_const238[iloc]
221 - bias_scanang238[iloc];
224 if (water_frac[iloc] > 0.99) {
226 dsval = ((2.410 - 0.0098 * btobsbc238) * innov[ich238][iloc] +
227 0.454 * innov[ich314][iloc] - innov[ich890][iloc]) * w1f6;
228 dsval = std::max(
static_cast<float>(0.0), dsval);
230 factch4[iloc] = pow(clwx, 2) + pow(innov[ich528][iloc] * w2f4, 2);
231 factch6[iloc] = pow(dsval, 2) + pow(innov[ich544][iloc] * w2f6, 2);
236 std::vector<float> OmFs{
std::abs(innov[ich238][iloc]),
std::abs(innov[ich314][iloc]),
241 result = any_of(OmFs.begin(), OmFs.end(), [](
float x){return x > 200.0;});
245 for (
size_t ich = ich238; ich <= ich544; ++ich) {
246 affected_channels[ich][iloc] = 1;
248 affected_channels[ich890][iloc] = 1;
249 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
250 affected_channels[ich][iloc] = 1;
254 if (water_frac[iloc] > 0.99) {
256 if (clwobs[0][iloc] > 999.0) {
257 for (
size_t ich = ich238; ich <= ich544; ++ich) {
258 affected_channels[ich][iloc] = 1;
260 affected_channels[ich890][iloc] = 1;
261 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
262 affected_channels[ich][iloc] = 1;
266 if (factch6[iloc] >= 1.0) {
267 for (
size_t ich = ich238; ich <= ich544; ++ich) {
268 affected_channels[ich][iloc] = 1;
270 affected_channels[ich890][iloc] = 1;
271 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
272 affected_channels[ich][iloc] = 1;
275 }
else if (cldeff_obs536 < -0.5) {
276 for (
size_t ich = ich238; ich <= ich544; ++ich) {
277 affected_channels[ich][iloc] = 1;
279 affected_channels[ich890][iloc] = 1;
280 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
281 affected_channels[ich][iloc] = 1;
284 }
else if (
std::abs(cldeff_obs890 - cldeff_obs1650) > 10.0) {
285 affected_channels[ich890][iloc] = 1;
286 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
287 affected_channels[ich][iloc] = 1;
289 if (
std::abs(cldeff_obs890 - cldeff_obs1650) > 15.0) {
290 for (
size_t ich = ich238; ich <= ich544; ++ich) {
291 affected_channels[ich][iloc] = 1;
296 float thrd238 = 0.025, thrd314 = 0.015, thrd503 = 0.030, thrd890 = 0.030;
297 float de238 = 0.0, de314 = 0.0, de503 = 0.0, de890 = 0.0;
298 float dbtde238 = dbtde[ich238][iloc];
299 float dbtde314 = dbtde[ich314][iloc];
300 float dbtde503 = dbtde[ich503][iloc];
301 float dbtde890 = dbtde[ich890][iloc];
302 if (dbtde238 != 0.0) de238 =
std::abs(innov[ich238][iloc]) / dbtde238 *
303 (obserr0[ich238] / obserr[ich238][iloc]) *
304 (1.0 - std::max(1.0, 10.0*clwobs[0][iloc]));
305 if (dbtde314 != 0.0) de314 =
std::abs(innov[ich314][iloc]) / dbtde314 *
306 (obserr0[ich314] / obserr[ich314][iloc]) *
307 (1.0 - std::max(1.0, 10.0*clwobs[0][iloc]));
308 if (dbtde503 != 0.0) de503 =
std::abs(innov[ich503][iloc]) / dbtde503 *
309 (obserr0[ich503] / obserr[ich503][iloc]) *
310 (1.0 - std::max(1.0, 10.0*clwobs[0][iloc]));
311 if (dbtde890 != 0.0) de890 =
std::abs(innov[ich890][iloc]) / dbtde890 *
312 (obserr0[ich890] / obserr[ich890][iloc]) *
313 (1.0 - std::max(1.0, 10.0*clwobs[0][iloc]));
314 bool qcemiss =
false;
315 qcemiss = de238 > thrd238 || de314 > thrd314 || de503 > thrd503 || de890 > thrd890;
317 for (
size_t ich = ich238; ich <= ich536; ++ich) {
318 affected_channels[ich][iloc] = 1;
320 affected_channels[ich890][iloc] = 1;
321 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
322 affected_channels[ich][iloc] = 1;
329 if (factch6[iloc] >= 1.0 || luse ==
false) {
330 for (
size_t ich = ich238; ich <= ich544; ++ich) {
331 affected_channels[ich][iloc] = 1;
333 affected_channels[ich890][iloc] = 1;
334 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
335 affected_channels[ich][iloc] = 1;
338 }
else if (factch4[iloc] > 0.5) {
339 for (
size_t ich = ich238; ich <= ich536; ++ich) {
340 affected_channels[ich][iloc] = 1;
342 affected_channels[ich890][iloc] = 1;
343 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
344 affected_channels[ich][iloc] = 1;
348 float thrd238 = 0.020, thrd314 = 0.015, thrd503 = 0.035, thrd890 = 0.015;
349 float de238 = 0.0, de314 = 0.0, de503 = 0.0, de890 = 0.0;
350 float dbtde238 = dbtde[ich238][iloc];
351 float dbtde314 = dbtde[ich314][iloc];
352 float dbtde503 = dbtde[ich503][iloc];
353 float dbtde890 = dbtde[ich890][iloc];
354 if (dbtde238 != 0.0) de238 =
std::abs(innov[ich238][iloc]) / dbtde238;
355 if (dbtde314 != 0.0) de314 =
std::abs(innov[ich314][iloc]) / dbtde314;
356 if (dbtde503 != 0.0) de503 =
std::abs(innov[ich503][iloc]) / dbtde503;
357 if (dbtde890 != 0.0) de890 =
std::abs(innov[ich890][iloc]) / dbtde890;
358 bool qcemiss =
false;
359 qcemiss = de238 > thrd238 || de314 > thrd314 || de503 > thrd503 || de890 > thrd890;
361 for (
size_t ich = ich238; ich <= ich536; ++ich) {
362 affected_channels[ich][iloc] = 1;
364 affected_channels[ich890][iloc] = 1;
365 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
366 affected_channels[ich][iloc] = 1;
377 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
378 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
379 out[ichan][iloc] = affected_channels[ichan][iloc];
HydrometeorCheckATMS(const eckit::LocalConfiguration &)
HydrometeorCheckATMSParameters options_
std::vector< int > channels_
const ufo::Variables & requiredVariables() const
geovals required to compute the function
void compute(const ObsFilterData &, ioda::ObsDataVector< float > &) const
compute the result of the function
oops::Parameter< std::string > testBiasTerm
oops::RequiredParameter< std::vector< float > > obserrClearSky
Observation error for each channel under clear-sky condition.
oops::RequiredParameter< std::string > channelList
List of channels available for assimilation.
oops::RequiredParameter< Variable > clwretFunction
Function used to retrieve the cloud liquid water from observation (CLWRetMW)
oops::RequiredParameter< Variable > obserrFunction
oops::Parameter< std::string > testHofX
Name of the HofX group used to replace the default group (default is HofX)
oops::Parameter< std::string > testBias
ObsFilterData provides access to all data related to an ObsFilter.
size_t nlocs() const
Returns the number of locations in the associated ObsSpace.
ioda::ObsSpace & obsspace() const
Returns reference to ObsSpace associated with ObsFilterData.
void get(const Variable &varname, std::vector< float > &values) const
Fills a std::vector with values of the specified variable.
oops::Variables toOopsVariables() const
integer function nlocs(this)
Return the number of observational locations in this Locations object.
static ObsFunctionMaker< HydrometeorCheckATMS > makerHydrometeorCheckATMS_("HydrometeorCheckATMS")
util::Duration abs(const util::Duration &duration)