OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
lac_st.c
Go to the documentation of this file.
1 /*-----------------------------------------------------------------------------
2  Function: stray_light_lac
3 
4  Returns: int32 (status)
5  Returns as 0, "not done", to indicate that the routine did not
6  return any useful information for the last call, but was filling
7  its buffers with scan line data; and 1, "done", to indicate that
8  the l1b_data and sl_flag arrays for scan line sl_scan have been
9  set.
10 
11  Description:
12  The function stray_light_lac processes LAC scan lines by detecting
13  bright targets (BTs) and labelling pixels as being within the BTs
14  or adjacent to them where they are likely to be contaminated by
15  stray light (ST) from the BTs. The Level-1B data for the ST pixels
16  in the along-scan direction are corrected for ST contamination
17  according to the method in Barnes et al. (1995). The routine
18  processes one scan line at a time using a rolling window for along-
19  track processing of five scan lines for LAC data. If along-track
20  processing is indicated (nscan < 5), each scan line is processed
21  individually without the rolling window.
22 
23  Parameters: (in calling order)
24  Type Name I/O Description
25  ---- ---- --- -----------
26  int32 *initial I Flag, should be set to "true" (a value
27  of 1) if it is the fst call for a scene
28  float32 Ltyp_frac I fraction of Ltypical for band 8
29  float32 Styp_frac I fraction value that will be applied
30  to knee value to calculate straylight
31  threshold
32  int32 nscans I the number of scan lines in the scene
33  (to be processed). Must be set to <5
34  to process only in the along scan
35  int32 nsamples I number of pixel data values in
36  l1b_data and sl_flag
37  int32 scan_no I scan line number of l1b_data input
38  int16 gn I Band 8 gain of scan line scan_no
39  float32 *rads I Radiances of calibration knees(8,4,5)
40  float32 *l1b_data I/O array of nsamples long containing
41  l1b_data of scan line scan_no
42  int32 *sl_scan O scan line number for which the
43  returned l1b_data apply
44  int32 *sl_flag O array of nsamples long containing
45  codes identifying BT pixels and the
46  proximity of others to BTs.
47  Notes:
48 
49  Modification history:
50  Programmer Organization Date Description of change
51  -------------- ------------ -------- ---------------------
52  Joel Gales Futuretech 10/16/00 1) Set AT in flag_buf
53  when initially setting
54  BT.
55  2) Set left edge found
56  if first pixel in scan
57  is above knee_val
58  Lakshmi Kumar Hughes STX 02/12/97 Added Styp_frac to input
59  parameter list
60  Removed PROTOTYPE defns.
61  Replaced const val 8 by
62  NBANDS
63  corrected algorithm that
64  finds edges
65  Lakshmi Kumar Hughes STX 10/12/95 Original development
66 ------------------------------------------------------------------------------*/
67 
68 #include "st_lt.h"
69 #include <mfhdf.h>
70 
71 int32_t
72 stray_light_lac(int32_t *initial, float Ltyp_frac, float Styp_frac,
73  int32_t nscans, int32_t nsamples, int32_t scan_no, int16_t gn,
74  float *rads, float *l1b_data, int32_t *sl_scan,
75  int32_t *sl_flag) {
76 
77  /*-----------------------------------------------------------------------------
78  ** i -- dummy index
79  ** n -- pixel pointer on the scan line being processed
80  ** p -- dummy index
81  ** band -- dummy index
82  ** status -- returns as 0 (NOTDONE) to indicate that the routine did not
83  return any useful information for the last call,
84  but was filling its buffers with scan line data;
85  and 1 (DONE) to indicate that the l1b_data and sl_flag
86  arrays for scan line sl_scan have been set
87  ** edge -- flag that indicates whether an edge was found or not
88  ** scans_done -- number of scans processed (if nscans < 5, scans_done = 2
89  ** scan -- pointer to the scan line being processed in the buffers--
90  the central scan line in a rolling window of five
91  consecutive scan lines
92  ** scan_p1 -- pointer to the scan line following scan in the buffers
93  (scan plus 1)
94  ** scan_p2 -- pointer to the scan line following that of scan_p2 in the
95  buffers (scan plus 2). Normally, it points to
96  scan data newly entered
97  ** prev_scans -- the number of scans preceding the one represented by scan
98  ** next_scans -- the number of scans following the one represented by scan
99  ** line_no -- a 5-integer array of the scan line numbers of the scan
100  lines in the buffers
101  ** flag_buf -- a 2-dimensional buffer (5 x nsamples) for marking BT and
102  SL codes for five consecutive scan lines
103  ** scan_m2 -- pointer to the scan line preceding that of scan_m1 in the
104  buffers (scan minus 2). It points to the data being
105  returned after a scan-line is processed. It is set
106  =scan here so that the porcessed scan is the one
107  returned when no along-track processing is required
108  ** scan_m1 -- pointer to the scan line preceding scan lin the buffers
109  (scan minus 1)
110  ** Ltypical_8 -- Ltypical value for band 8; = 1.09
111  ** Ltyp_thresh -- value used to test if the band-8 radiance difference from
112  one pixel to the next indicates the edge
113  ** l1b_buf -- a 3-dimensional buffer (8 x 5 x nsamples) for storing five
114  consecutive scan lines of Level-1B data for 8 bands
115  ** RRANGE -- Maximum number of pixels to the right of a BT that are
116  affected by ST from that BT; = 12
117  ** LRANGE -- Maximum number of pixels to the left (along scan) of a
118  BT that are affected by ST from that BT; = 14
119  ** K -- BT response constants for along-scan stray light correction
120  array of two dimensions: 8 bands by LRANGE+RRANGE+1;
121  values are from Table 8 of Barnes et al. (1995),
122  except for value of central pixel which equals 1 minus
123  table value
124  ----------------------------------------------------------------------------*/
125 
126  int32 i, n, p, band, farthest, status;
127  float32 delta, Ltyp_thresh, Ltypical_8 = 1.09;
128  float32 corr = 0, knee_val = 0, stray_thresh = 0;
129  float32 l1b_tmpbuf[NBANDS * MAXSAMPS];
130  int32 edge = 0, right_edge = -1, left_edge = -1;
131  static int32 scans_done, scan, scan_p1, scan_p2, prev_scans, next_scans;
132  static int32 scan_m1, scan_m2, rt_edge_found = FALSE;
133  static int32 line_no[MAXLINES], flag_buf[MAXLINES][MAXSAMPS];
134  static float32 l1b_buf[MAXBANDS][MAXLINES][MAXSAMPS];
135  float32 Ctyp_frac = 1.25, Ctyp_thresh;
136  float32 wt;
137 
138  /* If first call, initialize the counters and pointers and fill buffer
139  ** with first scan line. If along-track processing is requested (nscans > 4)
140  ** then return for more scans to fill the buffers; otherwise, set
141  ** scans_done = 2 and scan_m2 = scan so that the data are returned at the
142  ** end and continue to do along-scan correction for this scan line
143  */
144 
145  if (*initial == TRUE) {
146  Ltyp_thresh = Ltyp_frac * Ltypical_8;
147  scans_done = 0;
148  scan = 1;
149  scan_p1 = 0;
150  scan_p2 = 0;
151  prev_scans = 0;
152  next_scans = 0;
153  line_no[scan - 1] = scan_no;
154  for (i = 0; i < NBANDS; i++)
155  memcpy(l1b_buf[i][scan - 1], &l1b_data[i * nsamples],
156  (sizeof (float)*nsamples));
157  for (i = 0; i < nsamples; i++)
158  flag_buf[scan - 1][i] = BLANK;
159  status = NOTDONE;
160  if (nscans > 4) {
161  *initial = FALSE;
162  return status;
163  }
164  }
165 
166  if (*initial == FALSE) {
167  status = NOTDONE;
168  /* If only 1 scan has been obtained, get the 2nd and return for more */
169  if (scan_p1 == 0) {
170  scan_p1 = 2;
171  line_no[scan_p1 - 1] = scan_no;
172  for (i = 0; i < NBANDS; i++)
173  memcpy((float *) l1b_buf[i][scan_p1 - 1],
174  &l1b_data[i * nsamples], sizeof (float)*nsamples);
175  for (i = 0; i < nsamples; i++)
176  flag_buf[scan_p1 - 1][i] = BLANK;
177  return status;
178  }
179 
180  /* If only 2 scans have been obtained, get the 3rd; but now, we can
181  ** continue with along-track processing
182  */
183  if (scan_p2 == 0) {
184  scan_p2 = 3;
185  next_scans = 2;
186  line_no[scan_p2 - 1] = scan_no;
187  for (i = 0; i < NBANDS; i++)
188  memcpy((float *) l1b_buf[i][scan_p2 - 1],
189  &l1b_data[i * nsamples], sizeof (float)*nsamples);
190  for (i = 0; i < nsamples; i++)
191  flag_buf[scan_p2 - 1][i] = BLANK;
192  }
193 
194  /* If only 3 scans have been obtained, rotate the array pointers
195  ** (since the 1st scan line pointed to by scan has been processed),
196  ** get the 4th scan line, and process scan = 2
197  */
198  if (scans_done == 1) {
199  scan_m1 = 1;
200  scan = 2;
201  scan_p1 = 3;
202  scan_p2 = 4;
203  prev_scans = 1;
204  next_scans = 2;
205  line_no[scan_p2 - 1] = scan_no;
206  for (i = 0; i < NBANDS; i++)
207  memcpy((float *) l1b_buf[i][scan_p2 - 1],
208  &l1b_data[i * nsamples], sizeof (float)*nsamples);
209  for (i = 0; i < nsamples; i++)
210  flag_buf[scan_p2 - 1][i] = BLANK;
211  }
212 
213  /* If only 4 scans have been obtained, rotate the array pointers, get
214  ** the 5th scan line, and process scan = 3
215  */
216  if (scans_done == 2) {
217  scan_m2 = 1;
218  scan_m1 = 2;
219  scan = 3;
220  scan_p1 = 4;
221  scan_p2 = 5;
222  prev_scans = 2;
223  next_scans = 2;
224  line_no[scan_p2 - 1] = scan_no;
225  for (i = 0; i < NBANDS; i++)
226  memcpy((float *) l1b_buf[i][scan_p2 - 1],
227  &l1b_data[i * nsamples], sizeof (float)*nsamples);
228  for (i = 0; i < nsamples; i++)
229  flag_buf[scan_p2 - 1][i] = BLANK;
230  }
231 
232  /* If the buffers are full (as happens when scans_done > 2), rotate
233  ** the array pointers */
234  if (scans_done > 2) {
235  scan_m2 = (scan_m2) % 5 + 1;
236  scan_m1 = (scan_m1) % 5 + 1;
237  scan = (scan) % 5 + 1;
238  scan_p1 = (scan_p1) % 5 + 1;
239  scan_p2 = (scan_p2) % 5 + 1;
240 
241  /* If not all scan lines have been obtained, get the next one into
242  ** scan_p2 buffers */
243  if (scans_done < nscans - 2) {
244  line_no[scan_p2 - 1] = scan_no;
245  for (i = 0; i < NBANDS; i++)
246  memcpy((float *) l1b_buf[i][scan_p2 - 1],
247  &l1b_data[i * nsamples], sizeof (float)*nsamples);
248  for (i = 0; i < nsamples; i++)
249  flag_buf[scan_p2 - 1][i] = BLANK;
250  }
251  /* Otherwise, finish ones that haven't been processed. If all have
252  ** been processed (next_scans < 0), flush out those remaining */
253  else {
254  next_scans = next_scans - 1;
255  if (next_scans < 0) {
256  *sl_scan = line_no[scan_m2 - 1];
257  for (i = 0; i < NBANDS; i++)
258  memcpy((float *) &l1b_data[i * nsamples],
259  l1b_buf[i][scan_m2 - 1], sizeof (float)*nsamples);
260  for (i = 0; i < nsamples; i++)
261  sl_flag[i] = flag_buf[scan_m2 - 1][i];
262  status = DONE;
263  return status;
264  } /* end if */
265  } /* end if-else */
266  } /* end if */
267  } /* end if */
268 
269  if (*initial == TRUE) {
270  scans_done = 2;
271  scan_m2 = scan;
272  }
273 
274  /* setup clear water threshold value Ctyp_thresh */
275  Ctyp_thresh = Ctyp_frac * Ltypical_8;
276 
277  /* if input radiance is greater than its knee, mark that pix as BT */
278  knee_val = rads[7 * GAINS * KNEES + gn * KNEES + 1];
279  stray_thresh = Styp_frac * knee_val;
280 
281  for (p = 0; p < nsamples; p++) {
282  if (l1b_buf[7][scan - 1][p] > knee_val) {
283  flag_buf[scan - 1][p] = BT;
284 
285  if ((prev_scans >= 2) && (flag_buf[scan_m2 - 1][p] != BT))
286  flag_buf[scan_m2 - 1][p] = AT;
287  if ((prev_scans >= 1) && (flag_buf[scan_m1 - 1][p]) != BT)
288  flag_buf[scan_m1 - 1][p] = AT;
289  if (next_scans >= 1)
290  flag_buf[scan_p1 - 1][p] = AT;
291  if (next_scans >= 2)
292  flag_buf[scan_p2 - 1][p] = AT;
293  }
294  } /* end for */
295 
296 
297  /* Start loop to process the scan line pointed to by scan */
298  rt_edge_found = FALSE;
299  n = 0;
300  while (n < nsamples - 1) {
301  edge = NO;
302 
303  if (n == 0 && flag_buf[scan - 1][n] == BT) {
304  edge = LEFT;
305  rt_edge_found = FALSE;
306  }
307 
308  while (edge == NO && (n < nsamples - 1)) {
309  if (flag_buf[scan - 1][n] != BT || flag_buf[scan - 1][n + 1] != BT) {
310  delta = l1b_buf[7][scan - 1][n + 1] - l1b_buf[7][scan - 1][n];
311  if (delta > 0)
312  Ltyp_thresh =
313  max((Ltyp_frac * (l1b_buf[7][scan - 1][n + 1] - Ltypical_8)),
314  Ltyp_frac * Ltypical_8);
315  else
316  Ltyp_thresh =
317  max((Ltyp_frac * (l1b_buf[7][scan - 1][n] - Ltypical_8)),
318  Ltyp_frac * Ltypical_8);
319  if (delta > Ltyp_thresh && l1b_buf[7][scan - 1][n + 1] > stray_thresh) {
320  edge = LEFT;
321  rt_edge_found = FALSE;
322  }
323  if (-1 * delta > Ltyp_thresh && l1b_buf[7][scan - 1][n] > stray_thresh) {
324  if (!(rt_edge_found)) {
325  edge = RIGHT;
326  rt_edge_found = TRUE;
327  }
328  }
329  }
330  n++;
331  }
332  if (edge != NO) {
333  n--;
334 
335  /* If right edge is found first, set the scan-line start as the left
336  ** edge, and label the pixels after the right edge to be ST pixels
337  ** RRANGE = maximum number of pixels to the right (along scan) of
338  ** a BT that are affected by ST from that BT; = 12 */
339 
340  if (edge == RIGHT) {
341  right_edge = n;
342  for (i = n; i >= 0; i--) if (l1b_buf[7][scan - 1][i] < Ctyp_thresh) break;
343  if (i < 0) i = 0;
344  left_edge = i;
345  p = right_edge + 1;
346  farthest = min((right_edge + RRANGE), (nsamples - 1));
347  while (p <= farthest) {
348  if (flag_buf[scan - 1][p] == BT)
349  p = farthest + 1;
350  else {
351  if (flag_buf[scan - 1][p] == BLANK)
352  flag_buf[scan - 1][p] = p - right_edge;
353  }
354  p += 1;
355  }
356  } else {
357  left_edge = n + 1;
358  p = n;
359  farthest = max(left_edge - LRANGE, 0);
360  while (p >= farthest) {
361  if (flag_buf[scan - 1][p] == BT)
362  p = farthest - 1;
363  else {
364  if (flag_buf[scan - 1][p] == BLANK)
365  flag_buf[scan - 1][p] = left_edge - p;
366  else
367  if (flag_buf[scan - 1][p] > 0)
368  flag_buf[scan - 1][p] =
369  flag_buf[scan - 1][p] + 1000 * (left_edge - p);
370  } /* end else */
371  p = p - 1;
372  } /* end while */
373 
374  /* search for the associated right edge */
375  right_edge = nsamples - 1;
376  n = n + 1;
377  while ((n < nsamples - 1) && (edge == LEFT)) {
378  if (flag_buf[scan - 1][n] != BT || flag_buf[scan - 1][n + 1] != BT) {
379  if (l1b_buf[7][scan - 1][n + 1] < Ctyp_thresh) goto R_found;
380  delta = l1b_buf[7][scan - 1][n + 1] - l1b_buf[7][scan - 1][n];
381  if (delta > 0)
382  Ltyp_thresh =
383  max((Ltyp_frac * (l1b_buf[7][scan - 1][n + 1] - Ltypical_8)),
384  Ltyp_frac * Ltypical_8);
385  else
386  Ltyp_thresh =
387  max((Ltyp_frac * (l1b_buf[7][scan - 1][n] - Ltypical_8)),
388  Ltyp_frac * Ltypical_8);
389  if (-1 * delta > Ltyp_thresh &&
390  l1b_buf[7][scan - 1][n] > stray_thresh) {
391  R_found:
392  edge = RIGHT;
393  rt_edge_found = TRUE;
394  }
395  } /*if BT */
396  n++;
397  } /* while ((n < nsamples - 1) && (edge == LEFT)) */
398  if (edge == LEFT) /* right edge not found, setting last pix */
399  rt_edge_found = TRUE; /* as right edge */
400  if (edge == RIGHT) {
401  right_edge = n - 1;
402  p = right_edge + 1;
403  farthest = min((right_edge + RRANGE), (nsamples - 1));
404  while (p <= farthest) {
405  if (flag_buf[scan - 1][p] == BT)
406  p = farthest + 1;
407  else if (flag_buf[scan - 1][p] == BLANK)
408  flag_buf[scan - 1][p] = p - right_edge;
409  p += 1;
410  } /* end while */
411  } /* end if */
412  } /* end else */
413 
414  /* Label all pixels between both edges as BT pixels. Some of the
415  ** pixels might already be BT, will get set again to avoid another
416  ** if check */
417 
418  for (p = left_edge; p <= right_edge; p++) {
419  flag_buf[scan - 1][p] = BT;
420  if ((prev_scans >= 2) && (flag_buf[scan_m2 - 1][p] != BT))
421  flag_buf[scan_m2 - 1][p] = AT;
422  if ((prev_scans >= 1) && (flag_buf[scan_m1 - 1][p]) != BT)
423  flag_buf[scan_m1 - 1][p] = AT;
424  if (next_scans >= 1)
425  flag_buf[scan_p1 - 1][p] = AT;
426  if (next_scans >= 2)
427  flag_buf[scan_p2 - 1][p] = AT;
428  } /* end for */
429  if (prev_scans >= 1) {
430  if ((flag_buf[scan_m1 - 1][left_edge - 1] != BT) && (left_edge > 1))
431  flag_buf[scan_m1 - 1][left_edge - 1] = DIAG;
432  if ((flag_buf[scan_m1 - 1][right_edge + 1] != BT) &&
433  (right_edge < nsamples - 1))
434  flag_buf[scan_m1 - 1][right_edge + 1] = DIAG;
435  } /* end if */
436  if (next_scans >= 1) {
437  if ((flag_buf[scan_p1 - 1][left_edge - 1] != BT) && (left_edge > 1))
438  flag_buf[scan_p1 - 1][left_edge - 1] = DIAG;
439  if ((flag_buf[scan_p1 - 1][right_edge + 1] != BT) &&
440  (right_edge < nsamples - 1))
441  flag_buf[scan_p1 - 1][right_edge + 1] = DIAG;
442  } /* end if */
443  } /* end if */
444  if (rt_edge_found && n < nsamples - 1)
445  n = right_edge + 1;
446  } /* end while */
447 
448  /*
449  ** Loop through scan line to apply correction to ST pixels (flag_buf > 0)
450  **
451  ** K = BT response constants for along-scan stray light correction;
452  ** values are from Table 8 of Barnes et al. (1995), a normalized new table
453  ** (Feb. 1997).
454  */
455 
456  /* copy current processing scan line l1b data to a temporary buffer for
457  ** calculating the correction factor */
458 
459  for (i = 0; i < NBANDS; i++)
460  memcpy(&l1b_tmpbuf[i * nsamples], l1b_buf[i][scan - 1],
461  (sizeof (float)*nsamples));
462 
463  for (n = 0; n < nsamples; n++) {
464  if (flag_buf[scan - 1][n] > 0) {
465  for (band = 0; band < NBANDS; band++) {
466  corr = 0;
467  wt = 0; /* BAF, 4 Feb 2000: added division by sum of weights */
468  for (p = max(n - LRANGE, 0); p <= min(n + RRANGE, (nsamples - 1)); p++) {
469  corr += (l1b_tmpbuf[band * nsamples + p] * K[band][n - p + LRANGE]);
470  wt += K[band][n - p + LRANGE];
471  }
472  l1b_buf[band][scan - 1][n] = 2 * l1b_buf[band][scan - 1][n] - corr / wt;
473  }
474  }
475  }
476 
477  /*
478  ** if five scan lines have been obtained (and two have been processed), return
479  ** the earliest scan line (scan_m2) in the window
480  */
481 
482  scans_done = scans_done + 1;
483  if (scans_done > 2) {
484  *sl_scan = line_no[scan_m2 - 1];
485  for (i = 0; i < NBANDS; i++)
486  memcpy(&l1b_data[i * nsamples],
487  l1b_buf[i][scan_m2 - 1], (sizeof (float)*nsamples));
488  for (i = 0; i < nsamples; i++)
489  sl_flag[i] = flag_buf[scan_m2 - 1][i];
490  status = DONE;
491  } /* end if */
492  return status;
493 }
#define DIAG
Definition: st_lt.h:12
float rads[BANDS_DIMS_1A][GAINS_DIMS_1A][KNEES_DIMS_1A]
Definition: l1a_seawifs.c:47
#define LRANGE
Definition: cf.h:5
#define BLANK
Definition: st_lt.h:13
int status
Definition: l1_czcs_hdf.c:32
#define NO
Definition: l1.h:44
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
#define GAINS
Definition: calib_get_cal.h:10
#define FALSE
Definition: rice.h:164
#define RRANGE
Definition: cf.h:6
MOD_PR01 Production producing one five minute granule of output data in each run It can be configured to produce as many as three five minute granules per run Each execution with one construction record and one date file for each dataset In normal these are created by which splits them out of the hour datasets For LANCE they are created by which merges all session MODIS L0 datasets overlapping the requested time and extracts from the merged data those packets which fall within that time period Each scan of data is stored in the L1A granule that covers the start time of that scan
Definition: MOD_PR01_pr.txt:19
PARAM_TYPE_NONE Default value No parameter is buried in the product name name_prefix is case insensitive string compared to the product name PARAM_TYPE_VIS_WAVE The visible wavelength bands from the sensor are buried in the product name The product name is compared by appending and name_suffix ie aph_412_giop where prod_ix will be set to PARAM_TYPE_IR_WAVE same search method as PARAM_TYPE_VIS_WAVE except only wavelength above are looped through but prod_ix is still based ie aph_2_giop for the second band
#define TRUE
Definition: rice.h:165
#define NOTDONE
Definition: l1a_seawifs.c:19
#define AT
Definition: st_lt.h:11
#define KNEES
Definition: st_lt.h:32
float Ltyp_frac
Definition: l1a_seawifs.c:101
const double delta
#define MAXLINES
Definition: st_lt.h:26
CGAL::Exact_predicates_inexact_constructions_kernel K
Definition: cgal_interp.cpp:12
#define RIGHT
Definition: st_lt.h:15
#define MAXBANDS
Definition: l1_viirs_h5.c:23
#define BT
Definition: st_lt.h:10
#define MAXSAMPS
Definition: st_lt.h:28
int i
Definition: decode_rs.h:71
#define DONE
Definition: st_lt.h:24
@ NBANDS
Definition: make_L3_v1.1.c:53
int32_t stray_light_lac(int32_t *initial, float Ltyp_frac, float Styp_frac, int32_t nscans, int32_t nsamples, int32_t scan_no, int16_t gn, float *rads, float *l1b_data, int32_t *sl_scan, int32_t *sl_flag)
Definition: lac_st.c:72
#define LEFT
Definition: st_lt.h:16
float p[MODELMAX]
Definition: atrem_corl1.h:131
l2prod max