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
00049
00050 static double linval(double inval, double *kfacs, double tolerance,
00051 int niter, double *b, int norder);
00052 static double getkfac(long index, long ncpts, float reset_time,
00053 float read_time, float delay_time, float exptime);
00054 static void getco(double *a, int nord, int m);
00055
00058
00115
00116
00117 extern int vircam_genlincur(double **fdata, int nimages, double *exps,
00118 double mindit, vir_tfits *chantab,
00119 int norder, cpl_table **lchantab,
00120 double **lindata, int *status) {
00121
00122 const char *fctid = "vircam_genlincur";
00123 int retval,i,j,nbad,oldnorder,nullval,k,ii;
00124 long np;
00125 double *meds,sigfit,**aco,c0,lin_nom,*temp,*polyco,pt,*work,kfac;
00126 double sum,t10000,*kfacs;
00127 parquet *p,*pp;
00128 cpl_table *ctab,*lc;
00129 cpl_array *exparray,*medsarray,*polyfitco,*workarray;
00130 char colname[SZCOLNAME];
00131
00132
00133
00134 *lchantab = NULL;
00135 if (*status != VIR_OK)
00136 return(*status);
00137
00138
00139
00140 if (nimages < norder+1) {
00141 cpl_msg_error(fctid,"Not enought images (%d) for fit order (%d)",
00142 nimages,norder);
00143 FATAL_ERROR
00144 }
00145
00146
00147
00148 ctab = vircam_tfits_get_table(chantab);
00149 retval = vircam_chan_fill(ctab,&pp,&np);
00150 if (retval != VIR_OK) {
00151 *status = retval;
00152 return(retval);
00153 }
00154
00155
00156
00157
00158 lc = cpl_table_duplicate(ctab);
00159 oldnorder = cpl_table_get_int(lc,"norder",0,&nullval);
00160 if (oldnorder > norder) {
00161 for (i = norder+1; i <= oldnorder; i++) {
00162 snprintf(colname,SZCOLNAME,"coeff_%d",i);
00163 cpl_table_erase_column(lc,colname);
00164 }
00165 } else if (oldnorder < norder) {
00166 for (i = oldnorder+1; i <= norder; i++) {
00167 snprintf(colname,SZCOLNAME,"coeff_%d",i);
00168 if (cpl_table_has_column(lc,colname))
00169 continue;
00170 cpl_table_new_column(lc,colname,CPL_TYPE_DOUBLE);
00171 }
00172 }
00173
00174
00175
00176 exparray = cpl_array_wrap_double(exps,nimages);
00177 medsarray = cpl_array_new(nimages,CPL_TYPE_DOUBLE);
00178 meds = cpl_array_get_data_double(medsarray);
00179 aco = cpl_malloc(norder*sizeof(double *));
00180 for (i = 0; i < norder; i++)
00181 aco[i] = cpl_malloc(norder*sizeof(double));
00182 temp = cpl_malloc(norder*sizeof(double));
00183 kfacs = cpl_malloc(norder*sizeof(double));
00184
00185
00186
00187 *lindata = cpl_malloc(nimages*np*sizeof(double));
00188
00189
00190
00191 nbad = 0;
00192 for (i = 0; i < np; i++) {
00193 p = pp + i;
00194
00195
00196
00197 for (j = 0; j < nimages; j++)
00198 meds[j] = fdata[j][i];
00199
00200
00201
00202 if (vircam_polyfit(exparray,medsarray,norder,1,2,2.0,2.0,&polyfitco,
00203 &sigfit) != VIR_OK) {
00204 nbad++;
00205 cpl_table_set_int(lc,"norder",i,norder);
00206 cpl_table_set_double(lc,"coeff_1",i,1.0);
00207 for (k = 1; k < norder; k++) {
00208 snprintf(colname,SZCOLNAME,"coeff_%d",k+1);
00209 cpl_table_set_double(lc,colname,i,0.0);
00210 }
00211 freearray(polyfitco);
00212 continue;
00213 }
00214 polyco = cpl_array_get_data_double(polyfitco);
00215
00216
00217
00218 for (j = 0; j < nimages; j++)
00219 if (meds[j] > nom_val)
00220 break;
00221 t10000 = exps[j-1] + (nom_val - meds[j-1])/(meds[j] - meds[j-1]);
00222 sum = 0.0;
00223 for (j = 0; j < norder; j++)
00224 sum += (double)(j+1)*polyco[j]*pow(t10000,(double)j);
00225 lin_nom = 100.0*fabs(sum - polyco[0])/polyco[0];
00226
00227
00228
00229 for (j = 0; j < norder; j++) {
00230 getco(temp,norder,j+1);
00231 for (k = 0; k < norder; k++) {
00232 pt = pow(mindit,(double)(j-k));
00233 aco[j][k] = pt*temp[k];
00234 }
00235 }
00236
00237
00238
00239 if (vircam_solve_gauss(aco,polyco,norder) != VIR_OK) {
00240 nbad++;
00241 cpl_table_set_int(lc,"norder",i,norder);
00242 cpl_table_set_double(lc,"coeff_1",i,1.0);
00243 for (k = 1; k < norder; k++) {
00244 snprintf(colname,SZCOLNAME,"coeff_%d",k+1);
00245 cpl_table_set_double(lc,colname,i,0.0);
00246 }
00247 freearray(polyfitco);
00248 continue;
00249 }
00250
00251
00252
00253 c0 = polyco[0];
00254 for (j = 0; j < norder; j++) {
00255 polyco[j] /= pow(c0,(double)(j+1));
00256 snprintf(colname,SZCOLNAME,"coeff_%d",j+1);
00257 cpl_table_set_double(lc,colname,i,polyco[j]);
00258 }
00259 cpl_table_set_int(lc,"norder",i,norder);
00260
00261
00262
00263
00264
00265 workarray = cpl_array_new(nimages,CPL_TYPE_DOUBLE);
00266 work = cpl_array_get_data_double(workarray);
00267 for (j = 0; j < nimages; j++) {
00268 kfac = mindit/exps[j];
00269 kfacs[0] = 1.0;
00270 for (ii = 1; ii < norder; ii++)
00271 kfacs[ii] = pow((kfac+1.0),(double)(ii+1)) -
00272 pow(kfac,(double)(ii+1));
00273 work[j] = linval(meds[j],kfacs,0.5,10,polyco,norder);
00274 (*lindata)[j*np+i] = work[j];
00275 }
00276 freearray(polyfitco);
00277 (void)vircam_polyfit(exparray,workarray,2,0,2,2.0,2.0,&polyfitco,
00278 &sigfit);
00279 polyco = cpl_array_get_data_double(polyfitco);
00280 sigfit *= 100.0/nom_val;
00281 freearray(workarray);
00282 freearray(polyfitco);
00283
00284
00285
00286 cpl_table_set_double(lc,"lin_10000_err",i,sigfit);
00287 cpl_table_set_double(lc,"lin_10000",i,lin_nom);
00288 }
00289
00290
00291
00292 *lchantab = cpl_table_duplicate(lc);
00293 cpl_array_unwrap(exparray);
00294 freearray(medsarray);
00295 freespace2(aco,norder);
00296 freespace(temp);
00297 freetable(lc);
00298 vircam_chan_free(np,&pp);
00299 freespace(kfacs);
00300 if (nbad != 0) {
00301 cpl_msg_warning(fctid,"%d channels have a failed solution",nbad);
00302 WARN_RETURN
00303 }
00304 GOOD_STATUS
00305 }
00306
00307
00308
00349
00350
00351 extern int vircam_lincor(vir_fits *infile, vir_tfits *lchantab, int kconst,
00352 int ndit, int *status) {
00353 int retval,i,norder,ii;
00354 long naxis[2],j,rind,aind,ncpts,np;
00355 float *data,texp,reset_time,read_time,delay_time;
00356 double kfac_nom,lkfac,inval,outval,*lbb,dnd,*kfacs;
00357 const char *fctid = "vircam_lincor";
00358 parquet *pp;
00359 cpl_propertylist *plist;
00360 cpl_table *lctab;
00361 parquet *p;
00362
00363
00364
00365 if (*status != VIR_OK)
00366 return(*status);
00367
00368
00369
00370 if (cpl_propertylist_has(vircam_fits_get_ehu(infile),"ESO DRS LINCOR"))
00371 return(*status);
00372
00373
00374
00375 lctab = vircam_tfits_get_table(lchantab);
00376 retval = vircam_chan_fill(lctab,&p,&np);
00377 if (retval != VIR_OK)
00378 return(retval);
00379
00380
00381
00382 data = cpl_image_get_data(vircam_fits_get_image(infile));
00383 if (data == NULL) {
00384 vircam_chan_free(np,&p);
00385 cpl_msg_error(fctid,"Error mapping data in input image");
00386 FATAL_ERROR
00387 }
00388 naxis[0] = (long)cpl_image_get_size_x(vircam_fits_get_image(infile));
00389 naxis[1] = (long)cpl_image_get_size_y(vircam_fits_get_image(infile));
00390
00391
00392
00393 plist = vircam_fits_get_ehu(infile);
00394 if (vircam_pfits_get_exptime(plist,&texp) != VIR_OK) {
00395 vircam_chan_free(np,&p);
00396 cpl_msg_error(fctid,"No exposure time in %s",
00397 vircam_fits_get_fullname(infile));
00398 FATAL_ERROR
00399 }
00400 if (vircam_pfits_get_mindit(plist,&reset_time) != VIR_OK) {
00401 vircam_chan_free(np,&p);
00402 cpl_msg_error(fctid,"No mindit time in %s",
00403 vircam_fits_get_fullname(infile));
00404 FATAL_ERROR
00405 }
00406 read_time = reset_time;
00407 if (vircam_pfits_get_ditdelay(plist,&delay_time) != VIR_OK) {
00408 vircam_chan_free(np,&p);
00409 cpl_msg_error(fctid,"No dit delay time in %s",
00410 vircam_fits_get_fullname(infile));
00411 FATAL_ERROR
00412 }
00413
00414
00415
00416 kfac_nom = (double)(read_time/texp);
00417
00418
00419
00420 dnd = (double)ndit;
00421
00422
00423
00424 for (i = 0; i < np; i++) {
00425 pp = p + i;
00426 ncpts = (pp->delta_i)*(pp->delta_j);
00427
00428
00429
00430
00431 norder = pp->norder;
00432 if (norder == 1)
00433 continue;
00434 lbb = pp->bb;
00435
00436
00437
00438
00439 kfacs = cpl_malloc(norder*sizeof(double));
00440 if (kconst) {
00441 kfacs[0] = 1.0;
00442 for (ii = 1; ii < norder; ii++)
00443 kfacs[ii] = pow((kfac_nom+1.0),(double)(ii+1)) -
00444 pow(kfac_nom,(double)(ii+1));
00445 }
00446
00447
00448
00449 for (j = 0; j < ncpts; j++) {
00450
00451
00452
00453 rind = vircam_chan_d2r(pp,j);
00454 aind = vircam_chan_r2a(pp,naxis,rind);
00455 if (! kconst) {
00456 lkfac = getkfac(j,ncpts,reset_time,read_time,delay_time,texp);
00457 kfacs[0] = 1.0;
00458 for (ii = 1; ii < norder; ii++)
00459 kfacs[ii] = pow((lkfac+1.0),(double)(ii+1)) -
00460 pow(lkfac,(double)(ii+1));
00461 }
00462
00463
00464
00465 inval = ((double)data[aind])/dnd;
00466 outval = linval(inval,kfacs,0.5,10,lbb,norder);
00467 data[aind] = (float)(dnd*outval);
00468 }
00469 freespace(kfacs);
00470 }
00471
00472
00473
00474 cpl_propertylist_update_string(vircam_fits_get_ehu(infile),
00475 "ESO DRS LINCOR",
00476 vircam_tfits_get_filename(lchantab));
00477
00478
00479
00480 vircam_chan_free(np,&p);
00481 GOOD_STATUS
00482 }
00483
00484
00513
00514
00515 static double linval(double inval, double *kfacs, double tolerance,
00516 int niter, double *b, int norder) {
00517 int jj,iter;
00518 double val_old,val,tol,sum;
00519
00520 val = inval;
00521 iter = 0;
00522 tol = tolerance + 1.0;
00523 while (iter < niter && tol > tolerance) {
00524 val_old = val;
00525 iter++;
00526 sum = 0.0;
00527 for (jj = norder - 1; jj >= 1; jj--)
00528 sum = (sum + b[jj]*kfacs[jj])*val;
00529 sum *= val;
00530 val = inval - sum;
00531 tol = fabs(val - val_old);
00532 if (val > 65535.0) {
00533 val = 65535.0;
00534 break;
00535 } else if (val < -1000.0) {
00536 val = -1000.0;
00537 break;
00538 }
00539 }
00540 return(val);
00541 }
00542
00543
00544
00572
00573
00574 static double getkfac(long index, long npts, float reset_time,
00575 float read_time, float delay_time, float exptime) {
00576 double tkfac,dt1,dt2,dt3,dt4,df;
00577
00578 df = ((double)index/(double)npts);
00579 dt1 = (double)exptime;
00580 dt2 = (double)read_time;
00581 dt3 = (double)reset_time;
00582 dt4 = (double)delay_time;
00583 tkfac = (dt3 + dt4 + (dt2 - dt3)*df)/dt1;
00584 return(tkfac);
00585 }
00586
00587
00609
00610
00611 static void getco(double *a, int nord, int m) {
00612 int i,j,start;
00613
00614 for (i = 0; i < nord; i++)
00615 a[i] = 0.0;
00616 start = m-1;
00617 a[start] = 1.0;
00618 j = 1;
00619 for (i = start-1; i >= 0; i--) {
00620 j++;
00621 a[i] = a[i+1]*(double)(m - j + 2)/(double)(j-1);
00622 }
00623 }
00624
00625
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
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736