19 #include "ioda/ObsDataVector.h"
20 #include "oops/util/IntSetParser.h"
40 std::copy(channelset.begin(), channelset.end(), std::back_inserter(
channels_));
85 size_t nlocs = in.
nlocs();
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));
160 std::vector<std::vector<float>> bias(nchans, std::vector<float>(nlocs));
161 std::vector<std::vector<float>> innov(nchans, std::vector<float>(nlocs));
162 std::vector<float> hofx(nlocs);
163 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
167 for (
size_t iloc = 0; iloc < nlocs; ++iloc) {
168 innov[ichan][iloc] = btobs[ichan][iloc] - hofx[iloc] - bias[ichan][iloc];
175 in.
get(obserrvar, obserr);
180 in.
get(clwretvar, clwobs);
183 float w1f6 = 1.0/10.0, w2f6 = 1.0/0.80;
184 float w1f4 = 1.0/0.30, w2f4 = 1.0/1.80;
186 std::vector<std::vector<int>> affected_channels(nchans, std::vector<int>(nlocs));
189 for (
size_t iloc = 0; iloc < nlocs; ++iloc) {
191 bool luse = (water_frac[iloc] > 0.99 || land_frac[iloc] > 0.99);
194 for (
size_t ich = 0; ich < nchans; ++ich) {
195 affected_channels[ich][iloc] = 0;
199 float cldeff_obs536 = 0.0;
200 if (water_frac[iloc] > 0.99) {
201 cldeff_obs536 = btobs[ich536][iloc] - hofxclr536[iloc] - bias[ich536][iloc];
205 float cldeff_obs890 = 0.0;
206 if (water_frac[iloc] > 0.99) {
207 cldeff_obs890 = btobs[ich890][iloc] - hofxclr890[iloc] - bias[ich890][iloc];
211 float cldeff_obs1650 = 0.0;
212 if (water_frac[iloc] > 0.99) {
213 cldeff_obs1650 = btobs[ich1650][iloc] - hofxclr1650[iloc] - bias[ich1650][iloc];
217 std::vector<float> factch4(nlocs);
218 std::vector<float> factch6(nlocs);
219 float btobsbc238 = btobs[ich238][iloc] - bias_const238[iloc]
220 - bias_scanang238[iloc];
223 if (water_frac[iloc] > 0.99) {
225 dsval = ((2.410 - 0.0098 * btobsbc238) * innov[ich238][iloc] +
226 0.454 * innov[ich314][iloc] - innov[ich890][iloc]) * w1f6;
227 dsval = std::max(
static_cast<float>(0.0), dsval);
229 factch4[iloc] = pow(clwx, 2) + pow(innov[ich528][iloc] * w2f4, 2);
230 factch6[iloc] = pow(dsval, 2) + pow(innov[ich544][iloc] * w2f6, 2);
235 std::vector<float> OmFs{
std::abs(innov[ich238][iloc]),
std::abs(innov[ich314][iloc]),
240 result = any_of(OmFs.begin(), OmFs.end(), [](
float x){return x > 200.0;});
244 for (
size_t ich = ich238; ich <= ich544; ++ich) {
245 affected_channels[ich][iloc] = 1;
247 affected_channels[ich890][iloc] = 1;
248 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
249 affected_channels[ich][iloc] = 1;
253 if (water_frac[iloc] > 0.99) {
255 if (clwobs[0][iloc] > 999.0) {
256 for (
size_t ich = ich238; ich <= ich544; ++ich) {
257 affected_channels[ich][iloc] = 1;
259 affected_channels[ich890][iloc] = 1;
260 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
261 affected_channels[ich][iloc] = 1;
265 if (factch6[iloc] >= 1.0) {
266 for (
size_t ich = ich238; ich <= ich544; ++ich) {
267 affected_channels[ich][iloc] = 1;
269 affected_channels[ich890][iloc] = 1;
270 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
271 affected_channels[ich][iloc] = 1;
274 }
else if (cldeff_obs536 < -0.5) {
275 for (
size_t ich = ich238; ich <= ich544; ++ich) {
276 affected_channels[ich][iloc] = 1;
278 affected_channels[ich890][iloc] = 1;
279 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
280 affected_channels[ich][iloc] = 1;
283 }
else if (
std::abs(cldeff_obs890 - cldeff_obs1650) > 10.0) {
284 affected_channels[ich890][iloc] = 1;
285 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
286 affected_channels[ich][iloc] = 1;
288 if (
std::abs(cldeff_obs890 - cldeff_obs1650) > 15.0) {
289 for (
size_t ich = ich238; ich <= ich544; ++ich) {
290 affected_channels[ich][iloc] = 1;
295 float thrd238 = 0.025, thrd314 = 0.015, thrd503 = 0.030, thrd890 = 0.030;
296 float de238 = 0.0, de314 = 0.0, de503 = 0.0, de890 = 0.0;
297 float dbtde238 = dbtde[ich238][iloc];
298 float dbtde314 = dbtde[ich314][iloc];
299 float dbtde503 = dbtde[ich503][iloc];
300 float dbtde890 = dbtde[ich890][iloc];
301 if (dbtde238 != 0.0) de238 =
std::abs(innov[ich238][iloc]) / dbtde238 *
302 (obserr0[ich238] / obserr[ich238][iloc]) *
303 (1.0 - std::max(1.0, 10.0*clwobs[0][iloc]));
304 if (dbtde314 != 0.0) de314 =
std::abs(innov[ich314][iloc]) / dbtde314 *
305 (obserr0[ich314] / obserr[ich314][iloc]) *
306 (1.0 - std::max(1.0, 10.0*clwobs[0][iloc]));
307 if (dbtde503 != 0.0) de503 =
std::abs(innov[ich503][iloc]) / dbtde503 *
308 (obserr0[ich503] / obserr[ich503][iloc]) *
309 (1.0 - std::max(1.0, 10.0*clwobs[0][iloc]));
310 if (dbtde890 != 0.0) de890 =
std::abs(innov[ich890][iloc]) / dbtde890 *
311 (obserr0[ich890] / obserr[ich890][iloc]) *
312 (1.0 - std::max(1.0, 10.0*clwobs[0][iloc]));
313 bool qcemiss =
false;
314 qcemiss = de238 > thrd238 || de314 > thrd314 || de503 > thrd503 || de890 > thrd890;
316 for (
size_t ich = ich238; ich <= ich536; ++ich) {
317 affected_channels[ich][iloc] = 1;
319 affected_channels[ich890][iloc] = 1;
320 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
321 affected_channels[ich][iloc] = 1;
328 if (factch6[iloc] >= 1.0 || luse ==
false) {
329 for (
size_t ich = ich238; ich <= ich544; ++ich) {
330 affected_channels[ich][iloc] = 1;
332 affected_channels[ich890][iloc] = 1;
333 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
334 affected_channels[ich][iloc] = 1;
337 }
else if (factch4[iloc] > 0.5) {
338 for (
size_t ich = ich238; ich <= ich536; ++ich) {
339 affected_channels[ich][iloc] = 1;
341 affected_channels[ich890][iloc] = 1;
342 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
343 affected_channels[ich][iloc] = 1;
347 float thrd238 = 0.020, thrd314 = 0.015, thrd503 = 0.035, thrd890 = 0.015;
348 float de238 = 0.0, de314 = 0.0, de503 = 0.0, de890 = 0.0;
349 float dbtde238 = dbtde[ich238][iloc];
350 float dbtde314 = dbtde[ich314][iloc];
351 float dbtde503 = dbtde[ich503][iloc];
352 float dbtde890 = dbtde[ich890][iloc];
353 if (dbtde238 != 0.0) de238 =
std::abs(innov[ich238][iloc]) / dbtde238;
354 if (dbtde314 != 0.0) de314 =
std::abs(innov[ich314][iloc]) / dbtde314;
355 if (dbtde503 != 0.0) de503 =
std::abs(innov[ich503][iloc]) / dbtde503;
356 if (dbtde890 != 0.0) de890 =
std::abs(innov[ich890][iloc]) / dbtde890;
357 bool qcemiss =
false;
358 qcemiss = de238 > thrd238 || de314 > thrd314 || de503 > thrd503 || de890 > thrd890;
360 for (
size_t ich = ich238; ich <= ich536; ++ich) {
361 affected_channels[ich][iloc] = 1;
363 affected_channels[ich890][iloc] = 1;
364 for (
size_t ich = ich1650; ich <= ich1830e; ++ich) {
365 affected_channels[ich][iloc] = 1;
376 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
377 for (
size_t iloc = 0; iloc < nlocs; ++iloc) {
378 out[ichan][iloc] = affected_channels[ichan][iloc];