OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
get_qaa.c
Go to the documentation of this file.
1 /*
2  * get_qaa.c
3  *
4  * MSl12 wrapper for Quasi-Analytic Algorithm
5  *
6  * Naval Research Laboratory
7  * Stennis Space Center, MS
8  */
9 
10 #include <stdlib.h>
11 #include <math.h>
12 #include "qaa.h"
13 #include "l12_proto.h"
14 #include "l2prod.h"
15 
16 static int QaaRecNum = -1;
17 
18 static int nbandsVis; /* number of bands computed for line */
19 
20 /* one scan line of data */
21 
22 static float *atot; /* total absorption coefficient */
23 static float *adg; /* detrital absorption coefficient */
24 static float *aph; /* phytoplankton absorption coefficient */
25 static float *bb; /* backscatter coefficient */
26 static unsigned char *flags; /* per-pixel flags */
27 
28 /* pixel data set during initialization */
29 
30 static float *bbw; /* pure-water backscattering */
31 static float *aw; /* pure-water total absorption */
32 static float *fwave; /* wavelength (nm) */
33 
34 /* pixel data */
35 
36 static float *Rrs; /* above-water remote sensing reflectance */
37 static float *rrs; /* below-water remote sensing reflectance */
38 static float *u;
39 static float *a_qaa; /* total absorption coefficient */
40 static float *bb_qaa; /* backscatter coefficient */
41 static float *bbp_qaa; /* backscatter coefficient */
42 static float *adg_qaa; /* detrital absorption coefficient */
43 static float *aph_qaa; /* phytoplankton absorption coefficient */
44 
45 static int ib410, ib440, ib490, ib555, ib670;
46 static int do_decomp = 1;
47 
48 /* have we run for this scan line? */
49 
50 static int qaa_ran(int recnum) {
51  if (recnum == QaaRecNum)
52  return 1;
53  else
54  return 0;
55 }
56 
57 /*
58  * allocate private arrays for a single scan line (412 ... 555)
59  * check to see if the number of pixels in the line got bigger
60  */
61 static void qaa_alloc(int32_t npix, int32_t nbands) {
62  static int32_t currentNumPix = -1;
63 
64  if (npix > currentNumPix) {
65  if (currentNumPix != -1) {
66  free(atot);
67  free(aph);
68  free(adg);
69  free(bb);
70  free(flags);
71  }
72  currentNumPix = npix;
73  atot = (float*) calloc(npix*nbands, sizeof (float));
74  aph = (float*) calloc(npix*nbands, sizeof (float));
75  adg = (float*) calloc(npix*nbands, sizeof (float));
76  bb = (float*) calloc(npix*nbands, sizeof (float));
77  flags = (unsigned char*) calloc(npix, sizeof (unsigned char));
78  }
79 }
80 
81 /* allocate private arrays for a single pixel (may include a 640nm) */
82 
83 static void qaa_pixel_alloc(int nbands) {
84 
85  fwave = (float*) calloc(nbands, sizeof (float));
86  bbw = (float*) calloc(nbands, sizeof (float));
87  aw = (float*) calloc(nbands, sizeof (float));
88  Rrs = (float*) calloc(nbands, sizeof (float));
89  rrs = (float*) calloc(nbands, sizeof (float));
90  u = (float*) calloc(nbands, sizeof (float));
91  a_qaa = (float*) calloc(nbands, sizeof (float));
92  bb_qaa = (float*) calloc(nbands, sizeof (float));
93  bbp_qaa = (float*) calloc(nbands, sizeof (float));
94  adg_qaa = (float*) calloc(nbands, sizeof (float));
95  aph_qaa = (float*) calloc(nbands, sizeof (float));
96 
97 }
98 
99 /* NOTE: nbandsVis and l2rec->l1rec->nbands are not always equal */
100 
101 static void run_qaa(l2str *l2rec) {
102  static int firstCall = 1;
103 
104  l1str *l1rec = l2rec->l1rec;
105 
106  int ip, ib, ipb;
107  int i;
108  unsigned char flags_qaa;
109 
110 
111  if (firstCall) {
112 
113  int *w;
114 
115  firstCall = 0;
116 
117  /* limit to visible wavelengths */
118  nbandsVis = rdsensorinfo(l1rec->l1file->sensorID, l1_input->evalmask, "NbandsVIS", NULL);
119  printf("QAA v6 processing for %d bands\n", nbandsVis);
120 
121  qaa_pixel_alloc(nbandsVis);
122 
123  for (ib = 0; ib < nbandsVis; ib++)
124  fwave[ib] = l1rec->l1file->fwave[ib];
125  get_aw_bbw(l2rec, fwave, nbandsVis, aw, bbw);
126 
127  w = input->qaa_wave;
128  if (w[1] < 0 || w[2] < 0 || w[3] < 0 || w[4] < 0) {
129  printf("qaa: algorithm coefficients not provided for this sensor.\n");
130  exit(1);
131  }
132 
133  // qaaf_v6 needs these bands at the very minimum
134 
135  ib440 = bindex_get(w[1]);
136  ib490 = bindex_get(w[2]);
137  ib555 = bindex_get(w[3]);
138  ib670 = bindex_get(w[4]);
139  if (ib440 < 0 || ib490 < 0 || ib555 < 0 || ib670 < 0) {
140  printf("get_qaa: missing minimum required wavelengths "
141  "(need 440,490,555,670).\n");
142  printf("get_qaa: qaa_wave[1] =%d, qaa_wave[2] =%d, "
143  "qaa_wave[3] = %d, qaa_wave[4] = %d.\n",
144  w[1], w[2], w[3], w[4]);
145  exit(1);
146  }
147 
148  // if we want compute the aph/adg (call qaaf_decomp) we need this additional band
149 
150  ib410 = bindex_get(w[0]);
151  if (ib410 < 0) {
152  printf("get_qaa: incompatible sensor wavelengths for aph/adg (need 410).\n");
153  do_decomp = 0;
154  }
155  printf("QAA v6 bands: (%d) %d nm, (%d) %d nm, (%d) %d nm, (%d) %d nm, (%d) %d nm\n",
156  ib410, w[0], ib440, w[1], ib490, w[2], ib555, w[3], ib670, w[4]);
157  printf("QAA v6 wav :");
158  for (ib = 0; ib < nbandsVis; ib++)
159  printf(" %10.6f", fwave[ib]);
160  printf("\n");
161 
162  printf("QAA v6 aw :");
163  for (ib = 0; ib < nbandsVis; ib++)
164  printf(" %10.6f", aw[ib]);
165  printf("\n");
166 
167  printf("QAA v6 bbw :");
168  for (ib = 0; ib < nbandsVis; ib++)
169  printf(" %10.6f", bbw[ib]);
170  printf("\n");
171 
172  qaa_init(ib410, ib440, ib490, ib555, ib670);
173  qaa_set_param(QAA_S_PARAM, input->qaa_adg_s);
174  }
175 
176  // note that for l3gen the number of pixels changes
177  qaa_alloc(l1rec->npix, nbandsVis);
178 
179  for (ip = 0; ip < l1rec->npix; ip++) {
180 
181  /* clear static globals */
182  for (ib = 0; ib < nbandsVis; ib++) {
183  ipb = ip * nbandsVis + ib;
184  bb [ipb] = -0.1;
185  atot[ipb] = -0.1;
186  adg [ipb] = -0.1;
187  aph [ipb] = -0.1;
188  }
189  flags[ip] = 0;
190 
191  if (!l1rec->mask[ip]) {
192 
193  flags_qaa = 0;
194  for (i = 0; i < nbandsVis; i++)
195  Rrs[i] = l2rec->Rrs[ip * l1rec->l1file->nbands + i];
196 
197  // Version 6
198  qaaf_v6(nbandsVis, fwave, Rrs, aw, bbw, rrs, u, a_qaa, bb_qaa, &flags_qaa);
199  if (do_decomp)
200  qaaf_decomp(nbandsVis, fwave, rrs, a_qaa, aw, adg_qaa, aph_qaa,
201  &flags_qaa);
202 
203  /* store results for this pixel in static globals */
204 
205  for (ib = 0; ib < nbandsVis; ib++) {
206 
207  ipb = ip * nbandsVis + ib;
208 
209  if (isfinite(bb_qaa[ib]))
210  bb[ipb] = bb_qaa[ib];
211  else {
212  bb[ipb] = -0.1;
213  l1rec->flags[ip] |= PRODFAIL;
214  }
215 
216  if (isfinite(a_qaa[ib]))
217  atot[ipb] = a_qaa[ib];
218  else {
219  atot[ipb] = -0.1;
220  l1rec->flags[ip] |= PRODFAIL;
221  }
222 
223  if (isfinite(adg_qaa[ib]))
224  adg[ipb] = adg_qaa[ib];
225  else {
226  adg[ipb] = -0.1;
227  l1rec->flags[ip] |= PRODFAIL;
228  }
229 
230  if (isfinite(aph_qaa[ib]))
231  aph[ipb] = aph_qaa[ib];
232  else {
233  aph[ipb] = -0.1;
234  l1rec->flags[ip] |= PRODFAIL;
235  }
236 
237  /* ZP Lee, 17 August 2007 */
238  if (atot[ipb] > 0.0) atot[ipb] = MAX(atot[ipb], aw [ib]*1.05);
239  if (bb [ipb] > 0.0) bb [ipb] = MAX(bb [ipb], bbw[ib]*1.05);
240  }
241  flags[ip] = flags_qaa;
242 
243  }
244  }
245 
246  QaaRecNum = l1rec->iscan;
247 
248  return;
249 }
250 
251 /* interface to l2_hdf_generic() to return QAA flags */
252 
253 unsigned char *get_flags_qaa(l2str *l2rec) {
254  if (!qaa_ran(l2rec->l1rec->iscan))
255  run_qaa(l2rec);
256 
257  return (flags);
258 }
259 
260 void get_qaa(l2str *l2rec, l2prodstr *p, float prod[]) {
261  int prodID = p->cat_ix;
262  int ib = p->prod_ix;
263  int ip, ipb;
264 
265  if (!qaa_ran(l2rec->l1rec->iscan))
266  run_qaa(l2rec);
267 
268  for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
269 
270  ipb = ip * nbandsVis + ib;
271 
272  switch (prodID) {
273 
274  case CAT_a_qaa:
275  if (atot[ipb] > 0.0)
276  prod[ip] = atot[ipb];
277  else
278  prod[ip] = p->badData;
279  break;
280 
281  case CAT_adg_qaa:
282  if (adg[ipb] > 0.0)
283  prod[ip] = adg[ipb];
284  else
285  prod[ip] = p->badData;
286  break;
287 
288  case CAT_aph_qaa:
289  if (aph[ipb] > 0.0)
290  prod[ip] = aph[ipb];
291  else
292  prod[ip] = p->badData;
293  break;
294 
295  case CAT_bb_qaa:
296  if (bb[ipb] > 0.0)
297  prod[ip] = bb[ipb];
298  else
299  prod[ip] = p->badData;
300  break;
301 
302  case CAT_bbp_qaa:
303  if ((bb[ipb] - bbw[ib]) > 0.0)
304  prod[ip] = bb[ipb] - bbw[ib];
305  else
306  prod[ip] = p->badData;
307  break;
308 
309  case CAT_b_qaa:
310  if (bb[ipb] > 0.0)
311  prod[ip] = bb[ipb] * 53.56857 + 0.00765;
312  else
313  prod[ip] = p->badData;
314  break;
315 
316  case CAT_c_qaa:
317  if (bb[ipb] > 0.0 && atot[ipb] > 0.0)
318  prod[ip] = bb[ipb] * 53.56857 + 0.00765 + atot[ipb];
319  else
320  prod[ip] = p->badData;
321  break;
322 
323  default:
324  printf("-E- %s line %d : erroneous product ID %d passed to get_qaa().\n",
325  __FILE__, __LINE__, prodID);
326  exit(1);
327  }
328  }
329 
330  return;
331 }
332 
333 /* interface to convl12() to return QAA iops */
334 
335 void iops_qaa(l2str *l2rec) {
336  int ib, ip;
337 
338  if (!qaa_ran(l2rec->l1rec->iscan))
339  run_qaa(l2rec);
340 
341  for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
342  for (ib = 0; ib < nbandsVis; ib++) {
343  l2rec->a [ip * l2rec->l1rec->l1file->nbands + ib] = atot[ip * nbandsVis + ib];
344  l2rec->bb[ip * l2rec->l1rec->l1file->nbands + ib] = bb [ip * nbandsVis + ib];
345  }
346  }
347 
348  return;
349 }
350 
351 void qaa_iops_4_bshift(l2str *l2rec, float *adg_ref, float *bbp_ref) {
352  int ipb, ip;
353 
354  if (!qaa_ran(l2rec->l1rec->iscan))
355  run_qaa(l2rec);
356  for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
357  ipb = nbandsVis * ip + ib440;
358  adg_ref[ip] = adg[ipb];
359  bbp_ref[ip] = bb[ipb] - bbw[ib440];
360  }
361 }
362 
363 /* ------------------------------------------------------------------------------- */
364 /* interface to giop() */
365 
366 /* ------------------------------------------------------------------------------- */
367 int get_bbp_qaa(l2str *l2rec, int ip, float tab_wave[], float tab_bbp[], int tab_nwave) {
368  int ipb, ib;
369 
370  if (!qaa_ran(l2rec->l1rec->iscan))
371  run_qaa(l2rec);
372 
373  for (ib = 0; ib < nbandsVis; ib++) {
374  ipb = ip * nbandsVis + ib;
375  bbp_qaa[ib] = bb[ipb] - bbw[ib];
376  if (bbp_qaa[ib] < 0)
377  return (0);
378  }
379 
380  for (ib = 0; ib < tab_nwave; ib++) {
381  tab_bbp[ib] = linterp(fwave, bbp_qaa, nbandsVis, tab_wave[ib]);
382  }
383 
384  return (1);
385 }
#define MAX(A, B)
Definition: swl0_utils.h:26
int qaa_init(int i410, int i440, int i490, int i555, int i670)
initalize Quasi-Analytical Algorithm v4
Definition: qaa.c:132
@ QAA_S_PARAM
Definition: qaa.h:12
unsigned char * get_flags_qaa(l2str *l2rec)
Definition: get_qaa.c:253
#define NULL
Definition: decode_rs.h:63
int qaaf_v6(int nbands, float *wavel, float *Rrs, float *aw, float *bbw, float *rrs, float *u, float *a, float *bb, unsigned char *flags)
Quasi-Analytical Algorithm v4.
Definition: qaa.c:279
#define CAT_adg_qaa
Definition: l2prod.h:106
read l1rec
#define CAT_b_qaa
Definition: l2prod.h:161
#define PRODFAIL
Definition: l2_flags.h:41
void iops_qaa(l2str *l2rec)
Definition: get_qaa.c:335
#define CAT_aph_qaa
Definition: l2prod.h:105
#define CAT_c_qaa
Definition: l2prod.h:162
instr * input
#define CAT_bbp_qaa
Definition: l2prod.h:107
int bindex_get(int32_t wave)
Definition: windex.c:45
read recnum
float linterp(float xin[], float yin[], int32_t nin, float xout)
Definition: lspline.c:59
int qaa_set_param(int param,...)
set a parameter for Quasi-Analytical Algorithm
Definition: qaa.c:163
#define CAT_a_qaa
Definition: l2prod.h:102
l1_input_t * l1_input
Definition: l1_options.c:9
void get_aw_bbw(l2str *l2rec, float wave[], int nwave, float *aw, float *bbw)
flags
Definition: DDAlgorithm.h:22
#define CAT_bb_qaa
Definition: l2prod.h:104
int32_t nbands
data_t u
Definition: decode_rs.h:74
int get_bbp_qaa(l2str *l2rec, int ip, float tab_wave[], float tab_bbp[], int tab_nwave)
Definition: get_qaa.c:367
int32_t rdsensorinfo(int32_t, int32_t, const char *, void **)
Definition: rdsensorinfo.c:69
void qaa_iops_4_bshift(l2str *l2rec, float *adg_ref, float *bbp_ref)
Definition: get_qaa.c:351
int i
Definition: decode_rs.h:71
int qaaf_decomp(int nbands, float *wavel, float *rrs, float *a, float *aw, float *adg, float *aph, unsigned char *flags)
Quasi-Analytical Algorithm - decomposition of total absorption.
Definition: qaa.c:450
int npix
Definition: get_cmp.c:27
float p[MODELMAX]
Definition: atrem_corl1.h:131
void get_qaa(l2str *l2rec, l2prodstr *p, float prod[])
Definition: get_qaa.c:260