00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033
00034 #include <cpl.h>
00035
00036 #include <math.h>
00037
00038 #include "vircam_mods.h"
00039 #include "vircam_utils.h"
00040 #include "vircam_stats.h"
00041 #include "vircam_pfits.h"
00042 #include "vircam_channel.h"
00043
00044
00045 #define SZCOLNAME 16
00046
00047 static double nom_val = 10000;
00048 static double nom_kfac = 0.1;
00049
00050
00051 static double linval(double inval, double k, double tolerance, int niter,
00052 double *b, int norder);
00053 static double getkfac(long index, long ncpts, float reset_time,
00054 float read_time, float delay_time, float exptime);
00055 static void getco(double *a, int nord, int m);
00056
00059
00114
00115
00116 extern int vircam_genlincur(double **fdata, int nimages, double *exps,
00117 double mindit, vir_tfits *chantab,
00118 int norder, cpl_table **lchantab,
00119 double **lindata, int *status) {
00120
00121 const char *fctid = "vircam_genlincur";
00122 int retval,i,j,nbad,oldnorder,nullval,k;
00123 long np;
00124 double *meds,sigfit,**aco,c0,val,lin_nom,*temp,*polyco,pt,*work,kfac;
00125 double a0,a1,sum,sumsq;
00126 parquet *p,*pp;
00127 cpl_table *ctab,*lc;
00128 cpl_array *exparray,*medsarray,*polyfitco;
00129 char colname[SZCOLNAME];
00130
00131
00132
00133 *lchantab = NULL;
00134 if (*status != VIR_OK)
00135 return(*status);
00136
00137
00138
00139 if (nimages < norder+1) {
00140 cpl_msg_error(fctid,"Not enought images (%d) for fit order (%d)",
00141 nimages,norder);
00142 FATAL_ERROR
00143 }
00144
00145
00146
00147 ctab = vircam_tfits_get_table(chantab);
00148 retval = vircam_chan_fill(ctab,&pp,&np);
00149 if (retval != VIR_OK) {
00150 *status = retval;
00151 return(retval);
00152 }
00153
00154
00155
00156
00157 lc = cpl_table_duplicate(ctab);
00158 oldnorder = cpl_table_get_int(lc,"norder",0,&nullval);
00159 if (oldnorder > norder) {
00160 for (i = norder+1; i <= oldnorder; i++) {
00161 snprintf(colname,SZCOLNAME,"coeff_%d",i);
00162 cpl_table_erase_column(lc,colname);
00163 }
00164 } else if (oldnorder < norder) {
00165 for (i = oldnorder+1; i <= norder; i++) {
00166 snprintf(colname,SZCOLNAME,"coeff_%d",i);
00167 if (cpl_table_has_column(lc,colname))
00168 continue;
00169 cpl_table_new_column(lc,colname,CPL_TYPE_DOUBLE);
00170 }
00171 }
00172
00173
00174
00175 exparray = cpl_array_wrap_double(exps,nimages);
00176 medsarray = cpl_array_new(nimages,CPL_TYPE_DOUBLE);
00177 meds = cpl_array_get_data_double(medsarray);
00178 aco = cpl_malloc(norder*sizeof(double *));
00179 for (i = 0; i < norder; i++)
00180 aco[i] = cpl_malloc(norder*sizeof(double));
00181 temp = cpl_malloc(norder*sizeof(double));
00182
00183
00184
00185 *lindata = cpl_malloc(nimages*np*sizeof(double));
00186
00187
00188
00189 nbad = 0;
00190 for (i = 0; i < np; i++) {
00191 p = pp + i;
00192
00193
00194
00195 for (j = 0; j < nimages; j++)
00196 meds[j] = fdata[j][i];
00197
00198
00199
00200 if (vircam_polyfit(exparray,medsarray,norder,1,1,3.0,3.0,&polyfitco,
00201 &sigfit) != VIR_OK) {
00202 nbad++;
00203 cpl_table_set_int(lc,"norder",i,norder);
00204 cpl_table_set_double(lc,"coeff_1",i,1.0);
00205 for (k = 1; k < norder; k++) {
00206 snprintf(colname,SZCOLNAME,"coeff_%d",k+1);
00207 cpl_table_set_double(lc,colname,i,0.0);
00208 }
00209 continue;
00210 }
00211 polyco = cpl_array_get_data_double(polyfitco);
00212
00213
00214
00215 for (j = 0; j < norder; j++) {
00216 getco(temp,norder,j+1);
00217 for (k = 0; k < norder; k++) {
00218 pt = pow(mindit,(double)(j-k));
00219 aco[j][k] = pt*temp[k];
00220 }
00221 }
00222
00223
00224
00225 if (vircam_solve_gauss(aco,polyco,norder) != VIR_OK) {
00226 nbad++;
00227 cpl_table_set_int(lc,"norder",i,norder);
00228 cpl_table_set_double(lc,"coeff_1",i,1.0);
00229 for (k = 1; k < norder; k++) {
00230 snprintf(colname,SZCOLNAME,"coeff_%d",k+1);
00231 cpl_table_set_double(lc,colname,i,0.0);
00232 }
00233 continue;
00234 }
00235
00236
00237
00238 c0 = polyco[0];
00239 for (j = 0; j < norder; j++) {
00240 polyco[j] /= pow(c0,(double)(j+1));
00241 snprintf(colname,SZCOLNAME,"coeff_%d",j+1);
00242 cpl_table_set_double(lc,colname,i,polyco[j]);
00243 }
00244 cpl_table_set_int(lc,"norder",i,norder);
00245
00246
00247
00248
00249 val = linval(nom_val,nom_kfac,0.5,10,polyco,norder);
00250 lin_nom = 100*fabs(val - nom_val)/nom_val;
00251
00252
00253
00254
00255
00256 work = cpl_malloc(nimages*sizeof(double));
00257 for (j = 0; j < nimages; j++) {
00258 kfac = mindit/exps[j];
00259 work[j] = linval(meds[j],kfac,0.5,10,polyco,norder);
00260 (*lindata)[j*np+i] = work[j];
00261 }
00262 vircam_linfit(nimages,exps,work,&a0,&a1,&sigfit);
00263 sigfit *= 100.0/nom_val;
00264 freearray(polyfitco)
00265
00266
00267
00268 cpl_table_set_double(lc,"lin_10000_err",i,sigfit);
00269 cpl_table_set_double(lc,"lin_10000",i,lin_nom);
00270 freespace(work);
00271 }
00272
00273
00274
00275 *lchantab = cpl_table_duplicate(lc);
00276 cpl_array_unwrap(exparray);
00277 freearray(medsarray);
00278 freespace2(aco,norder);
00279 freespace(temp);
00280 freetable(lc);
00281 vircam_chan_free(np,&pp);
00282 if (nbad != 0) {
00283 cpl_msg_warning(fctid,"%d channels have a failed solution",nbad);
00284 WARN_RETURN
00285 }
00286 GOOD_STATUS
00287 }
00288
00289
00290
00331
00332
00333 extern int vircam_lincor(vir_fits *infile, vir_tfits *lchantab, int kconst,
00334 int ndit, int *status) {
00335 int retval,i,norder;
00336 long naxis[2],j,rind,aind,ncpts,np;
00337 float *data,texp,reset_time,read_time,delay_time;
00338 double kfac_nom,lkfac,inval,outval,*lbb,dnd;
00339 const char *fctid = "vircam_lincor";
00340 parquet *pp;
00341 cpl_propertylist *plist;
00342 cpl_table *lctab;
00343 parquet *p;
00344
00345
00346
00347 if (*status != VIR_OK)
00348 return(*status);
00349
00350
00351
00352 lctab = vircam_tfits_get_table(lchantab);
00353 retval = vircam_chan_fill(lctab,&p,&np);
00354 if (retval != VIR_OK)
00355 return(retval);
00356
00357
00358
00359 data = cpl_image_get_data(vircam_fits_get_image(infile));
00360 if (data == NULL) {
00361 vircam_chan_free(np,&p);
00362 cpl_msg_error(fctid,"Error mapping data in input image");
00363 FATAL_ERROR
00364 }
00365 naxis[0] = (long)cpl_image_get_size_x(vircam_fits_get_image(infile));
00366 naxis[1] = (long)cpl_image_get_size_y(vircam_fits_get_image(infile));
00367
00368
00369
00370 plist = vircam_fits_get_ehu(infile);
00371 if (vircam_pfits_get_exptime(plist,&texp) != VIR_OK) {
00372 vircam_chan_free(np,&p);
00373 cpl_msg_error(fctid,"No exposure time in %s",
00374 vircam_fits_get_fullname(infile));
00375 FATAL_ERROR
00376 }
00377 if (vircam_pfits_get_mindit(plist,&reset_time) != VIR_OK) {
00378 vircam_chan_free(np,&p);
00379 cpl_msg_error(fctid,"No mindit time in %s",
00380 vircam_fits_get_fullname(infile));
00381 FATAL_ERROR
00382 }
00383 read_time = reset_time;
00384 if (vircam_pfits_get_ditdelay(plist,&delay_time) != VIR_OK) {
00385 vircam_chan_free(np,&p);
00386 cpl_msg_error(fctid,"No dit delay time in %s",
00387 vircam_fits_get_fullname(infile));
00388 FATAL_ERROR
00389 }
00390
00391
00392
00393 kfac_nom = (double)(read_time/texp);
00394
00395
00396
00397 dnd = (double)ndit;
00398
00399
00400
00401 for (i = 0; i < np; i++) {
00402 pp = p + i;
00403 ncpts = (pp->delta_i)*(pp->delta_j);
00404
00405
00406
00407
00408 norder = pp->norder;
00409 if (norder == 1)
00410 continue;
00411 lbb = pp->bb;
00412
00413
00414
00415 for (j = 0; j < ncpts; j++) {
00416
00417
00418
00419 rind = vircam_chan_d2r(pp,j);
00420 aind = vircam_chan_r2a(pp,naxis,rind);
00421 if (kconst == 1)
00422 lkfac = kfac_nom;
00423 else
00424 lkfac = getkfac(j,ncpts,reset_time,read_time,delay_time,texp);
00425
00426
00427
00428 inval = ((double)data[aind])/dnd;
00429 outval = linval(inval,lkfac,0.5,10,lbb,norder);
00430 data[aind] = (float)(dnd*outval);
00431 }
00432 }
00433
00434
00435
00436 cpl_propertylist_update_string(vircam_fits_get_ehu(infile),
00437 "ESO DRS LINCOR",
00438 vircam_tfits_get_filename(lchantab));
00439
00440
00441
00442 vircam_chan_free(np,&p);
00443 GOOD_STATUS
00444 }
00445
00446
00475
00476
00477 static double linval(double inval, double k, double tolerance, int niter,
00478 double *b, int norder) {
00479 int jj,iter;
00480 double sc1,val_old,val,tol;
00481
00482 val = inval;
00483 iter = 0;
00484 tol = tolerance + 1.0;
00485 while (iter < niter && tol > tolerance) {
00486 val_old = val;
00487 iter++;
00488 sc1 = inval;
00489 for (jj = 1; jj < norder; jj++)
00490 sc1 -= b[jj]*pow(val,(double)jj+1)*
00491 ((pow((1.0+k),(double)jj+1) - pow(k,(double)(jj+1))));
00492 val = sc1;
00493 tol = fabs(val - val_old);
00494 }
00495 return(val);
00496 }
00497
00498
00499
00527
00528
00529 static double getkfac(long index, long npts, float reset_time,
00530 float read_time, float delay_time, float exptime) {
00531 double tkfac,dt1,dt2,dt3,dt4,df;
00532
00533 df = ((double)index/(double)npts);
00534 dt1 = (double)exptime;
00535 dt2 = (double)read_time;
00536 dt3 = (double)reset_time;
00537 dt4 = (double)delay_time;
00538 tkfac = (dt3 + dt4 + (dt2 - dt3)*df)/dt1;
00539 return(tkfac);
00540 }
00541
00542
00564
00565
00566 static void getco(double *a, int nord, int m) {
00567 int i,j,start;
00568
00569 for (i = 0; i < nord; i++)
00570 a[i] = 0.0;
00571 start = m-1;
00572 a[start] = 1.0;
00573 j = 1;
00574 for (i = start-1; i >= 0; i--) {
00575 j++;
00576 a[i] = a[i+1]*(double)(m - j + 2)/(double)(j-1);
00577 }
00578 }
00579
00580
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662