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)) &&
79 if (rhos885 < 0.005) {
87 int ib0, ib1, ib2, ib3, ib4, ib5, ib6, ib7, ib8;
88 float wav0, wav1, wav2, wav3, wav4, wav5, wav6, wav7, wav8,
fac, w681_fac;
92 static productInfo_t* ci_product_info;
94 switch (l2rec->l1rec->l1file->sensorID) {
116 switch (l2rec->l1rec->l1file->sensorID) {
144 if (l2rec->l1rec->l1file->sensorID !=
MERIS &&
145 l2rec->l1rec->l1file->sensorID !=
OLCIS3A &&
146 l2rec->l1rec->l1file->sensorID !=
OLCIS3B) {
147 printf(
"MCI not supported for this sensor (%s).\n",
157 printf(
"HABS_CI: Hmm, something's really messed up.\n");
161 if (ci_product_info ==
NULL) {
163 findProductInfo(
"CI_cyano", l2rec->l1rec->l1file->sensorID, ci_product_info);
170 if (ib1 < 0 || ib2 < 0 || ib3 < 0) {
171 printf(
"(M)CI_stumpf: incompatible sensor wavelengths for this algorithm\n");
175 for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
177 ipb = l2rec->l1rec->l1file->nbands*ip;
180 if ((l2rec->l1rec->height[ip] == 0 && l2rec->l1rec->dem[ip] < -1 *
input->shallow_water_depth) ||
181 (l2rec->l1rec->flags[ip] &
mask) != 0 ||
182 l2rec->l1rec->rhos[ipb + ib1] <= 0.0 ||
183 l2rec->l1rec->rhos[ipb + ib2] <= 0.0 ||
184 l2rec->l1rec->rhos[ipb + ib3] <= 0.0) {
186 l2rec->l1rec->flags[ip] |=
PRODFAIL;
193 ci[ip] =
fac * ((l2rec->l1rec->rhos[ipb + ib3] - l2rec->l1rec->rhos[ipb + ib1])*(wav2 - wav1) / (wav3 - wav1)
194 - (l2rec->l1rec->rhos[ipb + ib2]*w681_fac - l2rec->l1rec->rhos[ipb + ib1]));
197 if (l2rec->l1rec->l1file->sensorID ==
MERIS || l2rec->l1rec->l1file->sensorID ==
OLCIS3A
198 || l2rec->l1rec->l1file->sensorID ==
OLCIS3B) {
201 if (l2rec->l1rec->rhos[ipb + ib0] - l2rec->l1rec->rhos[ipb + ib6]
202 + (l2rec->l1rec->rhos[ipb + ib6] - l2rec->l1rec->rhos[ipb + ib1]) * (wav0 - wav6) / (wav1 - wav6) > 0) {
207 l2rec->l1rec->rhos[ipb + ib6], l2rec->l1rec->rhos[ipb + ib0],
208 l2rec->l1rec->rhos[ipb + ib1], l2rec->l1rec->rhos[ipb + ib3],
209 l2rec->l1rec->rhos[ipb + ib7], l2rec->l1rec->rhos[ipb + ib8], &ci[ip]);
212 if (l2rec->l1rec->rhos[ipb + ib1]
213 - l2rec->l1rec->rhos[ipb + ib0]
214 + (l2rec->l1rec->rhos[ipb + ib0]
215 - l2rec->l1rec->rhos[ipb + ib2]*w681_fac)
216 *(wav1 - wav0) / (wav2 - wav0) >= 0) {
224 l2rec->l1rec->flags[ip] |=
PRODFAIL;
228 if (nonci == 0) ci[ip] = 0;
230 if (nonci == 1) ci[ip] = 0;
237 ci[ip] =
fac * (l2rec->l1rec->rhos[ipb + ib2] - l2rec->l1rec->rhos[ipb + ib1]*w681_fac
238 - (l2rec->l1rec->rhos[ipb + ib3] - l2rec->l1rec->rhos[ipb + ib1]*w681_fac)*(wav2 - wav1) / (wav3 - wav1));
246 if (ci[ip] < ci_product_info->validMin) {
247 ci[ip] = ci_product_info->validMin;
253 for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
254 if (flags_habs[ip] != 0){
256 l2rec->l1rec->flags[ip] |=
PRODFAIL;
259 if (l2rec->l1rec->iscan == l2rec->l1rec->l1file->nscan) {
276 float wav6, wav7, wav8, wav9, wav10, wav14;
277 int ip, ipb, ib6, ib7, ib8, ib9, ib10, ib14;
278 float Rmax0, Rmax1, wavmax0, wavmax1, ndvi;
279 float sipf, sicf, bair, mph0, mph1;
280 float *rhos = l2rec->l1rec->rhos;
282 if ((l2rec->l1rec->l1file->sensorID !=
MERIS) &&
283 (l2rec->l1rec->l1file->sensorID !=
OLCIS3A) &&
284 (l2rec->l1rec->l1file->sensorID !=
OLCIS3B)) {
285 printf(
"MPH not supported for this sensor (%s).\n",
304 if (ib6 < 0 || ib7 < 0 || ib8 < 0 || ib9 < 0 || ib10 < 0 || ib14 < 0) {
305 printf(
"MPH_stumpf: incompatible sensor wavelengths for this algorithm\n");
309 for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
310 ipb = l2rec->l1rec->l1file->nbands*ip;
318 if (rhos[ipb + ib8] > rhos[ipb + ib9]) {
320 Rmax0 = rhos[ipb + ib8];
323 Rmax0 = rhos[ipb + ib9];
325 if (Rmax0 > rhos[ipb + ib10]) {
330 Rmax1 = rhos[ipb + ib10];
334 sipf = rhos[ipb + ib7] - rhos[ipb + ib6] - (rhos[ipb + ib8] - rhos[ipb + ib6]) * (664 - 619) / (681 - 619);
336 sicf = rhos[ipb + ib8] - rhos[ipb + ib7] - (rhos[ipb + ib9] - rhos[ipb + ib7]) * (681 - 664) / (709 - 664);
338 ndvi = (rhos[ipb + ib14] - rhos[ipb + ib7]) / (rhos[ipb + ib14] + rhos[ipb + ib7]);
340 bair = rhos[ipb + ib9] - rhos[ipb + ib7] - (rhos[ipb + ib14] - rhos[ipb + ib7]) * (709 - 664) / (885 - 664);
341 mph0 = Rmax0 - rhos[ipb + ib7] - (rhos[ipb + ib14] - rhos[ipb + ib7]) * (wavmax0 - 664) / (885 - 664);
342 mph1 = Rmax1 - rhos[ipb + ib7] - (rhos[ipb + ib14] - rhos[ipb + ib7]) * (wavmax1 - 664) / (885 - 664);
344 if (wavmax1 != wav10) {
346 if (sicf >= 0 || sipf <= 0 || bair <= 0.002) {
347 chl_mph[ip] = 5.24e9 * pow(mph0, 4) - 1.95e8 * pow(mph0, 3) + 2.46e6 * pow(mph0, 2) + 4.02e3 * mph0 + 1.97;
349 chl_mph[ip] = 22.44 * exp(35.79 * mph1);
352 if (mph1 >= 0.02 || ndvi >= 0.2) {
354 if (sicf < 0 && sipf > 0) {
355 chl_mph[ip] = 22.44 * exp(35.79 * mph1);
361 chl_mph[ip] = 5.24e9 * pow(mph0, 4) - 1.95e8 * pow(mph0, 3) + 2.46e6 * pow(mph0, 2) + 4.02e3 * mph0 + 1.97;
377 float wav6, wav7, wav8, wav9, wav10, wav14;
378 int ip, ipb, ib6, ib7, ib8, ib9, ib10, ib14;
379 float Rmax0, Rmax1, wavmax0, wavmax1, ndvi;
380 float sipf, sicf, bair, mph1, chl_mph;
381 float *rhos = l2rec->l1rec->rhos;
382 static float thresh = 350;
384 if ((l2rec->l1rec->l1file->sensorID !=
MERIS) &&
385 (l2rec->l1rec->l1file->sensorID !=
OLCIS3A) &&
386 (l2rec->l1rec->l1file->sensorID !=
OLCIS3B)) {
387 printf(
"MPH not supported for this sensor (%s).\n",
408 if (ib6 < 0 || ib7 < 0 || ib8 < 0 || ib9 < 0 || ib10 < 0 || ib14 < 0) {
409 printf(
"MPH_stumpf: incompatible sensor wavelengths for this algorithm\n");
413 for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
416 ipb = l2rec->l1rec->l1file->nbands*ip;
419 if (l2rec->l1rec->rhos[ipb + ib6] <= 0.0 ||
420 l2rec->l1rec->rhos[ipb + ib7] <= 0.0 ||
421 l2rec->l1rec->rhos[ipb + ib8] <= 0.0 ||
422 l2rec->l1rec->rhos[ipb + ib9] <= 0.0 ||
423 (l2rec->l1rec->flags[ip] &
LAND) != 0 ||
424 (l2rec->l1rec->flags[ip] &
NAVFAIL) != 0) {
425 l2rec->l1rec->flags[ip] |=
PRODFAIL;
428 if (rhos[ipb + ib8] > rhos[ipb + ib9]) {
430 Rmax0 = rhos[ipb + ib8];
433 Rmax0 = rhos[ipb + ib9];
435 if (Rmax0 > rhos[ipb + ib10]) {
440 Rmax1 = rhos[ipb + ib10];
444 sipf = rhos[ipb + ib7] - rhos[ipb + ib6] - (rhos[ipb + ib8] - rhos[ipb + ib6]) * (664 - 619) / (681 - 619);
446 sicf = rhos[ipb + ib8] - rhos[ipb + ib7] - (rhos[ipb + ib9] - rhos[ipb + ib7]) * (681 - 664) / (709 - 664);
448 ndvi = (rhos[ipb + ib14] - rhos[ipb + ib7]) / (rhos[ipb + ib14] + rhos[ipb + ib7]);
450 bair = rhos[ipb + ib9] - rhos[ipb + ib7] - (rhos[ipb + ib14] - rhos[ipb + ib7]) * (709 - 664) / (885 - 664);
452 mph1 = Rmax1 - rhos[ipb + ib7] - (rhos[ipb + ib14] - rhos[ipb + ib7]) * (wavmax1 - 664) / (885 - 664);
454 if (wavmax1 != wav10) {
456 if (sicf < 0 && sipf > 0 && bair > 0.002) {
458 chl_mph = 22.44 * exp(35.79 * mph1);
459 if (chl_mph > thresh)
463 if (mph1 >= 0.02 || ndvi >= 0.2) {
466 if (sicf < 0 && sipf > 0) {
468 chl_mph = 22.44 * exp(35.79 * mph1);
469 if (chl_mph > thresh)
487 int ib443, ib490, ib510, ib560, ib620, ib665, ib681, ib709, ib754, ib865, ib885;
489 float *rhos = l2rec->l1rec->rhos;
490 float mdsi, cv,
mean, sum, sdev, w681_fac;
495 if (l2rec->l1rec->l1file->sensorID !=
MERIS &&
496 l2rec->l1rec->l1file->sensorID !=
OLCIS3A &&
497 l2rec->l1rec->l1file->sensorID !=
OLCIS3B) {
498 printf(
"HABS flags not supported for this sensor (%s).\n",
515 if (ib443 < 0 || ib490 < 0 || ib510 < 0 || ib560 < 0 || ib620 < 0 || ib665 < 0 || ib681 < 0 || ib709 < 0 || ib754 < 0 || ib865 < 0 || ib885 < 0) {
516 printf(
"get_flags_habs: incompatible sensor wavelengths for this algorithm\n");
520 if (l2rec->l1rec->l1file->sensorID ==
OLCIS3A ||
521 l2rec->l1rec->l1file->sensorID ==
OLCIS3B) {
527 for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
529 ipb = l2rec->l1rec->l1file->nbands*ip;
534 flags_habs[ip] = (uint8_t) l2rec->l1rec->cloud[ip];
541 if (rhos[ipb + ib443] >= 0.0 &&
542 rhos[ipb + ib490] >= 0.0 &&
543 rhos[ipb + ib510] >= 0.0 &&
544 rhos[ipb + ib560] >= 0.0 &&
545 rhos[ipb + ib620] >= 0.0 &&
546 rhos[ipb + ib665] >= 0.0 &&
547 rhos[ipb + ib681] >= 0.0 &&
548 rhos[ipb + ib709] >= 0.0 &&
549 rhos[ipb + ib754] >= 0.0 &&
550 rhos[ipb + ib885] >= 0.0) {
552 if (rhos[ipb + ib885] > rhos[ipb + ib620] &&
553 rhos[ipb + ib885] > rhos[ipb + ib709] &&
554 rhos[ipb + ib885] > rhos[ipb + ib754] &&
555 rhos[ipb + ib885] > 0.01) {
560 if ((rhos[ipb + ib620] > rhos[ipb + ib560]) &&
561 (rhos[ipb + ib560] > 0.15) &&
562 (rhos[ipb + ib885] > 0.15)){
567 mdsi = (rhos[ipb + ib865] - rhos[ipb + ib885]) / (rhos[ipb + ib865] + rhos[ipb + ib885]);
570 int b[7] = {ib443, ib490, ib510, ib560, ib620, ib665, ib681};
572 for(
i = 0;
i < n; ++
i) {
573 sum += rhos[ipb +
b[
i]];
578 for(
i = 0;
i < n; ++
i) {
579 sdev += pow((rhos[ipb +
b[
i]] -
mean),2);
581 cv = sqrt(sdev / (n - 1)) /
mean;
583 if ((mdsi > 0.01) && (rhos[ipb + ib885] > 0.15) && (cv < 0.1)) {
587 float mci = 1.0 * (rhos[ipb + ib709] - rhos[ipb + ib681]*w681_fac
588 + (rhos[ipb + ib681]*w681_fac - rhos[ipb + ib754])*(709 - 681) / (754 - 681));
589 float ci = 1.0 * ((rhos[ipb + ib709] - rhos[ipb + ib665])*(681 - 665) / (709 - 665)
590 - (rhos[ipb + ib681]*w681_fac - rhos[ipb + ib665]));
593 rhos[ipb + ib560], rhos[ipb + ib620],
594 rhos[ipb + ib665], rhos[ipb + ib709],
595 rhos[ipb + ib865], rhos[ipb + ib885], &ci);
597 if ((mci < 0) && (ci > 0)) {
601 if (rhos[ipb + ib620] < 0.0 ||
602 rhos[ipb + ib665] < 0.0 ||
603 rhos[ipb + ib681] < 0.0 ||
604 rhos[ipb + ib709] < 0.0) {
615 int ib469, ib555, ib645, ib667, ib859, ib1240, ib2130;
617 float *rhos = l2rec->l1rec->rhos, *
Rrs = l2rec->Rrs, *cloud_albedo = l2rec->l1rec->cloud_albedo;
618 float ftemp, ftemp2, ftemp3;
619 float cloudthr = 0.027;
623 if (l2rec->l1rec->l1file->sensorID !=
MODISA && l2rec->l1rec->l1file->sensorID !=
MODIST) {
624 printf(
"HABS flags not supported for this sensor (%s).\n",
637 if (ib469 < 0 || ib555 < 0 || ib645 < 0 || ib667 < 0 || ib859 < 0 || ib1240 < 0 || ib2130 < 0) {
638 printf(
"get_flags_habs: incompatible sensor wavelengths for this algorithm\n");
642 for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
644 ipb = l2rec->l1rec->l1file->nbands*ip;
648 if (l2rec->chl[ip] < 0)
649 ftemp =
Rrs[ipb + ib667];
651 ftemp =
Rrs[ipb + ib667]*(0.45 + l2rec->chl[ip]*0.005) / 4.3;
653 if (
Rrs[ipb + ib667] < 0.0) ftemp = 0.0;
654 ftemp2 = cloud_albedo[ip] - ftemp;
656 if (ftemp2 > 0.027) flags_habs[ip] |=
HABS_CLOUD;
660 if (rhos[ipb + ib1240] / rhos[ipb + ib859] > 0.5 && (rhos[ipb + ib1240] + rhos[ipb + ib2130]) > 0.10) flags_habs[ip] |=
HABS_CLOUD;
665 ftemp = rhos[ipb + ib645] - rhos[ipb + ib555] + (rhos[ipb + ib555] - rhos[ipb + ib859])*(645.0 - 555.0) / (859.0 - 555.0);
666 ftemp2 = cloud_albedo[ip] + ftemp;
667 if (ftemp2 < cloudthr) flags_habs[ip] = 0;
668 if (rhos[ipb + ib859] / rhos[ipb + ib1240] > 4.0) flags_habs[ip] = 0;
672 if ((rhos[ipb + ib859] - rhos[ipb + ib469]) > 0.01 && cloud_albedo[ip] < 0.30) flags_habs[ip] = 0;
673 if ((rhos[ipb + ib859] - rhos[ipb + ib645]) > 0.01 && cloud_albedo[ip] < 0.15) flags_habs[ip] = 0;
674 if (rhos[ipb + ib1240] < 0.2)
675 ftemp2 = ftemp2 - (rhos[ipb + ib859] - rhos[ipb + ib1240]) *
fabs(rhos[ipb + ib859] - rhos[ipb + ib1240]) / cloudthr;
678 if (ftemp2 < cloudthr * 2) {
679 if ((rhos[ipb + ib555] - rhos[ipb + ib1240]) > (rhos[ipb + ib469] - rhos[ipb + ib1240])) {
680 ftemp3 = ftemp2 - (rhos[ipb + ib555] - rhos[ipb + ib1240]);
682 ftemp3 = ftemp2 - (rhos[ipb + ib469] - rhos[ipb + ib1240]);
686 if (ftemp3 < cloudthr) flags_habs[ip] = 0;
688 if (rhos[ipb + ib555] >= 0 && rhos[ipb + ib1240] >= 0.0 && rhos[ipb + ib1240] > rhos[ipb + ib555])
695 static int32_t currentLine = -1;
697 if (currentLine == l2rec->l1rec->iscan )
699 currentLine = l2rec->l1rec->iscan;
700 switch (l2rec->l1rec->l1file->sensorID) {
711 printf(
"HABS flags not supported for this sensor (%s).\n",