25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

284 lines
5.6 KiB

  1. /*
  2. * Atpdec
  3. * Copyright (c) 2003 by Thierry Leconte (F4DWV)
  4. *
  5. * $Id$
  6. *
  7. * This library is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Library General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Library General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Library General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. *
  21. */
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <sndfile.h>
  25. #include <math.h>
  26. typedef struct {
  27. double slope;
  28. double offset;
  29. } rgparam;
  30. static void rgcomp(double x[16], rgparam *rgpr)
  31. {
  32. /* 0.106,0.215,0.324,0.434,0.542,0.652,0.78,0.87 ,0.0 */
  33. const double y[9] = { 31.1,63.0,95.0,127.2,158.9,191.1,228.6,255.0, 0.0 };
  34. const double yavg=(y[0]+y[1]+y[2]+y[4]+y[5]+y[6]+y[7]+y[8])/9.0;
  35. double xavg;
  36. double sxx,sxy;
  37. int i;
  38. for(i=0,xavg=0.0;i<9;i++)
  39. xavg+=x[i];
  40. xavg/=9;
  41. for(i=0,sxx=0.0;i<9;i++) {
  42. float t=x[i]-xavg;
  43. sxx+=t*t;
  44. }
  45. for(i=0,sxy=0.0;i<9;i++) {
  46. sxy+=(x[i]-xavg)*(y[i]-yavg);
  47. }
  48. rgpr->slope=sxy/sxx;
  49. rgpr->offset=yavg-rgpr->slope*xavg;
  50. }
  51. static double rgcal(float x,rgparam *rgpr)
  52. {
  53. return(rgpr->slope*x+rgpr->offset);
  54. }
  55. static double tele[16];
  56. static nbtele;
  57. int Calibrate(float **prow,int nrow,int offset)
  58. {
  59. double teleline[3000];
  60. double wedge[16];
  61. rgparam regr[30];
  62. int n;
  63. int k;
  64. int mtelestart,telestart;
  65. int channel=-1;
  66. float max;
  67. printf("Calibration ");
  68. fflush(stdout);
  69. /* build telemetry values lines */
  70. for(n=0;n<nrow;n++) {
  71. int i;
  72. teleline[n]=0.0;
  73. for(i=3;i<43;i++)
  74. teleline[n]+=prow[n][i+offset+909];
  75. teleline[n]/=40;
  76. }
  77. if(nrow<192) {
  78. fprintf(stderr," impossible, not enought row\n");
  79. return (0);
  80. }
  81. /* find telemetry start */
  82. max=0.0;mtelestart=0;
  83. for(n=nrow/3-64;n<2*nrow/3-64;n++) {
  84. float df;
  85. df=(teleline[n-4]+teleline[n-3]+teleline[n-2]+teleline[n-1])/(teleline[n]+teleline[n+1]+teleline[n+2]+teleline[n+3]);
  86. if(df> max){ mtelestart=n; max=df; }
  87. }
  88. mtelestart-=64;
  89. telestart=mtelestart%128;
  90. if(mtelestart <0 || nrow<telestart+128) {
  91. fprintf(stderr," impossible, not enought row\n");
  92. return (0);
  93. }
  94. /* compute wedges and regression */
  95. for(n=telestart,k=0;n<nrow-128;n+=128,k++) {
  96. int j;
  97. for(j=0;j<16;j++) {
  98. int i;
  99. wedge[j]=0.0;
  100. for(i=1;i<7;i++)
  101. wedge[j]+=teleline[n+j*8+i];
  102. wedge[j]/=6;
  103. }
  104. rgcomp(wedge,&(regr[k]));
  105. if (k==1) {
  106. /* channel ID */
  107. for(j=0,max=10000.0,channel=-1;j<6;j++) {
  108. float df;
  109. df=wedge[15]-wedge[j]; df=df*df;
  110. if (df<max) { channel=j; max=df; }
  111. }
  112. for(j=0;j<16;j++)
  113. tele[j]=rgcal(wedge[j],&(regr[k]));
  114. }
  115. }
  116. nbtele=k;
  117. /* calibrate */
  118. for(n=0;n<nrow;n++) {
  119. float *pixelv;
  120. int i,c;
  121. pixelv=prow[n];
  122. for(i=0;i<954;i++) {
  123. float pv;
  124. int k,kof;
  125. pv=pixelv[i+offset];
  126. k=(n-telestart)/128;
  127. if(k>=nbtele) k=nbtele-1;
  128. kof=(n-telestart)%128;
  129. if(kof<64) {
  130. if(k<1) {
  131. pv=rgcal(pv,&(regr[k]));
  132. } else {
  133. pv=rgcal(pv,&(regr[k]))*(64+kof)/128.0+
  134. rgcal(pv,&(regr[k-1]))*(64-kof)/128.0;
  135. }
  136. } else {
  137. if((k+1)>=nbtele) {
  138. pv=rgcal(pv,&(regr[k]));
  139. } else {
  140. pv=rgcal(pv,&(regr[k]))*(192-kof)/128.0+
  141. rgcal(pv,&(regr[k+1]))*(kof-64)/128.0;
  142. }
  143. }
  144. if(pv>255.0) pv=255.0;
  145. if(pv<0.0) pv=0.0;
  146. pixelv[i+offset]=pv;
  147. }
  148. }
  149. printf("Done\n");
  150. return(channel);
  151. }
  152. /* ------------------------------temperature calibration -----------------------*/
  153. extern int satnum;
  154. const struct {
  155. float d[4][3];
  156. struct {
  157. float vc,A,B;
  158. } rad[3];
  159. struct {
  160. float Ns;
  161. float b[3];
  162. } cor[3];
  163. } satcal[2]=
  164. #include "satcal.h"
  165. typedef struct {
  166. double Nbb;
  167. double Cs;
  168. double Cb;
  169. int ch;
  170. } tempparam;
  171. /* temperature compensation for IR channel */
  172. static void tempcomp(double t[16], int ch,tempparam *tpr)
  173. {
  174. double Tbb,T[4];
  175. double C;
  176. double r;
  177. int n;
  178. tpr->ch=ch-3;
  179. /* compute equivalent T black body */
  180. for (n=0;n<4;n++) {
  181. float d0,d1,d2;
  182. C=t[9+n]*4;
  183. d0=satcal[satnum].d[n][0];
  184. d1=satcal[satnum].d[n][1];
  185. d2=satcal[satnum].d[n][2];
  186. T[n]=d0;
  187. T[n]+=d1*C; C=C*C;
  188. T[n]+=d2*C;
  189. }
  190. Tbb=(T[0]+T[1]+T[2]+T[3])/4.0;
  191. Tbb=satcal[satnum].rad[tpr->ch].A+satcal[satnum].rad[tpr->ch].B*Tbb;
  192. /* compute radiance Black body */
  193. C=satcal[satnum].rad[tpr->ch].vc;
  194. tpr->Nbb=c1*C*C*C/(exp(c2*C/Tbb)-1.0);
  195. /* store Count Blackbody and space */
  196. tpr->Cs=1023; /* don't know how to get it in the APT telemetry any idea ? */
  197. tpr->Cb=t[14]*4.0;
  198. }
  199. static double tempcal(float Ce,tempparam *rgpr)
  200. {
  201. double Nl,Nc,Ns,Ne;
  202. double T,vc;
  203. Ns=satcal[satnum].cor[rgpr->ch].Ns;
  204. Nl=Ns+(rgpr->Nbb-Ns)*(rgpr->Cs-Ce*4.0)/(rgpr->Cs-rgpr->Cb);
  205. Nc=satcal[satnum].cor[rgpr->ch].b[0]+
  206. satcal[satnum].cor[rgpr->ch].b[1]*Nl+
  207. satcal[satnum].cor[rgpr->ch].b[2]*Nl*Nl;
  208. Ne=Nl+Nc;
  209. vc=satcal[satnum].rad[rgpr->ch].vc;
  210. T=c2*vc/log(c1*vc*vc*vc/Ne+1.0);
  211. T=(T-satcal[satnum].rad[rgpr->ch].A)/satcal[satnum].rad[rgpr->ch].B;
  212. /* rescale to range 0-255 for -60-+40 °C */
  213. T=(T-273.15+60)/100*255.0;
  214. return(T);
  215. }
  216. int Temperature(float **prow,int nrow,int channel,int offset)
  217. {
  218. tempparam temp;
  219. int n;
  220. printf("Temperature ");
  221. tempcomp(tele,channel,&temp);
  222. for(n=0;n<nrow;n++) {
  223. float *pixelv;
  224. int i,c;
  225. pixelv=prow[n];
  226. for(i=0;i<954;i++) {
  227. float pv;
  228. pv=tempcal(pixelv[i+offset],&temp);
  229. if(pv>255.0) pv=255.0;
  230. if(pv<0.0) pv=0.0;
  231. pixelv[i+offset]=pv;
  232. }
  233. }
  234. printf("Done\n");
  235. }