OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
DbMaskOCI.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * NAME: DbMaskOCI.cpp
4  *
5  * DESCRIPTION: Object class that provides data structures and processes that
6  * compute cloud masks for a given granule of data.
7  *
8  * Created on: July 15, 2018
9  * Author: Sam Anderson, DB
10  *
11  * Modified:
12  *
13  *******************************************************************************/
14 
15 #include "deepblue/DbMaskOCI.h"
16 
17 #include <math.h>
18 
19 #include <Granule.h>
20 #include "deepblue/DbProcess.h"
21 
22 using namespace std;
23 
24 /**************************************************************************
25  * NAME: DbCloudMaskLandOCI()
26  *
27  * DESCRIPTION: Class Constructor / Destructor
28  *
29  *************************************************************************/
30 
32  p_ = 0;
33 }
34 
35 DbCloudMaskLandOCI::DbCloudMaskLandOCI(Granule* granule, DbProcessLand* proc) :
36  Mask(granule)
37 {
38  p_ = proc;
39 }
40 
42 }
43 
44 /**************************************************************************
45  * NAME: DbCloudMaskLandOCI::compute_1()
46  *
47  * DESCRIPTION: Initial set of cloud mask filters applied to modis units
48  *
49  *************************************************************************/
50 
51 int DbCloudMaskLandOCI::compute_1( const int iy, const int ix, short& mask,
52  short& snow1, short& snow2 )
53 {
54  int status = DT_SUCCESS;
55 
56  if (p_->rfl_[W412] < filltest) {
57  mask = shortfill;
58  snow1 = shortfill;
59  snow2 = shortfill;
60  return status;
61  }
62  mask = 0;
63  snow1 = 0;
64  snow2 = 0;
65 
66  float lat = g_->in_->latitude;
67  float lon = g_->in_->longitude;
68 
69  // Convert raw reflectances to modis units
70  float to_modis = PI;
71  float rfl[NUM_RFL_BANDS];
72  if (p_->rfl_[W412] > filltest) {
73  for (int ib=0; ib<NUM_RFL_BANDS; ib++) {
74  rfl[ib] = p_->rfl_[ib]*to_modis;
75  }
76  } else {
77  for (int ib=0; ib<NUM_RFL_BANDS; ib++) {
78  rfl[ib] = floatfill;
79  }
80  }
81 
82  int ilat = (int)((lat + 90.)*10.0);
83  if (ilat >= 1800) ilat = 1800-1;
84  if (ilat < 0) ilat = 0;
85  int ilon = (int)((lon + 180.0)*10.0);
86  if (ilon >= 3600) ilon = 3600-1;
87  if (ilon < 0) ilon = 0;
88  int gzflg = p_->gz_lut_->GEOZONE_FLAG[ilat][ilon];
89 // Define pixel range
90  int ix1 = max(ix-1,0);
91  int ix2 = min(ix+1,g_->pixels_-1);
92  int iy1 = max(iy-1,0);
93  int iy2 = min(iy+1,g_->lines_-1);
94 // Compute Rfl minmax ratios
95  float rflmin = 999.0;
96  float rflmax = -999.0;
97  for (int cx=ix1; cx<=ix2; cx++) {
98  for (int cy=iy1; cy<=iy2; cy++) {
99  float rf = p_->rfl_[W412][cy][cx];
100  if (rf > filltest) {
101  rflmin = (rf<rflmin) ? rf : rflmin;
102  rflmax = (rf>rflmax) ? rf : rflmax;
103  }
104  }
105  }
106  if (rflmax<1.E-8 || rflmin<1.E-8 ) {
107  mask = shortfill;
108  snow1 = shortfill;
109  snow2 = shortfill;
110  return DT_SUCCESS;
111  }
112  float minmax_rfl = rflmax/rflmin + DbProcessLand::delta;
113 // Begin cloud tests
114  if (minmax_rfl > 1.2) {
115  mask = 1;
116  }
117  if (p_->sr670_ >= 0.08 && minmax_rfl > 1.15) {
118  mask = 1;
119  }
120 // Over bright surfaces, apply RR1.38/0.66 and BTD11-12 threshold !JH
121 // test addition - 6/7/2011
122  if (p_->sr670_ >= 0.08 ) {
123 // if ((p_->dstar_ < 1.12 && solz < 68.0) ||
124 // (p_->dstar_ < 1.2 && solz > 68.0)) {
125  if (rfl[W1380] > 0.018 &&
126  p_->pwv_ >= 0.9) {
127  mask = 1; // Thin Cirrus Screening
128  }
129  if (gzflg == 24) {// Taklimakan
130  if (rfl[W1380] > 0.04 &&
131  p_->pwv_ < 0.9 &&
132 // p_->btd11_ > -2.5 &&
133  rfl[W670] < 0.45) {
134  mask = 1;
135  }
136 // if (p_->rfl_[W11000] < 265.0) {
137 // mask = 1; // Cloud Screening
138 // }
139  } else { // Everywhere else
140  if (rfl[W1380] > 0.018 &&
141  p_->pwv_ < 0.9 &&
142 // p_->btd11_ > -1.0 &&
143  rfl[W670] < 0.55) {
144  mask = 1;
145  }
146 // if (p_->rfl_[W11000] < 270.0) {
147 // mask = 1; // Cloud Screening
148 // }
149  }
150 // if (p_->sr670_ >= 0.16) {
151 // if (p_->rfl_[W11000] >= 270.0 &&
152 // p_->rfl_[W11000] < 281.0 &&
153 // p_->btd11_ > -0.5) {
154 // mask = 1; // Cloud Edge Contamination Removal
155 // }
156 // }
157 // }
158  }
159 // Over dark surfaces
160  if (p_->sr670_ > 0.0 && p_->sr670_ < 0.08 ) {
161 // if ((p_->dstar_ < 1.12 && solz < 68.0) ||
162 // (p_->dstar_ < 1.2 && solz > 68.0)) {
163  float dd = rfl[W670]/rfl[W412];
164  if (p_->rfl_[W2250] > 0.36 && dd < 0.95) {
165  mask = 1;
166  }
167  if (rfl[W1380] > 0.018 &&
168  p_->pwv_ > 0.4) {
169  mask = 1;
170  }
171 // if (p_->rfl_[W11000] < 270.0) {
172 // mask = 1;
173 // }
174 // }
175  }
176 // High AMF
177  if (lat > 60.0 && p_->amf_ > 7.0) {
178  if (rfl[W1380] > 0.018 &&
179  p_->pwv_ > 0.9) {
180  mask = 1;
181  }
182  if (rfl[W488] > 0.4) {
183  mask = 1;
184  }
185  }
186 // -- over *really* bright surfaces, except Arabian Peninsula (6 <= gzflg <= 11)
187 // if (gzflg < 6 || gzflg > 11) {
188 // if (p_->sr670_ > 0.25) {
189 // if (p_->dstar_ < 0.85 && p_->pwv_ < 2.3) {
190 // mask = 1;
191 // }
192 // }
193 // }
194  if ((gzflg == 5 || gzflg == 1 || gzflg == 26 || gzflg == 27) ||
195  (lon < 15.0 && ((lon >-20.0 && lon < 55.0) && gzflg == -999))) {
196 // if (p_->sr670_ < 0.08 && p_->dstar_ < 1.12) {
197  if (p_->sr670_ > 0.0 && p_->sr670_ < 0.08) {
198  if (rfl[W488] > 0.15) {
199  if (rfl[W2250] > 0.16) {
200  mask = 1;
201  }
202  }
203  }
204 // if (p_->sr670_ > 0.08 && p_->dstar_ < 1.12) {
205 // if (p_->sr670_ > 0.08) {
206 // if (rfl[W488] > 0.25) {
207 // if (p_->btd11_ > 3.0) {
208 // mask = 1;
209 // }
210 // }
211 // }
212  }
213 
214 // -- only apply these cloud tests over region 5 (N. Africa) and southern Africa.
215 // -- developed using MYD021KM.A2011171.A12[25|30]*.hdf as test case.
216 // -- over *really* bright surfaces, except Arabian Peninsula (6 <= gzflg <= 11)
217 // if (gzflg < 6 || gzflg > 11) {
218 // if (p_->sr670_ > 0.25) {
219 // if (p_->dstar_ < 0.85 && p_->pwv_ < 2.3) {
220 // if (p_->pwv_ < 2.3) {
221 // mask = 1;
222 // }
223 // }
224 // }
225 // if ((gzflg == 5 || gzflg == 1 || gzflg == 26 || gzflg == 27) ||
226 // (lat < 15.0 && (lon >-20.0 && lon < 55.0) && gzflg == shortfill)) {
227 //
228 // if (p_->sr670_ < 0.08 && p_->dstar_ < 1.12) {
229 // if (p_->sr670_ < 0.08) {
230 // if (rfl[W488] > 0.15) {
231 // if (rfl[W2250] > 0.16) {
232 // mask = 1;
233 // }
234 // }
235 // }
236 // if (p_->sr670_ > 0.08 && p_->dstar_ < 1.12) {
237 // if (p_->sr670_ > 0.08) {
238 // if (rfl[W488] > 0.25) {
239 // if (p_->btd11_ > 3.0) {
240 // mask = 1;
241 // }
242 // }
243 // }
244 // }
245 // -- try to detect snow cover and skip pixel.
246 // -- source: http://modis-snow-ice.gsfc.nasa.gov/?c=atbdt=atbd
247  float ndsi = floatfill;
248  if (rfl[W550] > filltest && rfl[W2250] > filltest) {
249  ndsi = (rfl[W550] - rfl[W1610]) /
250  (rfl[W550] + rfl[W1610]);
251  } else {
252  mask = 1;
253  }
254  if (ndsi > 0.35 && rfl[W865] > 0.11 && rfl[W550] > 0.1 ){
255 // && p_->rfl_[W11000] < 286.0) {
256  snow1 = 1;
257  }
258 // if (ndsi > -0.2 && rfl[W865] > 0.11 &&
259 // p_->rfl_[W11000] < 286.0) {
260  if (ndsi > -0.2 && rfl[W865] > 0.11) {
261  snow2 = 1;
262  }
263 // if ((p_->dstar_ >= 1.06 && solz < 68.0) &&
264 // (gzflg < 1 || (gzflg > 5 && gzflg != 26 && gzflg != 27
265 // && gzflg != 24))) {
266 // mask = 0;
267 // }
268  if (snow1 == 1) {
269  mask = 1;
270  }
271 
272  return status;
273 }
274 
275 /**************************************************************************
276  * NAME: DbCloudMaskLandOCI::compute_2()
277  *
278  * DESCRIPTION: Initial set of cloud mask filters applied to modis units
279  *
280  *************************************************************************/
281 
282 int DbCloudMaskLandOCI::compute_2( const int iy, const int ix,
283  short& mask, const short snow2 )
284 {
285  int status = DT_SUCCESS;
286 
287  if (p_->rfl_[W412] < filltest) {
288  mask = shortfill;
289  return status;
290  }
291  float lat = g_->in_->latitude;
292  float lon = g_->in_->longitude;
293  float solz = g_->in_->solar_zenith;
294  int ilat = (int)((lat + 90.)*10.0);
295  if (ilat >= 1800) ilat = 1800-1;
296  if (ilat < 0) ilat = 0;
297  int ilon = (int)((lon + 180.0)*10.0);
298  if (ilon >= 3600) ilon = 3600-1;
299  if (ilon < 0) ilon = 0;
300  int gzflg = p_->gz_lut_->GEOZONE_FLAG[ilat][ilon];
301  int sfcstd = p_->sp_lut_->SURFACE_ELEVATION[ilat][ilon];
302  int month = g_->in_->start_month;
303 
304  if (p_->ler412_ > 50.0) {
305  mask = 1;
306  }
307  if (p_->sr670_ < 0.1) {
308  if (p_->rfl_[W2250] > 0.05 &&
309  p_->ler412_ > 12.0) {
310  mask = 1;
311  }
312  }
313  if (p_->sr670_ < 0.08) {
314 // if (p_->dstar_ < 1.12) {
315 // if (p_->rfl_[W11000] > 270 &&
316 // p_->rfl_[W11000] < 274 &&
317  if (p_->ler412_ > 40.0) {
318  mask = 1;
319  }
320  if (solz > 72.0) {
321 // if (p_->rfl_[W11000] > 270 &&
322 // p_->rfl_[W11000] < 275 &&
323  if (p_->ler412_ > 20.0) {
324  mask = 1;
325  }
326  }
327 // }
328  }
329 // Define pixel range
330  int iy1 = max(iy-1,0);
331  int iy2 = min(iy+1,g_->lines_-1);
332  int ix1 = max(ix-1,0);
333  int ix2 = min(ix+1,g_->pixels_-1);
334 // Compute Ler minmax ratios
335  float lermin = 999.0;
336  float lermax = -999.0;
337  for (int cx=ix1; cx<=ix2; cx++) {
338  for (int cy=iy1; cy<=iy2; cy++) {
339 // float lr = p_->ler412_a_[cy][cx];
340 // if (lr > filltest) {
341 // lermin = (lr<lermin) ? lr : lermin;
342 // lermax = (lr>lermax) ? lr : lermax;
343 // }
344  lermin = 1;
345  lermax = 1;
346  }
347  }
348 
349  if (lermax<1.E-8 || lermin<1.E-8 ) {
350  mask = floatfill;
351  return DT_SUCCESS;
352  }
353  float minmax_ler = lermax/lermin + DbProcessLand::delta;
354 //-- N. America
355  if (snow2 == 1 && gzflg == 13 &&
356  p_->ndvi_ < 0.35 &&
357  sfcstd <= 50 && minmax_ler > 1.20) {
358  mask = 1;
359  }
360 //-- higher ndvi and minmax thresholds for spring at high latitudes
361  if (lat > 45 && month >= 2 && month <= 6 &&
362  snow2 == 1 && gzflg == 13 && p_->ndvi_ < 0.45 &&
363  sfcstd <= 50 && minmax_ler > 1.30) {
364  mask = 1;
365  }
366 //-- Rest of the world
367  if (snow2 == 1 && gzflg != 13 && p_->ndvi_ < 0.35 &&
368  sfcstd <= 50 && minmax_ler > 1.40) {
369  mask = 1;
370  }
371 // --higher ndvi threshold and lower minmax for spring at high latitudes
372  if (lat > 50 && month >= 2 && month <= 6 && snow2 == 1 &&
373  gzflg != 13 && p_->ndvi_ < 0.45 &&
374  sfcstd <= 50 && minmax_ler > 1.30) {
375  mask = 1;
376  }
377 //-- Mountainous regions
378  if (snow2 == 1 && sfcstd > 50 && minmax_ler > 1.80) {
379  mask = 1;
380  }
381 // -- detect anomalous D* values in large dust storm over Taklimakan
382 // -- region and resetthe cloud mask to 0.
383  if (gzflg == 24) {
384  if (p_->ler412_ > filltest &&
385  p_->ler488_ > filltest &&
386  p_->ler670_ > filltest) {
387 // if (p_->rfl_[W12000] < 280.0 &&
388  if (p_->ler488_/p_->ler670_ < 0.65 &&
389  p_->ler412_ > 18.0) {
390  mask = 0;
391  }
392  }
393  }
394 
395  return status;
396 }
397 
398 /**************************************************************************
399  * NAME: DbSmokeMaskOCI()
400  *
401  * DESCRIPTION: Class Constructor / Destructor
402  *
403  *************************************************************************/
404 
406  p_ = 0;
407 }
408 
409 DbSmokeMaskOCI::DbSmokeMaskOCI(Granule* granule, DbProcessLand* proc) :
410  Mask(granule) {
411  p_ = proc;
412 }
413 
415 }
416 
417 /**************************************************************************
418  * NAME: DbSmokeMaskOCI::compute()
419  *
420  * DESCRIPTION:
421  *
422  *************************************************************************/
423 
424 int DbSmokeMaskOCI::compute( const int iy, const int ix, short& mask )
425 {
426  int status = DT_SUCCESS;
427 
428  if (p_->rfl_[W1380] < filltest) {
429  mask = shortfill;
430  return status;
431  }
432  mask = 0;
433 
434  int ix1 = max(ix-1,0);
435  int ix2 = min(ix+1,g_->pixels_-1);
436  int iy1 = max(iy-1,0);
437  int iy2 = min(iy+1,g_->lines_-1);
438 // int cntbt11 = 0;
439  int cnt2250_1 = 0;
440  int cnt2250_2 = 0;
441 
442  float tler[3][3][3];
443  float tsr[3][3][3];
444  float td[3][3][3];
445  memset(&tler[0][0][0],0,sizeof(tler));
446  memset(&tsr[0][0][0],0,sizeof(tsr));
447  memset(&td[0][0][0],0,sizeof(td));
448  for (int cy=iy1; cy<=iy2; cy++) {
449  for (int cx=ix1; cx<=ix2; cx++) {
450 // tler[0][cy-iy1][cx-ix1] = p_->ler412_a_[cy][cx];
451 // tler[1][cy-iy1][cx-ix1] = p_->ler488_a_[cy][cx];
452 // tler[2][cy-iy1][cx-ix1] = p_->ler670_a_[cy][cx];
453 // tsr[0][cy-iy1][cx-ix1] = p_->sr412_a_[cy][cx];
454 // tsr[1][cy-iy1][cx-ix1] = p_->sr488_a_[cy][cx];
455 // tsr[2][cy-iy1][cx-ix1] = p_->sr670_a_[cy][cx];
456 // td[0][cy-iy1][cx-ix1] = p_->rfl_[W1380][cy][cx];
457 // td[1][cy-iy1][cx-ix1] = p_->rfl_[W2250][cy][cx];
458 // td[2][cy-iy1][cx-ix1] = p_->rfl_[W11000][cy][cx];
459 
460 // if (p_->rfl_[W11000][cy][cx] > 286.0) cntbt11++;
461  if (p_->rfl_[W2250][cy][cx] < 0.035) cnt2250_1++;
462  if (p_->rfl_[W2250][cy][cx] < 0.065) cnt2250_2++;
463  }
464  }
465  float rat488670 = p_->ler488_ / p_->ler670_;
466  float rat412488 = p_->ler412_ / p_->ler488_;
467 // if (p_->ler412_ > 12.0 && cntbt11 == 9) {
468  if (p_->ler412_ > 12.0) {
469  if ((p_->sr670_ < 0.08 && cnt2250_1 == 9) ||
470  (p_->sr670_ >= 0.08 && cnt2250_2 == 9)) {
471  if (p_->rfl_[W2250] < 0.025) {
472  mask = 1;
473  } else {
474  if (p_->ler412_ > 20.0 &&
475  p_->rfl_[W2250] < 0.04) {
476  mask = 1;
477  } else {
478  if (p_->ler488_ > 0.0 && p_->ler670_ > 0.0) {
479  rat488670 = p_->ler488_ / p_->ler670_;
480  if (rat488670 > 0.88) {
481  mask = 1;
482  } else {
483  if (rat488670 > 0.7 && rat488670 < 0.88 &&
484  p_->rfl_[W2250] < 0.04 &&
485  p_->rfl_[W1380] > 0.0015) {
486  mask = 1;
487  }
488  }
489  }
490  }
491  }
492  }
493  }
494  if (p_->sr670_ >= 0.12 || p_->ler670_ > 50.0) {
495  mask = 0;
496  }
497  if (rat412488/rat488670 > 0.94) {
498  mask = 0;
499  }
500 
501  return status;
502 }
503 
504 /**************************************************************************
505  * NAME: DbPyrocbMaskOCI()
506  *
507  * DESCRIPTION: Class Constructor / Destructor
508  *
509  *************************************************************************/
510 
512  p_ = 0;
513 }
514 
515 DbPyrocbMaskOCI::DbPyrocbMaskOCI(Granule* granule, DbProcessLand* proc) :
516  Mask(granule) {
517  p_ = proc;
518 }
519 
521 }
522 
523 /**************************************************************************
524  * NAME: DbPyrocbMaskOCI::compute()
525  *
526  * DESCRIPTION:
527  *
528  *************************************************************************/
529 
530 int DbPyrocbMaskOCI::compute( const int iy, const int ix, short& mask )
531 {
532  int status = DT_SUCCESS;
533 
534  if (p_->rfl_[W1380] < filltest) {
535  mask = shortfill;
536  return status;
537  }
538  mask= 0;
539  float rat412488 = p_->ler412_ / p_->ler488_;
540  if (p_->rfl_[W1380] > 0.06 &&
541  p_->rfl_[W2250] > 0.2 &&
542 // p_->rfl_[W11000] < 268.0 &&
543  p_->ler670_ > 24.0 &&
544  rat412488 < 0.7) {
545  mask = 1;
546  }
547 
548  return status;
549 }
550 
551 /**************************************************************************
552  * NAME: DbHighAltSmokeMaskOCI()
553  *
554  * DESCRIPTION: Class Constructor / Destructor
555  *
556  *************************************************************************/
557 
559  p_ = 0;
560 }
561 
563  Mask(granule) {
564  p_ = proc;
565 }
566 
568 }
569 
570 /**************************************************************************
571  * NAME: DbHighAltSmokeMaskOCI::compute()
572  *
573  * DESCRIPTION:
574  *
575  *************************************************************************/
576 
577 int DbHighAltSmokeMaskOCI::compute( const int iy, const int ix, short& mask )
578 {
579  int status = DT_SUCCESS;
580 
581  if (p_->rfl_[W1380] < filltest) {
582  mask = shortfill;
583  return status;
584  }
585  mask= 0;
586  float lat = g_->in_->latitude;
587  float lon = g_->in_->longitude;
588 
589  int ilat = (int)((lat + 90.)*10.0);
590  if (ilat >= 1800) ilat = 1800-1;
591  if (ilat < 0) ilat = 0;
592  int ilon = (int)((lon + 180.0)*10.0);
593  if (ilon >= 3600) ilon = 3600-1;
594  if (ilon < 0) ilon = 0;
595  int gzflg = p_->gz_lut_->GEOZONE_FLAG[ilat][ilon];
596 
597  int ix1 = max(ix-1,0);
598  int ix2 = min(ix+1,g_->pixels_-1);
599  int iy1 = max(iy-1,0);
600  int iy2 = min(iy+1,g_->lines_-1);
601  int cntW2250 = 0;
602 // int cntbt11 = 0;
603  float tler[3][3][3];
604  float tsr[3][3][3];
605  float td[3][3][3];
606  memset(&tler[0][0][0],0,sizeof(tler));
607  memset(&tsr[0][0][0],0,sizeof(tsr));
608  memset(&td[0][0][0],0,sizeof(td));
609  for (int cy=iy1; cy<=iy2; cy++) {
610  for (int cx=ix1; cx<=ix2; cx++) {
611 // tler[0][cy-iy1][cx-ix1] = p_->ler412_a_[cy][cx];
612 // tler[1][cy-iy1][cx-ix1] = p_->ler488_a_[cy][cx];
613 // tler[2][cy-iy1][cx-ix1] = p_->ler670_a_[cy][cx];
614 // tsr[0][cy-iy1][cx-ix1] = p_->sr412_a_[cy][cx];
615 // tsr[1][cy-iy1][cx-ix1] = p_->sr488_a_[cy][cx];
616 // tsr[2][cy-iy1][cx-ix1] = p_->sr670_a_[cy][cx];
617 // td[0][cy-iy1][cx-ix1] = p_->rfl_[W1380][cy][cx];
618 // td[1][cy-iy1][cx-ix1] = p_->rfl_[W2250][cy][cx];
619 // td[2][cy-iy1][cx-ix1] = p_->rfl_[W11000][cy][cx];
620 // if (p_->rfl_[W11000][cy][cx] > 280.0) cntbt11++;
621  if (p_->rfl_[W2250][cy][cx] < 0.25) cntW2250++;
622  }
623  }
624  float rat488670 = p_->ler488_ / p_->ler670_;
625  float rat412488 = p_->ler412_ / p_->ler488_;
626 
627 // if (p_->ler412_ > 12.0 && cntbt11 == 9) {
628  if (p_->ler412_ > 12.0) {
629  if ((p_->sr670_ < 0.08 && cntW2250 == 9) ||
630  (p_->sr670_ >= 0.08 && cntW2250 == 9)) {
631  if (p_->ler488_ > 18.0 &&
632  (rat488670 > 0.7 && rat488670 < 0.88) &&
633  p_->rfl_[W2250] < 0.22 &&
634  p_->rfl_[W1380] > 0.0032) {
635  mask = 1;
636  }
637  if (p_->ler488_ > 18.0 &&
638  (rat488670 > 0.7 && rat488670 < 0.88) &&
639  p_->rfl_[W2250] < 0.22 && rat412488 < 0.8) {
640  mask = 1;
641  }
642  if (p_->ler488_ > 18.0 &&
643  p_->rfl_[W1380] > 0.0015 && rat412488 < 0.8) {
644 // p_->rfl_[W11000] > 268.0 && rat412488 < 0.8) {
645  mask = 1;
646  }
647  if (gzflg == 31) {
648  if (p_->ler488_ > 18.0 &&
649  (rat488670 > 0.9 && rat488670 < 1.06) &&
650  (rat412488 > 0.7 && rat412488 < 0.88) &&
651  p_->rfl_[W2250] < 0.22 &&
652  p_->rfl_[W1380] > 0.0032) {
653  mask = 1;
654  }
655  }
656  }
657  }
658  if (p_->sr670_ >= 0.12 || p_->rfl_[W2250] > 0.06 ||
659  p_->ler670_ > 50.0 || p_->rfl_[W1380] < 0.0005 ||
660  p_->rfl_[W1380] > 0.013) {
661  mask = 0;
662  }
663  if (rat412488/rat488670 > 0.94) {
664  mask = 0;
665  }
666  return status;
667 }
668 
669 /**************************************************************************
670  * NAME: DbCloudMaskOceanOCI()
671  *
672  * DESCRIPTION: Class Constructor / Destructor
673  *
674  *************************************************************************/
675 
677  p_ = 0;
678 }
679 
680 DbCloudMaskOceanOCI::DbCloudMaskOceanOCI(Granule* granule, DbProcessOcean* proc) :
681  Mask(granule) {
682  p_ = proc;
683 }
684 
686 }
687 
688 /**************************************************************************
689  * NAME: DbCloudMaskOceanOCI::compute()
690  *
691  * DESCRIPTION:
692  *
693  *************************************************************************/
694 
695 int DbCloudMaskOceanOCI::compute( const int iy, const int ix, short& mask )
696 {
697  int status = DT_SUCCESS;
698 
699  if (p_->rfl_[W412] < filltest) {
700  mask = shortfill;
701  return DT_SUCCESS;
702  }
703  float lat = g_->in_->latitude;
704  float solz = g_->in_->solar_zenith;
705  float m01_avg = 0;
706  float m01_stddev = 0;
707  float m08_avg = 0;
708  float m08_stddev = 0;
709  mask = 0;
710 
711  int ipmin = max(ix-1,0);
712  int ipmax = min(ix+1, g_->pixels_-1);
713  int ilmin = max(iy-1,0);
714  int ilmax = min(iy+1, g_->lines_-1);
715 // M01 W412
716  int cnt = 0;
717  for (int il=ilmin; il<=ilmax; il++) {
718  for (int ip=ipmin; ip<=ipmax; ip++) {
719  if (p_->rfl_[W412][il][ip] > filltest &&
720  g_->in_->land_water[il][ip] == 0) {
721  m01_avg += p_->rfl_[W412][il][ip];
722  cnt++;
723  }
724  }
725  }
726  if (cnt >= 2) {
727  m01_avg /= cnt;
728  cnt = 0;
729  for (int il=ilmin; il<=ilmax; il++) {
730  for (int ip=ipmin; ip<=ipmax; ip++) {
731  if (p_->rfl_[W412][il][ip] > filltest &&
732  g_->in_->land_water[il][ip] == 0) {
733  m01_stddev += pow((p_->rfl_[W412][il][ip]-m01_avg),2);
734  cnt++;
735  }
736  }
737  }
738  m01_stddev = sqrt(m01_stddev/(cnt-1));
739  } else {
740  m01_stddev = floatfill;
741  }
742 // M08 W1240
743  cnt = 0;
744  for (int il=ilmin; il<=ilmax; il++) {
745  for (int ip=ipmin; ip<=ipmax; ip++) {
746  if (p_->rfl_[W1240][il][ip] > filltest &&
747  g_->in_->land_water[il][ip] == 0) {
748  m08_avg += p_->rfl_[W1240][il][ip];
749  cnt++;
750  }
751  }
752  }
753  if (cnt >= 2) {
754  m08_avg /= cnt;
755  cnt = 0;
756  for (int il=ilmin; il<=ilmax; il++) {
757  for (int ip=ipmin; ip<=ipmax; ip++) {
758  if (p_->rfl_[W1240][il][ip] > filltest &&
759  g_->in_->land_water[il][ip] == 0) {
760  m08_stddev += pow((p_->rfl_[W1240][il][ip]-m08_avg),2);
761  cnt++;
762  }
763  }
764  }
765  m08_stddev = sqrt(m08_stddev/(cnt-1));
766  } else {
767  m08_stddev = floatfill;
768  }
769  float cosza = cos(solz*DEG2RAD);
770  if (lat > 65.0) {
771  if ((m01_stddev > filltest &&
772  (m01_stddev > M01_STDV_THOLD*cosza)) ||
773  (m08_stddev > filltest &&
774  (m08_stddev > M08_HILAT_STDV_THOLD*cosza))) {
775  mask = 1;
776  }
777  } else {
778  if ((m01_stddev > filltest &&
779  m01_stddev > M01_STDV_THOLD*cosza) ||
780  (m08_stddev > filltest &&
781  m08_stddev > M08_STDV_THOLD*cosza)) {
782  mask = 1;
783  }
784  }
785 // -- perform the check on the 1.38 um band (M09)
786  if (p_->rfl_[W1380] > M09_THOLD*cosza) {
787  mask = 1;
788  }
789 // -- perform check on 488 nm band (M03)
790  if (p_->rfl_[W488] > M03_THOLD*cosza) {
791  mask = 1;
792  }
793 
794  return status;
795 }
796 
797 
798 
float rf(float x, float y, float z)
int compute(const int iy, const int ix, short &mask)
Definition: DbMaskOCI.cpp:577
int status
Definition: l1_czcs_hdf.c:32
These are used to scale the SD before writing it to the HDF4 file The default is and which means the product is not scaled at all Since the product is usually stored as a float inside of this is a way to write the float out as a integer l2prod min
static constexpr float M03_THOLD
Definition: DbMaskOCI.h:122
DbProcessOcean * p_
Definition: DbMaskOCI.h:139
static constexpr float M01_STDV_THOLD
Definition: DbMaskOCI.h:118
float rfl[NOWL]
Definition: DbAlgOcean.cpp:41
float * lat
int compute(const int iy, const int ix, short &mask)
Definition: DbMaskOCI.cpp:530
MOD_PR02 Error Meanings and Operator specific error codes that may be generated by the general meaning of these error codes and probably from the MOD01 granule
DbProcessLand * p_
Definition: DbMaskOCI.h:39
#define PI
Definition: l3_get_org.c:6
static constexpr float M09_THOLD
Definition: DbMaskOCI.h:121
DbProcessLand * p_
Definition: DbMaskOCI.h:89
const double delta
static constexpr float M08_STDV_THOLD
Definition: DbMaskOCI.h:119
a context in which it is NOT documented to do so subscript which cannot be easily calculated when extracting TONS attitude data from the Terra L0 files Corrected several defects in extraction of entrained ephemeris and and as HDF file for both the L1A and Geolocation enabling retrieval of South Polar DEM data Resolved Bug by changing to opent the geolocation file only after a successful read of the L1A and also by checking for fatal errors from not restoring C5 and to report how many of those high resolution values were water in the new WaterPresent SDS Added valid_range attribute to Land SeaMask Changed to bilinearly interpolate the geoid_height to remove artifacts at one degree lines Made corrections to const qualification of pointers allowed by new version of M API library Removed casts that are no longer for same not the geoid Corrected off by one error in calculation of high resolution offsets Corrected parsing of maneuver list configuration parameter Corrected to set Height SDS to fill values when geolocation when for elevation and land water mask
Definition: HISTORY.txt:114
static constexpr float M08_HILAT_STDV_THOLD
Definition: DbMaskOCI.h:120
float * lon
DbProcessLand * p_
Definition: DbMaskOCI.h:65
int compute(const int iy, const int ix, short &mask)
Definition: DbMaskOCI.cpp:695
#define DEG2RAD
Definition: GEO_geo.h:174
DbProcessLand * p_
Definition: DbMaskOCI.h:112
l2prod max