51 #define WESTBERRY2013 2
59 #include <gsl/gsl_fit.h>
63 static int32_t nbandVis;
72 static int bandNum550;
73 static int limitVisFlag;
77 static float nWater = 1.344;
88 static float *aphStar;
89 static float *aphStarR;
92 static float *kappaSen;
93 static float *kappaRam;
101 static float *aph1Sen;
102 static float *aph2Sen;
103 static float *aph1Ram;
104 static float *aph2Ram;
111 static float *t_sol_ram;
115 static float *ramLam;
116 static float *ramBandW;
119 static float *f0BarRam;
120 static float *rayRam;
123 static float *oxyRam;
124 static float *no2Ram;
126 static float *Rrs_ram;
130 static float *alphaCor;
131 static float *betaCor0;
132 static float *betaCor1;
135 static float lamCor1[6] = {412.0, 443.0, 488.0, 531.0, 551.0, 667.0};
136 static float alpha[6] = {0.003, 0.004, 0.011, 0.015, 0.017, 0.018};
137 static float beta0[6] = {0.014, 0.015, 0.010, 0.010, 0.010, 0.010};
138 static float beta1[6] = {-0.022, -0.023, -0.051, -0.070, -0.080, -0.081};
152 if (nc_inq_varid(grpid, varName, &varid) != NC_NOERR) {
153 fprintf(
stderr,
"-E- %s line %d: could not find netCDF variable \"%s\" in netCDF File.\n",
154 __FILE__, __LINE__, varName);
159 if (nc_inq_dimid(grpid,varName, &dimid) != NC_NOERR ) {
160 fprintf(
stderr,
"-E- %s line %d: could not find %s in netCDF File.\n",
161 __FILE__, __LINE__, varName);
165 if (nc_inq_dimlen(grpid, dimid, &varLen) != NC_NOERR ) {
166 fprintf(
stderr,
"-E- %s line %d: could not find netCDF variable dimensions in netCDF File.\n",
173 if (varLen != nbandVis && limitVisFlag!=1) {
174 fprintf(
stderr,
"-E- %s line %d: number of Raman coefficients %ld does not equal sensors visible"
176 __FILE__, __LINE__,varLen,nbandVis);
181 if (nc_get_var_float (grpid, varid, variable) != NC_NOERR ) {
182 fprintf(
stderr,
"-E- %s line %d: could not read netCDF variable %s in netCDF File.\n",
183 __FILE__, __LINE__,varName);
200 bbwR = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"bbwR");
201 aphStar = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"aphStar");
202 aphStarR = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"aphStarR");
203 bbtot = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"bbtot");
204 atot = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"atot");
205 bbtotR = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"bbtotR");
206 atotR = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"atotR");
208 kdSen = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"kdSen");
209 kdRam = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"kdRam");
210 kappaSen = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"kappaSen");
211 kappaRam = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"kappaRam");
213 betaCor0 = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"betaCor0");
214 betaCor1 = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"betaCor1");
215 alphaCor = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"alphaCor");
217 eDRam = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"eDRam");
218 eDSen = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"eDSen");
220 t_sol_ram = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"t_sol_ram");
223 l2rec->l1rec->l1file->nbands * sizeof (
float),
"Rrs_ram");
225 ramLam = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"ramLam");
226 ramBandW = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"ramBandW");
227 bRex = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"bRex");
228 f0BarRam = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"foBarRam");
229 rayRam = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"rayRam");
230 ozRam = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"ozRam");
231 wvRam = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"wvRam");
232 oxyRam = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"oxyRam");
233 no2Ram = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"no2Ram");
234 aph1Ram = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"aph1Ram");
235 aph2Ram = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"aph2Ram");
237 aph1Sen = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"aph1Sen");
238 aph2Sen = (
float*)
allocateMemory(nbandVis *
sizeof (
float),
"aph2Sen");
251 if ((filedir = getenv(
"OCDATAROOT")) ==
NULL) {
252 printf(
"-E- %s: OCDATAROOT env variable undefined.\n", __FILE__);
256 filehandle *
l1file = l2rec->l1rec->l1file;
272 printf(
"Loading Raman coefficients from: %s.\n",
filename);
277 if (nc_open(
filename, NC_NOWRITE, &ncid) != NC_NOERR) {
278 fprintf(
stderr,
"-E- %s line %d: could not open netCDF File \"%s\".\n",
284 if (nc_inq_grp_ncid(ncid,
"raman_coeffs", &grpid) != NC_NOERR) {
285 fprintf(
stderr,
"-E- %s line %d: could not find netCDF group \"raman_coeffs\".\n",
303 if (nc_inq_grp_ncid(ncid,
"sensor_coeffs", &grpid) != NC_NOERR) {
304 fprintf(
stderr,
"-E- %s line %d: could not find netCDF group \"sensor_coeffs\".\n",
313 if (nc_close(ncid) != NC_NOERR){
314 fprintf(
stderr,
"-E- %s line %d: could not close netCDF \"%s\".\n",
333 aphStar443 = aph1Sen[idx443] * pow(l2rec->chl[ip], (aph2Sen[idx443]));
337 for (iw = 0; iw < nbandVis; iw++) {
338 aphStar[iw] = (aph1Sen[iw] * pow(l2rec->chl[ip], (aph2Sen[iw])))
340 aphStarR[iw] = (aph1Ram[iw] * pow(l2rec->chl[ip], (aph2Ram[iw])))
346 aphM = (aphStar[idx443] - aphStar[idx412]) / (
lambda[idx443] -
lambda[idx412]);
347 aphC = aphStar[idx443] - aphM *
lambda[idx443];
350 for (iw = 0; iw < nbandVis; iw++) {
351 if (ramLam[iw] <= 400) {
352 aphStarR[iw] = (aphM * ramLam[iw] + aphC);
367 double logTsol[nbandVis];
368 double waveRatio[nbandVis];
370 double c0, c1, cov00, cov01, cov11,
sumsq;
371 int nbands = l2rec->l1rec->l1file->nbands;
374 for (iw = 0; iw < nbandVis; iw++) {
375 logTsol[iw] = log(l2rec->l1rec->t_sol[ip *
nbands + iw] / l2rec->l1rec->t_sol[ip *
nbands + idx488]);
380 gsl_fit_linear(waveRatio, 1, logTsol, 1, nbandVis, &c0, &c1, &cov00, &cov01, &cov11, &
sumsq);
384 for (iw = 0; iw < nbandVis; iw++) {
385 t_sol_ram[iw] = l2rec->l1rec->t_sol[ip *
nbands + idx488] * pow((ramLam[iw] /
lambda[idx488]), c1);
398 float rat, zeta, xi, term1, term2;
400 float rrs_a[nbandVis];
401 float rrs_s[nbandVis];
408 float acoefs[3] = {-1.146, -1.366, -0.469};
411 for (iw = 0; iw < nbandVis; iw++) {
412 rrs_a[iw] = l2rec->Rrs[ip * l2rec->l1rec->l1file->nbands + iw];
413 rrs_s[iw] = rrs_a[iw] / (0.52 + 1.7 * rrs_a[iw]);
417 if (rrs_a[idx550] <= 0.0)
418 rrs_a[idx550] = 0.001;
421 if ((rrs_a[idx670] > 20.0 * pow(rrs_a[idx550], 1.5)) || (rrs_a[idx670] < 0.9 * pow(rrs_a[idx550], 1.7))) {
422 rrs_a[idx670] = 1.27 * pow(rrs_a[idx550], 1.47) + 0.00018 * pow(rrs_a[idx488] / rrs_a[idx550], -3.19);
426 for (iw = 0; iw < nbandVis; iw++) {
427 u[iw] = (sqrt(g0 * g0 + 4.0 * g1 * rrs_s[iw]) - g0) / (2.0 * g1);
432 if (rrs_s[idx670] >= 0.0015) {
433 aref = aw[idx670] + 0.07 * pow(rrs_a[idx670] / rrs_s[idx443], 1.1);
437 numer = rrs_a[idx443] + rrs_a[idx488];
438 denom = rrs_a[idx550] + 5 * rrs_a[idx670]*(rrs_a[idx670] / rrs_a[idx488]);
440 rho = acoefs[0] + acoefs[1] * rho + acoefs[2] * rho*rho;
441 aref = aw[idx550] + pow(10.0, rho);
446 bbpref = ((
u[idxref] * aref) / (1.0 -
u[idxref])) - bbw[idxref];
449 rat = rrs_s[idx443] / rrs_s[idx550];
450 Ybbp = 2.0 * (1.0 - 1.2 * exp(-0.9 * rat));
454 bbp443 = bbpref * pow((
lambda[idxref] /
lambda[idx443]), Ybbp);
457 for (iw = 0; iw < nbandVis; iw++) {
458 bbt[iw] = bbpref * pow((
lambda[idxref] /
lambda[iw]), Ybbp) + bbw[iw];
462 for (iw = 0; iw < nbandVis; iw++) {
463 at[iw] = ((1.0 -
u[iw]) * bbt[iw]) /
u[iw];
468 Sdg = 0.015 + 0.002 / (0.6 + rrs_s[idx443] / rrs_s[idxref]);
472 zeta = 0.74 + 0.2 / (0.8 + rrs_s[idx443] / rrs_s[idxref]);
474 term1 = (at[idx412] - zeta * at[idx443]) - (aw[idx412] - zeta * aw[idx443]);
476 adg443 = term1 / term2;
479 aph443 = at[idx443] - adg443 - aw[idx443];
489 float bbpR, adgR, aphR;
493 for (iw = 0; iw < nbandVis; iw++) {
496 bbpR = bbp443 * pow((
lambda[idx443] / ramLam[iw]), Ybbp);
497 adgR = adg443 * exp(-Sdg * (ramLam[iw] -
lambda[idx443]));
498 aphR = aph443 * aphStarR[iw];
501 bbp = bbp443 * pow((
lambda[idx443] /
lambda[iw]), Ybbp);
502 adg = adg443 * exp(-Sdg * (
lambda[iw] -
lambda[idx443]));
503 aph = aph443 * aphStar[iw];
506 atotR[iw] = awR[iw] + adgR + aphR;
507 bbtotR[iw] = bbwR[iw] + bbpR;
510 atot[iw] = aw[iw] + adg + aph;
511 bbtot[iw] = bbw[iw] + bbp;
522 float solzRad, solzRadSw, muD, muU;
525 solzRad = l2rec->l1rec->solz[ip]*(
M_PI / 180.0);
526 solzRadSw = asin(sin(solzRad) / nWater);
529 muD = cos(solzRadSw);
532 for (iw = 0; iw < nbandVis; iw++) {
535 kdSen[iw] = (atot[iw] + bbtot[iw]) / muD;
536 kdRam[iw] = (atotR[iw] + bbtotR[iw]) / muD;
538 kappaSen[iw] = (atot[iw] + bbtot[iw]) / muU;
539 kappaRam[iw] = (atotR[iw] + bbtotR[iw]) / muU;
552 l1str *
l1rec = l2rec->l1rec;
555 float p0 = 29.92 * 33.8639;
556 float radCon =
M_PI / 180.0;
557 float ws = l2rec->l1rec->ws[ip];
558 float nw2= pow(nWater,2.);
561 float sin2Solz, rf0, a0,a1,a2,a3, rho_fres;
562 float solz, solzRad, cosSolz, mPres, mAtm, f0Ex;
563 float th2oEx, to2Ex, tno2Ex, to3Ex, tgEx;
564 float a_285R, a_225R,tau_to200R;
565 float no2_tr200R, eDRam_above;
574 solzRad =
l1rec->solz[ip]*radCon;
577 cosSolz = cos(solzRad);
580 sin2Solz = pow(sin(solzRad),2.);
585 rf0 = 0.5*( pow( (cosSolz - pow(nw2 - sin2Solz ,0.5))/(cosSolz + pow(nw2 + sin2Solz ,0.5)) ,2.)
586 + pow( (nw2*cosSolz - pow(nw2 - sin2Solz ,0.5))/(nw2*cosSolz + pow(nw2 + sin2Solz ,0.5)) ,2.) );
589 a0 = 0.001*(6.944831 - 1.912076*ws + 0.03654833*ws*ws);
590 a1 = 0.7431368 + 0.0679787*ws - 0.0007171*ws*ws;
591 a2 = 0.5650262 + 0.0061502*ws - 0.0239810*ws*ws + 0.0010695*ws*ws*ws;
592 a3 = -0.4128083 - 0.1271037*ws + 0.0283907*ws*ws - 0.0011706*ws*ws*ws;
595 rho_fres = a0 + rf0*(a1 + rf0*(a2 + a3*rf0));
602 mAtm = 1.0 / (cosSolz + 0.50572 * pow((86.07995 -
solz), -1.6364));
608 mPres = mAtm * (
l1rec->pr[ip] / p0);
612 if (l2rec->l1rec->no2_tropo[ip] > 0.0)
614 no2_tr200R =
l1rec->no2_frac[ip] *
l1rec->no2_tropo[ip];
620 for (iw = 0; iw < nbandVis; iw++) {
622 ipb = ip*
l1rec->l1file->nbands + iw;
625 f0Ex = f0BarRam[iw] *
l1rec->fsol;
628 to3Ex = exp(-(ozRam[iw] *
l1rec->oz[ip] /
l1rec->csolz[ip]) );
631 a_285R = no2Ram[iw] * (1.0 - 0.003 * (285.0 - 294.0));
632 a_225R = no2Ram[iw] * (1.0 - 0.003 * (225.0 - 294.0));
633 tau_to200R = a_285R * no2_tr200R + a_225R *
l1rec->no2_strat[ip];
634 tno2Ex = exp(-(tau_to200R /
l1rec->csolz[ip]) );
637 th2oEx = exp((-0.2385 * wvRam[iw] *
l1rec->wv[ip] * mAtm) /
638 (pow((1.0 + 20.07 * wvRam[iw] *
l1rec->wv[ip] * mAtm), 0.45)));
642 to2Ex = exp((-1.41 * oxyRam[iw] * mPres) / (pow((1.0 + 118.3 * oxyRam[iw] * mPres), 0.45)));
644 tgEx = to3Ex*tno2Ex*th2oEx*to2Ex;
647 eDRam_above = f0Ex * tgEx * t_sol_ram[iw]* cos(solzRad) * 10.0;
648 eDSen[iw] =
l1rec->Fo[iw] *
l1rec->tg_sol[ipb] *
l1rec->t_sol[ipb]* cos(solzRad) * 10.0;
650 eDRam[iw] = 1.03*(1.0 - rho_fres)*eDRam_above;
663 float Rrs443, Rrs550;
666 int nbands = l2rec->l1rec->l1file->nbands;
668 if (l2rec->l1rec->mask[ip]) {
673 Rrs443 = l2rec->Rrs[ip *
nbands + idx443];
674 Rrs550 = l2rec->Rrs[ip *
nbands + idx550];
677 for (iw = 0; iw < nbandVis; iw++) {
682 rFactor = alphaCor[iw] * Rrs443 / Rrs550 + betaCor0[iw] * pow(Rrs550, betaCor1[iw]);
684 rrs_a = l2rec->Rrs[ip *
nbands + iw];
686 Rrs_ram[ip *
nbands + iw] = rrs_a - rrs_a / (1.0 + rFactor);
689 Rrs_ram[ip *
nbands + iw] = 0.0;
709 int nbands = l2rec->l1rec->l1file->nbands;
710 float term0, term1, numer1, denom1;
715 if (l2rec->l1rec->mask[ip]) {
736 term0 = 1.0 / (4.0 *
M_PI * nWater * nWater);
740 for (iw = 0; iw < nbandVis; iw++) {
746 numer1 = bRex[iw] * eDRam[iw];
747 denom1 = (kdRam[iw]+kappaSen[iw])*eDSen[iw];
748 term1 = numer1 / denom1;
751 Rrs_rc = term0 * term1;
754 Rrs_ram[ip *
nbands + iw] = Rrs_rc;
757 Rrs_ram[ip *
nbands + iw] = 0.0;
772 int nbands = l2rec->l1rec->l1file->nbands;
776 if (l2rec->l1rec->mask[ip]) {
794 for (iw = 0; iw < nbandVis; iw++) {
798 Rrs_rc = 0.072 * (bRex[iw] * eDRam[iw]) / ((2.0 * atot[iw] + atotR[iw]) * eDSen[iw]);
801 Rrs_ram[ip *
nbands + iw] = Rrs_rc;
804 Rrs_ram[ip *
nbands + iw] = 0.0;
818 static int firstCall = 1;
819 static int sensorSupported;
829 switch (l2rec->l1rec->l1file->sensorID){
852 if (
input->raman_opt == 0) {
855 if (!sensorSupported) {
856 printf(
"Raman correction unsupported for this sensor. \n");
859 printf(
"No Raman scattering correction calculated for Rrs. \n");
863 }
else if (
input->raman_opt > 0 &&
input->raman_opt <= 3) {
866 printf(
"Compute Raman scattering correction #%d. \n",
input->raman_opt);
871 printf(
"-E- %s line %d : '%d' is not a valid Raman correction option.\n",
872 __FILE__, __LINE__,
input->raman_opt);
881 if (sensorSupported) {
887 for (iw = 0; iw < nbandVis; iw++) {
890 lambda[iw] = l2rec->l1rec->l1file->fwave[iw];
898 awR[iw] =
aw_spectra(ramLam[iw], ramBandW[iw]);
900 aw[iw] = l2rec->l1rec->l1file->aw[iw];
901 bbw[iw] = l2rec->l1rec->l1file->bbw[iw];
915 for (iw = 0; iw < nbandVis; iw++) {
930 for (iw = 0; iw < l2rec->l1rec->l1file->nbands; iw++) {
931 Rrs_ram[ip * l2rec->l1rec->l1file->nbands + iw] = 0.0;
948 l2rec->Rrs_raman = Rrs_ram;