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,k,ii,nullval;
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,
00142 "Not enought images (%" CPL_SIZE_FORMAT ") for fit order (%" CPL_SIZE_FORMAT ")",
00143 (cpl_size)nimages,(cpl_size)norder);
00144 FATAL_ERROR
00145 }
00146
00147
00148
00149 ctab = vircam_tfits_get_table(chantab);
00150 retval = vircam_chan_fill(ctab,&pp,&np);
00151 if (retval != VIR_OK) {
00152 *status = retval;
00153 return(retval);
00154 }
00155
00156
00157
00158
00159 lc = cpl_table_duplicate(ctab);
00160 oldnorder = cpl_table_get_int(lc,"norder",0,&nullval);
00161 if (oldnorder > norder) {
00162 for (i = norder+1; i <= oldnorder; i++) {
00163 snprintf(colname,SZCOLNAME,"coeff_%d",i);
00164 cpl_table_erase_column(lc,colname);
00165 }
00166 } else if (oldnorder < norder) {
00167 for (i = oldnorder+1; i <= norder; i++) {
00168 snprintf(colname,SZCOLNAME,"coeff_%d",i);
00169 if (cpl_table_has_column(lc,colname))
00170 continue;
00171 cpl_table_new_column(lc,colname,CPL_TYPE_DOUBLE);
00172 }
00173 }
00174
00175
00176
00177 exparray = cpl_array_wrap_double(exps,nimages);
00178 medsarray = cpl_array_new((cpl_size)nimages,CPL_TYPE_DOUBLE);
00179 meds = cpl_array_get_data_double(medsarray);
00180 aco = cpl_malloc(norder*sizeof(double *));
00181 for (i = 0; i < norder; i++)
00182 aco[i] = cpl_malloc(norder*sizeof(double));
00183 temp = cpl_malloc(norder*sizeof(double));
00184 kfacs = cpl_malloc(norder*sizeof(double));
00185
00186
00187
00188 *lindata = cpl_malloc(nimages*np*sizeof(double));
00189
00190
00191
00192 nbad = 0;
00193 for (i = 0; i < np; i++) {
00194 p = pp + i;
00195
00196
00197
00198 for (j = 0; j < nimages; j++)
00199 meds[j] = fdata[j][i];
00200
00201
00202
00203 if (vircam_polyfit(exparray,medsarray,norder,1,2,2.0,2.0,&polyfitco,
00204 &sigfit) != VIR_OK) {
00205 nbad++;
00206 cpl_table_set_int(lc,"norder",(cpl_size)i,norder);
00207 cpl_table_set_double(lc,"coeff_1",(cpl_size)i,1.0);
00208 for (k = 1; k < norder; k++) {
00209 snprintf(colname,SZCOLNAME,"coeff_%d",k+1);
00210 cpl_table_set_double(lc,colname,(cpl_size)i,0.0);
00211 }
00212 freearray(polyfitco);
00213 continue;
00214 }
00215 polyco = cpl_array_get_data_double(polyfitco);
00216
00217
00218
00219 for (j = 0; j < nimages; j++)
00220 if (meds[j] > nom_val)
00221 break;
00222 t10000 = exps[j-1] + (nom_val - meds[j-1])/(meds[j] - meds[j-1]);
00223 sum = 0.0;
00224 for (j = 0; j < norder; j++)
00225 sum += (double)(j+1)*polyco[j]*pow(t10000,(double)j);
00226 lin_nom = 100.0*fabs(sum - polyco[0])/polyco[0];
00227
00228
00229
00230 for (j = 0; j < norder; j++) {
00231 getco(temp,norder,j+1);
00232 for (k = 0; k < norder; k++) {
00233 pt = pow(mindit,(double)(j-k));
00234 aco[j][k] = pt*temp[k];
00235 }
00236 }
00237
00238
00239
00240 if (vircam_solve_gauss(aco,polyco,norder) != VIR_OK) {
00241 nbad++;
00242 cpl_table_set_int(lc,"norder",(cpl_size)i,norder);
00243 cpl_table_set_double(lc,"coeff_1",(cpl_size)i,1.0);
00244 for (k = 1; k < norder; k++) {
00245 snprintf(colname,SZCOLNAME,"coeff_%d",k+1);
00246 cpl_table_set_double(lc,colname,(cpl_size)i,0.0);
00247 }
00248 freearray(polyfitco);
00249 continue;
00250 }
00251
00252
00253
00254 c0 = polyco[0];
00255 for (j = 0; j < norder; j++) {
00256 polyco[j] /= pow(c0,(double)(j+1));
00257 snprintf(colname,SZCOLNAME,"coeff_%d",j+1);
00258 cpl_table_set_double(lc,colname,(cpl_size)i,polyco[j]);
00259 }
00260 cpl_table_set_int(lc,"norder",(cpl_size)i,norder);
00261
00262
00263
00264
00265
00266 workarray = cpl_array_new((cpl_size)nimages,CPL_TYPE_DOUBLE);
00267 work = cpl_array_get_data_double(workarray);
00268 for (j = 0; j < nimages; j++) {
00269 kfac = mindit/exps[j];
00270 kfacs[0] = 1.0;
00271 for (ii = 1; ii < norder; ii++)
00272 kfacs[ii] = pow((kfac+1.0),(double)(ii+1)) -
00273 pow(kfac,(double)(ii+1));
00274 work[j] = linval(meds[j],kfacs,0.5,10,polyco,norder);
00275 (*lindata)[j*np+i] = work[j];
00276 }
00277 freearray(polyfitco);
00278 (void)vircam_polyfit(exparray,workarray,2,0,2,2.0,2.0,&polyfitco,
00279 &sigfit);
00280 polyco = cpl_array_get_data_double(polyfitco);
00281 sigfit *= 100.0/nom_val;
00282 freearray(workarray);
00283 freearray(polyfitco);
00284
00285
00286
00287 cpl_table_set_double(lc,"lin_10000_err",(cpl_size)i,sigfit);
00288 cpl_table_set_double(lc,"lin_10000",(cpl_size)i,lin_nom);
00289 }
00290
00291
00292
00293 *lchantab = cpl_table_duplicate(lc);
00294 cpl_array_unwrap(exparray);
00295 freearray(medsarray);
00296 freespace2(aco,norder);
00297 freespace(temp);
00298 freetable(lc);
00299 vircam_chan_free(np,&pp);
00300 freespace(kfacs);
00301 if (nbad != 0) {
00302 cpl_msg_warning(fctid,
00303 "%" CPL_SIZE_FORMAT "channels have a failed solution",
00304 (cpl_size)nbad);
00305 WARN_RETURN
00306 }
00307 GOOD_STATUS
00308 }
00309
00310
00311
00352
00353
00354 extern int vircam_lincor(vir_fits *infile, vir_tfits *lchantab, int kconst,
00355 int ndit, int *status) {
00356 int retval,i,norder,ii;
00357 long naxis[2],j,rind,aind,ncpts,np;
00358 float *data,texp,reset_time,read_time,delay_time;
00359 double kfac_nom,lkfac,inval,outval,*lbb,dnd,*kfacs;
00360 const char *fctid = "vircam_lincor";
00361 parquet *pp;
00362 cpl_propertylist *plist;
00363 cpl_table *lctab;
00364 parquet *p;
00365
00366
00367
00368 if (*status != VIR_OK)
00369 return(*status);
00370
00371
00372
00373 if (cpl_propertylist_has(vircam_fits_get_ehu(infile),"ESO DRS LINCOR"))
00374 return(*status);
00375
00376
00377
00378 lctab = vircam_tfits_get_table(lchantab);
00379 retval = vircam_chan_fill(lctab,&p,&np);
00380 if (retval != VIR_OK)
00381 return(retval);
00382
00383
00384
00385 data = cpl_image_get_data(vircam_fits_get_image(infile));
00386 if (data == NULL) {
00387 vircam_chan_free(np,&p);
00388 cpl_msg_error(fctid,"Error mapping data in input image");
00389 FATAL_ERROR
00390 }
00391 naxis[0] = (long)cpl_image_get_size_x(vircam_fits_get_image(infile));
00392 naxis[1] = (long)cpl_image_get_size_y(vircam_fits_get_image(infile));
00393
00394
00395
00396 plist = vircam_fits_get_ehu(infile);
00397 if (vircam_pfits_get_exptime(plist,&texp) != VIR_OK) {
00398 vircam_chan_free(np,&p);
00399 cpl_msg_error(fctid,"No exposure time in %s",
00400 vircam_fits_get_fullname(infile));
00401 FATAL_ERROR
00402 }
00403 if (vircam_pfits_get_mindit(plist,&reset_time) != VIR_OK) {
00404 vircam_chan_free(np,&p);
00405 cpl_msg_error(fctid,"No mindit time in %s",
00406 vircam_fits_get_fullname(infile));
00407 FATAL_ERROR
00408 }
00409 read_time = reset_time;
00410 if (vircam_pfits_get_ditdelay(plist,&delay_time) != VIR_OK) {
00411 vircam_chan_free(np,&p);
00412 cpl_msg_error(fctid,"No dit delay time in %s",
00413 vircam_fits_get_fullname(infile));
00414 FATAL_ERROR
00415 }
00416
00417
00418
00419 kfac_nom = (double)(read_time/texp);
00420
00421
00422
00423 dnd = (double)ndit;
00424
00425
00426
00427 for (i = 0; i < np; i++) {
00428 pp = p + i;
00429 ncpts = (pp->delta_i)*(pp->delta_j);
00430
00431
00432
00433
00434 norder = pp->norder;
00435 if (norder == 1)
00436 continue;
00437 lbb = pp->bb;
00438
00439
00440
00441
00442 kfacs = cpl_malloc(norder*sizeof(double));
00443 if (kconst) {
00444 kfacs[0] = 1.0;
00445 for (ii = 1; ii < norder; ii++)
00446 kfacs[ii] = pow((kfac_nom+1.0),(double)(ii+1)) -
00447 pow(kfac_nom,(double)(ii+1));
00448 }
00449
00450
00451
00452 for (j = 0; j < ncpts; j++) {
00453
00454
00455
00456 rind = vircam_chan_d2r(pp,j);
00457 aind = vircam_chan_r2a(pp,naxis,rind);
00458 if (! kconst) {
00459 lkfac = getkfac(j,ncpts,reset_time,read_time,delay_time,texp);
00460 kfacs[0] = 1.0;
00461 for (ii = 1; ii < norder; ii++)
00462 kfacs[ii] = pow((lkfac+1.0),(double)(ii+1)) -
00463 pow(lkfac,(double)(ii+1));
00464 }
00465
00466
00467
00468 inval = ((double)data[aind])/dnd;
00469 outval = linval(inval,kfacs,0.5,10,lbb,norder);
00470 data[aind] = (float)(dnd*outval);
00471 }
00472 freespace(kfacs);
00473 }
00474
00475
00476
00477 cpl_propertylist_update_string(vircam_fits_get_ehu(infile),
00478 "ESO DRS LINCOR",
00479 vircam_tfits_get_filename(lchantab));
00480
00481
00482
00483 vircam_chan_free(np,&p);
00484 GOOD_STATUS
00485 }
00486
00487
00516
00517
00518 static double linval(double inval, double *kfacs, double tolerance,
00519 int niter, double *b, int norder) {
00520 int jj,iter;
00521 double val_old,val,tol,sum;
00522
00523 val = inval;
00524 iter = 0;
00525 tol = tolerance + 1.0;
00526 while (iter < niter && tol > tolerance) {
00527 val_old = val;
00528 iter++;
00529 sum = 0.0;
00530 for (jj = norder - 1; jj >= 1; jj--)
00531 sum = (sum + b[jj]*kfacs[jj])*val;
00532 sum *= val;
00533 val = inval - sum;
00534 tol = fabs(val - val_old);
00535 if (val > 65535.0) {
00536 val = 65535.0;
00537 break;
00538 } else if (val < -1000.0) {
00539 val = -1000.0;
00540 break;
00541 }
00542 }
00543 return(val);
00544 }
00545
00546
00547
00575
00576
00577 static double getkfac(long index, long npts, float reset_time,
00578 float read_time, float delay_time, float exptime) {
00579 double tkfac,dt1,dt2,dt3,dt4,df;
00580
00581 df = ((double)index/(double)npts);
00582 dt1 = (double)exptime;
00583 dt2 = (double)read_time;
00584 dt3 = (double)reset_time;
00585 dt4 = (double)delay_time;
00586 tkfac = (dt3 + dt4 + (dt2 - dt3)*df)/dt1;
00587 return(tkfac);
00588 }
00589
00590
00612
00613
00614 static void getco(double *a, int nord, int m) {
00615 int i,j,start;
00616
00617 for (i = 0; i < nord; i++)
00618 a[i] = 0.0;
00619 start = m-1;
00620 a[start] = 1.0;
00621 j = 1;
00622 for (i = start-1; i >= 0; i--) {
00623 j++;
00624 a[i] = a[i+1]*(double)(m - j + 2)/(double)(j-1);
00625 }
00626 }
00627
00628
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
00737
00738
00739
00740
00741
00742