/* calib.c Calibration for IDD and gvar raw data from GOES-8,9,10 Keith Brewster CAPS/Univ of Oklahoma */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include "mc_area.h" int chtab[4] = {2, 3, 4, 5}; int fkidx[6] = {-1, -1, 0, 1, 2, 3}; int iridx[6] = {-1, -1, 3, 4, 1, 2}; /* These calibration data are obtained from the following URL http://cimss.ssec.wisc.edu/calibration/ */ double g08fk1[4] = { 199980.00, 38792.00, 9737.80, 6944.50 }; double g08fk2[4] = { 3684.20, 2132.70, 1345.30, 1202.00 }; double g08tc1[4] = { 0.63568, 0.60603, 0.37351, 0.22171 }; double g08tc2[4] = { 0.99911, 0.99858, 0.99873, 0.99916 }; double g09fk1[4] = { 198810.00, 38732.00, 9717.20, 6899.50 }; double g09fk2[4] = { 3677.00, 2131.60, 1344.40, 1199.40 }; double g09tc1[4] = { 0.58637, 0.48409, 0.36225, 0.20144 }; double g09tc2[4] = { 0.99917, 0.99887, 0.99876, 0.99923 }; double g10fk1[4] = { 198400.00, 39086.00, 9774.30, 6828.50 }; double g10fk2[4] = { 3674.50, 2138.10, 1347.00, 1195.20 }; double g10tc1[4] = { 0.62223, 0.61437, 0.27790, 0.21145 }; double g10tc2[4] = { 0.99912, 0.99857, 0.99905, 0.99919 }; double g11fk1[4] = { 200180.00, 38789.00, 9653.40, 6877.80 }; double g11fk2[4] = { 3685.40, 2132.70, 1341.50, 1198.10 }; double g11tc1[4] = { 0.62864, 0.59339, 0.38284, 0.20258 }; double g11tc2[4] = { 0.99911, 0.99861, 0.99869, 0.99923 }; double g12fk1[4] = { 200960.00, 43702.00, 9685.90, 5047.10 }; double g12fk2[4] = { 3690.20, 2219.10, 1343.00, 1080.70 }; double g12tc1[4] = { 0.69703, 5.08315, 0.37554, 0.09537 }; double g12tc2[4] = { 0.99902, 0.98872, 0.99872, 0.99960 }; /* vis2radiance From raw GVAR visible data compute visible radiance */ int vis2radiance( gvcal, visim, vradiance, npixel ) struct cal_gvar *gvcal; long *visim; float *vradiance; long npixel; { static float vis1g; static float vis2g; static float vbias; static int avgd; long rawval; int i; if ( avgd != 1 ) { vis1g=0.; vis2g=0.; vbias=0.; for ( i=0 ; i < 8 ; i++) { vis1g+=gvcal->vis1gain[i]; vis2g+=gvcal->vis2gain[i]; vbias+=gvcal->visbias[i]; } vis1g=0.125*vis1g; vis2g=0.125*vis2g; vbias=0.125*vbias; printf(" Average vis 1 gain: %10.4f\n",vis1g); printf(" Average vis 2 gain: %10.4f\n",vis2g); printf(" Average vis bias: %10.4f\n",vbias); avgd=1; } for ( i=0 ; i < npixel ; i++ ){ rawval=*(visim+i); *(vradiance+i)= (vis2g*(rawval*rawval))+(vis1g*rawval)+vbias; } return(0); } /* vis2albedo From raw GVAR visible data compute visible albedo */ int vis2albedo( gvcal, visim, albedo, npixel) struct cal_gvar *gvcal; long *visim; float *albedo; long npixel; { static float vis1g; static float vis2g; static float vbias; static int avgd; float albtem,albmin,albmax; long rawval; int i; if ( avgd != 1 ) { vis1g=0.; vis2g=0.; vbias=0.; for ( i=0 ; i < 8 ; i++) { vis1g+=gvcal->vis1gain[i]; vis2g+=gvcal->vis2gain[i]; vbias+=gvcal->visbias[i]; } vis1g=0.125*vis1g; vis2g=0.125*vis2g; vbias=0.125*vbias; printf(" Average vis 1 gain: %10.4f\n",vis1g); printf(" Average vis 2 gain: %10.4f\n",vis2g); printf(" Average vis bias: %10.4f\n",vbias); avgd=1; } albmin=1.0; albmax=0.0; for ( i=0 ; i < npixel ; i++ ){ if( *(visim+i) > 0 ) { rawval=*(visim+i); albtem=gvcal->albedcon* ( (vis2g*(rawval*rawval))+(vis1g*rawval)+vbias); if( albtem > 1.0) albtem = 1.0; if( albtem < 0.0 ) albtem = 0.0; if( albtem > albmax) albmax = albtem; if( albtem < albmin) albmin = albtem; *(albedo+i)=albtem; } else *(albedo+i)=-999.0; if( (i % 500) == 0 ) { printf(" pixel %i raw %i albedo %10.4f\n", i,(int)*(visim+i),*(albedo+i)); } } printf(" vis2albedo: Minimum albedo: %8.4f Maximum albedo: %8.4f\n", albmin,albmax); return(0); } /* ir2radiance From raw GVAR IR data compute IR radiance */ int ir2radiance( gvcal, irim, radiance, ichan, npixel ) struct cal_gvar *gvcal; long *irim; float *radiance; int ichan; long npixel; { double gaininv; double bias; double rawval; int i,index; index=iridx[ichan]; printf( " gain is %10.4f bias: %10.4f\n", gvcal->ir1gain[index],gvcal->ir1bias[index]); gaininv = 1./((double)(gvcal->ir1gain[index])); bias = (double)(gvcal->ir1bias[index]); for ( i=0 ; i < npixel ; i++ ){ rawval=(double)(*(irim+i)); *(radiance+i)=(float)(gaininv*(rawval-bias)); } return(0); } /* ir2bright From raw GVAR IR data compute brightness temperature */ int ir2bright( gvcal, irim, bright, ibird, ichan, npixel ) struct cal_gvar *gvcal; long *irim; float *bright; int ibird; int ichan; long npixel; { double gaininv,bias; double rawval; double radiance; double expon,tt; float brttem,brtmin,brtmax; int i, index; index=iridx[ichan]; gaininv = 1./((double) (gvcal->ir1gain[index])); bias = (double) (gvcal->ir1bias[index]); printf( " gain is %10.4f bias: %10.4f\n", gvcal->ir1gain[index],bias); index=fkidx[ichan]; if ( index > -1 ) { printf(" Using calibration for goes%2d Channel %d\n", ibird,chtab[index]); } else { printf(" Problem with table indexing for ichan %d\n", ichan); printf(" Stopping in ir2bright\n"); exit(0); } brtmax=0.0; brtmin=999.0; if ( ibird == 8 ){ printf( " fk1:%10.2f fk2:%10.2f tc1:%8.4f tc2:%8.4f\n", g08fk1[index],g08fk2[index],g08tc1[index],g08tc2[index]); for ( i=0 ; i < npixel ; i++ ){ if(*(irim+i) > 0 ) { rawval=(double)(*(irim+i)); radiance=gaininv*(rawval-bias); expon=(g08fk1[index]/radiance) + 1.; tt=g08fk2[index]/log(expon); brttem=(tt-g08tc1[index])/ g08tc2[index]; if( brttem < 0.0 ) brttem = 0.0; if( brttem > brtmax ) brtmax = brttem; if( brttem < brtmin ) brtmin = brttem; *(bright+i)=brttem; } else { *(bright+i)=-999.; } if( (i % 500) == 0 ) { printf(" pixel:%i raw:%i radiance:%10.2f bright:%10.2f\n", i,(int)*(irim+i),radiance,*(bright+i)); } } } else if ( ibird == 9 ){ printf( " fk1:%10.2f fk2:%10.2f tc1:%8.4f tc2:%8.4f\n", g09fk1[index],g09fk2[index],g09tc1[index],g09tc2[index]); for ( i=0 ; i < npixel ; i++ ){ if(*(irim+i) > 0 ) { rawval=(double)(*(irim+i)); radiance=gaininv*(rawval-bias); expon=(g09fk1[index]/radiance) + 1.; tt=g09fk2[index]/log(expon); brttem=(tt-g09tc1[index])/ g09tc2[index]; if( brttem < 0.0 ) brttem = 0.0; if( brttem > brtmax ) brtmax = brttem; if( brttem < brtmin ) brtmin = brttem; *(bright+i)=brttem; } else { *(bright+i)=-999.; } if( (i % 500) == 0 ) printf(" pixel:%i raw:%i radiance:%10.2f bright:%10.2f\n", i,(int)*(irim+i),radiance,*(bright+i)); } } else if ( ibird == 10 ){ printf( " fk1:%10.2f fk2:%10.2f tc1:%8.4f tc2:%8.4f\n", g10fk1[index],g10fk2[index],g10tc1[index],g10tc2[index]); for ( i=0 ; i < npixel ; i++ ){ if(*(irim+i) > 0 ) { rawval=(double)(*(irim+i)); radiance=gaininv*(rawval-bias); expon=(g10fk1[index]/radiance) + 1.; tt=g10fk2[index]/log(expon); brttem=(tt-g10tc1[index])/ g10tc2[index]; if( brttem < 0.0 ) brttem = 0.0; if( brttem > brtmax ) brtmax = brttem; if( brttem < brtmin ) brtmin = brttem; *(bright+i)=brttem; } else { *(bright+i)=-999.; } if( (i % 500) == 0 ) printf(" pixel:%i raw:%i radiance:%10.2f bright:%10.2f\n", i,(int)*(irim+i),radiance,*(bright+i)); } } else if ( ibird == 11 ){ printf( " fk1:%10.2f fk2:%10.2f tc1:%8.4f tc2:%8.4f\n", g11fk1[index],g11fk2[index],g11tc1[index],g11tc2[index]); for ( i=0 ; i < npixel ; i++ ){ if(*(irim+i) > 0 ) { rawval=(double)(*(irim+i)); radiance=gaininv*(rawval-bias); expon=(g11fk1[index]/radiance) + 1.; tt=g11fk2[index]/log(expon); brttem=(tt-g11tc1[index])/ g11tc2[index]; if( brttem < 0.0 ) brttem = 0.0; if( brttem > brtmax ) brtmax = brttem; if( brttem < brtmin ) brtmin = brttem; *(bright+i)=brttem; } else { *(bright+i)=-999.; } if( (i % 500) == 0 ) printf(" pixel:%i raw:%i radiance:%10.2f bright:%10.2f\n", i,(int)*(irim+i),radiance,*(bright+i)); } } else if ( ibird == 12 ){ if ( index == 5 ) index = 4; printf( " fk1:%10.2f fk2:%10.2f tc1:%8.4f tc2:%8.4f\n", g12fk1[index],g12fk2[index],g12tc1[index],g12tc2[index]); for ( i=0 ; i < npixel ; i++ ){ if(*(irim+i) > 0 ) { rawval=(double)(*(irim+i)); radiance=gaininv*(rawval-bias); expon=(g12fk1[index]/radiance) + 1.; tt=g12fk2[index]/log(expon); brttem=(tt-g12tc1[index])/ g12tc2[index]; if( brttem < 0.0 ) brttem = 0.0; if( brttem > brtmax ) brtmax = brttem; if( brttem < brtmin ) brtmin = brttem; *(bright+i)=brttem; } else { *(bright+i)=-999.; } if( (i % 500) == 0 ) printf(" pixel:%i raw:%i radiance:%10.2f bright:%10.2f\n", i,(int)*(irim+i),radiance,*(bright+i)); } } else { printf(" That satellite is unknown. ibird = %d\n",ibird); printf(" Time to update tables in calib.c \n"); return(-1); } printf(" Minimum temp: %8.2f K Maximum temp: %8.2f K\n", brtmin,brtmax); printf(" Minimum temp: %8.2f C Maximum temp: %8.2f C\n", (brtmin-273.15),(brtmax-273.15)); return(0); } /* cnt2albedo From 1-byte VIS counts estimate albedo */ int cnt2albedo( visim, albedo, npixel ) long *visim; float *albedo; long npixel; { int i; float scaleinv,albtem,albmin,albmax; long imgcnt,imgmin,imgmax; imgmin=9999; imgmax=-9999; albmin=999.; albmax=0.; scaleinv = 1./255.; for ( i = 0 ; i < npixel ; i++ ) { imgcnt=*(visim+i); albtem=scaleinv*(float)(*(visim+i)); albtem=albtem*albtem; if ( albtem < 0. ) albtem = 0.; if ( albtem > 1. ) albtem = 1.0; if ( imgcnt < imgmin ) imgmin = imgcnt; if ( imgcnt > imgmax ) imgmax = imgcnt; if ( albtem < albmin ) albmin = albtem; if ( albtem > albmax ) albmax = albtem; *(albedo+i)=albtem; } printf(" cnt2albedo: Minimum imgcnt: %ld Maximum imgcnt: %ld\n", imgmin,imgmax); printf(" cnt2albedo: Minimum albedo: %8.4f Maximum albedo: %8.4f\n", albmin,albmax); return(0); } /* cnt2bright From 1-byte BRIT counts compute brightness temperature */ int cnt2bright( irim, bright, npixel ) long *irim; float *bright; long npixel; { static long c1 = 418; static long c2 = 660; static long irthr = 176; int i; float brttem,brtmin,brtmax; brtmin=999.; brtmax=0.; for ( i = 0 ; i < npixel ; i++ ) { if ( *(irim+i) > irthr ) { brttem=(float)(c1 - *(irim+i)); if ( brttem < brtmin ) brtmin = brttem; if ( brttem > brtmax ) brtmax = brttem; *(bright+i)=brttem; } else if ( *(irim+i) > 0 ) { brttem=0.5 * (float)(c2 - *(irim+i)); if ( brttem < 0. ) brttem = 0.; if ( brttem < brtmin ) brtmin = brttem; if ( brttem > brtmax ) brtmax = brttem; *(bright+i)=brttem; } else *(bright+i)=-999.0; } printf(" Minimum temp: %8.2f K Maximum temp: %8.2f K\n", brtmin,brtmax); printf(" Minimum temp: %8.2f C Maximum temp: %8.2f C\n", (brtmin-273.15),(brtmax-273.15)); return(0); }