/* * Atpdec * Copyright (c) 2003 by Thierry Leconte (F4DWV) * * $Id$ * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include typedef struct { double slope; double offset; } rgparam; static void rgcomp(double x[16], rgparam *rgpr) { /* 0.106,0.215,0.324,0.434,0.542,0.652,0.78,0.87 ,0.0 */ const double y[9] = { 31.1,63.0,95.0,127.2,158.9,191.1,228.6,255.0, 0.0 }; const double yavg=(y[0]+y[1]+y[2]+y[4]+y[5]+y[6]+y[7]+y[8])/9.0; double xavg; double sxx,sxy; int i; for(i=0,xavg=0.0;i<9;i++) xavg+=x[i]; xavg/=9; for(i=0,sxx=0.0;i<9;i++) { float t=x[i]-xavg; sxx+=t*t; } for(i=0,sxy=0.0;i<9;i++) { sxy+=(x[i]-xavg)*(y[i]-yavg); } rgpr->slope=sxy/sxx; rgpr->offset=yavg-rgpr->slope*xavg; } static double rgcal(float x,rgparam *rgpr) { return(rgpr->slope*x+rgpr->offset); } static double tele[16]; static nbtele; int Calibrate(float **prow,int nrow,int offset) { double teleline[3000]; double wedge[16]; rgparam regr[30]; int n; int k; int mtelestart,telestart; int channel=-1; float max; printf("Calibration "); fflush(stdout); /* build telemetry values lines */ for(n=0;n max){ mtelestart=n; max=df; } } mtelestart-=64; telestart=mtelestart%128; if(mtelestart <0 || nrow=nbtele) k=nbtele-1; kof=(n-telestart)%128; if(kof<64) { if(k<1) { pv=rgcal(pv,&(regr[k])); } else { pv=rgcal(pv,&(regr[k]))*(64+kof)/128.0+ rgcal(pv,&(regr[k-1]))*(64-kof)/128.0; } } else { if((k+1)>=nbtele) { pv=rgcal(pv,&(regr[k])); } else { pv=rgcal(pv,&(regr[k]))*(192-kof)/128.0+ rgcal(pv,&(regr[k+1]))*(kof-64)/128.0; } } if(pv>255.0) pv=255.0; if(pv<0.0) pv=0.0; pixelv[i+offset]=pv; } } printf("Done\n"); return(channel); } /* ------------------------------temperature calibration -----------------------*/ extern int satnum; const struct { float d[4][3]; struct { float vc,A,B; } rad[3]; struct { float Ns; float b[3]; } cor[3]; } satcal[2]= #include "satcal.h" typedef struct { double Nbb; double Cs; double Cb; int ch; } tempparam; /* temperature compensation for IR channel */ static void tempcomp(double t[16], int ch,tempparam *tpr) { double Tbb,T[4]; double C; double r; int n; tpr->ch=ch-3; /* compute equivalent T black body */ for (n=0;n<4;n++) { float d0,d1,d2; C=t[9+n]*4; d0=satcal[satnum].d[n][0]; d1=satcal[satnum].d[n][1]; d2=satcal[satnum].d[n][2]; T[n]=d0; T[n]+=d1*C; C=C*C; T[n]+=d2*C; } Tbb=(T[0]+T[1]+T[2]+T[3])/4.0; Tbb=satcal[satnum].rad[tpr->ch].A+satcal[satnum].rad[tpr->ch].B*Tbb; /* compute radiance Black body */ C=satcal[satnum].rad[tpr->ch].vc; tpr->Nbb=c1*C*C*C/(exp(c2*C/Tbb)-1.0); /* store Count Blackbody and space */ tpr->Cs=1023; /* don't know how to get it in the APT telemetry any idea ? */ tpr->Cb=t[14]*4.0; } static double tempcal(float Ce,tempparam *rgpr) { double Nl,Nc,Ns,Ne; double T,vc; Ns=satcal[satnum].cor[rgpr->ch].Ns; Nl=Ns+(rgpr->Nbb-Ns)*(rgpr->Cs-Ce*4.0)/(rgpr->Cs-rgpr->Cb); Nc=satcal[satnum].cor[rgpr->ch].b[0]+ satcal[satnum].cor[rgpr->ch].b[1]*Nl+ satcal[satnum].cor[rgpr->ch].b[2]*Nl*Nl; Ne=Nl+Nc; vc=satcal[satnum].rad[rgpr->ch].vc; T=c2*vc/log(c1*vc*vc*vc/Ne+1.0); T=(T-satcal[satnum].rad[rgpr->ch].A)/satcal[satnum].rad[rgpr->ch].B; /* rescale to range 0-255 for -60-+40 °C */ T=(T-273.15+60)/100*255.0; return(T); } int Temperature(float **prow,int nrow,int channel,int offset) { tempparam temp; int n; printf("Temperature "); tempcomp(tele,channel,&temp); for(n=0;n255.0) pv=255.0; if(pv<0.0) pv=0.0; pixelv[i+offset]=pv; } } printf("Done\n"); }