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 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include <string.h>
00037 #include <math.h>
00038 #include <assert.h>
00039
00040 #include "irplib_framelist.h"
00041
00042 #include "visir_spc_photom.h"
00043
00044 #include "visir_parameter.h"
00045 #include "visir_utils.h"
00046 #include "visir_pfits.h"
00047 #include "visir_spc_distortion.h"
00048
00049
00050
00051
00052
00053 static cpl_bivector * visir_spc_phot_model_from_cat(const char *, double,
00054 double);
00055 static int visir_spc_phot_model_rebin(const cpl_bivector *, cpl_table *);
00056
00057 static cpl_error_code visir_spc_sens_stat(const visir_spc_phot_config *,
00058 double *, double *,
00059 const cpl_table *);
00060
00061 static cpl_error_code visir_spc_phot_qc(cpl_propertylist *,
00062 const char *,
00063 double, double, double);
00064
00065
00069
00070
00073
00094
00095 cpl_table * visir_spc_phot_sensit(
00096 cpl_image ** combined,
00097 const irplib_framelist * rawframes,
00098 const char * recipename,
00099 const cpl_parameterlist * parlist,
00100 const visir_spc_phot_config * pconfig,
00101 const char * star_cat,
00102 const char * spc_cal_lines,
00103 const char * spc_cal_qeff,
00104 cpl_image ** pweight2d,
00105 cpl_propertylist * qclist,
00106 cpl_boolean do_ech,
00107 double wlen,
00108 double slitw,
00109 double temp,
00110 double fwhm,
00111 const visir_spc_resol resol)
00112 {
00113 cpl_errorstate cleanstate = cpl_errorstate_get();
00114 const cpl_propertylist * plist;
00115 double exptime;
00116 double dit, ndit;
00117 int ncycles, nnod;
00118 int icol1, icol2;
00119 int jcol1, jcol2;
00120 double ra, dec;
00121 cpl_imagelist * hcycle = NULL;
00122 cpl_image * imhcycle = NULL;
00123 cpl_image * comorder = NULL;
00124 cpl_image * order = NULL;
00125 const char * star_name;
00126 cpl_bivector * flux_model = NULL;
00127 cpl_table * spc_table = NULL;
00128 double factor;
00129 double * ext_array;
00130 double * spc_array;
00131 double * err_array;
00132 double sens_mean = -1.0;
00133 double sens_stdev = -1.0;
00134 int i;
00135
00136
00137 *pweight2d = NULL;
00138
00139 skip_if (0);
00140
00141 skip_if (rawframes == NULL);
00142
00143 jcol1 = visir_parameterlist_get_int(parlist, recipename,
00144 VISIR_PARAM_REJLEFT);
00145 jcol2 = visir_parameterlist_get_int(parlist, recipename,
00146 VISIR_PARAM_REJRIGHT);
00147
00148 skip_if (0);
00149
00150
00151 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DIT,
00152 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00153 if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DIT,
00154 CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5)) {
00155
00156
00157 visir_error_reset("DIT differs by more than %g", 1e-5);
00158 }
00159
00160
00161 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_RA,
00162 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00163
00164
00165 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DEC,
00166 CPL_TYPE_DOUBLE, CPL_TRUE, 1.0));
00167
00168 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_CHOP_NCYCLES,
00169 CPL_TYPE_INT, CPL_TRUE, 0.0));
00170
00171 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NDIT,
00172 CPL_TYPE_INT, CPL_TRUE, 0.0));
00173
00174 if (irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_STARNAME,
00175 CPL_TYPE_STRING, CPL_TRUE, 0.0)) {
00176 visir_error_reset("Rawframe(s) missing standard star name");
00177 }
00178
00179
00180
00181 plist = irplib_framelist_get_propertylist_const(rawframes, 0);
00182
00183 skip_if (0);
00184
00185
00186
00187 dit = visir_pfits_get_dit(plist);
00188
00189 ndit = visir_pfits_get_ndit(plist);
00190
00191 nnod = irplib_framelist_get_size(rawframes);
00192
00193 ncycles = visir_pfits_get_chop_ncycles(plist);
00194
00195 exptime = 2 * dit * ndit * nnod * ncycles;
00196
00197 skip_if (0);
00198
00199
00200 star_name = visir_pfits_get_starname(plist);
00201 if (star_name == NULL) visir_error_reset("Could not get standard star name");
00202
00203
00204 ra = visir_pfits_get_ra(plist);
00205 dec = visir_pfits_get_dec(plist);
00206
00207 skip_if (0);
00208
00209
00210 hcycle = visir_load_imagelist(rawframes, 0, CPL_FALSE);
00211 skip_if (0);
00212
00213 skip_if (pconfig->do_fixcombi && visir_spc_det_fix(combined, 1, CPL_TRUE,
00214 wlen, resol,
00215 pconfig->phi,
00216 pconfig->ksi,
00217 pconfig->eps,
00218 pconfig->delta,
00219 pconfig->plot));
00220
00221
00222 imhcycle = cpl_imagelist_get(hcycle, 0);
00223 skip_if (0);
00224
00225 skip_if (visir_spc_det_fix(&imhcycle, 1, CPL_FALSE,
00226 wlen, resol,
00227 pconfig->phi,
00228 pconfig->ksi,
00229 pconfig->eps,
00230 pconfig->delta,
00231 pconfig->plot));
00232
00233 if (do_ech) {
00234 skip_if (visir_spc_echelle_limit(&icol1, &icol2, wlen,
00235 pconfig->orderoffset,
00236 1, cpl_image_get_size_y(*combined)));
00237 skip_if (visir_qc_append_background(qclist, rawframes, icol1, icol2));
00238
00239 } else {
00240 icol1 = 1;
00241 icol2 = cpl_image_get_size_x(imhcycle);
00242
00243 skip_if (visir_qc_append_background(qclist, rawframes, 0, 0));
00244 }
00245
00246 if (do_ech) {
00247 if (jcol1 != 0) {
00248 cpl_msg_info(cpl_func, "Ignoring %d leftmost columns from %d to %d",
00249 jcol1, icol1, icol1 + jcol1);
00250 icol1 += jcol1;
00251 }
00252 if (jcol2 != 0) {
00253 cpl_msg_info(cpl_func, "Ignoring %d rightmost columns from %d to %d",
00254 jcol2, icol2 - jcol2, icol2);
00255 icol2 -= jcol2;
00256 }
00257 } else {
00258 if (jcol1 != 0) {
00259 cpl_msg_info(cpl_func, "Ignoring %d leftmost columns", jcol1);
00260 icol1 += jcol1;
00261 }
00262 if (jcol2 != 0) {
00263 cpl_msg_info(cpl_func, "Ignoring %d rightmost columns", jcol2);
00264 icol2 -= jcol2;
00265 }
00266 }
00267
00268 if (icol1 != 1 || icol2 != cpl_image_get_size_x(imhcycle)) {
00269 order = visir_spc_column_extract(imhcycle, icol1, icol2,
00270 pconfig->plot);
00271 skip_if (0);
00272
00273 comorder = visir_spc_column_extract(*combined, icol1, icol2,
00274 pconfig->plot);
00275 skip_if (0);
00276
00277 } else {
00278 order = imhcycle;
00279 comorder = *combined;
00280 }
00281
00282
00283 skip_if (visir_spc_extract_wcal(comorder,
00284 order, wlen, slitw, temp, fwhm,
00285 resol, pconfig->orderoffset,
00286 spc_cal_lines, spc_cal_qeff,
00287 &spc_table, pweight2d,
00288 qclist,
00289 pconfig->plot));
00290
00291 cpl_imagelist_delete(hcycle);
00292 hcycle = NULL;
00293
00294
00295 if ((flux_model=visir_spc_phot_model_from_cat(star_cat, ra, dec)) == NULL) {
00296 cpl_msg_error(cpl_func, "Cannot retrieve the flux model from the cat.");
00297 skip_if(1);
00298 }
00299
00300
00301 if (visir_spc_phot_model_rebin(flux_model, spc_table) == -1) {
00302 cpl_msg_error(cpl_func, "Cannot rebin the flux model");
00303 skip_if(1);
00304 }
00305 cpl_bivector_delete(flux_model);
00306 flux_model = NULL;
00307
00308
00309
00310
00311 cpl_table_duplicate_column(spc_table, "SENSITIVITY", spc_table,
00312 "STD_STAR_MODEL");
00313 cpl_table_set_column_unit(spc_table, "SENSITIVITY", "mJy");
00314
00315 ext_array = cpl_table_get_data_double(spc_table, "SENSITIVITY");
00316 spc_array = cpl_table_get_data_double(spc_table, "SPC_EXTRACTED");
00317 err_array = cpl_table_get_data_double(spc_table, "SPC_ERROR");
00318
00319 factor = sqrt(exptime)/6.0;
00320 for (i = 0; i < cpl_table_get_nrow(spc_table); i++) {
00321 ext_array[i] *= factor * err_array[i];
00322 if (ext_array[i] < 0 || spc_array[i] <= 0) {
00323 cpl_msg_warning(cpl_func, "Setting non-physical sensitivity in row %d "
00324 "to 0: %g/%g", i+1, ext_array[i], spc_array[i]);
00325 ext_array[i] = 0;
00326 } else {
00327 ext_array[i] /= spc_array[i];
00328 }
00329 }
00330
00331 skip_if(visir_spc_sens_stat(pconfig, &sens_mean, &sens_stdev, spc_table));
00332
00333
00334 skip_if (cpl_table_erase_column(spc_table, "SPC_EMISSIVITY"));
00335
00336 skip_if (visir_spc_phot_qc(qclist, star_name, exptime, sens_mean,
00337 sens_stdev));
00338
00339
00340 if (pconfig->plot) {
00341 visir_table_plot("", "t 'Extracted spectrum' w lines", "", spc_table,
00342 "WLEN", "SPC_EXTRACTED");
00343 visir_table_plot("", "t 'Extracted spectrum error' w lines", "",
00344 spc_table, "WLEN", "SPC_ERROR");
00345 visir_table_plot("", "t 'Standard star model' w lines", "", spc_table,
00346 "WLEN", "STD_STAR_MODEL");
00347 visir_table_plot("set grid;", "t 'Sensitivity (mJy)' w lines", "",
00348 spc_table, "WLEN", "SENSITIVITY");
00349 visir_image_plot("", "t 'The weight map'", "", *pweight2d);
00350 }
00351
00352 end_skip;
00353
00354 cpl_imagelist_delete(hcycle);
00355 cpl_bivector_delete(flux_model);
00356
00357 if (order != imhcycle) cpl_image_delete(order);
00358 if (comorder != *combined) cpl_image_delete(comorder);
00359
00360 if (cpl_error_get_code()) {
00361 cpl_table_delete(spc_table);
00362 spc_table = NULL;
00363 cpl_image_delete(*pweight2d);
00364 *pweight2d = NULL;
00365 }
00366
00367 return spc_table;
00368 }
00369
00372
00384
00385 static cpl_bivector * visir_spc_phot_model_from_cat(const char * star_cat,
00386 double ra,
00387 double dec)
00388 {
00389 const double max_radius = VISIR_STAR_MAX_RADIUS;
00390 const cpl_table * catalog = NULL;
00391 int nb_stars;
00392 const double * dd;
00393 const cpl_array * da;
00394 cpl_vector * v_ra = NULL;
00395 cpl_vector * v_dec = NULL;
00396 int min_dist_ind;
00397 cpl_bivector * model = NULL;
00398 cpl_vector * model_x = NULL;
00399 cpl_vector * model_y = NULL;
00400 const double conv_mJy = 3.33E8;
00401 double star_dist;
00402 int nb_vals;
00403
00404
00405 bug_if (0);
00406
00407
00408 catalog = cpl_table_load(star_cat, 1, 0);
00409 if (catalog == NULL) {
00410 cpl_msg_error(cpl_func, "Could not open the star catalog: %s",
00411 star_cat ? star_cat : "<NULL>");
00412 skip_if(1);
00413 }
00414
00415 nb_stars = cpl_table_get_nrow(catalog);
00416
00417 skip_if(nb_stars < 1);
00418
00419
00420 dd = cpl_table_get_data_double_const(catalog, "RA");
00421 skip_if (dd == NULL);
00422 v_ra = cpl_vector_wrap(nb_stars, (double*)dd);
00423 bug_if( v_ra == NULL);
00424
00425 dd = cpl_table_get_data_double_const(catalog, "DEC");
00426 skip_if (dd == NULL);
00427 v_dec = cpl_vector_wrap(nb_stars, (double*)dd);
00428 bug_if( v_dec == NULL);
00429
00430
00431 min_dist_ind = visir_star_find(v_ra, v_dec, ra, dec, max_radius, &star_dist);
00432
00433 skip_if (min_dist_ind < 0);
00434
00435 cpl_msg_info(cpl_func, "The standard star closest to (RA,DEC)=(%g,%g) is "
00436 "no. %d, '%s' at (RA,DEC)=(%g,%g) with the distance [degree]: "
00437 "%g", ra, dec, 1+min_dist_ind,
00438 cpl_table_get_string(catalog, "STARS", min_dist_ind),
00439 cpl_table_get_double(catalog, "RA", min_dist_ind, NULL),
00440 cpl_table_get_double(catalog, "DEC", min_dist_ind, NULL),
00441 star_dist);
00442
00443
00444 da = cpl_table_get_array(catalog, "WAVELENGTHS", min_dist_ind);
00445 skip_if (da == NULL);
00446 dd = cpl_array_get_data_double_const(da);
00447 skip_if (dd == NULL);
00448
00449 nb_vals = cpl_array_get_size(da);
00450
00451 model_x = cpl_vector_new(nb_vals);
00452 memcpy(cpl_vector_get_data(model_x), dd, nb_vals * sizeof(double));
00453
00454
00455 da = cpl_table_get_array(catalog, "MODEL_FLUX", min_dist_ind);
00456 skip_if (da == NULL);
00457 dd = cpl_array_get_data_double_const(da);
00458 skip_if (dd == NULL);
00459
00460 skip_if (nb_vals != cpl_array_get_size(da));
00461
00462 model_y = cpl_vector_new(nb_vals);
00463 memcpy(cpl_vector_get_data(model_y), dd, nb_vals * sizeof(double));
00464
00465
00466 bug_if (cpl_vector_multiply_scalar(model_y, conv_mJy));
00467 bug_if (cpl_vector_multiply(model_y, model_x));
00468 bug_if (cpl_vector_multiply(model_y, model_x));
00469
00470
00471 bug_if (cpl_vector_multiply_scalar(model_x, 1e-6));
00472
00473 model = cpl_bivector_wrap_vectors(model_x, model_y);
00474
00475 bug_if (model == NULL);
00476
00477 end_skip;
00478
00479 (void)cpl_vector_unwrap(v_ra);
00480 (void)cpl_vector_unwrap(v_dec);
00481 cpl_table_delete((cpl_table*)catalog);
00482
00483 if (cpl_error_get_code()) {
00484
00485 cpl_vector_delete(model_x);
00486 cpl_vector_delete(model_y);
00487 }
00488
00489 return model;
00490 }
00491
00492
00498
00499 static int visir_spc_phot_model_rebin(
00500 const cpl_bivector * model,
00501 cpl_table * spec_tab)
00502 {
00503 cpl_vector * bounds = NULL;
00504 cpl_vector * spec = NULL;
00505 double bin_pos;
00506 const int nrow = cpl_table_get_nrow(spec_tab);
00507 int i;
00508
00509
00510 skip_if (0);
00511
00512
00513 bounds = cpl_vector_new(nrow + 1);
00514 for (i=1 ; i<cpl_vector_get_size(bounds) - 1 ; i++) {
00515 bin_pos = (cpl_table_get(spec_tab, "WLEN", i-1, NULL) +
00516 cpl_table_get(spec_tab, "WLEN", i, NULL)) / 2.0;
00517 cpl_vector_set(bounds, i, bin_pos);
00518 }
00519 bin_pos = cpl_table_get(spec_tab, "WLEN", 0, NULL) -
00520 ((cpl_table_get(spec_tab, "WLEN", 1, NULL) -
00521 cpl_table_get(spec_tab, "WLEN", 0, NULL)) / 2.0);
00522 cpl_vector_set(bounds, 0, bin_pos);
00523 bin_pos =
00524 cpl_table_get(spec_tab, "WLEN", nrow-1, NULL) +
00525 ((cpl_table_get(spec_tab,"WLEN", 1, NULL) -
00526 cpl_table_get(spec_tab, "WLEN", 0, NULL)) / 2.0);
00527 cpl_vector_set(bounds, cpl_vector_get_size(bounds)-1, bin_pos);
00528
00529
00530 spec = cpl_vector_new(nrow);
00531
00532
00533 if (visir_vector_resample(spec, bounds, model)) {
00534 cpl_msg_error(cpl_func, "Cannot rebin the spectrum");
00535 skip_if(1);
00536 }
00537
00538
00539 cpl_table_new_column(spec_tab, "STD_STAR_MODEL", CPL_TYPE_DOUBLE);
00540 cpl_table_set_column_unit(spec_tab, "STD_STAR_MODEL", "mJy");
00541 for (i=0 ; i<nrow ; i++) {
00542 cpl_table_set_double(spec_tab, "STD_STAR_MODEL", i,
00543 cpl_vector_get(spec, i));
00544 }
00545
00546 end_skip;
00547
00548 cpl_vector_delete(spec);
00549 cpl_vector_delete(bounds);
00550
00551 return cpl_error_get_code();
00552 }
00553
00554
00563
00564 static cpl_error_code visir_spc_sens_stat(const visir_spc_phot_config * pconfig,
00565 double * psens_mean,
00566 double * psens_stdev,
00567 const cpl_table * spc_table)
00568 {
00569
00570 cpl_vector * sens_ignore = NULL;
00571 cpl_vector * sens_mini = NULL;
00572 double emis_min, emis_max;
00573 const int npix = cpl_table_get_nrow(spc_table);
00574 const int npix_ignore = 3;
00575 int i;
00576 int iok;
00577
00578 skip_if(0);
00579
00580 skip_if(pconfig == NULL);
00581
00582
00583
00584
00585
00586 sens_ignore = cpl_vector_wrap( npix - 2*npix_ignore, (double*)
00587 cpl_table_get_data_double_const(spc_table,
00588 "SENSITIVITY") + npix_ignore);
00589 skip_if(0);
00590
00591 if (pconfig->plot)
00592 visir_vector_plot("set grid;","t 'Truncated Sensitivity (mJy)' w lines",
00593 "", sens_ignore);
00594
00595 sens_mini = cpl_vector_duplicate(sens_ignore);
00596 skip_if(0);
00597
00598 emis_min = cpl_table_get_column_min(spc_table, "SPC_EMISSIVITY");
00599 emis_max = cpl_table_get_column_max(spc_table, "SPC_EMISSIVITY");
00600 skip_if(0);
00601
00602 emis_max = emis_min + pconfig->emis_tol * (emis_max - emis_min);
00603
00604 iok = 0;
00605 for (i=0; i < npix - 2*npix_ignore; i++) {
00606 const double emis = cpl_table_get(spc_table, "SPC_EMISSIVITY",
00607 i + npix_ignore, NULL);
00608
00609 skip_if(0);
00610
00611 if (emis > emis_max) continue;
00612
00613 if (i > iok)
00614 skip_if(cpl_vector_set(sens_mini, iok, cpl_vector_get(sens_mini, i)));
00615
00616 iok++;
00617
00618 }
00619
00620 assert( iok > 0);
00621
00622 skip_if(cpl_vector_set_size(sens_mini, iok));
00623
00624 *psens_mean = cpl_vector_get_mean(sens_mini);
00625
00626 if (iok == 1) {
00627 cpl_msg_warning(cpl_func, "Sensitivity computed on only 1 wavelength "
00628 "with emissivity %f", emis_max);
00629 *psens_stdev = 0;
00630 } else {
00631 cpl_msg_info(cpl_func, "Sensitivity computed on %d wavelengths with "
00632 "emissivity at most %f", iok, emis_max);
00633
00634 *psens_stdev = cpl_vector_get_stdev(sens_mini);
00635
00636 }
00637
00638
00639 end_skip;
00640
00641 cpl_vector_unwrap(sens_ignore);
00642 cpl_vector_delete(sens_mini);
00643
00644 return cpl_error_get_code();
00645
00646 }
00647
00648
00649
00660
00661 static cpl_error_code visir_spc_phot_qc(cpl_propertylist * self,
00662 const char * star_name,
00663 double exptime,
00664 double sens_mean,
00665 double sens_stdev)
00666 {
00667
00668 bug_if (cpl_propertylist_append_double(self, "ESO QC EXPTIME", exptime));
00669 bug_if (cpl_propertylist_append_double(self, "ESO QC SENS MEAN", sens_mean));
00670 bug_if (cpl_propertylist_append_double(self, "ESO QC SENS STDEV",
00671 sens_stdev));
00672
00673 bug_if (cpl_propertylist_append_string(self, "ESO QC STARNAME",
00674 star_name ? star_name : ""));
00675
00676 end_skip;
00677
00678 return cpl_error_get_code();
00679
00680 }