You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

276 lines
5.5 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. #define REGORDER 3
  27. typedef struct {
  28. double cf[REGORDER+1] ;
  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. extern void polyreg(const int m,const int n,const double x[],const double y[],double c[]);
  35. polyreg(REGORDER,9,x,y,rgpr->cf);
  36. }
  37. static double rgcal(float x,rgparam *rgpr)
  38. {
  39. double y,p;
  40. int i;
  41. for(i=0,y=0.0,p=1.0;i<REGORDER+1;i++) {
  42. y+=rgpr->cf[i]*p;
  43. p=p*x;
  44. }
  45. return(y);
  46. }
  47. static double tele[16];
  48. static nbtele;
  49. int Calibrate(float **prow,int nrow,int offset)
  50. {
  51. double teleline[3000];
  52. double wedge[16];
  53. rgparam regr[30];
  54. int n;
  55. int k;
  56. int mtelestart,telestart;
  57. int channel=-1;
  58. float max;
  59. printf("Calibration ");
  60. fflush(stdout);
  61. /* build telemetry values lines */
  62. for(n=0;n<nrow;n++) {
  63. int i;
  64. teleline[n]=0.0;
  65. for(i=3;i<43;i++)
  66. teleline[n]+=prow[n][i+offset+909];
  67. teleline[n]/=40;
  68. }
  69. if(nrow<192) {
  70. fprintf(stderr," impossible, not enought row\n");
  71. return (0);
  72. }
  73. /* find telemetry start */
  74. max=0.0;mtelestart=0;
  75. for(n=nrow/3-64;n<2*nrow/3-64;n++) {
  76. float df;
  77. df=(teleline[n-4]+teleline[n-3]+teleline[n-2]+teleline[n-1])/(teleline[n]+teleline[n+1]+teleline[n+2]+teleline[n+3]);
  78. if(df> max){ mtelestart=n; max=df; }
  79. }
  80. mtelestart-=64;
  81. telestart=mtelestart%128;
  82. if(mtelestart <0 || nrow<telestart+128) {
  83. fprintf(stderr," impossible, not enought row\n");
  84. return (0);
  85. }
  86. /* compute wedges and regression */
  87. for(n=telestart,k=0;n<nrow-128;n+=128,k++) {
  88. int j;
  89. for(j=0;j<16;j++) {
  90. int i;
  91. wedge[j]=0.0;
  92. for(i=1;i<7;i++)
  93. wedge[j]+=teleline[n+j*8+i];
  94. wedge[j]/=6;
  95. }
  96. rgcomp(wedge,&(regr[k]));
  97. if (k==1) {
  98. /* channel ID */
  99. for(j=0,max=10000.0,channel=-1;j<6;j++) {
  100. float df;
  101. df=wedge[15]-wedge[j]; df=df*df;
  102. if (df<max) { channel=j; max=df; }
  103. }
  104. for(j=0;j<16;j++)
  105. tele[j]=rgcal(wedge[j],&(regr[k]));
  106. }
  107. }
  108. nbtele=k;
  109. /* calibrate */
  110. for(n=0;n<nrow;n++) {
  111. float *pixelv;
  112. int i,c;
  113. pixelv=prow[n];
  114. for(i=0;i<954;i++) {
  115. float pv;
  116. int k,kof;
  117. pv=pixelv[i+offset];
  118. k=(n-telestart)/128;
  119. if(k>=nbtele) k=nbtele-1;
  120. kof=(n-telestart)%128;
  121. if(kof<64) {
  122. if(k<1) {
  123. pv=rgcal(pv,&(regr[k]));
  124. } else {
  125. pv=rgcal(pv,&(regr[k]))*(64+kof)/128.0+
  126. rgcal(pv,&(regr[k-1]))*(64-kof)/128.0;
  127. }
  128. } else {
  129. if((k+1)>=nbtele) {
  130. pv=rgcal(pv,&(regr[k]));
  131. } else {
  132. pv=rgcal(pv,&(regr[k]))*(192-kof)/128.0+
  133. rgcal(pv,&(regr[k+1]))*(kof-64)/128.0;
  134. }
  135. }
  136. if(pv>255.0) pv=255.0;
  137. if(pv<0.0) pv=0.0;
  138. pixelv[i+offset]=pv;
  139. }
  140. }
  141. printf("Done\n");
  142. return(channel);
  143. }
  144. /* ------------------------------temperature calibration -----------------------*/
  145. extern int satnum;
  146. const struct {
  147. float d[4][3];
  148. struct {
  149. float vc,A,B;
  150. } rad[3];
  151. struct {
  152. float Ns;
  153. float b[3];
  154. } cor[3];
  155. } satcal[2]=
  156. #include "satcal.h"
  157. typedef struct {
  158. double Nbb;
  159. double Cs;
  160. double Cb;
  161. int ch;
  162. } tempparam;
  163. /* temperature compensation for IR channel */
  164. static void tempcomp(double t[16], int ch,tempparam *tpr)
  165. {
  166. double Tbb,T[4];
  167. double C;
  168. double r;
  169. int n;
  170. tpr->ch=ch-3;
  171. /* compute equivalent T black body */
  172. for (n=0;n<4;n++) {
  173. float d0,d1,d2;
  174. C=t[9+n]*4;
  175. d0=satcal[satnum].d[n][0];
  176. d1=satcal[satnum].d[n][1];
  177. d2=satcal[satnum].d[n][2];
  178. T[n]=d0;
  179. T[n]+=d1*C; C=C*C;
  180. T[n]+=d2*C;
  181. }
  182. Tbb=(T[0]+T[1]+T[2]+T[3])/4.0;
  183. Tbb=satcal[satnum].rad[tpr->ch].A+satcal[satnum].rad[tpr->ch].B*Tbb;
  184. /* compute radiance Black body */
  185. C=satcal[satnum].rad[tpr->ch].vc;
  186. tpr->Nbb=c1*C*C*C/(exp(c2*C/Tbb)-1.0);
  187. /* store Count Blackbody and space */
  188. tpr->Cs=1023; /* don't know how to get it in the APT telemetry any idea ? */
  189. tpr->Cb=t[14]*4.0;
  190. }
  191. static double tempcal(float Ce,tempparam *rgpr)
  192. {
  193. double Nl,Nc,Ns,Ne;
  194. double T,vc;
  195. Ns=satcal[satnum].cor[rgpr->ch].Ns;
  196. Nl=Ns+(rgpr->Nbb-Ns)*(rgpr->Cs-Ce*4.0)/(rgpr->Cs-rgpr->Cb);
  197. Nc=satcal[satnum].cor[rgpr->ch].b[0]+
  198. satcal[satnum].cor[rgpr->ch].b[1]*Nl+
  199. satcal[satnum].cor[rgpr->ch].b[2]*Nl*Nl;
  200. Ne=Nl+Nc;
  201. vc=satcal[satnum].rad[rgpr->ch].vc;
  202. T=c2*vc/log(c1*vc*vc*vc/Ne+1.0);
  203. T=(T-satcal[satnum].rad[rgpr->ch].A)/satcal[satnum].rad[rgpr->ch].B;
  204. /* rescale to range 0-255 for -60-+40 °C */
  205. T=(T-273.15+60)/100*255.0;
  206. return(T);
  207. }
  208. int Temperature(float **prow,int nrow,int channel,int offset)
  209. {
  210. tempparam temp;
  211. int n;
  212. printf("Temperature ");
  213. tempcomp(tele,channel,&temp);
  214. for(n=0;n<nrow;n++) {
  215. float *pixelv;
  216. int i,c;
  217. pixelv=prow[n];
  218. for(i=0;i<954;i++) {
  219. float pv;
  220. pv=tempcal(pixelv[i+offset],&temp);
  221. if(pv>255.0) pv=255.0;
  222. if(pv<0.0) pv=0.0;
  223. pixelv[i+offset]=pv;
  224. }
  225. }
  226. printf("Done\n");
  227. }