NASA Logo
Ocean Color Science Software

ocssw V2022
get_chl.c
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include <math.h>
3 #include "l12_proto.h"
4 #include "chl.h"
5 
6 
7 float get_chl_ocx(l2str *l2rec, float Rrs[]);
8 
9 float chl_oc2(l2str *l2rec, float Rrs[]) {
10  static int32_t *w = NULL;
11  static float *a = NULL;
12  static int ib1 = -1;
13  static int ib2 = -1;
14 
15  float rat;
16  float Rrs1, Rrs2;
17  float chl = chlbad;
18 
19  if (w == NULL) {
20  w = input->chloc2w;
21  a = input->chloc2c;
22  if (w[0] < 0 || w[1] < 0) {
23  printf("chl_oc2: algorithm coefficients not provided for this sensor.\n");
24  exit(1);
25  }
26  ib1 = bindex_get(w[0]);
27  ib2 = bindex_get(w[1]);
28  if (ib1 < 0 || ib2 < 0) {
29  printf("chl_oc2: incompatible sensor wavelengths for this algorithm\n");
30  exit(1);
31  }
32  }
33 
34  Rrs1 = Rrs[ib1];
35  Rrs2 = Rrs[ib2];
36 
37  if (Rrs1 > 0.0 && Rrs2 > 0.0 && Rrs1 / Rrs2 <= 10.0) {
38  rat = Rrs1 / Rrs2;
39  if (rat > minrat && rat < maxrat) {
40  rat = log10(rat);
41  chl = (float)
42  pow(10.0, (a[0] + rat * (a[1] + rat * (a[2] + rat * (a[3] + rat * a[4])))));
43  chl = (chl > chlmin ? chl : chlmin);
44  chl = (chl < chlmax ? chl : chlmax);
45  }
46  }
47 
48  return (chl);
49 }
50 
51 float chl_oc3(l2str *l2rec, float Rrs[]) {
52  static int32_t *w = NULL;
53  static float *a = NULL;
54  static int ib1 = -1;
55  static int ib2 = -1;
56  static int ib3 = -1;
57 
58  float rat, minRrs;
59  float Rrs1, Rrs2, Rrs3, Rrsmax;
60  float chl = chlbad;
61  float *dRrs, *dchl,*covariance_matrix, tmpderiv;
62  int ibmax=-1;
63  uncertainty_t *uncertainty=l2rec->l1rec->uncertainty;
64  static int nbands=0;
65  float fit_unc=0.13;
66 
67  if(uncertainty){
68  dRrs=uncertainty->dRrs;
69  dchl=&uncertainty->dchl;
70  if(input->proc_uncertainty==2)
71  covariance_matrix=uncertainty->covaraince_matrix;
72  else
73  covariance_matrix=uncertainty->pixel_covariance;
74  }
75 
76  if (w == NULL) {
77  nbands=l2rec->l1rec->l1file->nbands;
78  w = input->chloc3w;
79  a = input->chloc3c;
80  if (w[0] < 0 || w[1] < 0 || w[2] < 0) {
81  printf("chl_oc3: algorithm coefficients not provided for this sensor.\n");
82  exit(1);
83  }
84  ib1 = bindex_get(w[0]);
85  ib2 = bindex_get(w[1]);
86  ib3 = bindex_get(w[2]);
87  if (ib1 < 0 || ib2 < 0 || ib3 < 0) {
88  printf("chl_oc3: incompatible sensor wavelengths for this algorithm\n");
89  exit(1);
90  }
91  }
92 
93  Rrs1 = Rrs[ib1];
94  Rrs2 = Rrs[ib2];
95  Rrs3 = Rrs[ib3];
96 
97  minRrs = MIN(Rrs1, Rrs2);
98 
99  if (Rrs3 > 0.0 && Rrs2 > 0.0 && minRrs > -0.001) {
100  rat = MAX(Rrs1, Rrs2) / Rrs3;
101  if (rat > minrat && rat < maxrat) {
102  rat = log10(rat);
103  chl = (float)
104  pow(10.0, (a[0] + rat * (a[1] + rat * (a[2] + rat * (a[3] + rat * a[4])))));
105 
106  if(uncertainty){
107  ibmax=ib1;
108  Rrsmax=Rrs1;
109  if(Rrs2>Rrs1){
110  ibmax=ib2;
111  Rrsmax=Rrs2;
112  }
113 
114  tmpderiv= chl* (a[1]+2*a[2]*rat+3*a[3]*rat*rat+4*a[4]*rat*rat*rat);
115 
116  *dchl=pow(tmpderiv,2)*(pow(dRrs[ibmax]/Rrsmax,2)+ pow(dRrs[ib3]/Rrs3,2));
117  *dchl-=2*pow(tmpderiv,2)/(Rrsmax*Rrs3)*covariance_matrix[ibmax*nbands+ib3]; //adding the covariance between Rrsmax and Rrs3
118  *dchl=sqrt(*dchl+chl*fit_unc*chl*fit_unc);
119  }
120 
121  chl = (chl > chlmin ? chl : chlmin);
122  chl = (chl < chlmax ? chl : chlmax);
123 
124  if(uncertainty){
125  if(fabs(chl-chlmin)<0.0000001 || fabs(chl-chlmax)<0.0000001)
126  *dchl=0;
127  }
128  }
129  }
130 
131  return (chl);
132 }
133 
134 float chl_oc3c(l2str *l2rec, float Rrs[]) {
135  static float a[] = {0.2515, -2.3798, 1.5823, -0.6372, -0.5692};
136  static int ib1 = -1;
137  static int ib2 = -1;
138  static int ib3 = -1;
139 
140  float rat, minRrs;
141  float Rrs1, Rrs2, Rrs3;
142  float chl = chlbad;
143 
144  if (ib1 < 0) {
145  ib1 = bindex_get(443);
146  ib2 = bindex_get(490);
147  ib3 = bindex_get_555();
148 
149  if (ib1 < 0 || ib2 < 0 || ib3 < 0) {
150  printf("chl_oc3: incompatible sensor wavelengths for this algorithm\n");
151  exit(1);
152  }
153  }
154 
155  Rrs1 = Rrs[ib1];
156  Rrs2 = Rrs[ib2];
157  Rrs3 = Rrs[ib3];
158 
159  minRrs = MIN(Rrs1, Rrs2);
160 
161  if (Rrs3 > 0.0 && Rrs2 > 0.0 && minRrs > -0.001) {
162  Rrs3 = conv_rrs_to_555(Rrs3, l2rec->l1rec->l1file->fwave[ib3],-99,NULL);
163  rat = MAX(Rrs1, Rrs2) / Rrs3;
164  if (rat > minrat && rat < maxrat) {
165  rat = log10(rat);
166  chl = (float)
167  pow(10.0, (a[0] + rat * (a[1] + rat * (a[2] + rat * (a[3] + rat * a[4])))));
168  chl = (chl > chlmin ? chl : chlmin);
169  chl = (chl < chlmax ? chl : chlmax);
170  }
171  }
172 
173  return (chl);
174 }
175 
176 float chl_oc4(l2str *l2rec, float Rrs[]) {
177  static int32_t *w = NULL;
178  static float *a = NULL;
179  static int ib1 = -1;
180  static int ib2 = -1;
181  static int ib3 = -1;
182  static int ib4 = -1;
183 
184  float rat, minRrs;
185  int ibmax;
186  float Rrs1, Rrs2, Rrs3, Rrs4, Rrsmax;
187  float chl = chlbad;
188 
189  float *dRrs, *dchl,*covariance_matrix, tmpderiv;
190  uncertainty_t *uncertainty=l2rec->l1rec->uncertainty;
191  static int nbands=0;
192  float fit_unc=0.13;
193 
194  if(uncertainty){
195  dRrs=uncertainty->dRrs;
196  dchl=&uncertainty->dchl;
197  if(input->proc_uncertainty==2)
198  covariance_matrix=uncertainty->covaraince_matrix;
199  else
200  covariance_matrix=uncertainty->pixel_covariance;
201  }
202 
203  if (w == NULL) {
204  nbands=l2rec->l1rec->l1file->nbands;
205  w = input->chloc4w;
206  a = input->chloc4c;
207  if (w[0] < 0 || w[1] < 0 || w[2] < 0 || w[3] < 0) {
208  printf("chl_oc4: algorithm coefficients not provided for this sensor.\n");
209  exit(1);
210  }
211  ib1 = bindex_get(w[0]);
212  ib2 = bindex_get(w[1]);
213  ib3 = bindex_get(w[2]);
214  ib4 = bindex_get(w[3]);
215  if (ib1 < 0 || ib2 < 0 || ib3 < 0 || ib4 < 0) {
216  printf("chl_oc4: incompatible sensor wavelengths for this algorithm\n");
217  exit(1);
218  }
219  }
220 
221  Rrs1 = Rrs[ib1];
222  Rrs2 = Rrs[ib2];
223  Rrs3 = Rrs[ib3];
224  Rrs4 = Rrs[ib4];
225 
226  minRrs = MIN(Rrs1, Rrs2);
227 
228  if (Rrs4 > 0.0 && Rrs3 > 0.0 && (Rrs2 > 0.0 || Rrs1 * Rrs2 > 0.0) && minRrs > -0.001) {
229  rat = MAX(MAX(Rrs1, Rrs2), Rrs3) / Rrs4;
230  if (rat > minrat && rat < maxrat) {
231  rat = log10(rat);
232  chl = (float)
233  pow(10.0, (a[0] + rat * (a[1] + rat * (a[2] + rat * (a[3] + rat * a[4])))));
234 
235  if(uncertainty){
236  if(Rrs1>=Rrs2 && Rrs1>=Rrs3){
237  ibmax=ib1;
238  Rrsmax=Rrs1;
239  }
240  else if(Rrs2>=Rrs1 && Rrs2>=Rrs3){
241  ibmax=ib2;
242  Rrsmax=Rrs2;
243  }
244  else{
245  ibmax=ib3;
246  Rrsmax=Rrs3;
247  }
248  tmpderiv= chl* (a[1]+2*a[2]*rat+3*a[3]*rat*rat+4*a[4]*rat*rat*rat);
249  *dchl=pow(tmpderiv,2)*(pow(dRrs[ibmax]/Rrsmax,2)+ pow(dRrs[ib4]/Rrs4,2));
250  *dchl-=2*pow(tmpderiv,2)/(Rrsmax*Rrs4)*covariance_matrix[ibmax*nbands+ib4]; //adding the covariance between Rrsmax and Rrs3
251  *dchl=sqrt(*dchl+chl*fit_unc*chl*fit_unc);
252  }
253 
254  chl = (chl > chlmin ? chl : chlmin);
255  chl = (chl < chlmax ? chl : chlmax);
256  if(uncertainty){
257  if(fabs(chl-chlmin)<0.0000001 || fabs(chl-chlmax)<0.0000001)
258  *dchl=0;
259  }
260  }
261  }
262 
263  return (chl);
264 }
265 
266 float chl_hu(l2str *l2rec, float Rrs[]) {
267  static float w[] = {443, 555, 670};
268  static float a[] = {-0.4287, 230.47};
269  static int ib1 = -1;
270  static int ib2 = -1;
271  static int ib3 = -1;
272  float fit_unc=0.13;
273 
274  float ci;
275  float Rrs1, Rrs2, Rrs3;
276  float dRrs2, dci;
277  float chl = chlbad;
278  static int nbands=0;
279 
280  uncertainty_t *uncertainty=l2rec->l1rec->uncertainty;
281  float *dRrs, *dchl, *covariance_matrix, cov_term=0;
282 
283  if(uncertainty){
284  dRrs=uncertainty->dRrs;
285  dchl=&uncertainty->dchl;
286  if(input->proc_uncertainty==2)
287  covariance_matrix=uncertainty->covaraince_matrix;
288  else
289  covariance_matrix=uncertainty->pixel_covariance;
290  }
291 
292  if (ib1 == -1) {
293  nbands=l2rec->l1rec->l1file->nbands;
294  ib1 = bindex_get(443);
295  ib2 = bindex_get_555();
296  ib3 = bindex_get(670);
297  if (ib3 < 0) ib3 = bindex_get(665);
298  if (ib3 < 0) ib3 = bindex_get(655);
299  if (ib3 < 0) ib3 = bindex_get(620); // for OCM2: need to add band correction
300  if (ib1 < 0 || ib2 < 0 || ib3 < 0) {
301  printf("chl_hu: incompatible sensor wavelengths for this algorithm\n");
302  printf("chl_hu: %d %d %d\n", ib1, ib2, ib3);
303  exit(1);
304  } else {
305  printf("chl_hu: using %7.2f %7.2f %7.2f\n", l2rec->l1rec->l1file->fwave[ib1], l2rec->l1rec->l1file->fwave[ib2], l2rec->l1rec->l1file->fwave[ib3]);
306  }
307  }
308 
309  Rrs1 = Rrs[ib1];
310  Rrs2 = Rrs[ib2];
311  Rrs3 = Rrs[ib3];
312 
313  // If all Rrs are bad then the pixel is masked, so return badval. For
314  // any other case, we want to return a valid value so that OCI can decide.
315 
316  if (Rrs3 > BAD_FLT + 1 && Rrs2 > BAD_FLT + 1 && Rrs1 > BAD_FLT + 1) {
317 
318  // The chl index (ci) is negative line height; ci=0 will yield chl > 0.3,
319  // where the algorithm is not considered valid, and not used in the
320  // merged algorithm.
321 
322  ci = 0;
323  dci=0;
324 
325  // We require that the red channel Rrs is valid (may be slightly negative
326  // in clear water due to noise), and that Rrs in blue and green be positive.
327  // Cases of negative blue radiance are likely high chl anyway.
328 
329  if (Rrs3 > BAD_FLT + 1 && Rrs2 > 0.0 && Rrs1 > 0.0) {
330  // shift Rrs2 to 555
331  if(uncertainty)
332  Rrs2 = conv_rrs_to_555(Rrs2, l2rec->l1rec->l1file->fwave[ib2],dRrs[ib2], &dRrs2);
333  else
334  Rrs2=conv_rrs_to_555(Rrs2, l2rec->l1rec->l1file->fwave[ib2],-99., NULL);
335  // compute index
336  ci = MIN(Rrs2 - (Rrs1 + (w[1] - w[0]) / (w[2] - w[0])*(Rrs3 - Rrs1)), 0.0);
337  // index should be negative in algorithm-validity range
338  if(uncertainty && ci<0){
339  dci=sqrt( dRrs2*dRrs2 + pow((w[2]-w[1])*dRrs[ib1]/(w[2]-w[0]),2) + pow((w[1]-w[0])*dRrs[ib3]/(w[2]-w[0]),2) );
340  cov_term=(w[1]-w[2])/(w[2]-w[0])*covariance_matrix[ib1*nbands+ib2];
341  cov_term+=(w[0]-w[1])/(w[2]-w[0])*covariance_matrix[ib2*nbands+ib3];
342  cov_term+=(w[1]-w[2])/(w[2]-w[0])*(w[0]-w[1])/(w[2]-w[0])*covariance_matrix[ib1*nbands+ib3];
343  dci=sqrt(dci*dci+cov_term);
344 
345  }
346  }
347  chl = (float) pow(10.0, a[0] + a[1] * ci);
348  if(uncertainty){
349  *dchl=chl*log(10)*a[1]*dci;
350  if(dci>0){
351  *dchl=sqrt(*dchl**dchl+fit_unc*chl*fit_unc*chl);
352  }
353  }
354 
355  chl = (chl > chlmin ? chl : chlmin);
356  chl = (chl < chlmax ? chl : chlmax);
357  }
358 
359  return (chl);
360 }
361 
362 float get_dchl_oci(l2str *l2rec,float Rrs[],float chl1,float chl2){
363  static float t1 = 0.25;
364  static float t2 = 0.35;
365  static float w[] = {443, 555, 670};
366  static float a[] = {-0.4909, 191.6590};
367  static float dcoef1[]={0.0203,6.303}; // uncertainty in coefficients of CI
368  static float dcoef2[]={0.0388, 0.169, 0.691, 1.552, 0.906}; // uncertainty in coefficients of OCX
369  float dmodel=0.;
370  static int ib1 = -1;
371  static int ib2 = -1;
372  static int ib3 = -1;
373  static int ib4 = -1;
374  static int ib5 = -1;
375 
376  float ci;
377  float Rrs1, Rrs2, Rrs3;
378  float dRrs2;
379  float chl = chlbad;
380  static int nbands=0;
381  float fit_unc=0.13;
382 
383  fit_unc=fit_unc* (chl1 * (t2 - chl1) / (t2 - t1)+ chl2 * (chl1 - t1) / (t2 - t1));
384 
385  uncertainty_t *uncertainty=l2rec->l1rec->uncertainty;
386  float *dRrs, *covariance_matrix,deriv[5]={0,0,0,0,0};
387 
388  static int32_t *w_ocx = NULL;
389  static float *a_ocx = NULL;
390 
391  float rat, minRrs;
392  float Rrs4, Rrs5;
393 
394  float tmpderiv;
395 
396  float deriv_chl1,deriv_chl2; //derivative of blended chl to chl1 and chl2
397  deriv_chl1=(t2-2*chl1+chl2)/(t2-t1);
398  deriv_chl2=(chl1-t1)/(t2-t1);
399 
400  if(uncertainty){
401  dRrs=uncertainty->dRrs;
402  if(input->proc_uncertainty==2)
403  covariance_matrix=uncertainty->covaraince_matrix;
404  else
405  covariance_matrix=uncertainty->pixel_covariance;
406  }
407 
408  if (ib1 == -1) {
409  nbands=l2rec->l1rec->l1file->nbands;
410  ib1 = bindex_get(443);
411  ib2 = bindex_get_555();
412  ib3 = bindex_get(670);
413  if (ib3 < 0) ib3 = bindex_get(665);
414  if (ib3 < 0) ib3 = bindex_get(655);
415  if (ib3 < 0) ib3 = bindex_get(620); // for OCM2: need to add band correction
416  if (ib1 < 0 || ib2 < 0 || ib3 < 0) {
417  printf("chl_hu: incompatible sensor wavelengths for this algorithm\n");
418  printf("chl_hu: %d %d %d\n", ib1, ib2, ib3);
419  exit(1);
420  }
421 
422  w_ocx = input->chloc3w;
423  a_ocx = input->chloc3c;
424  if (w_ocx[0] < 0 || w_ocx[1] < 0 || w_ocx[2] < 0) {
425  printf("chl_oc3: algorithm coefficients not provided for this sensor.\n");
426  exit(1);
427  }
428 
429  ib4 = bindex_get(w_ocx[1]);
430  ib5= bindex_get(w_ocx[2]);
431  if (ib1 < 0 || ib4 < 0 || ib5 < 0) {
432  printf("chl_oc3: incompatible sensor wavelengths for this algorithm\n");
433  exit(1);
434  }
435  }
436 
437  Rrs1 = Rrs[ib1];
438  Rrs2 = Rrs[ib2];
439  Rrs3 = Rrs[ib3];
440 
441  if (Rrs3 > BAD_FLT + 1 && Rrs2 > BAD_FLT + 1 && Rrs1 > BAD_FLT + 1) {
442 
443  ci = 0;
444 
445  // We require that the red channel Rrs is valid (may be slightly negative
446  // in clear water due to noise), and that Rrs in blue and green be positive.
447  // Cases of negative blue radiance are likely high chl anyway.
448 
449  if (Rrs3 > BAD_FLT + 1 && Rrs2 > 0.0 && Rrs1 > 0.0) {
450  // shift Rrs2 to 555
451  if(uncertainty)
452  Rrs2 = conv_rrs_to_555(Rrs2, l2rec->l1rec->l1file->fwave[ib2],dRrs[ib2], &dRrs2);
453  else
454  Rrs2=conv_rrs_to_555(Rrs2, l2rec->l1rec->l1file->fwave[ib2],-99., NULL);
455  // compute index
456  ci = MIN(Rrs2 - (Rrs1 + (w[1] - w[0]) / (w[2] - w[0])*(Rrs3 - Rrs1)), 0.0);
457  // index should be negative in algorithm-validity range
458  if(uncertainty && ci<0){
459  deriv[0]=chl1*log(10)*a[1]*(w[1]-w[2])/(w[2]-w[0]);
460  deriv[1]=chl1*log(10)*a[1];
461  deriv[2]=chl1*log(10)*a[1]*(w[0]-w[1])/(w[2]-w[0]);
462  }
463  }
464  }
465  else
466  return (chl);
467 
468 
469  Rrs4 = Rrs[ib4];
470  Rrs5 = Rrs[ib5];
471  minRrs = MIN(Rrs1, Rrs4);
472 
473  if (Rrs5 > 0.0 && Rrs4 > 0.0 && minRrs > -0.001) {
474  rat = MAX(Rrs1, Rrs4) / Rrs5;
475  if (rat > minrat && rat < maxrat) {
476  rat = log10(rat);
477  chl = (float)pow(10.0, (a_ocx[0] + rat * (a_ocx[1] + rat * (a_ocx[2] + rat * (a_ocx[3] + rat * a_ocx[4])))));
478 
479  if(uncertainty){
480  tmpderiv= chl* (a_ocx[1]+2*a_ocx[2]*rat+3*a_ocx[3]*rat*rat+4*a_ocx[4]*rat*rat*rat);
481  if(Rrs1>Rrs4){
482  deriv[0]=deriv_chl1*deriv[0]+deriv_chl2*tmpderiv/Rrs1;
483  }
484  else
485  deriv[3]=deriv_chl2*tmpderiv/Rrs4;
486 
487  deriv[4]=-deriv_chl2*tmpderiv/Rrs5;
488  }
489  deriv[1]*=deriv_chl1;
490  deriv[2]*=deriv_chl1;
491  }
492  else
493  return chl;
494 
495  }
496  else
497  return chl;
498 
499  chl=0;
500  int i,j;
501  int bindex[5];
502  bindex[0]=ib1;bindex[1]=ib2;bindex[2]=ib3;
503  bindex[3]=ib4;bindex[4]=ib5;
504  for(i=0;i<5;i++)
505  chl+=pow(deriv[i]*dRrs[bindex[i]],2);
506 
508  for(i=0;i<4;i++)
509  for(j=i+1;j<5;j++){
510  if(bindex[j]>=bindex[i])
511  chl+=2*deriv[i]*deriv[j]*covariance_matrix[bindex[i]*nbands+bindex[j]];
512  else
513  chl+=2*deriv[i]*deriv[j]*covariance_matrix[bindex[j]*nbands+bindex[i]];
514  }
515 
516  if(chl<0)
517  return BAD_FLT;
518  else{
519  dmodel=0.;
520  for(int icoef=0;icoef<5;icoef++)
521  dmodel+=(pow(rat,2*icoef)*pow(dcoef2[icoef],2));
522  dmodel*=pow(deriv_chl2*chl2*log(10),2);
523 
524  dmodel+=pow(deriv_chl1*chl1*log(10),2)*(dcoef1[0]*dcoef1[0]+pow(ci*dcoef1[1],2));
525 
526  return (sqrt(chl+fit_unc*fit_unc));
527  }
528 
529 }
530 
531 float chl_oci(l2str *l2rec, float Rrs[]) {
532  static float t1 = 0.25;
533  static float t2 = 0.35;
534 
535  float chl1 = chlbad;
536  float chl2 = chlbad;
537  float chl = chlbad;
538 
539  uncertainty_t *uncertainty=l2rec->l1rec->uncertainty;
540  float *dchl;
541  if(uncertainty)
542  dchl=&uncertainty->dchl;
543 
544  chl1 = chl_hu(l2rec, Rrs);
545 
546  if (chl1 <= t1)
547  chl = chl1;
548  else {
549  chl2 = get_chl_ocx(l2rec, Rrs);
550  if (chl2 > 0.0) {
551  if (chl1 >= t2)
552  chl = chl2;
553  else {
554  chl = chl1 * (t2 - chl1) / (t2 - t1)
555  + chl2 * (chl1 - t1) / (t2 - t1);
556  if(uncertainty)
557  *dchl=get_dchl_oci(l2rec,Rrs,chl1,chl2);
558  }
559  }
560  }
561 
562  return (chl);
563 }
564 
565 float chl_cdr(l2str *l2rec, float Rrs[]) {
566  static float chl_lo = 0.35;
567  static float chl_hi = 20.0;
568 
569  static float c_modisa[6] = {1.030e+00, 7.668e-02, 4.152e-01, 5.335e-01, -5.040e-01, 1.265e-01};
570  static float c_meris [6] = {1.0, 0.0, 0.0, 0.0, 0.0};
571  static float c_null [6] = {1.0, 0.0, 0.0, 0.0, 0.0};
572 
573  float chl1 = chlbad;
574  float chl2 = chlbad;
575  float lchl = chlbad;
576  float chl = chlbad;
577  float *c;
578  float rat;
579 
580  chl1 = get_default_chl(l2rec, Rrs);
581 
582  if (chl1 > 0.0) {
583  switch (l2rec->l1rec->l1file->sensorID) {
584  case MODISA:
585  c = c_modisa;
586  break;
587  case MERIS:
588  c = c_meris;
589  break;
590  case SEAWIFS:
591  case OCTS:
592  case OCM1:
593  case OCM2:
594  case MOS:
595  case HICO:
596  case MODIST:
597  case CZCS:
598  case OSMI:
599  case VIIRSN:
600  case VIIRSJ1:
601  case VIIRSJ2:
602  case OCRVC:
603  case GOCI:
604  c = c_null;
605  break;
606  default:
607  printf("%s Line %d: need a default chlorophyll algorithm for this sensor\n",
608  __FILE__, __LINE__);
609  exit(1);
610  break;
611  }
612 
613  chl = MAX(MIN(chl_hi, chl1), chl_lo);
614  lchl = log10(chl);
615  rat = c[0] + lchl * (c[1] + lchl * c[2] + lchl * (c[3] + lchl * (c[4] + lchl * c[5])));
616 
617  chl2 = chl1 / rat;
618  }
619 
620  return (chl2);
621 }
622 
623 /*======================================================================*
624  * *
625  * Implementation of ABI Chlorophyll (Shanmugam, 2011) *
626  * A new bio-optical algorithm for the remote sensing of algal blooms *
627  * in complex ocean waters *
628  * *
629  * Journal of Geophysical Research, 116(C4), C04016. *
630  * doi:10.1029/2010JC006796 *
631  *======================================================================*/
632 
633 float chl_abi(l2str *l2rec, float nLw[]) {
634  float chl1, chl2, chl3, chl4, chl5, chl6, chl7, Z;
635  float nLw1, nLw2, nLw3;
636  float chl = chlbad;
637  static int ib1 = -1, ib2 = -1, ib3 = -1;
638 
639  if (ib1 == -1) {
640  ib1 = bindex_get(443);
641 
642  ib2 = bindex_get(488);
643  if (ib2 < 0) ib2 = bindex_get(490);
644 
645  ib3 = bindex_get(547);
646  if (ib3 < 0) ib3 = bindex_get(555);
647 
648  if (ib1 < 0 || ib2 < 0 || ib3 < 0) {
649  printf("chl_abi is not compatible with this sensor\n");
650  exit(1);
651  } else {
652  printf("Calculating chl_abi using %7.2f %7.2f %7.2f\n",
653  l2rec->l1rec->l1file->fwave[ib1],
654  l2rec->l1rec->l1file->fwave[ib2],
655  l2rec->l1rec->l1file->fwave[ib3]);
656  }
657  }
658 
659 
660 
661 
662  nLw1 = nLw[ib1]; //443nm
663  nLw2 = nLw[ib2]; //488nm
664  nLw3 = nLw[ib3]; //547nm
665  if (nLw1 >-10.0) { //condition to avoid negative nLw
666  chl1 = ((nLw2 / nLw3) - nLw1) / ((nLw2 / nLw3) + nLw1);
667  chl2 = pow(10.0, chl1);
668  chl3 = (((nLw1 * nLw2) / 47.0)*((nLw1 * nLw2) / (nLw3 * nLw3)));
669  chl4 = chl2*chl3;
670  chl5 = 0.1403 * (pow(chl4, (-0.572)));
671  chl6 = pow(chl5, 1.056);
672  Z = pow(98, 1.056);
673  chl7 = chl6 / (chl6 + Z);
674  chl = 125.0 * chl7;
675  }
676  return (chl);
677 }
678 
679 float get_default_chl(l2str *l2rec, float Rrs[]) {
680 
681  switch (l2rec->l1rec->l1file->sensorID) {
682  case MOS:
683  return (chl_oc4(l2rec, Rrs));
684  case OSMI:
685  return (chl_oc3(l2rec, Rrs));
686  case L5TM:
687  case L7ETMP:
688  case MISR:
689  return (chl_oc2(l2rec, Rrs));
690  default:
691  return (chl_oci(l2rec, Rrs));
692  }
693 }
694 
695 float get_chl_ocx(l2str *l2rec, float Rrs[]) {
696  float chl;
697 
698  chl = chlbad;
699 
700  switch (l2rec->l1rec->l1file->sensorID) {
701  case SEAWIFS:
702  case OCTS:
703  case OCM1:
704  case OCM2:
705  case MOS:
706  case MERIS:
707  case HICO:
708  case OCIA:
709  case OCI:
710  case OCIS:
711  case HAWKEYE:
712  case AVIRIS:
713  case OLCIS3A:
714  case OLCIS3B:
715  chl = chl_oc4(l2rec, Rrs);
716  break;
717  case MODIST:
718  case MODISA:
719  case CZCS:
720  case OSMI:
721  case VIIRSN:
722  case VIIRSJ1:
723  case VIIRSJ2:
724  case OCRVC:
725  case GOCI:
726  case OLIL8:
727  case OLIL9:
728  case PRISM:
729  case SGLI:
730  case MSIS2A:
731  case MSIS2B:
732  chl = chl_oc3(l2rec,Rrs);
733  break;
734  case L5TM:
735  case L7ETMP:
736  case MISR:
737  chl = chl_oc2(l2rec,Rrs);
738  break;
739  default:
740  printf("%s Line %d: need a default chlorophyll algorithm for this sensor\n",
741  __FILE__,__LINE__);
742  exit(1);
743  break;
744  }
745 
746  return (chl);
747 }
748 
749 void get_chl(l2str *l2rec, int prodnum, float prod[]) {
750  int32_t ip;
751  int32_t ipb;
752 
753  int32_t nbands = l2rec->l1rec->l1file->nbands;
754  int32_t npix = l2rec->l1rec->npix;
755 
756  /* */
757  /* Compute desired products at each pixel */
758  /* */
759  for (ip = 0; ip < npix; ip++) {
760 
761  ipb = ip*nbands;
762 
763  switch (prodnum) {
764 
765  case DEFAULT_CHL:
766  prod[ip] = get_default_chl(l2rec, &l2rec->Rrs[ipb]);
767  break;
768  case CAT_chl_oc2:
769  prod[ip] = chl_oc2(l2rec, &l2rec->Rrs[ipb]);
770  break;
771  case CAT_chl_oc3:
772  prod[ip] = chl_oc3(l2rec, &l2rec->Rrs[ipb]);
773  break;
774  case CAT_chl_oc3c:
775  prod[ip] = chl_oc3c(l2rec, &l2rec->Rrs[ipb]);
776  break;
777  case CAT_chl_oc4:
778  prod[ip] = chl_oc4(l2rec, &l2rec->Rrs[ipb]);
779  break;
780  case CAT_chl_hu:
781  prod[ip] = chl_hu(l2rec, &l2rec->Rrs[ipb]);
782  break;
783  case CAT_chl_oci:
784  prod[ip] = chl_oci(l2rec, &l2rec->Rrs[ipb]);
785  break;
786  case CAT_chl_cdr:
787  prod[ip] = chl_cdr(l2rec, &l2rec->Rrs[ipb]);
788  break;
789  case CAT_chl_abi:
790  prod[ip] = chl_abi(l2rec, &l2rec->nLw[ipb]);
791  break;
792  default:
793  printf("Error: %s : Unknown product specifier: %d\n", __FILE__, prodnum);
794  exit(FATAL_ERROR);
795  break;
796  }
797 
798  if (prod[ip] == chlbad)
799  l2rec->l1rec->flags[ip] |= PRODFAIL;
800  }
801 }
802 
#define MAX(A, B)
Definition: swl0_utils.h:25
#define MIN(x, y)
Definition: rice.h:169
#define OLCIS3A
Definition: sensorDefs.h:32
float chl_oc3c(l2str *l2rec, float Rrs[])
Definition: get_chl.c:134
int j
Definition: decode_rs.h:73
#define DEFAULT_CHL
Definition: l12_parms.h:41
#define SGLI
Definition: sensorDefs.h:33
#define OCI
Definition: sensorDefs.h:42
#define MSIS2B
Definition: sensorDefs.h:38
#define CAT_chl_oc3c
Definition: l2prod.h:256
#define OSMI
Definition: sensorDefs.h:16
#define NULL
Definition: decode_rs.h:63
#define OLIL9
Definition: sensorDefs.h:45
#define CAT_chl_hu
Definition: l2prod.h:250
#define VIIRSN
Definition: sensorDefs.h:23
#define CAT_chl_cdr
Definition: l2prod.h:284
#define L5TM
Definition: sensorDefs.h:35
#define MERIS
Definition: sensorDefs.h:22
float chl_hu(l2str *l2rec, float Rrs[])
Definition: get_chl.c:266
#define MODIST
Definition: sensorDefs.h:18
#define CAT_chl_oc2
Definition: l2prod.h:32
#define PRODFAIL
Definition: l2_flags.h:41
#define OCIA
Definition: sensorDefs.h:29
#define OLIL8
Definition: sensorDefs.h:27
float chl_oc4(l2str *l2rec, float Rrs[])
Definition: get_chl.c:176
float chl_abi(l2str *l2rec, float nLw[])
Definition: get_chl.c:633
instr * input
float chl_cdr(l2str *l2rec, float Rrs[])
Definition: get_chl.c:565
int bindex_get(int32_t wave)
Definition: windex.c:45
#define HAWKEYE
Definition: sensorDefs.h:39
void get_chl(l2str *l2rec, int prodnum, float prod[])
Definition: get_chl.c:749
#define CAT_chl_oc4
Definition: l2prod.h:49
float chl_oc2(l2str *l2rec, float Rrs[])
Definition: get_chl.c:9
#define OCIS
Definition: sensorDefs.h:43
#define FATAL_ERROR
Definition: swl0_parms.h:5
float conv_rrs_to_555(float Rrs, float wave, float uRrs_in, float *uRrs_out)
Definition: convert_band.c:17
#define PRISM
Definition: sensorDefs.h:31
float chl_oci(l2str *l2rec, float Rrs[])
Definition: get_chl.c:531
#define CAT_chl_oc3
Definition: l2prod.h:72
#define AVIRIS
Definition: sensorDefs.h:30
float get_chl_ocx(l2str *l2rec, float Rrs[])
Definition: get_chl.c:695
#define MOS
Definition: sensorDefs.h:13
#define MISR
Definition: sensorDefs.h:40
#define L7ETMP
Definition: sensorDefs.h:36
float get_dchl_oci(l2str *l2rec, float Rrs[], float chl1, float chl2)
Definition: get_chl.c:362
#define BAD_FLT
Definition: jplaeriallib.h:19
#define OCTS
Definition: sensorDefs.h:14
float get_default_chl(l2str *l2rec, float Rrs[])
Definition: get_chl.c:679
#define MSIS2A
Definition: sensorDefs.h:34
#define CAT_chl_abi
Definition: l2prod.h:320
int32_t nbands
#define OCM1
Definition: sensorDefs.h:20
#define fabs(a)
Definition: misc.h:93
float chl_oc3(l2str *l2rec, float Rrs[])
Definition: get_chl.c:51
#define CZCS
Definition: sensorDefs.h:17
#define CAT_chl_oci
Definition: l2prod.h:254
#define VIIRSJ2
Definition: sensorDefs.h:44
#define OLCIS3B
Definition: sensorDefs.h:41
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude resolving resolving GSFcd00179 Corrected handling of fill values for[Sensor|Solar][Zenith|Azimuth] resolving MODxl01751 Changed to validate LUT version against a value retrieved from the resolving MODxl02056 Changed to calculate Solar Diffuser angles without adjustment for estimated post launch changes in the MODIS orientation relative to incidentally resolving defects MODxl01766 Also resolves MODxl01947 Changed to ignore fill values in SCI_ABNORM and SCI_STATE rather than treating them as resolving MODxl01780 Changed to use spacecraft ancillary data to recognise when the mirror encoder data is being set by side A or side B and to change calculations accordingly This removes the need for seperate LUTs for Side A and Side B data it makes the new LUTs incompatible with older versions of the and vice versa Also resolves MODxl01685 A more robust GRing algorithm is being which will create a non default GRing anytime there s even a single geolocated pixel in a granule Removed obsolete messages from seed as required for compatibility with version of the SDP toolkit Corrected test output file names to end in per delivery and then split off a new MYD_PR03 pcf file for Aqua Added AssociatedPlatformInstrumentSensor to the inventory metadata in MOD01 mcf and MOD03 mcf Created new versions named MYD01 mcf and MYD03 where AssociatedPlatformShortName is rather than Terra The program itself has been changed to read the Satellite Instrument validate it against the input L1A and LUT and to use it determine the correct files to retrieve the ephemeris and attitude data from Changed to produce a LocalGranuleID starting with MYD03 if run on Aqua data Added the Scan Type file attribute to the Geolocation copied from the L1A and attitude_angels to radians rather than degrees The accumulation of Cumulated gflags was moved from GEO_validate_earth_location c to GEO_locate_one_scan c
Definition: HISTORY.txt:464
#define HICO
Definition: sensorDefs.h:25
#define OCRVC
Definition: sensorDefs.h:24
#define SEAWIFS
Definition: sensorDefs.h:12
int i
Definition: decode_rs.h:71
PGE01 indicating that PGE02 PGE01 V6 for and PGE01 V2 for MOD03 were used to produce the granule By convention adopted in all MODIS Terra PGE02 code versions are The fourth digit of the PGE02 version denotes the LUT version used to produce the granule The source of the metadata environment variable ProcessingCenter was changed from a QA LUT value to the Process Configuration A sign used in error in the second order term was changed to a
Definition: HISTORY.txt:424
#define MODISA
Definition: sensorDefs.h:19
#define VIIRSJ1
Definition: sensorDefs.h:37
int npix
Definition: get_cmp.c:28
#define OCM2
Definition: sensorDefs.h:21
int bindex_get_555(void)
Definition: windex.c:57
#define GOCI
Definition: sensorDefs.h:26