|
ocssw
1.0
|
00001 /* 00002 * W. Robinson, SAIC, 10 Dec 2004 I/O routines for CZCS 00003 */ 00004 #include "hdf.h" 00005 #include "mfhdf.h" 00006 #include "l12_proto.h" 00007 #include "l1_czcs_hdf.h" 00008 #include "hdf_utils.h" 00009 #include <math.h> 00010 00011 #define NREC_IN_BUF 1 00012 #define NBND_CZCS 5 00013 #define POS_ERR_THRESH 2000. /* orbit position error tolerence */ 00014 00015 int syear, sday; /* data start date */ 00016 int32 smsec; /* data start time */ 00017 int16 eyear, eday; /* data end date */ 00018 int32 emsec; /* data end time */ 00019 int32 nscan; /* number of scans */ 00020 int32 npix; /* number pixels per scan */ 00021 int32 spix; /* start pixel number (from 0) */ 00022 int32 dpix; /* LAC pixel increment */ 00023 int32 epix; 00024 00025 char dtype[8]; 00026 00027 int32 nsta; 00028 int32 ninc; 00029 00030 uint8 *counts, cz_band_present; 00031 int32 *msec; 00032 int lgain,status; 00033 int16 *gain; 00034 float32 *tilt, *att_ang, *slope, *intercept; 00035 float32 *ctl_pt_lat, *ctl_pt_lon, *pos, *pos_err; 00036 int32 nctl_pt, *ctl_pt_cols; 00037 float *ctl_pt_vx, *ctl_pt_vy, *ctl_pt_vz, *y2_vx, *y2_vy, *y2_vz, *ctl_pt_x; 00038 float *lt750; /* internal 750 mn data source */ 00039 char *ring_sat; /* set to 1 if 443, 520 or 550 are saturated for ringing 00040 mask computation */ 00041 00042 int czcs_ring( int gain, float *lt750, char *ring_sat, l1str *l1rec ) 00043 /******************************************************************* 00044 00045 czcs_ring 00046 00047 purpose: use the Mueller ringing flagging algorithm to set the stray 00048 light mask for CZCS 00049 00050 Returns type: int - 0 if OK 00051 00052 Parameters: (in calling order) 00053 Type Name I/O Description 00054 ---- ---- --- ----------- 00055 int gain I gain for the line of data 00056 float * lt750 I 750 nm total rads 00057 char * ring_sat I 1 if bands 1,2,or 3 are 00058 saturated = use the 750 00059 excess rad in this case 00060 l1str * l1rec I/O L1 struc including tot rads, 00061 flags 00062 00063 Modification history: 00064 Programmer Date Description of change 00065 ---------- ---- --------------------- 00066 W. Robinson 31 May 2005 Original development 00067 W. Robinson 31 Jul 2007 repaired problem that occurs in SGIs 00068 if bsum = 0, avoid log and set ring 00069 distance to 0 00070 00071 Based on the algorithm of Mueller, J. L., Nimbus-7 CZCS: electronic 00072 overshoot due to cloud reflectance, Appl. Optics, Vol 27, No 3, 1 Feb, 00073 1988, pp 438 - 440 00074 Modified to only include the excess radiance in 750 for pixels where 00075 bands 1, 2, or 3 have saturated. This is to reduce the masking from 00076 coastal areas where the vis is not as bright as for cloud 00077 00078 *******************************************************************/ 00079 { 00080 static float gtrans[4] = { 1.0, 1.25, 1.5, 2.1 }; 00081 /* note that the values below have +- of 9.7 and 3.3 in paper */ 00082 /* standard values followed by low, high confidence values 00083 static float mueller_int = 3.9, mueller_slp = 30.8; 00084 static float mueller_int = -6.2, mueller_slp = 27.5; 00085 static float mueller_int = 13.6, mueller_slp = 34.1; 00086 */ 00087 static float mueller_int = 3.9, mueller_slp = 30.8; 00088 00089 static float l0_750 = 2.45; 00090 00091 float gfac, lthresh, gfac_ln, excess_brit[1968], bsub, bsum; 00092 int i, ipx, btarg, last_btarg, igrp, iavg, pxloc, n_ring; 00093 extern int32 npix; 00094 00095 /* 00096 * set up gfac - gain factor for line, lthresh, brightness threshold 00097 * and flags for current and last pixel above threshold radiance 00098 */ 00099 gfac = gtrans[ gain - 1]; 00100 lthresh = l0_750 / gfac; 00101 gfac_ln = log( gfac ); 00102 btarg = 0; 00103 last_btarg = 0; 00104 00105 /* 00106 * go through pixels and set the mask for pixels downstream of bright target 00107 */ 00108 for( i = 0; i < npix; i++ ) 00109 { 00110 if( *( lt750 + i ) > lthresh ) 00111 { 00112 btarg = 1; 00113 excess_brit[i] = 00114 ( *( ring_sat + i ) == 1 ) ? *( lt750 + i ) - lthresh : 0.; 00115 l1rec->stlight[i] = 1; 00116 } 00117 else 00118 excess_brit[i] = 0.; 00119 00120 if( ( btarg == 0 ) && ( last_btarg == 1 ) ) 00121 { 00122 /* 00123 * sum up excess brightness in 5 groups of 10, weighted by f(dist) 00124 */ 00125 bsum = 0.; 00126 for( igrp = 0; igrp < 5; igrp++ ) 00127 { 00128 bsub = 0.; 00129 for( iavg = 0; iavg < 10; iavg++ ) 00130 { 00131 pxloc = i - 1 - ( iavg + igrp * 10 ); 00132 if( pxloc >= 0 ) 00133 bsub += excess_brit[ pxloc ]; 00134 } 00135 bsub = bsub / 10.; 00136 bsum += bsub * exp( -0.32 * ( igrp + 1 ) ); 00137 } 00138 /* 00139 * compute # pixels to mask and mark the pixels in that range 00140 */ 00141 bsum = ( bsum > 450.) ? 450. : bsum; 00142 if( bsum > 0. ) 00143 { 00144 n_ring = mueller_int + mueller_slp * ( log( bsum ) + gfac_ln ); 00145 n_ring = ( n_ring < 0 ) ? 0 : n_ring; 00146 } 00147 else 00148 n_ring = 0; 00149 00150 for( ipx = 0; ipx < n_ring; ipx++ ) 00151 { 00152 pxloc = ipx + i; 00153 if( pxloc < npix ) 00154 l1rec->stlight[pxloc] = 1; 00155 } 00156 } 00157 /* 00158 * lastly, reset to go to next pixel 00159 */ 00160 last_btarg = btarg; 00161 btarg = 0; 00162 } 00163 return 0; 00164 } 00165 00166 #define NBND 4 00167 #define NGAIN 4 00168 #define NEPOCH 5 00169 00170 int get_czcscal( char *file, int orbit, int16 year, int16 day, int32 msec, short l1acnt[], float slope750, float intercept750, int16 igain, float32 l1brads[] ) 00171 /****************************************************************** 00172 00173 get_czcscal 00174 purpose: replicate the Evans & Gordon calibration 00175 00176 Modification history: 00177 Programmer Date Description of change 00178 ---------- ---- --------------------- 00179 Sean Bailey 08 Feb 2006 Original development 00180 00181 Based on the original czcscaleg.f 00182 Modified to use cal_czcs.hdf 00183 00184 *******************************************************************/ 00185 { 00186 static int firstCall = 1; 00187 int status; 00188 static float slope_coeff[NGAIN][NBND_CZCS]; 00189 static float offsets[NGAIN][NBND_CZCS]; 00190 static float rk[NGAIN][NBND_CZCS]; 00191 static float tdecay[NEPOCH][NBND_CZCS]; 00192 static int orbitepoch[NEPOCH]; 00193 static float timeconst[2]; 00194 static float time_dep[NBND_CZCS][NGAIN][3]; 00195 00196 int epochidx = 0; 00197 int i, j, iorbit; 00198 float rden, rnum, x1, x2; 00199 float tcorr, slp, S; 00200 static int orbepoch670 = 6750; 00201 float g[NBND]; 00202 float64 jsec = yds2unix(year,day,((double)(msec))/1000.0); 00203 float64 refjsec = yds2unix(1978,278,(double)0.0); 00204 float64 decayday = (jsec - refjsec)/86400.; 00205 00206 igain -= 1; 00207 00208 if (firstCall) { 00209 char name [H4_MAX_NC_NAME] = ""; 00210 char sdsname[H4_MAX_NC_NAME] = ""; 00211 int32 sd_id; 00212 int32 sds_id; 00213 int32 rank; 00214 int32 nt; 00215 int32 dims[H4_MAX_VAR_DIMS]; 00216 int32 nattrs; 00217 int32 start[3] = {0,0,0}; 00218 int32 end [3] = {1,1,1}; 00219 int32 status; 00220 /* get the current calibration */ 00221 if (file == NULL) { 00222 fprintf(stderr, 00223 "-E %s Line %d: No calibration file specified.\n", 00224 __FILE__,__LINE__); 00225 exit(1); 00226 } 00227 00228 printf("Loading caltable: %s\n",file); 00229 /* Open the file */ 00230 sd_id = SDstart(file, DFACC_RDONLY); 00231 if (sd_id == FAIL){ 00232 fprintf(stderr,"-E- %s line %d: SDstart(%s, %d) failed.\n", 00233 __FILE__,__LINE__,file,DFACC_RDONLY); 00234 exit(1); 00235 } 00236 00237 strcpy(sdsname,"slope_coeff"); 00238 sds_id = SDselect(sd_id, SDnametoindex(sd_id,sdsname)); 00239 status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs); 00240 status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) slope_coeff); 00241 if (status != 0) { 00242 printf("-E- %s Line %d: Error reading SDS %s from %s.\n", 00243 __FILE__,__LINE__,sdsname,file); 00244 exit(1); 00245 } else { 00246 status = SDendaccess(sds_id); 00247 } 00248 00249 strcpy(sdsname,"offsets"); 00250 sds_id = SDselect(sd_id, SDnametoindex(sd_id,sdsname)); 00251 status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs); 00252 status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) offsets); 00253 if (status != 0) { 00254 printf("-E- %s Line %d: Error reading SDS %s from %s.\n", 00255 __FILE__,__LINE__,sdsname,file); 00256 exit(1); 00257 } else { 00258 status = SDendaccess(sds_id); 00259 } 00260 00261 strcpy(sdsname,"rk"); 00262 sds_id = SDselect(sd_id, SDnametoindex(sd_id,sdsname)); 00263 status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs); 00264 status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) rk); 00265 if (status != 0) { 00266 printf("-E- %s Line %d: Error reading SDS %s from %s.\n", 00267 __FILE__,__LINE__,sdsname,file); 00268 exit(1); 00269 } else { 00270 status = SDendaccess(sds_id); 00271 } 00272 00273 strcpy(sdsname,"dec"); 00274 sds_id = SDselect(sd_id, SDnametoindex(sd_id,sdsname)); 00275 status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs); 00276 status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) tdecay); 00277 if (status != 0) { 00278 printf("-E- %s Line %d: Error reading SDS %s from %s.\n", 00279 __FILE__,__LINE__,sdsname,file); 00280 exit(1); 00281 } else { 00282 status = SDendaccess(sds_id); 00283 } 00284 00285 strcpy(sdsname,"iorbdec"); 00286 sds_id = SDselect(sd_id, SDnametoindex(sd_id,sdsname)); 00287 status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs); 00288 status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) orbitepoch); 00289 if (status != 0) { 00290 printf("-E- %s Line %d: Error reading SDS %s from %s.\n", 00291 __FILE__,__LINE__,sdsname,file); 00292 exit(1); 00293 } else { 00294 status = SDendaccess(sds_id); 00295 } 00296 00297 strcpy(sdsname,"timeconst"); 00298 sds_id = SDselect(sd_id, SDnametoindex(sd_id,sdsname)); 00299 status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs); 00300 status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) timeconst); 00301 if (status != 0) { 00302 printf("-E- %s Line %d: Error reading SDS %s from %s.\n", 00303 __FILE__,__LINE__,sdsname,file); 00304 exit(1); 00305 } else { 00306 status = SDendaccess(sds_id); 00307 } 00308 00309 strcpy(sdsname,"time_dep"); 00310 sds_id = SDselect(sd_id, SDnametoindex(sd_id,sdsname)); 00311 status = SDgetinfo(sds_id, name, &rank, dims, &nt, &nattrs); 00312 status = SDreaddata(sds_id, start, NULL, dims, (VOIDP) time_dep); 00313 if (status != 0) { 00314 printf("-E- %s Line %d: Error reading SDS %s from %s.\n", 00315 __FILE__,__LINE__,sdsname,file); 00316 exit(1); 00317 } else { 00318 status = SDendaccess(sds_id); 00319 } 00320 /* terminate access to the SD interface and close the file */ 00321 status = SDend(sd_id); 00322 00323 firstCall = 0; 00324 } 00325 00326 iorbit = MIN(orbit,39000); 00327 for (j=0; j< NEPOCH - 1; j++) { 00328 if ((iorbit >= orbitepoch[j]) && (iorbit <= orbitepoch[j+1])) 00329 epochidx = j; 00330 } 00331 00332 x1 = (float) orbitepoch[epochidx]; 00333 x2 = (float) orbitepoch[epochidx + 1]; 00334 rden = (float) orbitepoch[epochidx + 1] - (float) orbitepoch[epochidx]; 00335 00336 for (i = 0; i < NBND; i++){ 00337 /* Calculate time dependent correction... */ 00338 /* double exp 00339 tcorr = time_dep[i][igain][0] - time_dep[i][igain][1] * (1.0 - exp(timeconst[0]*decayday)) - time_dep[i][igain][2] *(1.0 - exp(timeconst[1]*decayday)); 00340 */ 00341 /* single exp */ 00342 tcorr = time_dep[i][igain][0] - time_dep[i][igain][1] * (1.0 - exp(-1*time_dep[i][igain][2] *decayday)); 00343 00344 rnum = tdecay[epochidx + 1][i] - tdecay[epochidx][i]; 00345 slp = rnum/rden; 00346 00347 /* Antione modification for 670nm */ 00348 if (i == 3 && iorbit > orbepoch670) { 00349 rden = (float) orbitepoch[4] - (float) orbepoch670; 00350 rnum = tdecay[4][i] - tdecay[3][i]; 00351 slp = rnum/rden; 00352 S = (float) iorbit - (float) orbepoch670; 00353 g[i] = 1.0 / (S * slp + tdecay[3][i]); 00354 00355 } else { 00356 S = (float) iorbit - (float) orbitepoch[epochidx]; 00357 g[i] = 1.0 / (S * slp + tdecay[epochidx][i]); 00358 } 00359 /*fprintf(stderr,"i: %d g: %8.6f tcorr: %8.6f\n",i,g[i],tcorr);*/ 00360 00361 l1brads[i] = (tcorr * g[i] * rk[igain][i] * slope_coeff[igain][i] * (float) l1acnt[i]) + offsets[igain][i]; 00362 00363 } 00364 00365 l1brads[4] = slope750 * (float) l1acnt[4] + intercept750; 00366 00367 return 0; 00368 } 00369 /* 00370 W. Robinson, SAIC, 6 Jan 2006 add code to read the position and 00371 position error SDSes 00372 */ 00373 00374 int openl1_czcs(filehandle *file) 00375 { 00376 00377 /* */ 00378 /* get_l1a_open interface */ 00379 /* */ 00380 int32 fileID; 00381 int32 status; 00382 int16 sy, sd; 00383 int i; 00384 00385 /* open the file and get the file ID */ 00386 fileID = SDstart(file->name, DFACC_RDONLY); 00387 00388 if (fileID < 0) { 00389 fprintf(stderr, 00390 "-E %s Line %d: Error opening %s for reading.\n", 00391 __FILE__,__LINE__,file->name); 00392 return(1); 00393 } 00394 status = getHDFattr(fileID, "Start Year", "", (VOIDP) &sy ); 00395 syear = (int32) sy; 00396 status = getHDFattr(fileID, "Start Day", "", (VOIDP) &sd ); 00397 sday = (int32) sd; 00398 status = getHDFattr(fileID, "Start Millisec", "", (VOIDP) &smsec); 00399 status = getHDFattr(fileID, "End Year", "", (VOIDP) &eyear); 00400 status = getHDFattr(fileID, "End Day", "", (VOIDP) &eday); 00401 status = getHDFattr(fileID, "End Millisec", "", (VOIDP) &emsec); 00402 status = getHDFattr(fileID, "Number of Scan Lines", "", (VOIDP) &nscan); 00403 status = getHDFattr(fileID, "Data Type", "", (VOIDP) &dtype); 00404 00405 status = getHDFattr(fileID, "Pixels per Scan Line", "", (VOIDP) &npix); 00406 status = getHDFattr(fileID, "LAC Pixel Start Number", "", (VOIDP) &nsta); 00407 status = getHDFattr(fileID, "LAC Pixel Subsampling", "", (VOIDP) &ninc); 00408 00409 status = getHDFattr(fileID, "Orbit Number", "", (VOIDP)&file->orbit_number); 00410 /* WDR not in czcs l1 file, so comment for now 00411 status = getHDFattr(fileID, "Orbit Node Longitude", "", 00412 (VOIDP)&file->orbit_node_lon); 00413 status = getHDFattr(fileID, "Node Crossing Time", "", 00414 (VOIDP)&file->node_crossing_time[0]); 00415 */ 00416 status = getHDFattr( fileID, "Number of Pixel Control Points", "", 00417 (VOIDP)&nctl_pt ); 00418 status = getHDFattr( fileID, "Parameter Presence Code", "", 00419 (VOIDP)&cz_band_present ); 00420 00421 /* call cdata.f to initialize global FORTRAN common block data */ 00422 cdata_(); 00423 00424 00425 file->npix = npix; 00426 file->nscan = nscan; 00427 file->sensorID = CZCS; 00428 file->sd_id = fileID; 00429 00430 msec = (int32 *) calloc(nscan, sizeof(int32)); 00431 status = rdSDS(file->sd_id,"msec",0,0,0,0, (VOIDP) msec); 00432 00433 att_ang = (float32 *) calloc( nscan * 3, sizeof( float32 ) ); 00434 status = rdSDS( file->sd_id, "att_ang", 0, 0, 0, 0, (VOIDP) att_ang ); 00435 00436 ctl_pt_cols = (int32 *) calloc( nctl_pt, sizeof( int32 ) ); 00437 status = rdSDS( file->sd_id, "cntl_pt_cols", 0, 0, 0, 0, 00438 (VOIDP) ctl_pt_cols ); 00439 ctl_pt_x = (float *) calloc( nctl_pt, sizeof( float ) ); 00440 for( i = 0; i < nctl_pt; i++ ) 00441 ctl_pt_x[i] = (float) ctl_pt_cols[i] - 1.; 00442 00443 tilt = (float32 *) calloc(nscan, sizeof(float32)); 00444 status = rdSDS(file->sd_id,"tilt",0,0,0,0, (VOIDP) tilt); 00445 00446 slope = (float32 *) calloc(nscan * 6, sizeof(float32)); 00447 status = rdSDS(file->sd_id,"slope",0,0,0,0, (VOIDP) slope ); 00448 intercept = (float32 *) calloc(nscan * 6, sizeof(float32)); 00449 status = rdSDS(file->sd_id,"intercept",0,0,0,0, (VOIDP) intercept ); 00450 /* get nav orbit data */ 00451 pos = (float32 *) malloc( nscan * 3 * sizeof(float32) ); 00452 status = rdSDS( file->sd_id, "orb_vec", 0, 0, 0, 0, (VOIDP) pos ); 00453 pos_err = (float32 *) malloc( nscan * sizeof(float32) ); 00454 status = rdSDS( file->sd_id, "pos_err", 0, 0, 0, 0, (VOIDP) pos_err ); 00455 00456 gain = (int16 *) malloc( nscan * sizeof( int16 ) ); 00457 counts = (uint8 *) malloc( npix * NBND_CZCS* sizeof( uint8 ) ); 00458 ctl_pt_lat = (float32 *) malloc( nctl_pt * sizeof( float32 ) ); 00459 ctl_pt_lon = (float32 *) malloc( nctl_pt * sizeof( float32 ) ); 00460 ctl_pt_vx = (float32 *) malloc( nctl_pt * sizeof( float32 ) ); 00461 ctl_pt_vy = (float32 *) malloc( nctl_pt * sizeof( float32 ) ); 00462 ctl_pt_vz = (float32 *) malloc( nctl_pt * sizeof( float32 ) ); 00463 y2_vx = (float32 *) malloc( npix * sizeof( float32 ) ); 00464 y2_vy = (float32 *) malloc( npix * sizeof( float32 ) ); 00465 y2_vz = (float32 *) malloc( npix * sizeof( float32 ) ); 00466 lt750 = (float *) malloc( npix * sizeof( float ) ); 00467 ring_sat = (char *) malloc( npix * sizeof( char ) ); 00468 00469 spix = nsta - 1; 00470 dpix = ninc; 00471 epix = spix + npix * dpix; 00472 00473 00474 return (status); 00475 } 00476 00477 /* 00478 W. Robinson 31 May 2005 add ringing masking call 00479 W. Robinson, SAIC, 6 Jan 2005 add code to compute sat angles with 00480 cz_posll_2_satang if pos_err is acceptable 00481 J. Gales 23 Sep 2005 add kludge for subsetted pixel range in 00482 satang 00483 (note that satang may not give proper values in pixel subsets with this 00484 but it may be academic with...) 00485 W. Robinson, SAIC, 10 Sep 2010 use vectors instead of lat, lon when 00486 doing interpolation of ctl pt lat, lon to 00487 all samples 00488 */ 00489 00490 int readl1_czcs(filehandle *file, int32_t recnum, l1str *l1rec) 00491 { 00492 /*void czcscal_( int *, float[], float[], short *, int *, float * );*/ 00493 void satang_( double *, double *, float *, float *, float *, float *, 00494 float *, float *, float *, float * ); 00495 void sunangs_( int *, int *, float *, float *, float *, float *, float * ); 00496 int ll2vec( float *, float * ); 00497 int vec2ll( float *, float * ); 00498 short cnt_vec[NBND_CZCS]; 00499 float lt_lcl[NBND_CZCS], yout1, yout2, yout3, llvec[2], vec[3], gmt; 00500 int ipx, ibnd, orbit, i, tpix; 00501 uint8 cal_sum[5], cal_scan[6]; 00502 int32 status, navbad, ltsat; 00503 double pi, radeg; 00504 int32_t ib; 00505 00506 int32_t nwave = l1rec->nbands; 00507 int32_t *bindx = l1rec->bindx; 00508 char *cal_path = file->calfile; 00509 /* load scan times */ 00510 /* int year = *l1rec->year; 00511 int day = *l1rec->day;*/ 00512 /* int32 msec = l1rec->msec[recnum];*/ 00513 00514 float lonbuf[1968], latbuf[1968], senzbuf[1968], senabuf[1968]; 00515 00516 /* 00517 * read in the line of counts, latitude, longitude 00518 */ 00519 status = rdSDS( file->sd_id, "band1", recnum, 0, 1, npix, (VOIDP) counts ); 00520 status = rdSDS( file->sd_id, "band2", recnum, 0, 1, npix, 00521 (VOIDP) ( counts + npix ) ); 00522 status = rdSDS( file->sd_id, "band3", recnum, 0, 1, npix, 00523 (VOIDP) ( counts + 2 * npix ) ); 00524 status = rdSDS( file->sd_id, "band4", recnum, 0, 1, npix, 00525 (VOIDP) ( counts + 3 * npix ) ); 00526 status = rdSDS( file->sd_id, "band5", recnum, 0, 1, npix, 00527 (VOIDP) ( counts + 4 * npix ) ); 00528 00529 status = rdSDS( file->sd_id, "gain", recnum, 0, 1, 1, (VOIDP) gain); 00530 status = rdSDS( file->sd_id, "latitude", recnum, 0, 1, nctl_pt, 00531 (VOIDP) ctl_pt_lat ); 00532 status = rdSDS( file->sd_id, "longitude", recnum, 0, 1, nctl_pt, 00533 (VOIDP) ctl_pt_lon ); 00534 00535 status = rdSDS( file->sd_id, "cal_sum", recnum, 0, 1, 5, (VOIDP) cal_sum ); 00536 status = rdSDS( file->sd_id, "cal_scan", recnum, 0, 1, 6, (VOIDP) cal_scan ); 00537 /* 00538 * flag setting for entire line: set navfail if cal_sum shows problems 00539 * (suspect it is * bad ephemeris or atitude) and set hilt if bands 00540 * missing 00541 */ 00542 ltsat = 0; 00543 navbad = 0; 00544 if( ( cz_band_present & 0XF8 ) != 0XF8 ) 00545 ltsat = 1; 00546 else 00547 { 00548 if( ( cal_sum[3] != 0 ) || ( cal_sum[4] != 0 ) ) 00549 navbad = 1; 00550 if( ( cal_scan[0] != 0 ) || ( cal_scan[1] != 0 ) || 00551 ( cal_scan[2] != 0 ) || ( cal_scan[3] != 0 ) || 00552 ( cal_scan[4] != 0 ) ) 00553 { 00554 ltsat = 1; 00555 navbad = 1; 00556 } 00557 } 00558 /* 00559 * calibrate the radiances and set flags for pixels 00560 */ 00561 for( ipx = 0; ipx < npix; ipx++ ) 00562 { 00563 for( ibnd = 0; ibnd < NBND_CZCS; ibnd++ ) 00564 { 00565 cnt_vec[ibnd] = *( counts + ipx + ibnd * npix ); 00566 if( ( cnt_vec[ibnd] == 255) || ( ltsat == 1 ) ) l1rec->hilt[ipx] = 1; 00567 } 00568 *( ring_sat + ipx ) = ( ( cnt_vec[0] == 255 ) || ( cnt_vec[1] == 255 ) 00569 || ( cnt_vec[2] == 255 ) ) ? 1 : 0; 00570 /* 00571 * call the fortran calibration routine 00572 */ 00573 orbit = ( int ) file->orbit_number; 00574 /*czcscal_( &orbit, slope + recnum * 6, 00575 intercept + recnum * 6, cnt_vec, &lgain, lt_lcl );*/ 00576 status = get_czcscal( cal_path, orbit, syear, sday, msec[recnum], 00577 cnt_vec, slope[4], intercept[4], gain[0], lt_lcl ); 00578 /* 00579 * assign the calibrated radiances 00580 */ 00581 for( ibnd = 0; ibnd < nwave; ibnd++ ) 00582 { 00583 ib = bindx[ ibnd ]; 00584 l1rec->Lt[ ipx * NBANDS + ib ] = lt_lcl[ibnd]; 00585 } 00586 /* 00587 * save the 750 nm data here 00588 */ 00589 *( lt750 + ipx ) = lt_lcl[4]; 00590 00591 if( navbad == 1 ) l1rec->navfail[ipx] = 1; 00592 } 00593 /* 00594 * set the ringing mask 00595 */ 00596 czcs_ring( gain[0], lt750, ring_sat, l1rec ); 00597 /* 00598 * get navigation at all points from control point lat and lon values 00599 * use spline interpolation to fill in, do in vector space to avoid date 00600 * line discontinuity 00601 */ 00602 for( i = 0; i < nctl_pt; i++ ) 00603 { 00604 llvec[0] = ctl_pt_lat[i]; 00605 llvec[1] = ctl_pt_lon[i]; 00606 if( ll2vec( llvec, vec ) == 0 ) 00607 { 00608 ctl_pt_vx[i] = *vec; 00609 ctl_pt_vy[i] = *( vec + 1 ); 00610 ctl_pt_vz[i] = *( vec + 2 ); 00611 } 00612 else 00613 { 00614 fprintf(stderr, "-E %s Line %d: ll2vec failure.\n", 00615 __FILE__,__LINE__); 00616 exit(1); 00617 } 00618 } 00619 spline( ctl_pt_x, ctl_pt_vx, nctl_pt, 1e30, 1e30, y2_vx ); 00620 spline( ctl_pt_x, ctl_pt_vy, nctl_pt, 1e30, 1e30, y2_vy ); 00621 spline( ctl_pt_x, ctl_pt_vz, nctl_pt, 1e30, 1e30, y2_vz ); 00622 for( i = 0; i < npix; i++ ) 00623 { 00624 tpix = i * ninc /*+ spix*/; 00625 splint( ctl_pt_x, ctl_pt_vx, y2_vx, nctl_pt, tpix, &yout1 ); 00626 splint( ctl_pt_x, ctl_pt_vy, y2_vy, nctl_pt, tpix, &yout2 ); 00627 splint( ctl_pt_x, ctl_pt_vz, y2_vz, nctl_pt, tpix, &yout3 ); 00628 00629 *vec = yout1; *( vec + 1 ) = yout2; *( vec + 2 ) = yout3; 00630 vec2ll( vec, llvec ); 00631 00632 l1rec->lon[i] = llvec[1]; 00633 l1rec->lat[i] = llvec[0]; 00634 } 00635 /* 00636 * calculate geometry. For sensor angles, use the orbit info if the 00637 * position error is available and within error threshold 00638 */ 00639 if( ( *( pos_err + recnum ) >= 0. ) && 00640 ( *( pos_err + recnum ) < POS_ERR_THRESH ) ) 00641 { 00642 cz_posll_2_satang( ( pos + 3 * recnum ), npix, l1rec->lat, l1rec->lon, 00643 l1rec->senz, l1rec->sena ); 00644 } 00645 else 00646 { 00647 pi = PI; radeg = RADEG; 00648 for (i=0; i<1968; i++) { 00649 lonbuf[i] = 0.0; 00650 latbuf[i] = 0.0; 00651 senzbuf[i] = 0.0; 00652 senabuf[i] = 0.0; 00653 } 00654 00655 for (i=0; i<npix; i++) { 00656 lonbuf[i] = l1rec->lon[i]; 00657 latbuf[i] = l1rec->lat[i]; 00658 } 00659 00660 satang_( &pi, &radeg, tilt + recnum, att_ang + 3 * recnum + 1, 00661 att_ang + 3 * recnum + 2, att_ang + 3 * recnum, lonbuf, 00662 latbuf, senzbuf, senabuf ); 00663 00664 for (i=0; i<npix; i++) { 00665 l1rec->senz[i] = senzbuf[i]; 00666 l1rec->sena[i] = senabuf[i]; 00667 } 00668 } 00669 00670 00671 /* for( i = spix; i < epix; i = i + ninc )*/ 00672 for (i=0; i<npix; i++) 00673 { 00674 gmt = (float) msec[recnum] / ( 1000. * 3600 ); 00675 sunangs_( &syear, &sday, &gmt, ( l1rec->lon ) + i, ( l1rec->lat ) + i, 00676 ( l1rec->solz ) + i, ( l1rec->sola ) + i ); 00677 } 00678 /* 00679 * set scan time 00680 */ 00681 if( recnum > 0 ) 00682 { 00683 if( msec[recnum] < msec[recnum-1] ) 00684 { 00685 printf("changing the day\n"); 00686 sday += 1; 00687 if( *l1rec->day > ( 365 + ( *l1rec->year % 4 == 0 ) ) ) 00688 { 00689 syear += 1; 00690 sday = 1; 00691 } 00692 } 00693 } 00694 *l1rec->year = syear; 00695 *l1rec->day = sday; 00696 *l1rec->msec = msec[recnum]; 00697 00698 return(status); 00699 } 00700 00701 /* W. Robinson, SAIC, 6 Jan 2005 include the pos, pos_err arrays in free */ 00702 00703 int closel1_czcs(filehandle *file) 00704 { 00705 free(msec); 00706 free(tilt); 00707 free( att_ang ); 00708 free( counts ); 00709 free( ctl_pt_lat ); 00710 free( ctl_pt_lon ); 00711 free( ctl_pt_vx ); 00712 free( ctl_pt_vy ); 00713 free( ctl_pt_vz ); 00714 free( y2_vx ); 00715 free( y2_vy ); 00716 free( y2_vz ); 00717 free( ctl_pt_x ); 00718 free( ctl_pt_cols ); 00719 free( slope ); 00720 free( intercept ); 00721 free( lt750 ); 00722 free( ring_sat ); 00723 free( pos ); 00724 free( pos_err ); 00725 00726 SDend(file->sd_id); 00727 00728 return(0); 00729 } 00730 00731 #define re 6378.137 00732 #define f 1. / 298.257 00733 #define omf2 ( 1 - f ) * ( 1 - f ) 00734 00735 int cz_posll_2_satang( float *pos, int npix, float *lat, float *lon, 00736 float *senz, float *sena ) 00737 /******************************************************************* 00738 00739 cz_posll_2_satang 00740 00741 purpose: convert satellite position, lat, lon into satellite zenith 00742 and azimuth for a line of czcs data 00743 00744 Returns type: int - 0 if no problems 00745 00746 Parameters: (in calling order) 00747 Type Name I/O Description 00748 ---- ---- --- ----------- 00749 float * pos I position (x, y, z) of 00750 satellite in meters 00751 int npix I # pixels of lat, lon to find 00752 sat angles for 00753 float * lat I latitude array in degrees E 00754 float * lon I longitude array in degrees E 00755 float * senz O sensor zenith in degrees 00756 float * sena O sensor azimuth in degrees 00757 00758 Modification history: 00759 Programmer Date Description of change 00760 ---------- ---- --------------------- 00761 W. Robinson, SAIC 5-Jan-2006 Original development 00762 00763 *******************************************************************/ 00764 { 00765 double up[3], ea[3], no[3], radeg, upxy, xlmat[3][3], xlatg, gv[3]; 00766 double r, rh[3], rl[3]; 00767 int i, j; 00768 00769 radeg = 90. / asin( 1. ); 00770 00771 for( i = 0; i < npix; i++ ) 00772 { 00773 /* 00774 * Compute the local vertical, East and North unit vectors 00775 */ 00776 up[0] = cos( *( lat + i ) / radeg ) * cos( *( lon + i ) / radeg ); 00777 up[1] = cos( *( lat + i ) / radeg ) * sin( *( lon + i ) / radeg ); 00778 up[2] = sin( *( lat + i ) / radeg ); 00779 00780 upxy = sqrt( up[0] * up[0] + up[1] * up[1] ); 00781 00782 ea[0] = -up[1] / upxy; 00783 ea[1] = up[0] / upxy; 00784 ea[2] = 0.; 00785 00786 cross_prod( up, ea, no ); 00787 00788 /* 00789 * Store vectors in 3x3 array 00790 */ 00791 for( j = 0; j < 3; j++ ) 00792 { 00793 xlmat[0][j] = ea[j]; 00794 xlmat[1][j] = no[j]; 00795 xlmat[2][j] = up[j]; 00796 } 00797 /* 00798 * Compute geocentric position vector 00799 */ 00800 xlatg = radeg * atan( tan( *( lat + i ) / radeg ) * omf2 ); 00801 gv[0] = cos( xlatg / radeg ) * cos( *( lon + i ) / radeg ); 00802 gv[1] = cos( xlatg / radeg ) * sin( *( lon + i ) / radeg ); 00803 gv[2] = sin( xlatg / radeg ); 00804 00805 r = re * ( 1. - f ) / 00806 sqrt( 1. - ( 2. - f ) * f * pow( cos( xlatg / radeg ), 2 ) ); 00807 00808 /* note that pos is in m but rest of constants are in km, hence the 00809 1000 factor */ 00810 for( j = 0; j < 3; j++ ) 00811 rh[j] = pos[j] / 1000. - r * gv[j]; 00812 /* 00813 * Transform the pixel-to-spacecraft vector into the local frame 00814 */ 00815 matrix_mult( rh, xlmat, rl ); 00816 /* 00817 * Compute the sensor zenith and azimuth 00818 * if zenith close to 0, set azimuth to 0 (and normalize azimuth) 00819 */ 00820 *( senz + i ) = radeg * atan2( sqrt( rl[0] * rl[0] + rl[1] * rl[1] ), 00821 rl[2] ); 00822 if( *( senz + i ) > 0.05 ) 00823 *( sena + i ) = radeg * atan2( rl[0], rl[1] ); 00824 else 00825 *( sena + i ) = 0.; 00826 00827 if( *( sena + i ) < 0. ) *( sena + i ) += 360.; 00828 } 00829 /* 00830 * and end 00831 */ 00832 return 0; 00833 } 00834 00835 void matrix_mult( double vecin[3], double matrix[3][3], double vecout[3] ) 00836 /******************************************************************* 00837 00838 matrix_mult 00839 00840 purpose: multiply a vector by a matrix and produce the output vector 00841 00842 Returns type: void 00843 00844 Parameters: (in calling order) 00845 Type Name I/O Description 00846 ---- ---- --- ----------- 00847 double[3] vecin I input vector 00848 double[3][3] matrix I rotation matrix 00849 double[3] vecout O rotated vector 00850 00851 Modification history: 00852 Programmer Date Description of change 00853 ---------- ---- --------------------- 00854 W. Robinson, SAIC 2-Nov-2005 Original development 00855 00856 *******************************************************************/ 00857 { 00858 int i, j; 00859 for( i = 0; i < 3; i++ ) 00860 { 00861 vecout[i] = 0.; 00862 for( j = 0; j < 3; j++ ) 00863 { 00864 vecout[i] += matrix[i][j] * vecin[j]; 00865 } 00866 } 00867 } 00868 00869 void cross_prod( double *v1, double *v2, double *vout ) 00870 /******************************************************************* 00871 00872 cross_prod 00873 00874 purpose: produce the cross product of 2 vectors 00875 00876 Returns type: void 00877 00878 Parameters: (in calling order) 00879 Type Name I/O Description 00880 ---- ---- --- ----------- 00881 double * v1 I vector 1 00882 double * v2 I vector 1 00883 double * vout O v1 X v2 00884 00885 Modification history: 00886 Programmer Date Description of change 00887 ---------- ---- --------------------- 00888 W. Robinson, SAIC 4-Jan-2006 Original development 00889 00890 *******************************************************************/ 00891 { 00892 *vout = v1[1] * v2[2] - v1[2] * v2[1]; 00893 *( vout + 1 ) = v1[2] * v2[0] - v1[0] * v2[2]; 00894 *( vout + 2 ) = v1[0] * v2[1] - v1[1] * v2[0]; 00895 }
1.7.6.1