/* cc -O corr_refl.c -o corr_refl -I$HDFINC -L$HDFLIB -lmfhdf -ldf -lz -lm -ljpeg */ #include #include #include #include "mfhdf.h" #define MAXNAMELENGTH 200 #define Nbands 7 #define DEG2RAD 0.0174532925199 /* PI/180 */ #define UO3 0.319 #define UH2O 2.93 #define REFLMIN -0.01 #define REFLMAX 1.6 #define ANCPATH "." #define DEMSDSNAME "Elevation" #define REFSDS SOLZ #define MISSING -2 #define MAXSOLZ 86.5 #define MAXAIRMASS 18 #define FILL_INT16 32767 #ifdef LINUX #define logf(x) (float) log((double) x) #define cosf(x) (float) cos((double) x) #define expf(x) (float) exp((double) x) #define sqrtf(x) (float) sqrt((double) x) #endif typedef struct { char *name, *filename; int32 file_id, id, index, num_type, rank, n_attr, Nl, Np, *plane, Nplanes, rowsperscan; int32 start[MAX_VAR_DIMS], edges[MAX_VAR_DIMS], dim_sizes[MAX_VAR_DIMS]; void *data, *fillvalue; float64 factor, offset; } SDS; int getatmvariables(float mus, float muv, float phi, int16 height, char *process, float *sphalb, float *rhoray, float *TtotraytH2O, float *tOG); void chand(float phi, float muv, float mus, float *tau, float *rhoray, float *trup, float *trdown, char *process); float csalbr(float tau); double fintexp1(float tau); double fintexp3(float tau); float correctedrefl(float refl, float TtotraytH2O, float tOG, float rhoray, float sphalb); enum {BAND1, BAND2, BAND3, BAND4, BAND5, BAND6, BAND7, SOLZ, SENZ, SOLA, SENA, LON, LAT, Nitems}; int main(int argc, char *argv[]) { char MOD021KMfile[MAXNAMELENGTH], MOD02HKMfile[MAXNAMELENGTH], MOD02QKMfile[MAXNAMELENGTH], filename[MAXNAMELENGTH]; char *ancpath; SDS sds[Nitems], outsds[Nbands], atmsds, dem, height; int32 MOD02QKMfile_id, MOD02HKMfile_id, MOD021KMfile_id, sd_id, attr_index, count, num_type; int ib, j, iscan, Nscans, irow, jcol, idx, crsidx; char SDSlocatorQKM[Nitems][30] = {"EV_250_RefSB", "EV_250_RefSB", "EV_500_RefSB", "EV_500_RefSB", "EV_500_RefSB", "EV_500_RefSB", "EV_500_RefSB", "SolarZenith", "SensorZenith", "SolarAzimuth", "SensorAzimuth", "Longitude", "Latitude"}; char SDSlocatorHKM[Nitems][30] = {"EV_250_Aggr500_RefSB", "EV_250_Aggr500_RefSB", "EV_500_RefSB", "EV_500_RefSB", "EV_500_RefSB", "EV_500_RefSB", "EV_500_RefSB", "SolarZenith", "SensorZenith", "SolarAzimuth", "SensorAzimuth", "Longitude", "Latitude"}; char SDSlocator1KM[Nitems][30] = {"EV_250_Aggr1km_RefSB", "EV_250_Aggr1km_RefSB", "EV_500_Aggr1km_RefSB", "EV_500_Aggr1km_RefSB", "EV_500_Aggr1km_RefSB", "EV_500_Aggr1km_RefSB", "EV_500_Aggr1km_RefSB", "SolarZenith", "SensorZenith", "SolarAzimuth", "SensorAzimuth", "Longitude", "Latitude"}; char indexlocator[Nitems] = {0, 1, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0}; char numtypelocator[Nitems] = { DFNT_UINT16, DFNT_UINT16, DFNT_UINT16, DFNT_UINT16, DFNT_UINT16, DFNT_UINT16, DFNT_UINT16, DFNT_INT16, DFNT_INT16, DFNT_INT16, DFNT_INT16, DFNT_FLOAT32, DFNT_FLOAT32 }; int16 *l1bdata[Nbands], *sola, *solz, *sena, *senz, *fillsolz; float32 *lon, *lat; char attr_name[50]; float64 scale_factor[Nitems], scale_offset[Nitems]; char TOA=FALSE, nearest=FALSE, sealevel=FALSE, verbose=FALSE, force=FALSE, process[Nbands]; char output1km=FALSE, output500m=FALSE; char *ptr; float refl, *mus, muv, phi; float *rhoray, *sphalb, *TtotraytH2O, *tOG; int aggfactor, crsrow1, crsrow2, crscol1, crscol2; float mus0, mus11, mus12, mus21, mus22; float fractrow, fractcol, t, u; float rhoray0, rhoray11, rhoray12, rhoray21, rhoray22; float sphalb0, sphalb11, sphalb12, sphalb21, sphalb22; float reflmin=REFLMIN, reflmax=REFLMAX, maxsolz=MAXSOLZ; int demrow1, demcol1, demrow2, demcol2; int height11, height12, height21, height22; MOD021KMfile[0] = (char)NULL; MOD02HKMfile[0] = (char)NULL; MOD02QKMfile[0] = (char)NULL; filename[0] = (char)NULL; for (ib=0; ib= 1 && ib <= Nbands) process[ib - 1] = TRUE; if ( ptr = strchr(ptr, 32) ) ptr++; else ptr = strchr(argv[j], (char)NULL); } } else if ( strstr(argv[j], "-of=") == argv[j] ) { if ( sscanf(argv[j], "-of=%s", filename) != 1 ) { fprintf(stderr, "Cannot parse output file\n"); exit(-1); } if (verbose) printf("Output file: %s\n", filename); } else if ( strstr(ptr = MAX(strrchr(argv[j], 47) + 1, argv[j]), "MOD02QKM.") == ptr ) { strcpy(MOD02QKMfile, argv[j]); if (verbose) printf("Input MOD02QKM file: %s\n", MOD02QKMfile); } else if ( strstr(ptr = MAX(strrchr(argv[j], 47) + 1, argv[j]), "MOD02HKM.") == ptr ) { strcpy(MOD02HKMfile, argv[j]); if (verbose) printf("Input MOD02HKM file: %s\n", MOD02HKMfile); } else if ( strstr(ptr = MAX(strrchr(argv[j], 47) + 1, argv[j]), "MOD021KM.") == ptr || strstr(ptr = MAX(strrchr(argv[j], 47) + 1, argv[j]), "MOD02CRS.") == ptr || strstr(ptr = MAX(strrchr(argv[j], 47) + 1, argv[j]), "MOD09CRS.") == ptr ) { strcpy(MOD021KMfile, argv[j]); if (verbose) printf("Input geolocation file: %s\n", MOD021KMfile); } else if ( strstr(argv[j], "-range=") == argv[j] ) { if ( sscanf(argv[j], "-range=%g,%g", &reflmin, &reflmax) != 2 ) { fprintf(stderr, "Cannot parse output range\n"); exit(-1); } if (verbose) printf("Output range: %g-%g\n", reflmin, reflmax); } else if ( strstr(argv[j], "-maxsolz=") == argv[j] ) { if ( sscanf(argv[j], "-maxsolz=%g", &maxsolz) != 1 ) { fprintf(stderr, "Cannot parse max. solar zenith angle\n"); exit(-1); } if (verbose) printf("Max. solar zenith angle: %g\n", maxsolz); } else if ( strcmp(argv[j], "-1km") == 0 ) { output1km = TRUE; printf("1km-resolution output requested\n"); } else if ( strcmp(argv[j], "-500m") == 0 ) { output500m = TRUE; printf("500m-resolution output requested\n"); } else if ( strcmp(argv[j], "-v") == 0 ) { verbose = TRUE; printf("Verbose mode requested\n"); } else if ( strcmp(argv[j], "-f") == 0 ) { force = TRUE; printf("Force overwrite existing output file\n"); } else if ( strcmp(argv[j], "-nearest") == 0 ) { nearest = TRUE; if (verbose) printf("Interpolation disabled\n"); } else if ( strcmp(argv[j], "-toa") == 0 ) { TOA = TRUE; if (verbose) printf("Top-of-the-atmosphere reflectance requested. No atmospheric correction.\n"); } else if ( strcmp(argv[j], "-sealevel") == 0 ) { sealevel = TRUE; if (verbose) printf("Sea-level atmospheric correction requested. Terrain height ignored.\n"); } } if ( MOD021KMfile[0] == (char)NULL || /* Mandatory for angles */ MOD02HKMfile[0] == (char)NULL && /* HKM file is mandatory */ ! output1km || /* Unless 1km output is requested */ MOD02QKMfile[0] == (char)NULL && /* QKM file is mandatory */ ! output500m && /* Unless 500m or 1km output is requested */ ! output1km || filename[0] == (char)NULL ) { /* Output filename is mandatory */ fprintf(stderr, "Unable to get all arguments\n"); fprintf(stderr, "Usage: corr_refl [-f] [-v] [-nearest] [-toa] [-sealevel] [-range=min,max] -of= -bands=\n"); exit(-1); } if ( MOD02QKMfile[0] && ! output500m && ! output1km && (MOD02QKMfile_id = SDstart(MOD02QKMfile, DFACC_READ)) == -1 ) { fprintf(stderr, "Cannot open file %s.\n", MOD02QKMfile); exit(-1); } if ( MOD02HKMfile[0] && ! output1km && (MOD02HKMfile_id = SDstart(MOD02HKMfile, DFACC_READ)) == -1 ) { fprintf(stderr, "Cannot open file %s.\n", MOD02HKMfile); exit(-1); } if ( MOD021KMfile[0] && (MOD021KMfile_id = SDstart(MOD021KMfile, DFACC_READ)) == -1 ) { fprintf(stderr, "Cannot open file %s.\n", MOD021KMfile); exit(-1); } dem.filename = (char*)malloc(MAXNAMELENGTH * sizeof(char)); if ((ancpath = getenv("ANCPATH")) == NULL) sprintf(dem.filename, "%s/tbase.hdf", ANCPATH); else sprintf(dem.filename, "%s/tbase.hdf", ancpath); if ( (dem.file_id = SDstart(dem.filename, DFACC_READ)) == -1 ) { fprintf(stderr, "Cannot open file %s.\n", dem.filename); exit(-1); } if ( ! force && fopen(filename, "r") != NULL ) { fprintf(stderr, "File %s already exits.\n", filename); exit(-1); } if (output500m) { sds[BAND1].file_id = sds[BAND2].file_id = MOD02HKMfile_id; sds[BAND1].filename = sds[BAND2].filename = MOD02HKMfile; } else if (output1km) { sds[BAND1].file_id = sds[BAND2].file_id = MOD021KMfile_id; sds[BAND1].filename = sds[BAND2].filename = MOD021KMfile; } else { sds[BAND1].file_id = sds[BAND2].file_id = MOD02QKMfile_id; sds[BAND1].filename = sds[BAND2].filename = MOD02QKMfile; } if (output1km) { sds[BAND3].file_id = sds[BAND4].file_id = sds[BAND5].file_id = sds[BAND6].file_id = sds[BAND7].file_id = MOD021KMfile_id; sds[BAND3].filename = sds[BAND4].filename = sds[BAND5].filename = sds[BAND6].filename = sds[BAND7].filename = MOD021KMfile; } else { sds[BAND3].file_id = sds[BAND4].file_id = sds[BAND5].file_id = sds[BAND6].file_id = sds[BAND7].file_id = MOD02HKMfile_id; sds[BAND3].filename = sds[BAND4].filename = sds[BAND5].filename = sds[BAND6].filename = sds[BAND7].filename = MOD02HKMfile; } sds[SOLZ].file_id = sds[SOLA].file_id = sds[SENZ].file_id = sds[SENA].file_id = sds[LON].file_id = sds[LAT].file_id = MOD021KMfile_id; sds[SOLZ].filename = sds[SOLA].filename = sds[SENZ].filename = sds[SENA].filename = sds[LON].filename = sds[LAT].filename = MOD021KMfile; for (ib=0; ib= Nbands) { fprintf(stderr, "No L1B SDS can be read successfully.\n"); exit(-1); } Nscans = sds[ib].Nl / sds[ib].rowsperscan; if ( (sd_id = SDstart(filename, DFACC_CREATE)) == -1 ) { fprintf(stderr, "Cannot open file %s.\n", filename); exit(-1); } for (ib=0; ib= maxsolz) solz[idx] = *fillsolz; if (solz[idx] != *fillsolz) mus[idx] = cos(solz[idx] * sds[SOLZ].factor * DEG2RAD); } for (idx=0; idx dem.Nl - 1) demrow2 = demrow1 - 1; t = (fractrow - demrow1) / (demrow2 - demrow1); fractcol = (lon[idx] + 180) * dem.Np / 360; demcol1 = floor(fractcol); demcol2 = demcol1 + 1; if (demcol1 < 0) demcol1 = demcol2 + 1; if (demcol2 > dem.Np - 1) demcol2 = demcol1 - 1; u = (fractcol - demcol1) / (demcol2 - demcol1); height11 = ((int16 *)dem.data)[demrow1 * dem.Np + demcol1]; height12 = ((int16 *)dem.data)[demrow1 * dem.Np + demcol2]; height21 = ((int16 *)dem.data)[demrow2 * dem.Np + demcol1]; height22 = ((int16 *)dem.data)[demrow2 * dem.Np + demcol2]; ((int16 *)height.data)[idx] = t * u * height22 + t * (1 - u) * height21 + (1 - t) * u * height12 + (1 - t) * (1 - u) * height11; if (((int16 *)height.data)[idx] < 0) ((int16 *)height.data)[idx] = 0; } } if (! TOA) { for (irow=0; irow sds[REFSDS].rowsperscan - 1) crsrow2 = crsrow1 - 1; t = (fractrow - crsrow1) / (crsrow2 - crsrow1); } for (jcol=0; jcol sds[REFSDS].Np - 1) crscol2 = crscol1 - 1; u = (fractcol - crscol1) / (crscol2 - crscol1); /* We want u=0 on coarse pixel center */ mus11 = mus[crsrow1 * sds[REFSDS].Np + crscol1]; mus12 = mus[crsrow1 * sds[REFSDS].Np + crscol2]; mus21 = mus[crsrow2 * sds[REFSDS].Np + crscol1]; mus22 = mus[crsrow2 * sds[REFSDS].Np + crscol2]; mus0 = t * u * mus22 + (1 - t) * u * mus12 + t * (1 - u) * mus21 + (1 - t) * (1 - u) * mus11; if (! TOA) { rhoray11 = rhoray[(crsrow1 * sds[REFSDS].Np + crscol1) * Nbands + ib]; rhoray12 = rhoray[(crsrow1 * sds[REFSDS].Np + crscol2) * Nbands + ib]; rhoray21 = rhoray[(crsrow2 * sds[REFSDS].Np + crscol1) * Nbands + ib]; rhoray22 = rhoray[(crsrow2 * sds[REFSDS].Np + crscol2) * Nbands + ib]; rhoray0 = t * u * rhoray22 + (1 - t) * u * rhoray12 + t * (1 - u) * rhoray21 + (1 - t) * (1 - u) * rhoray11; sphalb11 = sphalb[(crsrow1 * sds[REFSDS].Np + crscol1) * Nbands + ib]; sphalb12 = sphalb[(crsrow1 * sds[REFSDS].Np + crscol2) * Nbands + ib]; sphalb21 = sphalb[(crsrow2 * sds[REFSDS].Np + crscol1) * Nbands + ib]; sphalb22 = sphalb[(crsrow2 * sds[REFSDS].Np + crscol2) * Nbands + ib]; sphalb0 = t * u * sphalb22 + (1 - t) * u * sphalb12 + t * (1 - u) * sphalb21 + (1 - t) * (1 - u) * sphalb11; } } refl = (l1bdata[ib][idx] - sds[ib].offset) * sds[ib].factor / mus0; if (! TOA) { refl = correctedrefl(refl, TtotraytH2O[crsidx * Nbands + ib], tOG[crsidx * Nbands + ib], rhoray0, sphalb0); } if (refl > reflmax) refl = reflmax; if (refl < reflmin) refl = reflmin; ((int16 *)outsds[ib].data)[idx] = refl / outsds[ib].factor + 0.5; } } } for (ib=0; ib MAXAIRMASS) return -1; psurfratio = expf(-height / 8000.); for (ib=0; ib