OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
DtMask.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * NAME: DtMask.cpp
4  *
5  * DESCRIPTION: Object class that provides data structures and processes that
6  * compute cloud masks for a given DDProcess object class.
7  *
8  * Created on: November 3, 2016
9  * Author: Sam Anderson, DT
10  *
11  * Modified:
12  *
13  *******************************************************************************/
14 
15 #include "darktarget/DtMask.h"
16 
17 #include <math.h>
18 
19 #include <DDProcess.h>
20 #include "darktarget/DtAlgorithm.h"
21 
22 using namespace std;
23 
24 /**************************************************************************
25  * NAME: DtCloudMaskLand()
26  *
27  * DESCRIPTION: Class Constructor
28  *
29  *************************************************************************/
30 
32 }
33 
34 /**************************************************************************
35  * NAME: DtCloudMaskLand()
36  *
37  * DESCRIPTION: Class Constructor
38  *
39  *************************************************************************/
40 
42  p_ = process;
43  mask_cirrus_ = 0;
44  snowmask_ = 0;
45 }
46 
47 /**************************************************************************
48  * NAME: ~DtCloudMaskLand()
49  *
50  * DESCRIPTION: Class Destructor
51  *
52  *************************************************************************/
53 
55 }
56 
57 /**************************************************************************
58  * NAME: initialize()
59  *
60  * DESCRIPTION: Virtual function initializes data and object classes for
61  * cloud mask operations.
62  *
63  *************************************************************************/
64 
66  return DTDB_SUCCESS;
67 }
68 
69 /**************************************************************************
70  * NAME: compute()
71  *
72  * DESCRIPTION: Virtual function computes cloud mask over land using spatial
73  * variability of 0.47 (>0.01) and 1.38 um (>0.007) reflectance as well
74  * as absolute value of 1.38 um > 0.1
75  *
76  * INPUT PARAMETERS:
77  *
78  * ISWATH Number of pixels at 1 km resolution along scan
79  * ILINE Number of pixels at 1 km resolution against scan
80  * Refl_3 Reflectance at 0.47 um
81  * Refl_26 Reflectance at 1.38 um
82  *
83  * OUTPUT PARAMETERS:
84  *
85  * CLDMSK_1KM Cloud mask at 1 km resolution
86  * CldMsk_500 Cloud mask at 500m resolution
87  * CldMsk_250 Cloud mask at 250m resolution
88  *
89  *************************************************************************/
90 
91 int DtCloudMaskLand::compute( unsigned char& mask )
92 {
93  int status = DTDB_SUCCESS;
94 
95  mask = 1;
96 
97  if (p_->rfl_[(size_t)rhot_band::W410] < 0) {
98  mask = DFILL_UBYTE;
99  return status;
100  }
101  float m03_avg = 0;
102  float m03_stddev = 0;
103  float m09_avg = 0;
104  float m09_stddev = 0;
105 
106 // Gather 3x3 grid
107  float rfl[NTWL][3][3];
108  memset(rfl,0,sizeof(rfl));
109  for (size_t iw=0; iw<NTWL; iw++) {
110  for (size_t il=0; il<=2; il++) {
111  for (size_t ip=0; ip<=2; ip++) {
112  rfl[iw][il][ip] = p_->rfla_[iw][il][ip];
113  }
114  }
115  }
116 
117 // M03 W488
118  size_t cnt = 0;
119  for (size_t il=0; il<=2; il++) {
120  for (size_t ip=0; ip<=2; ip++) {
121  if (rfl[(size_t)rhot_band::W490][il][ip] > 0) {
122  m03_avg += rfl[(size_t)rhot_band::W490][il][ip];
123  cnt++;
124  }
125  }
126  }
127  if (cnt >= 2) {
128  m03_avg /= cnt;
129  cnt = 0;
130  for (size_t il=0; il<=2; il++) {
131  for (size_t ip=0; ip<=2; ip++) {
132  if (rfl[(size_t)rhot_band::W490][il][ip] > 0) {
133  m03_stddev += pow((rfl[(size_t)rhot_band::W490][il][ip]-m03_avg),2);
134  cnt++;
135  }
136  }
137  }
138  m03_stddev = sqrt(m03_stddev/(cnt-1));
139  } else {
140  m03_stddev = DFILL_FLOAT;
141  }
142 // M09 W1380
143  cnt = 0;
144  for (size_t il=0; il<=2; il++) {
145  for (size_t ip=0; ip<=2; ip++) {
146  if (rfl[(size_t)rhot_band::W1380][il][ip] > 0) {
147  m09_avg += rfl[(size_t)rhot_band::W1380][il][ip];
148  cnt++;
149  }
150  }
151  }
152  if (cnt >= 2) {
153  m09_avg /= cnt;
154  cnt = 0;
155  for (size_t il=0; il<=2; il++) {
156  for (size_t ip=0; ip<=2; ip++) {
157  if (rfl[(size_t)rhot_band::W1380][il][ip] > 0) {
158  m09_stddev += pow((rfl[(size_t)rhot_band::W1380][il][ip]-m09_avg),2);
159  cnt++;
160  }
161  }
162  }
163  m09_stddev = sqrt(m09_stddev/(cnt-1));
164  } else {
165  m09_stddev = DFILL_FLOAT;
166  }
167 
168  if ((m03_stddev > 0 && (m03_stddev > THRHLD470_STD)) ||
169  (m09_stddev > 0 && (m09_stddev > THRHLD1380_STD))) {
170  mask = 0;
171  } else {
172  mask = 1;
173  }
174 // -- perform the check on the 1.38 um band (M09)
175  if (rfl[(size_t)rhot_band::W1380][1][1] > THRHLD1380) {
176  mask = 0;
177  }
178 // -- perform check on 488 nm band (M03)
179  if (rfl[(size_t)rhot_band::W490][1][1] > THRHLD470) {
180  mask = 0;
181  }
182 
183  compute_snowmask();
184 
185  return status;
186 }
187 
188 
189 /**************************************************************************
190  * NAME: compute_snowmask()
191  *
192  * DESCRIPTION: Compute transmission corrections and snow mask
193  *
194  *************************************************************************/
195 
197 {
198  int status = DTDB_SUCCESS;
199 
200 // For Snow masking
201  snowmask_ = 1;
202 /*
203 // Compute Temperature(convert from radiance to temperature 11.um channel)
204 // Derive constants
205  float c1 = 2.0*PlancksConstant*(SpeedOfLight*SpeedOfLight);
206  float c2 = (PlancksConstant*SpeedOfLight)/BoltzConstant;
207 // convert wavelength to meters
208  float w_meter = (1.0e-6*WAV2);
209 // Compute Rong_rond ratio
210  float ratio = 0;
211  float r865 = p_->rfl_[(size_t)rhot_band::W865];
212  float r1240 = p_->rfl_[(size_t)rhot_band::W1240];
213  float r11000 = p_->rfl_[(size_t)rhot_band::W11000];
214 
215  if((r865 > 0) && (r1240 > 0)) {
216  ratio = (r865 - r1240) / (r865 + r1240);
217  }
218  else {
219  ratio = 0.0;
220  }
221  float temp = 285;
222  if (p_->instrument_ != sensor::POCI) {
223  temp = c2 / (w_meter*log(c1/(1.0e+6 * r11000 * pow(w_meter,5)+1.0)));
224  }
225 // Set snow mask as snowy pixel based on Ratio and temp.
226  if ((ratio > 0.01) && (temp < 285)) {
227  snowmask_ = 0;
228  }
229 */
230  return status;
231 }
232 
233 /**************************************************************************
234  * NAME: DtCloudMaskOcean()
235  *
236  * DESCRIPTION: Class Constructor
237  *
238  *************************************************************************/
239 
241 }
242 
243 /**************************************************************************
244  * NAME: DtCloudMaskOcean()
245  *
246  * DESCRIPTION: Class Constructor
247  *
248  *************************************************************************/
249 
251  p_ = proc;
252 }
253 
254 /**************************************************************************
255  * NAME: ~DtCloudMaskOcean()
256  *
257  * DESCRIPTION: Class Destructor
258  *
259  *************************************************************************/
260 
262 }
263 
264 /**************************************************************************
265  * NAME: initialize()
266  *
267  * DESCRIPTION: Virtual function initializes data and object classes for
268  * cloud mask operations.
269  *
270  *************************************************************************/
271 
273  return DTDB_SUCCESS;
274 }
275 
276 /**************************************************************************
277  * NAME: compute()
278  *
279  * DESCRIPTION: Compute cloud mask. This is a port of the Deep Blue cloud
280  * mask with modifications for compatibility with Dark Target reflectance
281  * units and inversion of the mask bit (here 0 = cloud, 1 = no cloud)
282  *
283  *************************************************************************/
284 
285 int DtCloudMaskOcean::compute( unsigned char& mask )
286 {
287  int status = DTDB_SUCCESS;
288 
289  if (p_->rfl_[(size_t)rhot_band::W410] < 0) {
290  mask = DFILL_UBYTE;
291  return status;
292  }
293  float lat = p_->lat_;
294  float solz = p_->solz_;
295  float m01_avg = 0;
296  float m01_stddev = 0;
297  float m08_avg = 0;
298  float m08_stddev = 0;
299  mask = 1;
300 
301 // Convert to units of normalize radiance
302  float rfl[NTWL][3][3];
303  memset(rfl,0,sizeof(rfl));
304  double cossza = cos(solz*DEGtoRAD);
305  for (size_t iw=0; iw<NTWL; iw++) {
306  for (size_t il=0; il<=2; il++) {
307  for (size_t ip=0; ip<=2; ip++) {
308  if (p_->rfla_[iw][il][ip] < 0) {
309  rfl[iw][il][ip] = DFILL_FLOAT;
310  } else {
311  rfl[iw][il][ip] = p_->rfla_[iw][il][ip]*cossza/M_PI;
312  }
313  }
314  }
315  }
316 
317 // M01 W412
318  size_t cnt = 0;
319  for (size_t il=0; il<=2; il++) {
320  for (size_t ip=0; ip<=2; ip++) {
321  if (rfl[(size_t)rhot_band::W410][il][ip] > 0) {
322  m01_avg += rfl[(size_t)rhot_band::W410][il][ip];
323  cnt++;
324  }
325  }
326  }
327  if (cnt >= 2) {
328  m01_avg /= cnt;
329  cnt = 0;
330  for (size_t il=0; il<=2; il++) {
331  for (size_t ip=0; ip<=2; ip++) {
332  if (rfl[(size_t)rhot_band::W410][il][ip] > 0) {
333  m01_stddev += pow((rfl[(size_t)rhot_band::W410][il][ip]-m01_avg),2);
334  cnt++;
335  }
336  }
337  }
338  m01_stddev = sqrt(m01_stddev/(cnt-1));
339  } else {
340  m01_stddev = DFILL_FLOAT;
341  }
342 // M08 W1240
343  cnt = 0;
344  for (size_t il=0; il<=2; il++) {
345  for (size_t ip=0; ip<=2; ip++) {
346  if (rfl[(size_t)rhot_band::W1240][il][ip] > 0) {
347  m08_avg += rfl[(size_t)rhot_band::W1240][il][ip];
348  cnt++;
349  }
350  }
351  }
352  if (cnt >= 2) {
353  m08_avg /= cnt;
354  cnt = 0;
355  for (size_t il=0; il<=2; il++) {
356  for (size_t ip=0; ip<=2; ip++) {
357  if (rfl[(size_t)rhot_band::W1240][il][ip] > 0) {
358  m08_stddev += pow((rfl[(size_t)rhot_band::W1240][il][ip]-m08_avg),2);
359  cnt++;
360  }
361  }
362  }
363  m08_stddev = sqrt(m08_stddev/(cnt-1));
364  } else {
365  m08_stddev = DFILL_FLOAT;
366  }
367  float cosza = cos(solz*DEGtoRAD);
368  if (lat > 65.0) {
369  if ((m01_stddev > 0 &&
370  (m01_stddev > M01_STDV_THOLD*cosza)) ||
371  (m08_stddev > 0 &&
372  (m08_stddev > M08_HILAT_STDV_THOLD*cosza))) {
373  mask = 0;
374  } else {
375  mask = 1;
376  }
377  } else {
378  if ((m01_stddev > 0 &&
379  m01_stddev > M01_STDV_THOLD*cosza) ||
380  (m08_stddev > 0 &&
381  m08_stddev > M08_STDV_THOLD*cosza)) {
382  mask = 0;
383  } else {
384  mask = 1;
385  }
386  }
387 // -- perform the check on the 1.38 um band (M09)
388  if (rfl[(size_t)rhot_band::W1380][1][1] > M09_THOLD*cosza) {
389  mask = 0;
390  }
391 // -- perform check on 488 nm band (M03)
392  if (rfl[(size_t)rhot_band::W490][1][1] > M03_THOLD*cosza) {
393  mask = 0;
394  }
395 
396  return status;
397 }
398 
399 /**************************************************************************
400  * NAME: DtSedimentMask()
401  *
402  * DESCRIPTION: Class Constructor
403  *
404  *************************************************************************/
405 
407 }
408 
409 /**************************************************************************
410  * NAME: DtSedimentMask()
411  *
412  * DESCRIPTION: Class Constructor
413  *
414  *************************************************************************/
415 
417  p_ = proc;
418 }
419 
420 /**************************************************************************
421  * NAME: ~DtSedimentMask()
422  *
423  * DESCRIPTION: Class Destructor
424  *
425  *************************************************************************/
426 
428 }
429 
430 /**************************************************************************
431  * NAME: initialize()
432  *
433  * DESCRIPTION: Virtual function initializes data and object classes for
434  * cloud mask operations.
435  *
436  *************************************************************************/
437 
439  return DTDB_SUCCESS;
440 }
441 
442 /**************************************************************************
443  * NAME: compute()
444  *
445  * DESCRIPTION: Make sediment array
446  *
447  *************************************************************************/
448 
450  int status = DTDB_SUCCESS;
451 
452  float x[NWAV];
453  float y[NWAV];
454  float sig[NWAV] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
455  bool bUseWav[NWAV];
456  bUseWav[D488] = (p_->rfl_[(size_t)rhot_band::W490] > 0) ? true : false;
457  bUseWav[D550] = false;
458  bUseWav[D670] = false;
459  bUseWav[D865] = false;
460 // bUseWav[D1240] = (p_->rfl_[W124] > 0) ? true : false;
461  bUseWav[D1240] = false; // conform to bug in fortran code
462  bUseWav[D1610] = (p_->rfl_[(size_t)rhot_band::W1610] > 0) ? true : false;
463  bUseWav[D2250] = (p_->rfl_[(size_t)rhot_band::W2250] > 0) ? true : false;
464  float logRefl[NWAV];
465  logRefl[D488] = log(p_->rfl_[(size_t)rhot_band::W490]);
466  logRefl[D550] = 0;
467  logRefl[D670] = 0;
468  logRefl[D865] = 0;
469  logRefl[D1240] = log(p_->rfl_[(size_t)rhot_band::W1240]);
470  logRefl[D1610] = log(p_->rfl_[(size_t)rhot_band::W1610]);
471  logRefl[D2250] = log(p_->rfl_[(size_t)rhot_band::W2250]);
472 
473  DtAlgOcean* pdto = static_cast<DtAlgOcean*> (p_);
474  int numWaves = 0;
475  for (int iWav = 0; iWav < NWAV; iWav++) {
476  if (bUseWav[iWav]) {
477  x[numWaves] = log(pdto->lut_.WAVE[iWav]);
478  y[numWaves] = logRefl[iWav];
479  numWaves++;
480  }
481  }
482  float acoef = 0.0;
483  float bcoef = 0.0;
484  float del_wav55 = 0.0;
485  if (numWaves > 2) {
486  pdto->fit_line(x, y, sig, numWaves, acoef, bcoef);
487  del_wav55 = p_->rfl_[(size_t)rhot_band::W550]
488  - exp(acoef + bcoef * log(pdto->lut_.WAVE[D550]));
489  } else
490  del_wav55 = 0.0;
491 
492  mask = 1;
493  float r488 = p_->rfl_[(size_t)rhot_band::W490];
494  float r2250 = p_->rfl_[(size_t)rhot_band::W2250];
495 // mask1 true it is sediment+smoke+dust set mask to sediments
496  if ((r2250 < 0.10) && (del_wav55 >= 0.015)) {
497  mask = 0;
498 // mask2 true it is smoke+dust and no sediments set previous sediment mask
499 // to no sediment because it smoke or dust.
500  if ((r488 >= 0.25) && (del_wav55 >= 0.015)) {
501  mask = 1;
502  }
503  }
504 
505  return status;
506 }
507 
508 
509 
@ D865
Definition: DtAlgorithm.h:20
int compute_snowmask()
Definition: DtMask.cpp:196
int status
Definition: l1_czcs_hdf.c:32
constexpr unsigned char DFILL_UBYTE
Definition: DDataset.hpp:28
@ D2250
Definition: DtAlgorithm.h:23
float rfl[NOWL]
Definition: DbAlgOcean.cpp:41
float * lat
@ D550
Definition: DtAlgorithm.h:18
@ D670
Definition: DtAlgorithm.h:19
int initialize()
Definition: DtMask.cpp:272
int compute(short &mask)
Definition: DtMask.cpp:449
#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
@ D488
Definition: DtAlgorithm.h:17
int initialize()
Definition: DtMask.cpp:65
constexpr float DFILL_FLOAT
Definition: DDataset.hpp:25
int compute(unsigned char &mask)
Definition: DtMask.cpp:285
int compute(unsigned char &mask)
Definition: DtMask.cpp:91
dtOceanAerosolLUT lut_
Definition: DtAlgorithm.h:234
@ D1610
Definition: DtAlgorithm.h:22
int initialize()
Definition: DtMask.cpp:438
@ D1240
Definition: DtAlgorithm.h:21
int fit_line(float x[], float y[], float sig[], int ndata, float &A, float &B)
float WAVE[NWAV]
Definition: DtLutNetcdf.h:130