29 #define radians(degrees) ((degrees) * M_PI / 180.0)
30 #define degrees(radians) ((radians) * 180.0 / M_PI)
35 #define SEAWIFS_NBANDS 8
36 #define MODIS_NBANDS 9
43 #define ABSIND_NS 3891200
45 #define IOPF_NIWA_BADGEOM 0x0020
59 static int th_s_n, th_v_n, dphi_n;
62 static int ap_n, bp_n;
72 static const int seawifs_map[
VBANDS] = {0, 1, 2, 3, 4, 5};
73 static const int modis_map[
VBANDS] = {0, 1, 2, 3, 4, 5};
75 static const int *band_map;
98 static float interpol(
float *
v,
float *
x,
float u,
int size) {
99 static const int rsize = 1;
108 s1 = ((
x[1] -
x[0]) >= 0) ? 1 : -1;
114 for (
i = 0;
i <= rsize;
i++) {
116 d = s1 * (
u -
x[ix]);
121 while ((s1 * (
u -
x[ix + 1]) > 0.0) && (ix < m2)) {
125 while ((s1 * (
u -
x[ix]) < 0.0) && (ix > 0)) {
129 r =
v[ix] + (
u -
x[ix]) * (
v[ix + 1] -
v[ix]) / (
x[ix + 1] -
x[ix]);
143 static int setgeom(
float sun_theta,
float sen_theta,
float dphi) {
147 float th_s_ent, th_v_ent, dphi_ent;
150 printf(
"setgeom starting: [%f %f %f]\n", sun_theta * 180. /
M_PI,
151 sen_theta * 180. /
M_PI, dphi * 180. /
M_PI);
156 th_s_ent = floor(interpol(th_s_ind, th_s_lev, sun_theta,
TH_NS) + 0.5);
157 th_v_ent = floor(interpol(th_v_ind, th_v_lev, sen_theta,
TH_NS) + 0.5);
159 dphi = dphi +
M_PI * 2.0;
160 if (dphi >
M_PI * 2.0)
161 dphi = dphi -
M_PI * 2.0;
162 dphi_ent = floor(interpol(dphi_ind, dphi_lev, dphi,
DPHI_NS) + 0.5);
169 printf(
"[th_s_ent th_v_ent dphi_ent tabind]=[%f %f %f %d]\n",
170 th_s_ent, th_v_ent, dphi_ent, tabind);
175 printf(
"\nWARNING: NIWA-IOP: Table limits exceeded.\n");
184 abst[
x][
y][
i] = absen[
pos +
x];
190 printf(
"LUT loaded: abst=%d\n"), abst;
193 printf(
"Bands first:");
195 printf(
" %f", abst[0][0][
x]);
197 printf(
"Bands last:");
215 static int load_work_tab(
void) {
217 char lutdir[FILENAME_MAX];
218 char fname[FILENAME_MAX];
222 if ((tmp_str = getenv(
"OCDATAROOT")) ==
NULL) {
223 printf(
"\nERROR: NIWA-IOP: OCDATAROOT environment variable is not defined.\n");
228 strcat(
lutdir,
"/common");
230 printf(
"LUT dir = %s\n",
lutdir);
234 sprintf(fname,
"%s/niwa_iop_h.txt",
lutdir);
236 printf(
"NIWA-IOP: Reading LUT header file %s\n", fname);
238 fp = fopen(fname,
"r");
240 printf(
"\nERROR: NIWA-IOP: Cannot open %s\n", fname);
244 fscanf(fp,
"%d", &lut_nbands);
245 if (lut_nbands !=
LBANDS) {
246 printf(
"\nERROR: NIWA-IOP: Band mismatch opening %s\n", fname);
250 fscanf(fp,
"%f", &band_lev[
i]);
252 fscanf(fp,
"%d", &th_s_n);
254 fscanf(fp,
"%f", &th_s_lev[
i]);
258 printf(
"th_s_n %d th_s_lev %f %f\n", th_s_n, th_s_lev[0], th_s_lev[1]);
261 fscanf(fp,
"%d", &th_v_n);
263 fscanf(fp,
"%f", &th_v_lev[
i]);
267 printf(
"th_v_n %d th_v_lev %f %f\n", th_v_n, th_v_lev[0], th_v_lev[1]);
270 fscanf(fp,
"%d", &dphi_n);
272 fscanf(fp,
"%f", &dphi_lev[
i]);
276 printf(
"dphi_n %d dphi_lev %f %f\n", dphi_n, dphi_lev[0], dphi_lev[1]);
279 fscanf(fp,
"%d", &ap_n);
281 fscanf(fp,
"%f", &ap_lev[
i]);
283 printf(
"ap_n %d ap_lev %f %f\n", ap_n, ap_lev[0], ap_lev[1]);
286 fscanf(fp,
"%d", &bp_n);
288 fscanf(fp,
"%f", &bp_lev[
i]);
290 printf(
"bp_n %d bp_lev %f %f\n", bp_n, bp_lev[0], bp_lev[1]);
295 printf(
"NIWA-IOP: Loaded OK %s\n", fname);
306 sprintf(fname,
"%s/niwa_iop.dat",
lutdir);
307 printf(
"NIWA-IOP: Loading LUT data from %s\n", fname);
309 fp = fopen(fname,
"r");
311 printf(
"\nERROR: NIWA-IOP: Cannot open %s\n", fname);
316 absind = th_s_n * th_v_n * dphi_n * ap_n * bp_n *
LBANDS;
318 printf(
"S_F_T: absind= %d\n", absind);
321 if ((absen = (
float *) calloc((absind),
sizeof (
float))) == 0) {
322 printf(
"\nERROR: NIWA-IOP: memory allocation failure, absen\n");
326 fread(absen,
sizeof (
float), absind, fp);
330 printf(
"NIWA-IOP: %s Loaded OK\n", fname);
331 printf(
"absen first %f %f %f %f %f %f %f %f\n", absen[0], absen[1], absen[2], absen[3],
332 absen[4], absen[5], absen[6], absen[7]);
333 printf(
"absen last %f %f %f %f %f %f %f %f\n", absen[absind - 8], absen[absind - 7],
334 absen[absind - 6], absen[absind - 5], absen[absind - 4], absen[absind - 3],
335 absen[absind - 2], absen[absind - 1]);
349 static void mbcucof(
float y[],
float y1[],
float y2[],
float y12[],
float d1,
float d2,
float *cl) {
350 static const int wt[16][16] = {
351 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
352 {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
353 {-3, 0, 0, 3, 0, 0, 0, 0, -2, 0, 0, -1, 0, 0, 0, 0},
354 {2, 0, 0, -2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0},
355 {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
356 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
357 {0, 0, 0, 0, -3, 0, 0, 3, 0, 0, 0, 0, -2, 0, 0, -1},
358 {0, 0, 0, 0, 2, 0, 0, -2, 0, 0, 0, 0, 1, 0, 0, 1},
359 {-3, 3, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
360 {0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, -2, -1, 0, 0},
361 {9, -9, 9, -9, 6, 3, -3, -6, 6, -6, -3, 3, 4, 2, 1, 2},
362 {-6, 6, -6, 6, -4, -2, 2, 4, -3, 3, 3, -3, -2, -1, -1, -2},
363 {2, -2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
364 {0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 1, 1, 0, 0},
365 {-6, 6, -6, 6, -3, -3, 3, 3, -4, 4, 2, -2, -2, -2, -1, -1},
366 {4, -4, 4, -4, 2, 2, -2, -2, 2, -2, -2, 2, 1, 1, 1, 1}
370 float xx, d1d2,
x[16];
373 for (
i = 0;
i < 4;
i++) {
375 x[
i + 4] = y1[
i] * d1;
376 x[
i + 8] = y2[
i] * d2;
377 x[
i + 12] = y12[
i] * d1d2;
379 for (
i = 0;
i < 16;
i++) {
381 for (
k = 0;
k < 16;
k++)
382 xx += wt[
i][
k] *
x[
k];
395 static float f_abx(
float a,
float b,
int band) {
400 int al, bl, ah, bh, xl, xh, yl,
yh;
401 float t,
u, d1, d2,
c[4][4], cl[16];
402 float yy[4], y1[4], y2[4], y12[4];
405 if ((
a < 0.0) || (
b < 0.0))
409 ain = interpol(a_ind, ap_lev,
a,
AP_NS);
410 bin = interpol(b_ind, bp_lev,
b,
BP_NS);
418 al = (ain > 0) ? (
int) floor(ain) : 0;
419 bl = (bin > 0) ? (
int) floor(bin) : 0;
427 if ((al == ah) || (bl == bh))
431 for (
i = 0;
i < 4;
i++) {
432 x = (
i == 0 ||
i == 3) ? al : ah;
433 y = (
i < 2) ? bl : bh;
434 xl = (
x == 0) ?
x :
x - 1;
436 yl = (
y == 0) ?
y :
y - 1;
440 y1[
i] = (tarr[xh][
y] - tarr[xl][
y]) / (ap_lev[xh] - ap_lev[xl]);
441 y2[
i] = (tarr[
x][
yh] - tarr[
x][yl]) / (bp_lev[
yh] - bp_lev[yl]);
442 y12[
i] = (tarr[xh][
yh] - tarr[xh][yl] - tarr[xl][
yh] + tarr[xl][yl])
443 / ((ap_lev[xh] - ap_lev[xl]) * (bp_lev[
yh] - bp_lev[yl]));
445 d1 = ap_lev[ah] - ap_lev[al];
446 d2 = bp_lev[bh] - bp_lev[bl];
449 mbcucof(yy, y1, y2, y12, d1, d2, cl);
451 for (
x = 0;
x < 4;
x++)
452 for (
y = 0;
y < 4;
y++)
454 t = (
a - ap_lev[al]) / d1;
455 u = (
b - bp_lev[bl]) / d2;
457 for (
i = 3;
i >= 0;
i--)
472 static float f_ab(
float a,
float b,
int band,
int sensor_id) {
478 res1 = f_abx(
a,
b, 4);
479 res += ((530 - 510) / (555 - 510)) * (res1 -
res);
496 static int iop_model1(
float Rrs[],
int sensor_id, abs_res_t *
result) {
497 static const float b_tilde = 0.01756;
498 static const float init_a[] = {0.05, 0.06, 0.05, 0.04, 0.02, 0.03};
499 static const int maxIts = 20;
500 static const float tol = 0.001;
502 float minEpsa, maxEpsa;
504 float new_err, old_err;
505 float b490, hib490, lob490, bstep, temp1;
506 float bestb[2], besta[2];
533 for (iw = 0; iw <
VBANDS; iw++) {
539 for (iw = 0; iw <
VBANDS; iw++) {
547 b[iw] = (
lambda[iw] /
lambda[2]) * (0.841 * (lambda[iw] / lambda[2]) - 2.806) + 2.965;
552 for (iw = 0; iw <
VBANDS; iw++) {
553 bn[iw] =
b[iw] /
b[2];
557 printf(
"--- START iop_model1 ---\n");
558 printf(
"rho=[%f %f %f %f %f %f]\n", rho[0], rho[1], rho[2], rho[3], rho[4], rho[5]);
559 printf(
"b=[%f %f %f %f %f %f]\n",
b[0],
b[1],
b[2],
b[3],
b[4],
b[5]);
560 printf(
"bn=[%f %f %f %f %f %f]\n", bn[0], bn[1], bn[2], bn[3], bn[4], bn[5]);
565 for (iw = 3; iw < 5; iw++)
566 b[iw] =
b[2] * bn[iw];
567 for (iw = 2; iw < 5; iw++)
571 new_err = old_err - 1;
573 while ((old_err - new_err) >
tol && iter < maxIts) {
576 for (iw = 2; iw < 5; iw++) {
577 F[iw] = f_ab(0.0,
b[iw], iw, sensor_id);
579 temp[iw] = (rho[iw] * aw[iw] /
F[iw] - bbw[iw]) / b_tilde;
581 printf(
"b[%d]=%f\n", iw, temp[iw]);
588 new_err += fabsf(temp[iw] -
b[iw]) /
b[iw];
592 temp1 = (
b[2] +
b[3] / bn[3] +
b[4] / bn[4]) / 3.;
593 for (iw = 2; iw < 5; iw++)
594 b[iw] = temp1 * bn[iw];
596 printf(
"%d getting bF [b2,F2] =[%f %f] -> %f\n", iter,
b[2],
F[2], new_err);
603 printf(
"got a+F: iter=%d new_err=%f\n", iter, new_err);
604 printf(
"F=[%f %f %f]\n",
F[2],
F[3],
F[4]);
605 printf(
"a=[%f %f %f]\n",
a[2],
a[3],
a[4]);
606 printf(
"b=[%f %f %f]\n",
b[2],
b[3],
b[4]);
607 printf(
"lob490=%f\n", lob490);
613 for (iw = 3; iw < 5; iw++)
614 if (
b[iw] / bn[iw] > lob490)
615 lob490 =
b[iw] / bn[iw];
618 printf(
"lob490=%f\n", lob490);
624 bstep = pow((hib490 / lob490), (1.0 / 15.0)) - 1.0;
626 printf(
"bstep=%f lob490\n", bstep, lob490);
634 for (iw = 2; iw < 4; iw++) {
635 b[iw] = b490 * bn[iw];
636 a[iw] =
F[2] * (
b[iw] * b_tilde + bbw[iw]) / rho[iw] - aw[iw];
643 new_err = old_err - 1;
644 while ((old_err - new_err) >
tol && iter < maxIts) {
648 for (iw = 2; iw < 4; iw++) {
650 F[iw] = f_ab(
a[iw],
b[iw], iw, sensor_id);
652 temp1 =
F[iw] * (
b[iw] * b_tilde + bbw[iw]) / rho[iw] - aw[iw];
657 new_err += fabsf(temp1 -
a[iw]) /
a[iw];
662 printf(
"%d 1getting aF [a2,F2] =[%f %f] -> %f\n", iter,
a[2],
F[2], new_err);
663 printf(
"%d 1getting aF [a3,F3] =[%f %f] -> %f\n", iter,
a[3],
F[3], new_err);
667 printf(
"finished iters\n");
672 if (bestb[0] < 0.0 ||
a[2] /
a[3] > maxEpsa) {
678 if (bestb[1] < 0.0) {
683 }
else if (
a[2] /
a[3] > minEpsa) {
690 printf(
"besta=[%f %f]\n", besta[0], besta[1]);
691 printf(
"bestb=[%f %f]\n", bestb[0], bestb[1]);
694 b490 += b490 * bstep;
696 printf(
" [a,b,epsa]=[%f %f %f]\n",
a[2], b490,
a[2] /
a[3]);
697 printf(
"---finished while\n");
700 }
while (b490 < 1.1 * hib490 &&
a[2] /
a[3] > minEpsa);
703 if (bestb[0] > 0.0 && bestb[1] > 0.0) {
706 temp1 = pow(besta[0] * besta[1], 0.5);
708 if (b490 > 1.1 * hib490)
710 else if (bestb[1] / bestb[0] > 20.)
711 b490 = pow(bestb[0] * bestb[1], 0.5);
712 else if (temp1 > 1.0)
714 else if (temp1 < 0.01)
717 b490 = 0.5 * (bestb[0] + bestb[1]);
720 printf(
"FINAL1 b490=%f\n", b490);
726 else if (b490 < lob490)
729 printf(
"FINAL2 b490=%f\n", b490);
733 for (iw = 0; iw <
VBANDS; iw++) {
735 b[iw] = b490 * bn[iw];
738 a[iw] = 0.2 * (
b[iw] * b_tilde + bbw[iw]) / rho[iw] - aw[iw];
745 new_err = new_err - 1.;
746 while ((old_err - new_err) >
tol && iter < maxIts) {
749 F[iw] = f_ab(
a[iw],
b[iw], iw, sensor_id);
751 temp1 =
F[iw] * (
b[iw] * b_tilde + bbw[iw]) / rho[iw] - aw[iw];
756 new_err += fabsf(temp1 -
a[iw]) /
a[iw];
760 printf(
"%d 2getting aF [a2,F2] =[%f %f] -> %f\n", iter,
a[2],
F[2], new_err);
764 printf(
"finished iters\n");
768 result->bb[iw] =
b[iw] * b_tilde;
769 if (
a[iw] > 0.001001) {
774 printf(
"%d main.result1 [a,bb]=[%f %f]\n", iw,
result->a[iw],
result->bb[iw]);
785 printf(
"Returning\n");
786 (
success) ? printf(
"success\n") : printf(
"fail\n");
805 static void init(l2str *l2rec) {
808 filehandle *
l1file = l2rec->l1rec->l1file;
810 printf(
"\nUsing NIWA / UoP / Moore IOP algorithm.\n");
813 printf(
"\nERROR: NIWA-IOP: failed to load look-up tables.\n");
817 printf(
"loaded work table OK\n");
820 switch (
l1file->sensorID) {
823 band_map = seawifs_map;
828 band_map = modis_map;
831 printf(
"\nERROR: NIWA-IOP: The NIWA IOP algorithm requires SeaWiFS or MODIS LAC input data.\n");
832 printf(
" [sensor ID = %d]\n",
l1file->sensorID);
837 for (iw = 0; iw <
VBANDS; iw++) {
840 bbw[iw] =
l1file->bbw[ib];
846 if (
input->brdf_opt > 0) {
847 printf(
"\nWARNING: NIWA-IOP: brdf correction detected, attempting to reverse (use brdf_opt=0 in future).\n\n");
861 void niwa_iop(l2str *l2rec,
float niwa_a[],
float niwa_bb[],
int16 niwa_iopf[]) {
862 static int first_time = 1;
864 int iw, ib, ip, ibp, badrrs;
868 l1str *
l1rec = l2rec->l1rec;
878 for (ip = 0; ip <
l1rec->npix; ip++) {
882 for (ib = 0; ib <
nbands; ib++) {
883 ibp = ip *
l1file->nbands + ib;
890 if (
l1rec->mask[ip]) {
897 for (iw = 0; iw <
VBANDS; iw++) {
900 ibp = ip *
l1file->nbands + band_map[iw];
903 Rrs[iw] = l2rec->Rrs[ibp];
906 if (
input->brdf_opt > 0) {
907 brdf[iw] = l2rec->brdf[ibp];
908 Rrs[iw] = (brdf[iw] > 0) ?
Rrs[iw] / brdf[iw] : -1;
933 if (!setgeom(theta0Rad, thetaRad, dphiRad)) {
934 printf(
"WARNING: NIWA-IOP: Viewing geometry is out of look-up table bounds for NIWA IOP algorithm.\n");
943 for (iw = 0; iw <
VBANDS; iw++) {
944 ibp = ip *
l1file->nbands + band_map[iw];
945 niwa_a[ibp] =
result.a[iw];
946 niwa_bb[ibp] =
result.bb[iw];
961 for (ip = 0; ip <
l1rec->npix; ip++)
962 if (niwa_iopf[ip] != 0)