28 static int numFlagMPHPixels = -1;
29 static int numFlagHABSPixels = -1;
30 static uint8_t *flags_mph =
NULL;
31 static uint8_t *flags_habs =
NULL;
35 if((numFlagMPHPixels != numPix) || !flags_mph) {
36 numFlagMPHPixels = numPix;
39 flags_mph = (uint8_t*) malloc(numPix);
43 if((numFlagHABSPixels != numPix) || !flags_habs) {
44 numFlagHABSPixels = numPix;
47 flags_habs = (uint8_t*) malloc(numPix);
52 float rhos620,
float rhos665,
float rhos709,
float rhos865,
53 float rhos885,
float *ci) {
55 float kd, kd_709, ss_560;
57 kd = (0.7 * ((((rhos620 + rhos665) / 2.) - rhos885) / (((rhos443 + rhos490) / 2.) - rhos885)));
60 kd_709 = (0.7 * ((rhos709 - rhos885) / (((rhos443 + rhos490) / 2.) - rhos885)));
63 if (kd_709 > kd) kd = kd_709;
66 ss_560 = rhos560 - rhos443 + (rhos443 - rhos620)*(560 - 443) / (620 - 443);
69 if (((((rhos620 + rhos665) / 2.) - rhos885) > 0) &&
70 ((((rhos443 + rhos490) / 2.) - rhos885) > 0)) {
72 ((rhos865 <= rhos490) ||
73 (rhos865 <= rhos665) ||
74 (rhos865 <= rhos709)) &&
83 int ib0, ib1, ib2, ib3, ib4, ib5, ib6, ib7, ib8;
84 float wav0, wav1, wav2, wav3, wav4, wav5, wav6, wav7, wav8,
fac;
88 static productInfo_t* ci_product_info;
90 switch (l2rec->l1rec->l1file->sensorID) {
105 switch (l2rec->l1rec->l1file->sensorID) {
133 if (l2rec->l1rec->l1file->sensorID !=
MERIS &&
134 l2rec->l1rec->l1file->sensorID !=
OLCIS3A &&
135 l2rec->l1rec->l1file->sensorID !=
OLCIS3B) {
136 printf(
"MCI not supported for this sensor (%s).\n",
146 printf(
"HABS_CI: Hmm, something's really messed up.\n");
150 if (ci_product_info ==
NULL) {
152 findProductInfo(
"CI_cyano", l2rec->l1rec->l1file->sensorID, ci_product_info);
159 if (ib1 < 0 || ib2 < 0 || ib3 < 0) {
160 printf(
"(M)CI_stumpf: incompatible sensor wavelengths for this algorithm\n");
164 for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
166 ipb = l2rec->l1rec->l1file->nbands*ip;
169 if ((l2rec->l1rec->height[ip] == 0 && l2rec->l1rec->dem[ip] < -1 *
input->shallow_water_depth) ||
170 (l2rec->l1rec->flags[ip] &
mask) != 0 ||
171 l2rec->l1rec->rhos[ipb + ib1] <= 0.0 ||
172 l2rec->l1rec->rhos[ipb + ib2] <= 0.0 ||
173 l2rec->l1rec->rhos[ipb + ib3] <= 0.0) {
175 l2rec->l1rec->flags[ip] |=
PRODFAIL;
182 ci[ip] =
fac * ((l2rec->l1rec->rhos[ipb + ib3] - l2rec->l1rec->rhos[ipb + ib1])*(wav2 - wav1) / (wav3 - wav1)
183 - (l2rec->l1rec->rhos[ipb + ib2] - l2rec->l1rec->rhos[ipb + ib1]));
185 if (l2rec->l1rec->rhos[ipb + ib6] < l2rec->l1rec->rhos[ipb + ib0]) {
189 if (l2rec->l1rec->l1file->sensorID ==
MERIS || l2rec->l1rec->l1file->sensorID ==
OLCIS3A
190 || l2rec->l1rec->l1file->sensorID ==
OLCIS3B) {
193 l2rec->l1rec->rhos[ipb + ib6], l2rec->l1rec->rhos[ipb + ib0],
194 l2rec->l1rec->rhos[ipb + ib1], l2rec->l1rec->rhos[ipb + ib3],
195 l2rec->l1rec->rhos[ipb + ib7], l2rec->l1rec->rhos[ipb + ib8], &ci[ip]);
198 if (l2rec->l1rec->rhos[ipb + ib1]
199 - l2rec->l1rec->rhos[ipb + ib0]
200 + (l2rec->l1rec->rhos[ipb + ib0]
201 - l2rec->l1rec->rhos[ipb + ib2])
202 *(wav1 - wav0) / (wav2 - wav0) >= 0) {
210 l2rec->l1rec->flags[ip] |=
PRODFAIL;
214 if (nonci == 0) ci[ip] = 0;
216 if (nonci == 1) ci[ip] = 0;
223 ci[ip] =
fac * (l2rec->l1rec->rhos[ipb + ib2] - l2rec->l1rec->rhos[ipb + ib1]
224 - (l2rec->l1rec->rhos[ipb + ib3] - l2rec->l1rec->rhos[ipb + ib1])*(wav2 - wav1) / (wav3 - wav1));
232 if (ci[ip] < ci_product_info->validMin) {
233 ci[ip] = ci_product_info->validMin;
239 for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
240 if (flags_habs[ip] != 0){
242 l2rec->l1rec->flags[ip] |=
PRODFAIL;
245 if (l2rec->l1rec->iscan == l2rec->l1rec->l1file->nscan) {
262 float wav6, wav7, wav8, wav9, wav10, wav14;
263 int ip, ipb, ib6, ib7, ib8, ib9, ib10, ib14;
264 float Rmax0, Rmax1, wavmax0, wavmax1, ndvi;
265 float sipf, sicf, bair, mph0, mph1;
266 float *rhos = l2rec->l1rec->rhos;
268 if ((l2rec->l1rec->l1file->sensorID !=
MERIS) &&
269 (l2rec->l1rec->l1file->sensorID !=
OLCIS3A) &&
270 (l2rec->l1rec->l1file->sensorID !=
OLCIS3B)) {
271 printf(
"MPH not supported for this sensor (%s).\n",
290 if (ib6 < 0 || ib7 < 0 || ib8 < 0 || ib9 < 0 || ib10 < 0 || ib14 < 0) {
291 printf(
"MPH_stumpf: incompatible sensor wavelengths for this algorithm\n");
295 for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
296 ipb = l2rec->l1rec->l1file->nbands*ip;
304 if (rhos[ipb + ib8] > rhos[ipb + ib9]) {
306 Rmax0 = rhos[ipb + ib8];
309 Rmax0 = rhos[ipb + ib9];
311 if (Rmax0 > rhos[ipb + ib10]) {
316 Rmax1 = rhos[ipb + ib10];
320 sipf = rhos[ipb + ib7] - rhos[ipb + ib6] - (rhos[ipb + ib8] - rhos[ipb + ib6]) * (664 - 619) / (681 - 619);
322 sicf = rhos[ipb + ib8] - rhos[ipb + ib7] - (rhos[ipb + ib9] - rhos[ipb + ib7]) * (681 - 664) / (709 - 664);
324 ndvi = (rhos[ipb + ib14] - rhos[ipb + ib7]) / (rhos[ipb + ib14] + rhos[ipb + ib7]);
326 bair = rhos[ipb + ib9] - rhos[ipb + ib7] - (rhos[ipb + ib14] - rhos[ipb + ib7]) * (709 - 664) / (885 - 664);
327 mph0 = Rmax0 - rhos[ipb + ib7] - (rhos[ipb + ib14] - rhos[ipb + ib7]) * (wavmax0 - 664) / (885 - 664);
328 mph1 = Rmax1 - rhos[ipb + ib7] - (rhos[ipb + ib14] - rhos[ipb + ib7]) * (wavmax1 - 664) / (885 - 664);
330 if (wavmax1 != wav10) {
332 if (sicf >= 0 || sipf <= 0 || bair <= 0.002) {
333 chl_mph[ip] = 5.24e9 * pow(mph0, 4) - 1.95e8 * pow(mph0, 3) + 2.46e6 * pow(mph0, 2) + 4.02e3 * mph0 + 1.97;
335 chl_mph[ip] = 22.44 * exp(35.79 * mph1);
338 if (mph1 >= 0.02 || ndvi >= 0.2) {
340 if (sicf < 0 && sipf > 0) {
341 chl_mph[ip] = 22.44 * exp(35.79 * mph1);
347 chl_mph[ip] = 5.24e9 * pow(mph0, 4) - 1.95e8 * pow(mph0, 3) + 2.46e6 * pow(mph0, 2) + 4.02e3 * mph0 + 1.97;
363 float wav6, wav7, wav8, wav9, wav10, wav14;
364 int ip, ipb, ib6, ib7, ib8, ib9, ib10, ib14;
365 float Rmax0, Rmax1, wavmax0, wavmax1, ndvi;
366 float sipf, sicf, bair, mph1, chl_mph;
367 float *rhos = l2rec->l1rec->rhos;
368 static float thresh = 350;
370 if ((l2rec->l1rec->l1file->sensorID !=
MERIS) &&
371 (l2rec->l1rec->l1file->sensorID !=
OLCIS3A) &&
372 (l2rec->l1rec->l1file->sensorID !=
OLCIS3B)) {
373 printf(
"MPH not supported for this sensor (%s).\n",
394 if (ib6 < 0 || ib7 < 0 || ib8 < 0 || ib9 < 0 || ib10 < 0 || ib14 < 0) {
395 printf(
"MPH_stumpf: incompatible sensor wavelengths for this algorithm\n");
399 for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
402 ipb = l2rec->l1rec->l1file->nbands*ip;
405 if (l2rec->l1rec->rhos[ipb + ib6] <= 0.0 ||
406 l2rec->l1rec->rhos[ipb + ib7] <= 0.0 ||
407 l2rec->l1rec->rhos[ipb + ib8] <= 0.0 ||
408 l2rec->l1rec->rhos[ipb + ib9] <= 0.0 ||
409 (l2rec->l1rec->flags[ip] &
LAND) != 0 ||
410 (l2rec->l1rec->flags[ip] &
NAVFAIL) != 0) {
411 l2rec->l1rec->flags[ip] |=
PRODFAIL;
414 if (rhos[ipb + ib8] > rhos[ipb + ib9]) {
416 Rmax0 = rhos[ipb + ib8];
419 Rmax0 = rhos[ipb + ib9];
421 if (Rmax0 > rhos[ipb + ib10]) {
426 Rmax1 = rhos[ipb + ib10];
430 sipf = rhos[ipb + ib7] - rhos[ipb + ib6] - (rhos[ipb + ib8] - rhos[ipb + ib6]) * (664 - 619) / (681 - 619);
432 sicf = rhos[ipb + ib8] - rhos[ipb + ib7] - (rhos[ipb + ib9] - rhos[ipb + ib7]) * (681 - 664) / (709 - 664);
434 ndvi = (rhos[ipb + ib14] - rhos[ipb + ib7]) / (rhos[ipb + ib14] + rhos[ipb + ib7]);
436 bair = rhos[ipb + ib9] - rhos[ipb + ib7] - (rhos[ipb + ib14] - rhos[ipb + ib7]) * (709 - 664) / (885 - 664);
438 mph1 = Rmax1 - rhos[ipb + ib7] - (rhos[ipb + ib14] - rhos[ipb + ib7]) * (wavmax1 - 664) / (885 - 664);
440 if (wavmax1 != wav10) {
442 if (sicf < 0 && sipf > 0 && bair > 0.002) {
444 chl_mph = 22.44 * exp(35.79 * mph1);
445 if (chl_mph > thresh)
449 if (mph1 >= 0.02 || ndvi >= 0.2) {
452 if (sicf < 0 && sipf > 0) {
454 chl_mph = 22.44 * exp(35.79 * mph1);
455 if (chl_mph > thresh)
473 int ib443, ib490, ib510, ib560, ib620, ib665, ib681, ib709, ib754, ib865, ib885;
475 float *rhos = l2rec->l1rec->rhos;
476 float mdsi, cv,
mean, sum, sdev;
481 if (l2rec->l1rec->l1file->sensorID !=
MERIS &&
482 l2rec->l1rec->l1file->sensorID !=
OLCIS3A &&
483 l2rec->l1rec->l1file->sensorID !=
OLCIS3B) {
484 printf(
"HABS flags not supported for this sensor (%s).\n",
501 if (ib443 < 0 || ib490 < 0 || ib510 < 0 || ib560 < 0 || ib620 < 0 || ib665 < 0 || ib681 < 0 || ib709 < 0 || ib754 < 0 || ib865 < 0 || ib885 < 0) {
502 printf(
"get_flags_habs: incompatible sensor wavelengths for this algorithm\n");
506 for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
508 ipb = l2rec->l1rec->l1file->nbands*ip;
513 flags_habs[ip] = (uint8_t) l2rec->l1rec->cloud[ip];
520 if (rhos[ipb + ib443] >= 0.0 &&
521 rhos[ipb + ib490] >= 0.0 &&
522 rhos[ipb + ib510] >= 0.0 &&
523 rhos[ipb + ib560] >= 0.0 &&
524 rhos[ipb + ib620] >= 0.0 &&
525 rhos[ipb + ib665] >= 0.0 &&
526 rhos[ipb + ib681] >= 0.0 &&
527 rhos[ipb + ib709] >= 0.0 &&
528 rhos[ipb + ib754] >= 0.0 &&
529 rhos[ipb + ib885] >= 0.0) {
531 if (rhos[ipb + ib885] > rhos[ipb + ib620] &&
532 rhos[ipb + ib885] > rhos[ipb + ib709] &&
533 rhos[ipb + ib885] > rhos[ipb + ib754] &&
534 rhos[ipb + ib885] > 0.01) {
539 if ((rhos[ipb + ib620] > rhos[ipb + ib560]) &&
540 (rhos[ipb + ib560] > 0.15) &&
541 (rhos[ipb + ib885] > 0.15)){
546 mdsi = (rhos[ipb + ib865] - rhos[ipb + ib885]) / (rhos[ipb + ib865] + rhos[ipb + ib885]);
549 int b[7] = {ib443, ib490, ib510, ib560, ib620, ib665, ib681};
551 for(
i = 0;
i < n; ++
i) {
552 sum += rhos[ipb +
b[
i]];
557 for(
i = 0;
i < n; ++
i) {
558 sdev += pow((rhos[ipb +
b[
i]] -
mean),2);
560 cv = sqrt(sdev / (n - 1)) /
mean;
562 if ((mdsi > 0.01) && (rhos[ipb + ib885] > 0.15) && (cv < 0.1)) {
566 float mci = 1.0 * (rhos[ipb + ib709] - rhos[ipb + ib681]
567 + (rhos[ipb + ib681] - rhos[ipb + ib754])*(709 - 681) / (754 - 681));
568 float ci = 1.0 * ((rhos[ipb + ib709] - rhos[ipb + ib665])*(681 - 665) / (709 - 665)
569 - (rhos[ipb + ib681] - rhos[ipb + ib665]));
572 rhos[ipb + ib560], rhos[ipb + ib620],
573 rhos[ipb + ib665], rhos[ipb + ib709],
574 rhos[ipb + ib865], rhos[ipb + ib885], &ci);
576 if ((mci < 0) && (ci > 0)) {
580 if (rhos[ipb + ib620] < 0.0 ||
581 rhos[ipb + ib665] < 0.0 ||
582 rhos[ipb + ib681] < 0.0 ||
583 rhos[ipb + ib709] < 0.0) {
594 int ib469, ib555, ib645, ib667, ib859, ib1240, ib2130;
596 float *rhos = l2rec->l1rec->rhos, *
Rrs = l2rec->Rrs, *cloud_albedo = l2rec->l1rec->cloud_albedo;
597 float ftemp, ftemp2, ftemp3;
598 float cloudthr = 0.027;
602 if (l2rec->l1rec->l1file->sensorID !=
MODISA && l2rec->l1rec->l1file->sensorID !=
MODIST) {
603 printf(
"HABS flags not supported for this sensor (%s).\n",
616 if (ib469 < 0 || ib555 < 0 || ib645 < 0 || ib667 < 0 || ib859 < 0 || ib1240 < 0 || ib2130 < 0) {
617 printf(
"get_flags_habs: incompatible sensor wavelengths for this algorithm\n");
621 for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
623 ipb = l2rec->l1rec->l1file->nbands*ip;
627 if (l2rec->chl[ip] < 0)
628 ftemp =
Rrs[ipb + ib667];
630 ftemp =
Rrs[ipb + ib667]*(0.45 + l2rec->chl[ip]*0.005) / 4.3;
632 if (
Rrs[ipb + ib667] < 0.0) ftemp = 0.0;
633 ftemp2 = cloud_albedo[ip] - ftemp;
635 if (ftemp2 > 0.027) flags_habs[ip] |=
HABS_CLOUD;
639 if (rhos[ipb + ib1240] / rhos[ipb + ib859] > 0.5 && (rhos[ipb + ib1240] + rhos[ipb + ib2130]) > 0.10) flags_habs[ip] |=
HABS_CLOUD;
644 ftemp = rhos[ipb + ib645] - rhos[ipb + ib555] + (rhos[ipb + ib555] - rhos[ipb + ib859])*(645.0 - 555.0) / (859.0 - 555.0);
645 ftemp2 = cloud_albedo[ip] + ftemp;
646 if (ftemp2 < cloudthr) flags_habs[ip] = 0;
647 if (rhos[ipb + ib859] / rhos[ipb + ib1240] > 4.0) flags_habs[ip] = 0;
651 if ((rhos[ipb + ib859] - rhos[ipb + ib469]) > 0.01 && cloud_albedo[ip] < 0.30) flags_habs[ip] = 0;
652 if ((rhos[ipb + ib859] - rhos[ipb + ib645]) > 0.01 && cloud_albedo[ip] < 0.15) flags_habs[ip] = 0;
653 if (rhos[ipb + ib1240] < 0.2)
654 ftemp2 = ftemp2 - (rhos[ipb + ib859] - rhos[ipb + ib1240]) *
fabs(rhos[ipb + ib859] - rhos[ipb + ib1240]) / cloudthr;
657 if (ftemp2 < cloudthr * 2) {
658 if ((rhos[ipb + ib555] - rhos[ipb + ib1240]) > (rhos[ipb + ib469] - rhos[ipb + ib1240])) {
659 ftemp3 = ftemp2 - (rhos[ipb + ib555] - rhos[ipb + ib1240]);
661 ftemp3 = ftemp2 - (rhos[ipb + ib469] - rhos[ipb + ib1240]);
665 if (ftemp3 < cloudthr) flags_habs[ip] = 0;
667 if (rhos[ipb + ib555] >= 0 && rhos[ipb + ib1240] >= 0.0 && rhos[ipb + ib1240] > rhos[ipb + ib555])
674 static int32_t currentLine = -1;
676 if (currentLine == l2rec->l1rec->iscan )
678 currentLine = l2rec->l1rec->iscan;
679 switch (l2rec->l1rec->l1file->sensorID) {
690 printf(
"HABS flags not supported for this sensor (%s).\n",