35 #define NPAR 3 //Number of free model parameters
36 #define MAXITR 1500 //Maximum number of LM optimisation iterations
37 static int32_t swimScanNum = -1;
38 static int32_t LastRecNum = -1;
41 static int32_t nbandVis;
52 static float *aphstar;
53 static float *adgstar;
54 static float *bbpstar;
61 static const double grd1 = 0.08945;
62 static const double grd2 = 0.1247;
64 static double invCosSolz;
65 static double invCosSenz;
70 static int benthicProportionId;
71 static int benthicROutOfBounds;
72 static int benthicRFileExist;
75 static size_t numBottomTypes;
76 static double upperLat;
77 static double lowerLat;
78 static double deltaLat;
79 static double leftLon;
80 static double rightLon;
81 static double deltaLon;
83 static double* reflectance;
84 static double* benthicRefl;
88 static float taphw[10] = {412.0, 443.0, 469.0, 488.0, 531.0, 551.0, 555.0,
90 static float taphs[10] = {0.840353901, 1.0, 0.821449702, 0.689387045,
91 0.217028284, 0.14646583, 0.134941382, 0.122233711, 0.291530253,
96 static float reflw[10] = {412.0, 443.0, 469.0, 488.0, 531.0, 551.0, 555.0,
98 static float refls[10] = {0.167663599, 0.197465145, 0.224745351, 0.24005827,
99 0.28106442, 0.297352629, 0.30027302, 0.337329977, 0.309064323, 0.310894269};
106 if (
recnum == LastRecNum )
119 if (nc_get_att_double(ncfile, varid,
attrName, &
val) != NC_NOERR) {
121 "-E- %s line %d: could get attribute %s from netCDF File.\n",
134 if (nc_inq_varid(ncfile,
name, &varid) != NC_NOERR) {
135 fprintf(
stderr,
"-E- %s line %d: could not find %s in netCDF File.\n",
136 __FILE__, __LINE__,
name);
147 if (nc_inq_vardimid(ncfile, varid, dimIds) != NC_NOERR) {
148 char name[NC_MAX_NAME];
149 nc_inq_varname(ncfile, varid,
name);
151 "-E- %s line %d: could not find dimension Ids of %s in netCDF File.\n",
152 __FILE__, __LINE__,
name);
163 if (nc_inq_dimlen(ncfile, dimId, &length) != NC_NOERR) {
164 char name[NC_MAX_NAME];
165 nc_inq_dim(ncfile, dimId,
name, &length);
167 "-E- %s line %d: could not get size of dimension \"%s\" in netCDF File.\n",
168 __FILE__, __LINE__,
name);
184 size_t numWavelengths;
185 double firstWavelength;
186 double deltaWavelength;
187 double reflectanceScale;
188 double reflectanceOffset;
191 if (strlen(fileName) != 0) {
193 printf(
"Reading benthic reflectance from: %s \n", fileName);
195 benthicRFileExist = 1;
198 printf(
"-E- No benthic reflectance file supplied: use default benthic albedo spectra \n");
200 benthicRFileExist = 0;
206 if (benthicRFileExist) {
207 if (nc_open(fileName, NC_NOWRITE, &ncfile) != NC_NOERR) {
208 fprintf(
stderr,
"-E- %s line %d: could not open netCDF File \"%s\".\n",
209 __FILE__, __LINE__, fileName);
214 lowerLat =
getAttr(NC_GLOBAL,
"lower_lat");
215 upperLat =
getAttr(NC_GLOBAL,
"upper_lat");
216 leftLon =
getAttr(NC_GLOBAL,
"left_lon");
217 rightLon =
getAttr(NC_GLOBAL,
"right_lon");
220 while (leftLon > 180.0)
222 while (leftLon < -180.0)
224 while (rightLon > 180.0)
226 while (rightLon < -180.0)
228 while (rightLon <= leftLon)
231 firstWavelength =
getAttr(NC_GLOBAL,
"firstWavelength");
232 deltaWavelength =
getAttr(NC_GLOBAL,
"deltaWavelength");
235 if (deltaWavelength <= 0) {
237 "-E- %s line %d: deltaWavelength must be > 0 in netCDF File \"%s\".\n",
238 __FILE__, __LINE__, fileName);
245 reflectanceScale = 1.0 /
getAttr(varid,
"scale_factor");
246 reflectanceOffset =
getAttr(varid,
"add_offset");
254 numBottomTypes * nbandVis *
sizeof (
double),
"reflectance");
270 int firstIndex = round(
271 (
lambda[
band] - 5 - firstWavelength) / deltaWavelength);
274 if (firstIndex >= numWavelengths) {
278 int numIndex = round(11.0 / deltaWavelength);
279 if (firstIndex + numIndex >= numWavelengths) {
280 numIndex = numWavelengths - firstIndex;
285 start[1] = firstIndex;
288 ushort tmpShort[numIndex];
289 if (nc_get_vara_ushort(ncfile, varid,
start,
count,
290 tmpShort) != NC_NOERR) {
292 "-E- %s line %d: could not read values of reflectance in netCDF File \"%s\".\n",
293 __FILE__, __LINE__, fileName);
300 for (
i = 0;
i < numIndex;
i++)
302 reflectance[
bottom * nbandVis +
band] = sum / numIndex
303 * reflectanceScale + reflectanceOffset;
309 benthicProportionId =
getVarId(
"benthicProportion");
316 if (tmpSize != numBottomTypes) {
318 "-E- %s line %d: numBottomTypes in benthicProportion is not the same as in reflectance in netCDF File \"%s\".\n",
319 __FILE__, __LINE__, fileName);
323 deltaLat = (upperLat - lowerLat) / numLat;
324 deltaLon = (rightLon - leftLon) / numLon;
335 static int32_t refln = -1;
340 for (refln = 0; refln < nbandVis; refln++) {
341 if (reflw[refln] < 0) {
369 if (lat < lowerLat || lat > upperLat) {
374 if (lon < leftLon || lon > rightLon) {
380 if (latFlag || lonFlag) {
382 benthicROutOfBounds = 1;
393 benthicROutOfBounds = 0;
397 latIndex = (
lat - lowerLat) / deltaLat;
398 lonIndex = (
lon - leftLon) / deltaLon;
407 count[2] = numBottomTypes;
409 uint8_t benthicPercent[numBottomTypes];
410 if (nc_get_vara_uchar(ncfile, benthicProportionId,
start,
count,
411 benthicPercent) != NC_NOERR) {
413 "-E- %s line %d: could not read values from benthicProportion in netCDF File.\n",
425 benthicRefl[
band] = sum;
433 void swim_func(
double *initialParams,
double *rrsTotal,
int numParams,
434 int numBands,
void* dataPtr) {
451 for (iw = 0; iw < numBands; iw++) {
454 ac = aw[iw] + initialParams[0] * aphstar[iw]
455 + initialParams[1] * adgstar[iw];
456 bb = bbw[iw] + initialParams[2] * bbpstar[iw];
464 duC = 1.03 * pow((1 + 2.48 *
u), 0.5);
465 duB = 1.04 * pow((1.54 + 5.4 *
u), 0.5);
468 rrsDeep = grd1 *
u + grd2 * pow(
u, 2);
475 * (invCosSolz + (duC * invCosSenz))));
478 rrsBenthos = (benthicRefl[iw] /
M_PI)
479 * exp(-1.0 * kappa * depth * (invCosSolz + (duB * invCosSenz)));
481 rrsTotal[iw] = rrsColumn + rrsBenthos;
493 static int32_t taphn = -1;
496 static float adg_s = -1;
497 static float bbp_s = -1;
503 l1str *
l1rec = l2rec->l1rec;
506 double rrs_s[
l1rec->l1file->nbands];
508 double fitParams[
NPAR];
509 double opts[LM_OPTS_SZ];
510 double info[LM_INFO_SZ];
520 if (swimScanNum == -1) {
554 l1rec->npix * nbandVis * sizeof (
double),
"benthicRefl");
567 for (taphn = 0; taphn < nbandVis; taphn++)
568 if (taphw[taphn] < 0)
572 for (iw = 0; iw < nbandVis; iw++) {
580 adgstar[iw] = exp(-adg_s * (
lambda[iw] - 443.0));
583 bbpstar[iw] = pow((443.0 /
lambda[iw]), bbp_s);
597 swimScanNum =
l1rec->iscan;
605 for (iw = 0; iw < nbandVis; iw++) {
611 iter[
i * nbandVis + iw] = 0;
618 if (
l1rec->mask[
i] == 0) {
621 double solzRad = (
l1rec->solz[
i] *
M_PI) / 180.0;
622 double senzRad = (
l1rec->senz[
i] *
M_PI) / 180.0;
623 invCosSolz = 1.0 / cos(solzRad);
624 invCosSenz = 1.0 / cos(senzRad);
626 depth = 0 -
l1rec->dem[
i];
628 for (iw = 0; iw < nbandVis; iw++) {
632 rrs_s[iw] =
Rrs / (0.52 + 1.7 *
Rrs);
633 if (rrs_s[iw] >= 0.0)
646 if (!benthicRFileExist) {
648 if (defaultRefl < 0) {
674 fitParams[2] = 0.001;
685 double lowerBounds[
NPAR] = {-0.0003755, -0.0003755, -0.0001195625};
686 double upperBounds[
NPAR] = {5.0, 5.0, 5.0};
694 statusLM = dlevmar_bc_dif(
swim_func, fitParams, rrs_s, m, n,
710 aph443 = fitParams[0];
711 adg443 = fitParams[1];
712 bbp443 = fitParams[2];
715 for (iw = 0; iw < nbandVis; iw++) {
720 aph[
i * nbandVis + iw] = aph443 * aphstar[iw];
721 adg[
i * nbandVis + iw] = adg443 * adgstar[iw];
722 bbp[
i * nbandVis + iw] = bbp443 * bbpstar[iw];
723 atot[
i * nbandVis + iw] = aw[iw] + aph443 * aphstar[iw]
724 + adg443 * adgstar[iw];
725 bbtot[
i * nbandVis + iw] = bbw[iw] + bbp443 * bbpstar[iw];
733 LastRecNum =
l1rec->iscan;
741 void get_swim(l2str *l2rec, l2prodstr *
p,
float prod[]) {
744 l1str *
l1rec = l2rec->l1rec;
750 int bandNum =
p->prod_ix;
752 printf(
"-E- %s line %d : prod_ix must be positive, prod_ix=%d\n",
753 __FILE__, __LINE__,
p->prod_ix);
756 if (bandNum >= nbandVis) {
758 "-E- %s line %d : prod_ix must be less than numBands=%d, prod_ix=%d\n",
759 __FILE__, __LINE__, nbandVis,
p->prod_ix);
763 for (ip = 0; ip < l2rec->l1rec->npix; ip++) {
768 prod[ip] = atot[ip * nbandVis + bandNum];
772 prod[ip] = bbtot[ip * nbandVis + bandNum];
776 prod[ip] = adg[ip * nbandVis + bandNum];
780 prod[ip] = aph[ip * nbandVis + bandNum];
784 prod[ip] = bbp[ip * nbandVis + bandNum];
788 printf(
"-E- %s line %d : erroneous product ID %d passed to swim.\n",
789 __FILE__, __LINE__,
p->cat_ix);
802 l1str *
l1rec = l2rec->l1rec;
808 for (ip = 0; ip <
l1rec->npix; ip++) {
809 for (ib = 0; ib < nbandVis; ib++) {
810 l2rec->a[ip *
l1rec->l1file->nbands + ib] = atot[ip * nbandVis + ib];
811 l2rec->bb[ip *
l1rec->l1file->nbands + ib] = bbtot[ip * nbandVis + ib];