ocssw  1.0
/disk01/web/ocssw/build/src/l2gen/qaa.c (r8106/r7411)
Go to the documentation of this file.
00001 
00090 #include <stdlib.h>
00091 #include <math.h>
00092 #include <stdarg.h>
00093 #include <assert.h>
00094 #include "qaa.h"
00095 
00096 static int idx410 = -1;
00097 static int idx440 = -1;
00098 static int idx490 = -1;
00099 static int idx555 = -1;
00100 static int idx670 = -1;
00101 static int initialized  = 0;
00102 static int aph_check = 1;
00103 static double S = 0.015;
00104 static double chl = -1;
00105 static double acoefs[3];
00106 
00112 int
00113 qaa_is_initialized( void )
00114 {
00115     return initialized;
00116 }
00117 
00132 int
00133 qaa_init( int i410, int i440, int i490, int i555, int i670 )
00134 {
00135     idx410 = i410;
00136     idx440 = i440;
00137     idx490 = i490;
00138     idx555 = i555;
00139     idx670 = i670;
00140 
00141 //  SeaWiFS coefficients
00142 
00143     acoefs[0] = -1.146;
00144     acoefs[1] = -1.366;
00145     acoefs[2] = -0.469;
00146 
00147     initialized = 1;
00148 
00149     return 0;
00150 }
00151 
00164 int
00165 qaa_set_param( int param, ... )
00166 {
00167     va_list  ap;
00168     va_start( ap, param );
00169     switch (param) {
00170     case QAA_S_PARAM:
00171         S = va_arg(ap,double);
00172         break;
00173     case QAA_CHL_PARAM:
00174         chl = va_arg(ap,double);
00175         break;
00176     case QAA_COEFS_PARAM:
00177         acoefs[0] = va_arg(ap,double);
00178         acoefs[1] = va_arg(ap,double);
00179         acoefs[2] = va_arg(ap,double);
00180         break;
00181     case QAA_APH_CHECK:
00182         aph_check = va_arg(ap,int);
00183         break;
00184     }
00185     va_end(ap);
00186     return 0;
00187 }
00188 
00205 int
00206 qaa_v6( int nbands, double *wavel, double *Rrs, double *aw, double *bbw,
00207          double *rrs, double *u, double *a, double *bb, unsigned char *flags  )
00208 {
00209 
00210     const double g0 = 0.08945;
00211     const double g1 = 0.1247;
00212 
00213     int     i, idxref;
00214 
00215     double  rat, aref;
00216     double  bbpref;
00217     double  Y;
00218     double  rho, numer, denom;
00219 
00220     assert( idx440 >= 0 );
00221     assert( idx490 >= 0 );
00222     assert( idx555 >= 0 );
00223     assert( nbands >= 0 );
00224 
00225     /* pre-test 670 */
00226     if ( (Rrs[idx670] > 20.0*pow(Rrs[idx555],1.5)) ||
00227          (Rrs[idx670] < 0.9*pow(Rrs[idx555],1.7)) ) {
00228         Rrs[idx670] = 1.27*pow(Rrs[idx555],1.47) + 0.00018*pow(Rrs[idx490]/Rrs[idx555],-3.19);
00229         if ( flags ) *flags |= 0x02;
00230     }
00231 
00232     /* Step 0 */
00233     for ( i = 0; i < nbands; i++ ) {
00234         rrs[i] = Rrs[i] / (0.52 + 1.7 * Rrs[i] );
00235         if ( Rrs[i] < 0.0 )
00236             if ( flags ) *flags |= 0x01;
00237     }
00238 
00239     /* Step 1 */
00240     for ( i = 0; i < nbands; i++ )
00241         u[i]   = (sqrt(g0*g0 + 4.0*g1*rrs[i]) - g0) / (2.0 * g1);
00242 
00243     /* Step 2 */
00244     if ( Rrs[idx670] >= 0.0015 ) {
00245         aref    = aw[idx670] + 0.07*pow(Rrs[idx670]/Rrs[idx440],1.1);
00246         idxref  = idx670;
00247     } else {
00248         numer   = Rrs[idx440] + Rrs[idx490];
00249         denom   = Rrs[idx555] + 5*Rrs[idx670]*(Rrs[idx670]/Rrs[idx490]);
00250         rho     = log10( numer / denom );
00251         rho     = acoefs[0] + acoefs[1]*rho + acoefs[2]*rho*rho;
00252         aref    = aw[idx555] + pow(10.0,rho);
00253         idxref  = idx555;
00254     }
00255 
00256     /* Step 3 */
00257     bbpref = ((u[idxref] * aref) / (1.0 - u[idxref])) - bbw[idxref];
00258 
00259     /* Step 4 */
00260     rat    = rrs[idx440] / rrs[idx555];
00261     Y = 2.0 * (1.0 - 1.2 * exp( -0.9*rat) );
00262 
00263     /* Step 5 */
00264     for ( i = 0; i < nbands; i++ ) {
00265         bb[i] = bbpref * pow((wavel[idxref]/wavel[i]),Y) + bbw[i];
00266         if ( bb[i] < 0.0 )
00267             if ( flags ) *flags |= 0x04;
00268     }
00269 
00270     /* Step 6 */
00271     for ( i = 0; i < nbands; i++ ) {
00272         a[i] = ((1.0 - u[i]) * bb[i]) / u[i];
00273         if ( a[i] < 0.0 )
00274             if ( flags ) *flags |= 0x08;
00275     }
00276 
00277     return 0;
00278 }
00279 
00285 int
00286 qaaf_v6( int nbands, float *wavel, float *Rrs, float *aw, float *bbw,
00287          float *rrs, float *u, float *a, float *bb,
00288          unsigned char *flags  )
00289 {
00290 
00291     const float g0 = 0.08945;
00292     const float g1 = 0.1247;
00293 
00294     float   rho, numer, denom;
00295 
00296     float   rat, aref;
00297     float   bbpref;
00298     float   Y;
00299 
00300     int     i, idxref;
00301 
00302     assert( idx440 >= 0 );
00303     assert( idx490 >= 0 );
00304     assert( idx555 >= 0 );
00305     assert( idx670 >= 0 );
00306     assert( nbands >= 0 );
00307 
00308     /* Test for bad Rrs at idx555 */
00309     if ( Rrs[idx555] <= 0.0 )
00310         Rrs[idx555] = 0.001;
00311 
00312     /* pre-test 670 */
00313     if ( (Rrs[idx670] > 20.0*powf(Rrs[idx555],1.5)) ||
00314          (Rrs[idx670] < 0.9*powf(Rrs[idx555],1.7)) ) {
00315         Rrs[idx670] = 1.27*powf(Rrs[idx555],1.47) + 0.00018*powf(Rrs[idx490]/Rrs[idx555],-3.19);
00316         if ( flags ) *flags |= 0x02;
00317     }
00318 
00319     /* Step 0 */
00320     for ( i = 0; i < nbands; i++ ) {
00321         rrs[i] = Rrs[i] / (0.52 + 1.7 * Rrs[i] );
00322         if ( Rrs[i] < 0.0 )
00323             if ( flags ) *flags |= 0x01;
00324     }
00325 
00326     /* Step 1 */
00327     for ( i = 0; i < nbands; i++ )
00328         u[i]   = (sqrt(g0*g0 + 4.0*g1*rrs[i]) - g0) / (2.0 * g1);
00329 
00330     /* Step 2 */
00331     if ( Rrs[idx670] >= 0.0015 ) {
00332         aref   = aw[idx670] + 0.07*pow(Rrs[idx670]/Rrs[idx440],1.1);
00333         idxref = idx670;
00334     } else {
00335         numer  = Rrs[idx440] + Rrs[idx490];
00336         denom  = Rrs[idx555] + 5*Rrs[idx670]*(Rrs[idx670]/Rrs[idx490]);
00337         rho    = log10f( numer / denom );
00338         rho    = acoefs[0] + acoefs[1]*rho + acoefs[2]*rho*rho;
00339         aref   = aw[idx555] + powf(10.0,rho);
00340         idxref = idx555;
00341     }
00342 
00343     /* Step 3 */
00344     bbpref = ((u[idxref] * aref) / (1.0 - u[idxref])) - bbw[idxref];
00345 
00346     /* Step 4 */
00347     rat   = rrs[idx440] / rrs[idx555];
00348     Y = 2.0 * (1.0 - 1.2 * expf( -0.9*rat) );
00349 
00350     /* Step 5 */
00351     for ( i = 0; i < nbands; i++ ) {
00352         bb[i] = bbpref * pow((wavel[idxref]/wavel[i]),Y) + bbw[i];
00353         if ( bb[i] < 0.0 )
00354             if ( flags ) *flags |= 0x04;
00355     }
00356 
00357     /* Step 6 */
00358     for ( i = 0; i < nbands; i++ ) {
00359         a[i] = ((1.0 - u[i]) * bb[i]) / u[i];
00360         if ( a[i] < 0.0 )
00361             if ( flags ) *flags |= 0x08;
00362     }
00363 
00364     return 0;
00365 }
00366 
00387 int
00388 qaa_decomp( int nbands, double *wavel, double *rrs, double *a, double *aw,
00389             double *adg, double *aph, unsigned char *flags )
00390 {
00391     int     i;
00392     double  symbol, x1, x2;
00393     double  zeta, denom, dif1, dif2;
00394     double  rat, ag440;
00395     double  Sr;
00396 
00397     assert( idx410 >= 0 );
00398     assert( idx440 >= 0 );
00399     assert( idx555 >= 0 );
00400     assert( nbands >= 0 );
00401 
00402     /* step 7 */
00403     rat    = rrs[idx440] / rrs[idx555];
00404     symbol = 0.74 + ( 0.2 / ( 0.8 + rat ) );
00405 
00406     /* step 8 */
00407     Sr   = S + 0.002 / ( 0.6 + rat );
00408     zeta = exp( Sr * (wavel[idx440] - wavel[idx410]) );
00409 
00410     /* step 9 */
00411     denom = zeta - symbol;
00412     dif1  = a[idx410]  - symbol * a[idx440];
00413     dif2  = aw[idx410] - symbol * aw[idx440];
00414     ag440 = (dif1 - dif2) / denom;
00415 
00416     for ( i = 0; i < nbands; i++ ) {
00417         adg[i] = ag440 * exp( Sr * (wavel[idx440] - wavel[i]));
00418     aph[i] = a[i] - adg[i] - aw[i];
00419     }
00420 
00421     /* check aph443 range */
00422 
00423     if ( aph_check ) {
00424 
00425     x1 = aph[idx440] / a[idx440];
00426     if ( x1 < 0.15 || x1 > 0.6 ) {
00427 
00428         if ( flags ) *flags |= 0x10;
00429 
00430         x2 = -0.8 + 1.4 * (a[idx440] - aw[idx440])/(a[idx410] - aw[idx410]);
00431         if ( x2 < 0.15 ) {
00432         x2 = 0.15;
00433         if ( flags ) *flags |= 0x20;
00434         }
00435         if ( x2 > 0.6 ) {
00436         x2 = 0.6;
00437         if ( flags ) *flags |= 0x40;
00438         }
00439 
00440         aph[idx440] = a[idx440] * x2;
00441         ag440 = a[idx440] - aph[idx440] - aw[idx440];
00442 
00443         for ( i = 0; i < nbands; i++ ) {
00444             adg[i] = ag440 * exp( Sr * (wavel[idx440] - wavel[i]));
00445             aph[i] = a[i] - adg[i] - aw[i];
00446         }
00447 
00448         }
00449     }
00450     return 0;
00451 }
00452 
00458 int
00459 qaaf_decomp( int nbands, float *wavel, float *rrs, float *a, float *aw,
00460              float *adg, float *aph, unsigned char *flags )
00461 {
00462     int    i;
00463     float  symbol, x1, x2;
00464     float  zeta, denom, dif1, dif2;
00465     float  rat, ag440;
00466     float  Sr;
00467 
00468     assert( idx410 >= 0 );
00469     assert( idx440 >= 0 );
00470     assert( idx555 >= 0 );
00471     assert( nbands >= 0 );
00472 
00473     /* step 7 */
00474     rat    = rrs[idx440] / rrs[idx555];
00475     symbol = 0.74 + ( 0.2 / ( 0.8 + rat ) );
00476 
00477     /* step 8 */
00478     Sr   = S + 0.002 / ( 0.6 + rat );
00479     zeta = expf( Sr * (wavel[idx440] - wavel[idx410]) );
00480 
00481     /* step 9 */
00482     denom  = zeta - symbol;
00483     dif1   = a[idx410]  - symbol * a[idx440];
00484     dif2   = aw[idx410] - symbol * aw[idx440];
00485     ag440  = (dif1 - dif2) / denom;
00486 
00487     for ( i = 0; i < nbands; i++ ) {
00488         adg[i] = ag440 * expf( Sr * (wavel[idx440] - wavel[i]));
00489     aph[i] = a[i] - adg[i] - aw[i];
00490     }
00491 
00492     /* check aph443 range */
00493 
00494     if ( aph_check ) {
00495 
00496         x1 = aph[idx440] / a[idx440];
00497         if ( x1 < 0.15 || x1 > 0.6 ) {
00498 
00499             if ( flags ) *flags |= 0x10;
00500 
00501             x2 = -0.8 + 1.4 * (a[idx440] - aw[idx440])/(a[idx410] - aw[idx410]);
00502             if ( x2 < 0.15 ) {
00503                 x2 = 0.15;
00504                 if ( flags ) *flags |= 0x20;
00505             }
00506             if ( x2 > 0.6 ) {
00507                 x2 = 0.6;
00508                 if ( flags ) *flags |= 0x40;
00509             }
00510 
00511             aph[idx440] = a[idx440] * x2;
00512             ag440 = a[idx440] - aph[idx440] - aw[idx440];
00513 
00514             for ( i = 0; i < nbands; i++ ) {
00515                 adg[i] = ag440 * expf( Sr * (wavel[idx440] - wavel[i]));
00516                 aph[i] = a[i] - adg[i] - aw[i];
00517             }
00518 
00519         }
00520 
00521     }
00522 
00523     return 0;
00524 }
00525 
00526 #ifdef TEST_QAA
00527 
00528 #include <stdio.h>
00529 
00530 /*
00531  * to compile:
00532  * cc -o qaa -g -DTEST_QAA -I. qaa.c -lm
00533  * ./qaa
00534  */
00535 
00536 
00537 
00538 static void print_out( int n, float *fwl, float *Rrs, float *rrs, float *u,
00539            float *a, float *aph, float *adg, float *aw, float *bb, float *bbw )
00540 {
00541 
00542     int i;
00543 
00544     printf("lamda ");
00545     for ( i = 0; i < n; i++ )
00546     printf("%9.0f ", fwl[i]);
00547     printf("\n");
00548 
00549     printf("Rrs : ");
00550     for ( i = 0; i < n; i++ )
00551     printf("%9.6f ", Rrs[i]);
00552     printf("\n");
00553 
00554     printf("rrs : ");
00555     for ( i = 0; i < n; i++ )
00556     printf("%9.6f ", rrs[i]);
00557     printf("\n");
00558 
00559     printf("u   : ");
00560     for ( i = 0; i < n; i++ )
00561     printf("%9.6f ", u[i]);
00562     printf("\n");
00563 
00564     printf("a   : ");
00565     for ( i = 0; i < n; i++ )
00566     printf("%9.6f ", a[i]);
00567     printf("\n");
00568 
00569     printf("aph : ");
00570     for ( i = 0; i < n; i++ )
00571     printf("%9.6f ", aph[i]);
00572     printf("\n");
00573 
00574     printf("adg : ");
00575     for ( i = 0; i < n; i++ )
00576     printf("%9.6f ", adg[i]);
00577     printf("\n");
00578 
00579     printf("aw  : ");
00580     for ( i = 0; i < n; i++ )
00581     printf("%9.6f ", aw[i]);
00582     printf("\n");
00583 
00584     printf("bb  : ");
00585     for ( i = 0; i < n; i++ )
00586     printf("%9.6f ", bb[i]);
00587     printf("\n");
00588 
00589     printf("bbw : ");
00590     for ( i = 0; i < n; i++ )
00591     printf("%9.6f ", bbw[i]);
00592     printf("\n");
00593 
00594 }
00595 
00596 int
00597 main( int argc, char *argv[] )
00598 {
00599 
00600     /* the 5th position here will be changed for 640nm later down in code */
00601 
00602 #define NBANDS      6
00603 #define NUM_SPECTRA 24
00604     float Rrs_insitu[NUM_SPECTRA][NBANDS] = {
00605     /*    412       443       490       510       555       670 */
00606         { 0.001919, 0.002297, 0.004420, 0.005547, 0.009138, 0.004110},
00607         { 0.001753, 0.002657, 0.004348, 0.005212, 0.007641, 0.003950},
00608         { 0.003968, 0.003374, 0.002932, 0.002142, 0.001214, 0.000136},
00609         { 0.001332, 0.001414, 0.002116, 0.002464, 0.003891, 0.001669},
00610         { 0.001572, 0.001537, 0.002132, 0.002504, 0.004157, 0.001909},
00611         { 0.004830, 0.004084, 0.003540, 0.002648, 0.001584, 0.000194},
00612         { 0.001145, 0.001457, 0.002501, 0.002945, 0.004180, 0.001524},
00613         { 0.000921, 0.001004, 0.001465, 0.001456, 0.001363, 0.000252},
00614         { 0.003120, 0.003226, 0.003530, 0.002857, 0.001882, 0.000196},
00615         { 0.005170, 0.004682, 0.003794, 0.002535, 0.001343, 0.000131},
00616         { 0.004718, 0.004378, 0.003763, 0.002627, 0.001472, 0.000151},
00617         { 0.003503, 0.003394, 0.003358, 0.002510, 0.001507, 0.000181},
00618         { 0.001005, 0.001131, 0.001879, 0.002219, 0.003316, 0.001100},
00619         { 0.007704, 0.006917, 0.005540, 0.003721, 0.002129, 0.000389},
00620         { 0.003311, 0.003071, 0.002920, 0.002315, 0.001508, 0.000285},
00621         { 0.003476, 0.003285, 0.003073, 0.002347, 0.001436, 0.000200},
00622         { 0.004661, 0.005739, 0.008028, 0.007809, 0.006632, 0.001035},
00623         { 0.004212, 0.004859, 0.006455, 0.006117, 0.004895, 0.000676},
00624         { 0.002090, 0.002280, 0.003091, 0.002780, 0.002177, 0.000444},
00625         { 0.003237, 0.003042, 0.002947, 0.002317, 0.001440, 0.000166},
00626         { 0.003125, 0.003444, 0.004119, 0.003777, 0.002875, 0.000413},
00627         { 0.002637, 0.002896, 0.003477, 0.002987, 0.002085, 0.000251},
00628         { 0.003472, 0.003596, 0.003834, 0.003067, 0.001969, 0.000331},
00629         { 0.004554, 0.003772, 0.002074, 0.002082, 0.001338, 0.000120}
00630     };
00631 
00632     float fwl[NBANDS] ={ 412,      443,      490,      510,      555,       670 };
00633     float aw[NBANDS]  ={ 0.004994, 0.007512, 0.025010, 0.040020, 0.077080, 0.445600 };
00634     float bbw[NBANDS] ={ 0.003271, 0.002421, 0.001568, 0.001339, 0.000939, 0.000426 };
00635 
00636     int   i, j;
00637     float Rrs[NBANDS];
00638     float rrs[NBANDS];
00639     float u[NBANDS];
00640     float a[NBANDS];
00641     float bb[NBANDS];
00642     float aph[NBANDS];
00643     float adg[NBANDS];
00644     unsigned char flags;
00645 
00646     int   idx410 = 0;
00647     int   idx440 = 1;
00648     int   idx490 = 2;
00649     int   idx555 = 4;
00650     int   idx670 = 5;
00651     int   nbands;
00652 
00653     // Ping's bbw using 0.0038 * pow((400.0/lambda),4.32);
00654 //    for ( i = 0; i< NBANDS; i++ )
00655 //        bbw[i] = 0.0038 * pow(400.0/fwl[i],4.32);
00656 
00657     qaa_init( idx410, idx440, idx490, idx555, idx670 );
00658     qaa_set_param( QAA_APH_CHECK, 0 );
00659 
00660     printf("QAA v6\n" );
00661     for ( j = 0; j < NUM_SPECTRA; j++ ) {
00662 
00663     flags  = 0;
00664         nbands = NBANDS;
00665     /* 412 to 670 */
00666     for ( i = 0; i < nbands; i++ )
00667         Rrs[i] = Rrs_insitu[j][i];
00668 
00669     qaaf_v6( nbands, fwl, Rrs, aw, bbw, rrs, u, a, bb, NULL );
00670     qaaf_decomp( nbands, fwl, rrs, a, aw, adg, aph, NULL );
00671 
00672     for ( i = 0; i < 6; i++ )
00673         if ( a[i] < aw[i] )
00674         flags |= 0x08;
00675 
00676     for ( i = 0; i < 6; i++ )
00677         if ( bb[i] < bbw[i] )
00678         flags |= 0x80;
00679 
00680     print_out( nbands, fwl, Rrs, rrs, u, a, aph, adg, aw, bb, bbw );
00681 
00682     if ( flags & 0x10 )
00683         printf("original aph/a ratio was out of range (0.15 to 0.6)\n");
00684     if ( flags & 0x20 )
00685         printf("    and was forced to minimum (0.15)\n");
00686     if ( flags & 0x40 )
00687         printf("    and was forced to maximum (0.6)\n");
00688     printf("\n");
00689     }
00690 
00691     return 0;
00692 }
00693 #endif