OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
DbMask.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * NAME: DbMask.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/DbMask.h"
16 
17 #include <math.h>
18 
19 #include <DDProcess.h>
20 #include "deepblue/DbAlgorithm.h"
21 
22 using namespace std;
23 
24 /**************************************************************************
25  * NAME: DbCloudMaskLand()
26  *
27  * DESCRIPTION: Class Constructor / Destructor
28  *
29  *************************************************************************/
30 
32  p_ = 0;
33 }
34 
36 {
37  p_ = proc;
38 }
39 
41 }
42 
43 /**************************************************************************
44  * NAME: DbCloudMaskLand::compute_1()
45  *
46  * DESCRIPTION: Initial set of cloud mask filters applied to modis units
47  *
48  *************************************************************************/
49 
50 int DbCloudMaskLand::compute_1( const size_t iy, const size_t ix, short& mask,
51  short& snow1, short& snow2 )
52 {
53  int status = DTDB_SUCCESS;
54 
55  if (p_->rfl_[(size_t)rhot_band::W410] < 0) {
56  mask = DFILL_SHORT;
57  snow1 = DFILL_SHORT;
58  snow2 = DFILL_SHORT;
59  return status;
60  }
61  mask = 0;
62  snow1 = 0;
63  snow2 = 0;
64 
65  float lat = p_->lat_;
66  float lon = p_->lon_;
67 
68  // Convert raw reflectances to modis units
69  float rfl[NTWL];
70  if (p_->rfl_[(size_t)rhot_band::W410] > 0) {
71  for (size_t ib=0; ib<NTWL; ib++) {
72  rfl[ib] = p_->rfl_[ib];
73  }
74  } else {
75  for (size_t ib=0; ib<NTWL; ib++) {
76  rfl[ib] = DFILL_FLOAT;
77  }
78  }
79 
80  int ilat = (int)((lat + 90.)*10.0);
81  if (ilat >= 1800) ilat = 1800-1;
82  if (ilat < 0) ilat = 0;
83  int ilon = (int)((lon + 180.0)*10.0);
84  if (ilon >= 3600) ilon = 3600-1;
85  if (ilon < 0) ilon = 0;
86  int gzflg = p_->gz_lut_->GEOZONE_FLAG[ilat][ilon];
87  // Define pixel range
88  size_t ix1 = (ix==0) ? 0 : ix-1;
89  size_t ix2 = min(ix+1,p_->pixels_-1);
90  size_t iy1 = (iy==0) ? 0 : iy-1;
91  size_t iy2 = min(iy+1,p_->lines_-1);
92  // Compute Rfl minmax ratios
93  float rflmin = 999.0;
94  float rflmax = -999.0;
95  for (size_t cx=ix1; cx<=ix2; cx++) {
96  for (size_t cy=iy1; cy<=iy2; cy++) {
97  float rf = p_->rfla_[(size_t)rhot_band::W410][cy-iy1][cx-ix1];
98  if (rf > 0) {
99  rflmin = (rf<rflmin) ? rf : rflmin;
100  rflmax = (rf>rflmax) ? rf : rflmax;
101  }
102  }
103  }
104  if (rflmax<1.E-8 || rflmin<1.E-8 ) {
105  mask = DFILL_SHORT;
106  snow1 = DFILL_SHORT;
107  snow2 = DFILL_SHORT;
108  return DTDB_SUCCESS;
109  }
110  float minmax_rfl = rflmax/rflmin + DbAlgLand::delta;
111  // Begin cloud tests
112  if (minmax_rfl > 1.2) {
113  mask = 1;
114  }
115  if (p_->sr670_ >= 0.08 && minmax_rfl > 1.15) {
116  mask = 1;
117  }
118 // Over bright surfaces, apply RR1.38/0.66 and BTD11-12 threshold !JH
119 // test addition - 6/7/2011
120  if (p_->sr670_ >= 0.08 ) {
121  if (rfl[(size_t)rhot_band::W1380] > 0.018 && p_->pwv_ >= 0.9) {
122  mask = 1; // Thin Cirrus Screening
123  }
124  if (gzflg == 24) {// Taklimakan
125  if (rfl[(size_t)rhot_band::W1380] > 0.04 && p_->pwv_ < 0.9 &&
126  rfl[(size_t)rhot_band::W670] < 0.45) {
127  mask = 1;
128  }
129  } else if (rfl[(size_t)rhot_band::W1380] > 0.018 && p_->pwv_ < 0.9 &&
130  rfl[(size_t)rhot_band::W670] < 0.55) {
131  mask = 1;
132  }
133  }
134 // Over dark surfaces
135  if (p_->sr670_ > 0.0 && p_->sr670_ < 0.08 ) {
136  float dd = rfl[(size_t)rhot_band::W670]/rfl[(size_t)rhot_band::W410];
137  if (p_->rfl_[(size_t)rhot_band::W2250] > 0.36 && dd < 0.95) {
138  mask = 1;
139  }
140  if (rfl[(size_t)rhot_band::W1380] > 0.018 &&
141  p_->pwv_ > 0.4) {
142  mask = 1;
143  }
144  }
145 // High AMF
146  if (lat > 60.0 && p_->amf_ > 7.0) {
147  if (rfl[(size_t)rhot_band::W1380] > 0.018 &&
148  p_->pwv_ > 0.9) {
149  mask = 1;
150  }
151  if (rfl[(size_t)rhot_band::W490] > 0.4) {
152  mask = 1;
153  }
154  }
155  if ((gzflg == 5 || gzflg == 1 || gzflg == 26 || gzflg == 27) ||
156  (lon < 15.0 && ((lon >-20.0 && lon < 55.0) && gzflg == -999))) {
157  if (p_->sr670_ > 0.0 && p_->sr670_ < 0.08 ) {
158  if (rfl[(size_t)rhot_band::W490] > 0.15) {
159  if (rfl[(size_t)rhot_band::W2250] > 0.16) {
160  mask = 1;
161  }
162  }
163  }
164  }
165 
166 // -- try to detect snow cover and skip pixel.
167 // -- source: http://modis-snow-ice.gsfc.nasa.gov/?c=atbdt=atbd
168  float ndsi = DFILL_FLOAT;
169  if (rfl[(size_t)rhot_band::W550] > 0 && rfl[(size_t)rhot_band::W2250] > 0) {
170  ndsi = (rfl[(size_t)rhot_band::W550] - rfl[(size_t)rhot_band::W1610]) /
171  (rfl[(size_t)rhot_band::W550] + rfl[(size_t)rhot_band::W1610]);
172  } else {
173  mask = 1;
174  }
175  if (ndsi > 0.35 && rfl[(size_t)rhot_band::W865] > 0.11 &&
176  rfl[(size_t)rhot_band::W550] > 0.1) {
177  snow1 = 1;
178  }
179  if (ndsi > -0.2 && rfl[(size_t)rhot_band::W865] > 0.11) {
180  snow2 = 1;
181  }
182  if (snow1 == 1) {
183  mask = 1;
184  }
185 
186  return status;
187 }
188 
189 /**************************************************************************
190  * NAME: DbCloudMaskLand::compute_2()
191  *
192  * DESCRIPTION: Initial set of cloud mask filters applied to modis units
193  *
194  *************************************************************************/
195 
196 
197 int DbCloudMaskLand::compute_2( const size_t iy, const size_t ix,
198  short& mask, const short snow2 )
199 {
200  int status = DTDB_SUCCESS;
201 
202  if (p_->rfl_[(size_t)rhot_band::W410] < 0) {
203  mask = DFILL_SHORT;
204  return status;
205  }
206  float lat = p_->lat_;
207  float lon = p_->lon_;
208  float solz = p_->solz_;
209  int ilat = (int)((lat + 90.)*10.0);
210  if (ilat >= 1800) ilat = 1800-1;
211  if (ilat < 0) ilat = 0;
212  int ilon = (int)((lon + 180.0)*10.0);
213  if (ilon >= 3600) ilon = 3600-1;
214  if (ilon < 0) ilon = 0;
215  int gzflg = p_->gz_lut_->GEOZONE_FLAG[ilat][ilon];
216  int sfcstd = p_->sp_lut_->SURFACE_ELEVATION[ilat][ilon];
217  int month = p_->month_;
218 
219  if (p_->ler412_ > 50.0) {
220  mask = 1;
221  }
222  if (p_->sr670_ < 0.1) {
223  if (p_->rfl_[(size_t)rhot_band::W2250] > 0.05 &&
224  p_->ler412_ > 12.0) {
225  mask = 1;
226  }
227  }
228  if (p_->sr670_ < 0.08) {
229  if (p_->ler412_ > 40.0) {
230  mask = 1;
231  }
232  if (p_->ler412_ > 20.0 && solz > 72.0) {
233  mask = 1;
234  }
235  }
236 // Define pixel range
237  size_t ix1 = (ix==0) ? 0 : ix-1;
238  size_t ix2 = min(ix+1,p_->pixels_-1);
239  size_t iy1 = (iy==0) ? 0 : iy-1;
240  size_t iy2 = min(iy+1,p_->lines_-1);
241 // Compute Ler minmax ratios
242  float lermin = 999.0;
243  float lermax = -999.0;
244  for (size_t cx=ix1; cx<=ix2; cx++) {
245  for (size_t cy=iy1; cy<=iy2; cy++) {
246 // float lr = p_->ler412_a_[cy][cx];
247 // if (lr > 0) {
248 // lermin = (lr<lermin) ? lr : lermin;
249 // lermax = (lr>lermax) ? lr : lermax;
250 // }
251  lermin = 1;
252  lermax = 1;
253  }
254  }
255 
256  if (lermax<1.E-8 || lermin<1.E-8 ) {
257  mask = DFILL_FLOAT;
258  return DTDB_SUCCESS;
259  }
260  float minmax_ler = lermax/lermin + DbAlgLand::delta;
261 //-- N. America
262  if (snow2 == 1 && gzflg == 13 &&
263  p_->ndvi_ < 0.35 &&
264  sfcstd <= 50 && minmax_ler > 1.20) {
265  mask = 1;
266  }
267 //-- higher ndvi and minmax thresholds for spring at high latitudes
268  if (lat > 45 && month >= 2 && month <= 6 &&
269  snow2 == 1 && gzflg == 13 && p_->ndvi_ < 0.45 &&
270  sfcstd <= 50 && minmax_ler > 1.30) {
271  mask = 1;
272  }
273 //-- Rest of the world
274  if (snow2 == 1 && gzflg != 13 && p_->ndvi_ < 0.35 &&
275  sfcstd <= 50 && minmax_ler > 1.40) {
276  mask = 1;
277  }
278 // --higher ndvi threshold and lower minmax for spring at high latitudes
279  if (lat > 50 && month >= 2 && month <= 6 && snow2 == 1 &&
280  gzflg != 13 && p_->ndvi_ < 0.45 &&
281  sfcstd <= 50 && minmax_ler > 1.30) {
282  mask = 1;
283  }
284 //-- Mountainous regions
285  if (snow2 == 1 && sfcstd > 50 && minmax_ler > 1.80) {
286  mask = 1;
287  }
288 // -- detect anomalous D* values in large dust storm over Taklimakan
289 // -- region and resetthe cloud mask to 0.
290  if (gzflg == 24) {
291  if (p_->ler412_ > 0 &&
292  p_->ler488_ > 0 &&
293  p_->ler670_ > 0) {
294  if (p_->ler488_/p_->ler670_ < 0.65 &&
295  p_->ler412_ > 18.0) {
296  mask = 0;
297  }
298  }
299  }
300 
301  return status;
302 }
303 
304 /**************************************************************************
305  * NAME: DbSmokeMask()
306  *
307  * DESCRIPTION: Class Constructor / Destructor
308  *
309  *************************************************************************/
310 
312  p_ = 0;
313 }
314 
316  p_ = proc;
317 }
318 
320 }
321 
322 /**************************************************************************
323  * NAME: DbSmokeMask::compute()
324  *
325  * DESCRIPTION:
326  *
327  *************************************************************************/
328 
329 int DbSmokeMask::compute( const size_t iy, const size_t ix, short& mask )
330 {
331  int status = DTDB_SUCCESS;
332 
333  if (p_->rfl_[(size_t)rhot_band::W1380] < 0) {
334  mask = DFILL_SHORT;
335  return status;
336  }
337  mask = 0;
338 
339  size_t ix1 = (ix==0) ? 0 : ix-1;
340  size_t ix2 = min(ix+1,p_->pixels_-1);
341  size_t iy1 = (iy==0) ? 0 : iy-1;
342  size_t iy2 = min(iy+1,p_->lines_-1);
343  int cnt2250_1 = 0;
344  int cnt2250_2 = 0;
345 
346  float tler[3][3][3];
347  float tsr[3][3][3];
348  float td[3][3][3];
349  memset(&tler[0][0][0],0,sizeof(tler));
350  memset(&tsr[0][0][0],0,sizeof(tsr));
351  memset(&td[0][0][0],0,sizeof(td));
352  for (size_t cy=iy1; cy<=iy2; cy++) {
353  for (size_t cx=ix1; cx<=ix2; cx++) {
354 // tler[0][cy-iy1][cx-ix1] = p_->ler412_a_[cy][cx];
355 // tler[1][cy-iy1][cx-ix1] = p_->ler488_a_[cy][cx];
356 // tler[2][cy-iy1][cx-ix1] = p_->ler670_a_[cy][cx];
357 // tsr[0][cy-iy1][cx-ix1] = p_->sr412_a_[cy][cx];
358 // tsr[1][cy-iy1][cx-ix1] = p_->sr488_a_[cy][cx];
359 // tsr[2][cy-iy1][cx-ix1] = p_->sr670_a_[cy][cx];
360 // td[0][cy-iy1][cx-ix1] = p_->rfla_[(size_t)rhot_band::W1380][cy][cx];
361 // td[1][cy-iy1][cx-ix1] = p_->rfla_[(size_t)rhot_band::W2250][cy][cx];
362 // td[2][cy-iy1][cx-ix1] = p_->rfla_[(size_t)rhot_band::W11000][cy][cx];
363 
364  if (p_->rfla_[(size_t)rhot_band::W2250][cy-iy1][cx-ix1] < 0.035) cnt2250_1++;
365  if (p_->rfla_[(size_t)rhot_band::W2250][cy-iy1][cx-ix1] < 0.065) cnt2250_2++;
366  }
367  }
368  float rat488670 = p_->ler488_ / p_->ler670_;
369  float rat412488 = p_->ler412_ / p_->ler488_;
370  if (p_->ler412_ > 12.0) {
371  if ((p_->sr670_ < 0.08 && cnt2250_1 == 9) ||
372  (p_->sr670_ >= 0.08 && cnt2250_2 == 9)) {
373  if (p_->rfl_[(size_t)rhot_band::W2250] < 0.025) {
374  mask = 1;
375  } else {
376  if (p_->ler412_ > 20.0 &&
377  p_->rfl_[(size_t)rhot_band::W2250] < 0.04) {
378  mask = 1;
379  } else {
380  if (p_->ler488_ > 0.0 && p_->ler670_ > 0.0) {
381  rat488670 = p_->ler488_ / p_->ler670_;
382  if (rat488670 > 0.88) {
383  mask = 1;
384  } else {
385  if (rat488670 > 0.7 && rat488670 < 0.88 &&
386  p_->rfl_[(size_t)rhot_band::W2250] < 0.04 &&
387  p_->rfl_[(size_t)rhot_band::W1380] > 0.0015) {
388  mask = 1;
389  }
390  }
391  }
392  }
393  }
394  }
395  }
396  if (p_->sr670_ >= 0.12 || p_->ler670_ > 50.0) {
397  mask = 0;
398  }
399  if (rat412488/rat488670 > 0.94) {
400  mask = 0;
401  }
402 
403  return status;
404 }
405 
406 /**************************************************************************
407  * NAME: DbPyrocbMask()
408  *
409  * DESCRIPTION: Class Constructor / Destructor
410  *
411  *************************************************************************/
412 
414  p_ = 0;
415 }
416 
418  p_ = proc;
419 }
420 
422 }
423 
424 /**************************************************************************
425  * NAME: DbPyrocbMask::compute()
426  *
427  * DESCRIPTION:
428  *
429  *************************************************************************/
430 
431 int DbPyrocbMask::compute( const size_t iy, const size_t ix, short& mask )
432 {
433  int status = DTDB_SUCCESS;
434 
435  if (p_->rfl_[(size_t)rhot_band::W1380] < 0) {
436  mask = DFILL_SHORT;
437  return status;
438  }
439  mask= 0;
440  float rat412488 = p_->ler412_ / p_->ler488_;
441  if (p_->rfl_[(size_t)rhot_band::W1380] > 0.06 &&
442  p_->rfl_[(size_t)rhot_band::W2250] > 0.2 &&
443  p_->ler670_ > 24.0 &&
444  rat412488 < 0.7) {
445  mask = 1;
446  }
447 
448  return status;
449 }
450 
451 /**************************************************************************
452  * NAME: DbHighAltSmokeMask()
453  *
454  * DESCRIPTION: Class Constructor / Destructor
455  *
456  *************************************************************************/
457 
459  p_ = 0;
460 }
461 
463  p_ = proc;
464 }
465 
467 }
468 
469 /**************************************************************************
470  * NAME: DbHighAltSmokeMask::compute()
471  *
472  * DESCRIPTION:
473  *
474  *************************************************************************/
475 
476 int DbHighAltSmokeMask::compute( const size_t iy, const size_t ix, short& mask )
477 {
478  int status = DTDB_SUCCESS;
479 
480  if (p_->rfl_[(size_t)rhot_band::W1380] < 0) {
481  mask = DFILL_SHORT;
482  return status;
483  }
484  mask= 0;
485  float lat = p_->lat_;
486  float lon = p_->lon_;
487 
488  int ilat = (int)((lat + 90.)*10.0);
489  if (ilat >= 1800) ilat = 1800-1;
490  if (ilat < 0) ilat = 0;
491  int ilon = (int)((lon + 180.0)*10.0);
492  if (ilon >= 3600) ilon = 3600-1;
493  if (ilon < 0) ilon = 0;
494  int gzflg = p_->gz_lut_->GEOZONE_FLAG[ilat][ilon];
495 
496  size_t ix1 = (ix==0) ? 0 : ix-1;
497  size_t ix2 = min(ix+1,p_->pixels_-1);
498  size_t iy1 = (iy==0) ? 0 : iy-1;
499  size_t iy2 = min(iy+1,p_->lines_-1);
500  int cntW2250 = 0;
501  float tler[3][3][3];
502  float tsr[3][3][3];
503  float td[3][3][3];
504  memset(&tler[0][0][0],0,sizeof(tler));
505  memset(&tsr[0][0][0],0,sizeof(tsr));
506  memset(&td[0][0][0],0,sizeof(td));
507  for (size_t cy=iy1; cy<=iy2; cy++) {
508  for (size_t cx=ix1; cx<=ix2; cx++) {
509 // tler[0][cy-iy1][cx-ix1] = p_->ler412_a_[cy][cx];
510 // tler[1][cy-iy1][cx-ix1] = p_->ler488_a_[cy][cx];
511 // tler[2][cy-iy1][cx-ix1] = p_->ler670_a_[cy][cx];
512 // tsr[0][cy-iy1][cx-ix1] = p_->sr412_a_[cy][cx];
513 // tsr[1][cy-iy1][cx-ix1] = p_->sr488_a_[cy][cx];
514 // tsr[2][cy-iy1][cx-ix1] = p_->sr670_a_[cy][cx];
515 // td[0][cy-iy1][cx-ix1] = p_->rfl_[(size_t)rhot_band::W1380][cy][cx];
516 // td[1][cy-iy1][cx-ix1] = p_->rfl_[(size_t)rhot_band::W2250][cy][cx];
517 // td[2][cy-iy1][cx-ix1] = p_->rfl_[(size_t)rhot_band::W11000][cy][cx];
518  if (p_->rfla_[(size_t)rhot_band::W2250][cy-iy1][cx-ix1] < 0.25) cntW2250++;
519  }
520  }
521  float rat488670 = p_->ler488_ / p_->ler670_;
522  float rat412488 = p_->ler412_ / p_->ler488_;
523 
524  if (p_->ler412_ > 12.0) {
525  if ((p_->sr670_ < 0.08 && cntW2250 == 9) ||
526  (p_->sr670_ >= 0.08 && cntW2250 == 9)) {
527  if (p_->ler488_ > 18.0 &&
528  (rat488670 > 0.7 && rat488670 < 0.88) &&
529  p_->rfl_[(size_t)rhot_band::W2250] < 0.22 &&
530  p_->rfl_[(size_t)rhot_band::W1380] > 0.0032) {
531  mask = 1;
532  }
533  if (p_->ler488_ > 18.0 && (rat488670 > 0.7 && rat488670 < 0.88) &&
534  p_->rfl_[(size_t)rhot_band::W2250] < 0.22 && rat412488 < 0.8) {
535  mask = 1;
536  }
537  if (p_->ler488_ > 18.0 && p_->rfl_[(size_t)rhot_band::W1380] > 0.0015 &&
538  rat412488 < 0.8) {
539  mask = 1;
540  }
541  if (gzflg == 31) {
542  if (p_->ler488_ > 18.0 &&
543  (rat488670 > 0.9 && rat488670 < 1.06) &&
544  (rat412488 > 0.7 && rat412488 < 0.88) &&
545  p_->rfl_[(size_t)rhot_band::W2250] < 0.22 &&
546  p_->rfl_[(size_t)rhot_band::W1380] > 0.0032) {
547  mask = 1;
548  }
549  }
550  }
551  }
552  if (p_->sr670_ >= 0.12 || p_->rfl_[(size_t)rhot_band::W2250] > 0.06 ||
553  p_->ler670_ > 50.0 || p_->rfl_[(size_t)rhot_band::W1380] < 0.0005 ||
554  p_->rfl_[(size_t)rhot_band::W1380] > 0.013) {
555  mask = 0;
556  }
557  if (rat412488/rat488670 > 0.94) {
558  mask = 0;
559  }
560  return status;
561 }
562 
563 /**************************************************************************
564  * NAME: DbCloudMaskOcean()
565  *
566  * DESCRIPTION: Class Constructor / Destructor
567  *
568  *************************************************************************/
569 
571 }
572 
574  p_ = proc;
575 }
576 
578 }
579 
580 /**************************************************************************
581  * NAME: DbCloudMaskOcean::compute()
582  *
583  * DESCRIPTION:
584  *
585  *************************************************************************/
586 
587 
589 {
590  int status = DTDB_SUCCESS;
591 
592  if (p_->rfl_[(size_t)rhot_band::W410] < 0) {
593  mask = DFILL_SHORT;
594  return status;
595  }
596  float lat = p_->lat_;
597  float solz = p_->solz_;
598  float m01_avg = 0;
599  float m01_stddev = 0;
600  float m08_avg = 0;
601  float m08_stddev = 0;
602  mask = 0;
603 
604 // Convert to units of normalize radiance
605  float rfl[NTWL][3][3];
606  memset(rfl,0,sizeof(rfl));
607  double cossza = cos(solz*DEGtoRAD);
608  for (size_t iw=0; iw<NTWL; iw++) {
609  for (size_t il=0; il<=2; il++) {
610  for (size_t ip=0; ip<=2; ip++) {
611  if (p_->rfla_[iw][il][ip] < 0) {
612  rfl[iw][il][ip] = DFILL_FLOAT;
613  } else {
614  rfl[iw][il][ip] = p_->rfla_[iw][il][ip]*cossza/M_PI;
615  }
616  }
617  }
618  }
619 
620 // M01 W412
621  size_t cnt = 0;
622  for (size_t il=0; il<=2; il++) {
623  for (size_t ip=0; ip<=2; ip++) {
624  if (rfl[(size_t)rhot_band::W410][il][ip] > 0) {
625  m01_avg += rfl[(size_t)rhot_band::W410][il][ip];
626  cnt++;
627  }
628  }
629  }
630  if (cnt >= 2) {
631  m01_avg /= cnt;
632  cnt = 0;
633  for (size_t il=0; il<=2; il++) {
634  for (size_t ip=0; ip<=2; ip++) {
635  if (rfl[(size_t)rhot_band::W410][il][ip] > 0) {
636  m01_stddev += pow((rfl[(size_t)rhot_band::W410][il][ip]-m01_avg),2);
637  cnt++;
638  }
639  }
640  }
641  m01_stddev = sqrt(m01_stddev/(cnt-1));
642  } else {
643  m01_stddev = DFILL_FLOAT;
644  }
645 // M08 W1240
646  cnt = 0;
647  for (size_t il=0; il<=2; il++) {
648  for (size_t ip=0; ip<=2; ip++) {
649  if (rfl[(size_t)rhot_band::W1240][il][ip] > 0) {
650  m08_avg += rfl[(size_t)rhot_band::W1240][il][ip];
651  cnt++;
652  }
653  }
654  }
655  if (cnt >= 2) {
656  m08_avg /= cnt;
657  cnt = 0;
658  for (size_t il=0; il<=2; il++) {
659  for (size_t ip=0; ip<=2; ip++) {
660  if (rfl[(size_t)rhot_band::W1240][il][ip] > 0) {
661  m08_stddev += pow((rfl[(size_t)rhot_band::W1240][il][ip]-m08_avg),2);
662  cnt++;
663  }
664  }
665  }
666  m08_stddev = sqrt(m08_stddev/(cnt-1));
667  } else {
668  m08_stddev = DFILL_FLOAT;
669  }
670  float cosza = cos(solz*DEGtoRAD);
671  if (lat > 65.0) {
672  if ((m01_stddev > 0 &&
673  (m01_stddev > M01_STDV_THOLD*cosza)) ||
674  (m08_stddev > 0 &&
675  (m08_stddev > M08_HILAT_STDV_THOLD*cosza))) {
676  mask = 1;
677  } else {
678  mask = 0;
679  }
680  } else {
681  if ((m01_stddev > 0 &&
682  m01_stddev > M01_STDV_THOLD*cosza) ||
683  (m08_stddev > 0 &&
684  m08_stddev > M08_STDV_THOLD*cosza)) {
685  mask = 1;
686  } else {
687  mask = 0;
688  }
689  }
690 // -- perform the check on the 1.38 um band (M09)
691  if (rfl[(size_t)rhot_band::W1380][1][1] > M09_THOLD*cosza) {
692  mask = 1;
693  }
694 // -- perform check on 488 nm band (M03)
695  if (rfl[(size_t)rhot_band::W490][1][1] > M03_THOLD*cosza) {
696  mask = 1;
697  }
698 
699  return status;
700 }
701 
float rf(float x, float y, float z)
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
int compute(const size_t iy, const size_t ix, short &mask)
Definition: DbMask.cpp:431
float rfl[NOWL]
Definition: DbAlgOcean.cpp:41
float * lat
static constexpr float delta
Definition: DbAlgorithm.h:77
~DbSmokeMask()
Definition: DbMask.cpp:319
#define M_PI
Definition: pml_iop.h:15
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
int compute(const size_t iy, const size_t ix, short &mask)
Definition: DbMask.cpp:329
constexpr float DFILL_FLOAT
Definition: DDataset.hpp:25
int compute(short &mask)
Definition: DbMask.cpp:588
int compute(const size_t iy, const size_t ix, short &mask)
Definition: DbMask.cpp:476
float * lon
int compute_2(const size_t iy, const size_t ix, short &mask, const short snow2)
Definition: DbMask.cpp:197
constexpr short DFILL_SHORT
Definition: DDataset.hpp:27
int compute_1(const size_t iy, const size_t ix, short &mask, short &snow1, short &snow2)
Definition: DbMask.cpp:50