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 #include <math.h>
00033 #include <cpl.h>
00034 #include <moses.h>
00035 #include <fors_dfs.h>
00036 #include <fors_qc.h>
00037
00038 static int fors_sumflux_create(cpl_plugin *);
00039 static int fors_sumflux_exec(cpl_plugin *);
00040 static int fors_sumflux_destroy(cpl_plugin *);
00041 static int fors_sumflux(cpl_parameterlist *, cpl_frameset *);
00042
00043 static char fors_sumflux_description[] =
00044 "This recipe is used to monitor any lamp flux on the CCD. The input raw\n"
00045 "image should be either a FLUX_ARC_LSS or a FLUX_FLAT_LSS frame. After the\n"
00046 "background subtraction the total signal is integrated and divided by the\n"
00047 "exposure time and by the total number of CCD original pixels (keeping\n"
00048 "into account a possible rebinned readout). In the case of FORS2 frames\n"
00049 "the background is the median level evaluated from the available overscan\n"
00050 "regions. In the case of FORS1 data, where overscan regions are missing,\n"
00051 "the background is evaluated as the median level of the first 200 CCD columns\n"
00052 "for flat field data, while for arc lamp data a background map evaluated\n"
00053 "from the regions without spectral lines is computed and subtracted. The\n"
00054 "background subtracted frame is written to output in all cases, and the QC\n"
00055 "parameters QC LAMP FLUX and QC LAMP FLUXERR are computed.\n\n"
00056 "Input files:\n\n"
00057 " DO category: Type: Explanation: Required:\n"
00058 " FLUX_FLAT_LSS Raw Flat field exposure Y\n"
00059 " or FLUX_ARC_LSS Raw Arc lamp exposure Y\n\n"
00060 "Output files:\n\n"
00061 " DO category: Data type: Explanation:\n"
00062 " FLUX_LAMP_LSS FITS image Background subtracted integration region\n\n";
00063
00064 #define fors_sumflux_exit(message) \
00065 { \
00066 if (message) cpl_msg_error(recipe, message); \
00067 cpl_free(instrume); \
00068 cpl_free(pipefile); \
00069 cpl_image_delete(master_bias); \
00070 cpl_image_delete(exposure); \
00071 cpl_propertylist_delete(header); \
00072 cpl_propertylist_delete(qclist); \
00073 cpl_table_delete(overscans); \
00074 cpl_msg_indent_less(); \
00075 return -1; \
00076 }
00077
00078 #define fors_sumflux_exit_memcheck(message) \
00079 { \
00080 if (message) cpl_msg_info(recipe, message); \
00081 cpl_free(instrume); \
00082 cpl_free(pipefile); \
00083 cpl_image_delete(master_bias); \
00084 cpl_image_delete(exposure); \
00085 cpl_propertylist_delete(header); \
00086 cpl_propertylist_delete(qclist); \
00087 cpl_table_delete(overscans); \
00088 cpl_msg_indent_less(); \
00089 return 0; \
00090 }
00091
00092
00104 int cpl_plugin_get_info(cpl_pluginlist *list)
00105 {
00106 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
00107 cpl_plugin *plugin = &recipe->interface;
00108
00109 cpl_plugin_init(plugin,
00110 CPL_PLUGIN_API,
00111 FORS_BINARY_VERSION,
00112 CPL_PLUGIN_TYPE_RECIPE,
00113 "fors_sumflux",
00114 "Integrate flux from all or part of the input frame",
00115 fors_sumflux_description,
00116 "Carlo Izzo",
00117 PACKAGE_BUGREPORT,
00118 "This file is currently part of the FORS Instrument Pipeline\n"
00119 "Copyright (C) 2002-2010 European Southern Observatory\n\n"
00120 "This program is free software; you can redistribute it and/or modify\n"
00121 "it under the terms of the GNU General Public License as published by\n"
00122 "the Free Software Foundation; either version 2 of the License, or\n"
00123 "(at your option) any later version.\n\n"
00124 "This program is distributed in the hope that it will be useful,\n"
00125 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00126 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
00127 "GNU General Public License for more details.\n\n"
00128 "You should have received a copy of the GNU General Public License\n"
00129 "along with this program; if not, write to the Free Software Foundation,\n"
00130 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
00131 fors_sumflux_create,
00132 fors_sumflux_exec,
00133 fors_sumflux_destroy);
00134
00135 cpl_pluginlist_append(list, plugin);
00136
00137 return 0;
00138 }
00139
00140
00151 static int fors_sumflux_create(cpl_plugin *plugin)
00152 {
00153 cpl_recipe *recipe;
00154 cpl_parameter *p;
00155
00156
00157
00158
00159
00160
00161 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00162 recipe = (cpl_recipe *)plugin;
00163 else
00164 return -1;
00165
00166
00167
00168
00169
00170 recipe->parameters = cpl_parameterlist_new();
00171
00172
00173
00174
00175
00176
00177 p = cpl_parameter_new_value("fors.fors_sumflux.xlow",
00178 CPL_TYPE_INT,
00179 "X coordinate of lower left corner "
00180 "of integration region (pixel)",
00181 "fors.fors_sumflux",
00182 0);
00183 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xlow");
00184 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00185 cpl_parameterlist_append(recipe->parameters, p);
00186
00187
00188
00189
00190
00191 p = cpl_parameter_new_value("fors.fors_sumflux.ylow",
00192 CPL_TYPE_INT,
00193 "Y coordinate of lower left corner "
00194 "of integration region (pixel)",
00195 "fors.fors_sumflux",
00196 0);
00197 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ylow");
00198 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00199 cpl_parameterlist_append(recipe->parameters, p);
00200
00201
00202
00203
00204
00205 p = cpl_parameter_new_value("fors.fors_sumflux.xhigh",
00206 CPL_TYPE_INT,
00207 "X coordinate of upper right corner "
00208 "of integration region (pixel) (0 = CCD size)",
00209 "fors.fors_sumflux",
00210 0);
00211 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xhigh");
00212 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00213 cpl_parameterlist_append(recipe->parameters, p);
00214
00215
00216
00217
00218
00219 p = cpl_parameter_new_value("fors.fors_sumflux.yhigh",
00220 CPL_TYPE_INT,
00221 "Y coordinate of upper right corner "
00222 "of integration region (pixel) (0 = CCD size)",
00223 "fors.fors_sumflux",
00224 0);
00225 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "yhigh");
00226 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00227 cpl_parameterlist_append(recipe->parameters, p);
00228
00229 return 0;
00230 }
00231
00232
00241 static int fors_sumflux_exec(cpl_plugin *plugin)
00242 {
00243 cpl_recipe *recipe;
00244
00245 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00246 recipe = (cpl_recipe *)plugin;
00247 else
00248 return -1;
00249
00250 return fors_sumflux(recipe->parameters, recipe->frames);
00251 }
00252
00253
00262 static int fors_sumflux_destroy(cpl_plugin *plugin)
00263 {
00264 cpl_recipe *recipe;
00265
00266 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00267 recipe = (cpl_recipe *)plugin;
00268 else
00269 return -1;
00270
00271 cpl_parameterlist_delete(recipe->parameters);
00272
00273 return 0;
00274 }
00275
00276
00286 static int fors_sumflux(cpl_parameterlist *parlist, cpl_frameset *frameset)
00287 {
00288
00289 const char *recipe = "fors_sumflux";
00290
00291
00292
00293
00294
00295
00296 int xlow;
00297 int ylow;
00298 int xhig;
00299 int yhig;
00300
00301
00302
00303
00304
00305 cpl_image *master_bias = NULL;
00306 cpl_image *exposure = NULL;
00307 cpl_image *background = NULL;
00308 cpl_image *dummy = NULL;
00309
00310 cpl_table *overscans = NULL;
00311
00312 cpl_propertylist *header = NULL;
00313 cpl_propertylist *qclist = NULL;
00314
00315
00316
00317
00318
00319 const char *arc_tag = "FLUX_ARC_LSS";
00320 const char *flat_tag = "FLUX_FLAT_LSS";
00321
00322 char version[80];
00323 char lamp[20];
00324 const char *exposure_tag;
00325 const char *flux_tag = "FLUX_LAMP_LSS";
00326 double time;
00327 double norm_factor;
00328 int nframes;
00329 int rebin;
00330 int nx, ny;
00331 double gain;
00332 double flux, flux_err;
00333 int i;
00334
00335 char *instrume = NULL;
00336 char *pipefile = NULL;
00337
00338
00339 snprintf(version, 80, "%s-%s", PACKAGE, PACKAGE_VERSION);
00340
00341 cpl_msg_set_indentation(2);
00342
00343 if (dfs_files_dont_exist(frameset))
00344 fors_sumflux_exit(NULL);
00345
00346
00347
00348
00349
00350
00351 cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
00352 cpl_msg_indent_more();
00353
00354 xlow = dfs_get_parameter_int(parlist, "fors.fors_sumflux.xlow", NULL);
00355 ylow = dfs_get_parameter_int(parlist, "fors.fors_sumflux.ylow", NULL);
00356 xhig = dfs_get_parameter_int(parlist, "fors.fors_sumflux.xhigh", NULL);
00357 yhig = dfs_get_parameter_int(parlist, "fors.fors_sumflux.yhigh", NULL);
00358
00359 if (cpl_error_get_code())
00360 fors_sumflux_exit("Failure getting the configuration parameters");
00361
00362 if (xlow > xhig || ylow > yhig || xhig < 0 || yhig < 0)
00363 fors_sumflux_exit("Invalid integration region");
00364
00365
00366
00367
00368
00369
00370 cpl_msg_indent_less();
00371 cpl_msg_info(recipe, "Check input set-of-frames:");
00372 cpl_msg_indent_more();
00373
00374 if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID"))
00375 fors_sumflux_exit("Input frames are not from the same chip");
00376
00377 nframes = cpl_frameset_count_tags(frameset, arc_tag)
00378 + cpl_frameset_count_tags(frameset, flat_tag);
00379
00380 if (nframes == 0)
00381 fors_sumflux_exit("Missing input LSS calibration exposures");
00382
00383 if (nframes > 1) {
00384 cpl_msg_error(recipe, "Too many LSS calibration exposures found (%d). "
00385 "Just one is required.", nframes);
00386 fors_sumflux_exit(NULL);
00387 }
00388
00389 if (cpl_frameset_count_tags(frameset, arc_tag) > 0)
00390 exposure_tag = arc_tag;
00391 else
00392 exposure_tag = flat_tag;
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 cpl_msg_indent_less();
00412 cpl_msg_info(recipe, "Load %s frame...", exposure_tag);
00413 cpl_msg_indent_more();
00414
00415 exposure = dfs_load_image(frameset, exposure_tag, CPL_TYPE_FLOAT, 0, 0);
00416 if (exposure == NULL)
00417 fors_sumflux_exit("Cannot load input frame");
00418
00419
00420
00421
00422
00423 header = dfs_load_header(frameset, exposure_tag, 0);
00424
00425 if (header == NULL)
00426 fors_sumflux_exit("Cannot load input frame header");
00427
00428 time = cpl_propertylist_get_double(header, "EXPTIME");
00429
00430 if (cpl_error_get_code() != CPL_ERROR_NONE)
00431 fors_sumflux_exit("Missing keyword EXPTIME in input frame header");
00432
00433 instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
00434 if (instrume == NULL)
00435 fors_sumflux_exit("Missing keyword INSTRUME in input frame header");
00436 instrume = cpl_strdup(instrume);
00437
00438 if (instrume[4] == '1')
00439 snprintf(version, 80, "%s/%s", "fors1", VERSION);
00440 if (instrume[4] == '2')
00441 snprintf(version, 80, "%s/%s", "fors2", VERSION);
00442
00443 rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX");
00444
00445 if (cpl_error_get_code() != CPL_ERROR_NONE)
00446 fors_sumflux_exit("Missing keyword ESO DET WIN1 BINX in input "
00447 "frame header");
00448
00449 rebin *= cpl_propertylist_get_int(header, "ESO DET WIN1 BINY");
00450
00451 if (cpl_error_get_code() != CPL_ERROR_NONE)
00452 fors_sumflux_exit("Missing keyword ESO DET WIN1 BINY in input "
00453 "frame header");
00454
00455 if (rebin > 1) {
00456 cpl_msg_info(recipe,
00457 "One readout pixel corresponds to %d chip pixels", rebin);
00458 }
00459
00460 gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD");
00461
00462 if (cpl_error_get_code() != CPL_ERROR_NONE)
00463 fors_sumflux_exit("Missing keyword ESO DET OUT1 CONAD in arc lamp "
00464 "frame header");
00465
00466 cpl_msg_info(recipe, "The gain factor is: %.2f e-/ADU", gain);
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 switch (instrume[4]) {
00477 case '1':
00478 #ifdef OLD_FORS1
00479 cpl_msg_info(recipe, "Remove low-flux region level...");
00480 if (exposure_tag == flat_tag) {
00481 overscans = cpl_table_new(2);
00482 cpl_table_new_column(overscans, "xlow", CPL_TYPE_INT);
00483 cpl_table_new_column(overscans, "ylow", CPL_TYPE_INT);
00484 cpl_table_new_column(overscans, "xhig", CPL_TYPE_INT);
00485 cpl_table_new_column(overscans, "yhig", CPL_TYPE_INT);
00486
00487 nx = cpl_image_get_size_x(exposure);
00488 ny = cpl_image_get_size_y(exposure);
00489
00490
00491
00492 cpl_table_set_int(overscans, "xlow", 0, 200);
00493 cpl_table_set_int(overscans, "ylow", 0, 0);
00494 cpl_table_set_int(overscans, "xhig", 0, nx);
00495 cpl_table_set_int(overscans, "yhig", 0, ny);
00496
00497
00498
00499 cpl_table_set_int(overscans, "xlow", 1, 0);
00500 cpl_table_set_int(overscans, "ylow", 1, 0);
00501 cpl_table_set_int(overscans, "xhig", 1, 200);
00502 cpl_table_set_int(overscans, "yhig", 1, ny);
00503 }
00504 else {
00505 background = mos_arc_background(exposure, 15, 15);
00506 cpl_image_subtract(exposure, background);
00507 cpl_image_delete(background);
00508 }
00509 #else
00510 cpl_msg_info(recipe, "Remove bias, evaluated on overscan regions...");
00511 overscans = mos_load_overscans_vimos(header, 1);
00512 #endif
00513 break;
00514 case '2':
00515 cpl_msg_info(recipe, "Remove bias, evaluated on overscan regions...");
00516 overscans = mos_load_overscans_vimos(header, 1);
00517 break;
00518 default:
00519 cpl_msg_error(recipe, "Invalid instrument name: %s", instrume);
00520 fors_sumflux_exit(NULL);
00521 }
00522
00523 if (overscans) {
00524 dummy = mos_remove_bias(exposure, NULL, overscans);
00525 cpl_table_delete(overscans); overscans = NULL;
00526 cpl_image_delete(exposure); exposure = dummy;
00527
00528 if (exposure == NULL)
00529 fors_sumflux_exit("Cannot remove bias from input frame");
00530 }
00531
00532 nx = cpl_image_get_size_x(exposure);
00533 ny = cpl_image_get_size_y(exposure);
00534
00535 if (xhig == 0)
00536 xhig = nx;
00537
00538 if (yhig == 0)
00539 yhig = ny;
00540
00541 if (xlow > nx || ylow > ny || xhig < 0 || yhig < 0)
00542 fors_sumflux_exit("The integration region lays outside the CCD");
00543
00544 if (xlow == xhig || ylow == yhig)
00545 fors_sumflux_exit("The integration area is zero");
00546
00547 norm_factor = rebin * time * (xhig - xlow) * (yhig - ylow);
00548
00549 flux = cpl_image_get_flux(exposure);
00550 if (flux > 0.0) {
00551 flux_err = sqrt(flux/gain);
00552 }
00553 else {
00554 flux = 0.0;
00555 flux_err = 0.0;
00556 }
00557
00558 flux /= norm_factor;
00559 flux_err /= norm_factor;
00560
00561 cpl_msg_info(recipe, "Flux: %.4f +/- %.4f (ADU/s*pixel)", flux, flux_err);
00562
00563 cpl_image_divide_scalar(exposure, norm_factor);
00564
00565
00566
00567
00568
00569
00570
00571
00572 qclist = cpl_propertylist_new();
00573
00574 fors_qc_start_group(qclist, "2.0", instrume);
00575
00576 if (fors_qc_write_string("PRO.CATG", flux_tag,
00577 "Product category", instrume))
00578 fors_sumflux_exit("Cannot write product category to QC log file");
00579
00580 if (fors_qc_keyword_to_paf(header, "ESO DPR TYPE", NULL,
00581 "DPR type", instrume))
00582 fors_sumflux_exit("Missing keyword DPR TYPE in frame header");
00583
00584 if (fors_qc_keyword_to_paf(header, "ESO TPL ID", NULL,
00585 "Template", instrume))
00586 fors_sumflux_exit("Missing keyword TPL ID in frame header");
00587
00588 if (fors_qc_keyword_to_paf(header, "ESO INS GRIS1 NAME", NULL,
00589 "Grism name", instrume))
00590 fors_sumflux_exit("Missing keyword INS GRIS1 NAME in frame header");
00591
00592 if (fors_qc_keyword_to_paf(header, "ESO INS GRIS1 ID", NULL,
00593 "Grim identifier", instrume))
00594 fors_sumflux_exit("Missing keyword INS GRIS1 ID in frame header");
00595
00596 if (cpl_propertylist_has(header, "ESO INS FILT1 NAME"))
00597 fors_qc_keyword_to_paf(header, "ESO INS FILT1 NAME", NULL,
00598 "Filter name", instrume);
00599
00600 if (fors_qc_keyword_to_paf(header, "ESO INS COLL NAME", NULL,
00601 "Collimator name", instrume))
00602 fors_sumflux_exit("Missing keyword INS COLL NAME in frame header");
00603
00604 if (fors_qc_keyword_to_paf(header, "ESO DET CHIP1 ID", NULL,
00605 "Chip identifier", instrume))
00606 fors_sumflux_exit("Missing keyword DET CHIP1 ID in frame header");
00607
00608 if (fors_qc_keyword_to_paf(header, "ESO INS SLIT WID",
00609 "arcsec", "Slit width", instrume))
00610 fors_sumflux_exit("Missing keyword ESO INS SLIT WID in frame header");
00611
00612 if (fors_qc_keyword_to_paf(header, "ESO DET OUT1 CONAD", "e-/ADU",
00613 "Conversion from ADUs to electrons", instrume))
00614 fors_sumflux_exit("Missing keyword ESO DET OUT1 CONAD in frame header");
00615
00616 if (fors_qc_keyword_to_paf(header, "ESO DET WIN1 BINX", NULL,
00617 "Binning factor along X", instrume))
00618 fors_sumflux_exit("Missing keyword ESO DET WIN1 BINX in frame header");
00619
00620 if (fors_qc_keyword_to_paf(header, "ESO DET WIN1 BINY", NULL,
00621 "Binning factor along Y", instrume))
00622 fors_sumflux_exit("Missing keyword ESO DET WIN1 BINY in frame header");
00623
00624 for (i = 1; i < 7; i++) {
00625 snprintf(lamp, 20, "ESO INS LAMP%d NAME", i);
00626 if (cpl_propertylist_has(header, lamp))
00627 fors_qc_keyword_to_paf(header, lamp, NULL,
00628 "Name of lamp on", instrume);
00629 }
00630
00631 if (fors_qc_keyword_to_paf(header, "ARCFILE", NULL,
00632 "Archive name of input data", instrume))
00633 fors_sumflux_exit("Missing keyword ARCFILE in frame header");
00634
00635 cpl_propertylist_delete(header); header = NULL;
00636
00637 pipefile = dfs_generate_filename(flux_tag);
00638 if (fors_qc_write_string("PIPEFILE", pipefile,
00639 "Pipeline product name", instrume))
00640 fors_sumflux_exit("Cannot write PIPEFILE to QC log file");
00641 cpl_free(pipefile); pipefile = NULL;
00642
00643
00644
00645
00646
00647
00648 if (fors_qc_write_qc_double(qclist, flux, "QC.LAMP.FLUX", "ADU/s*pixel",
00649 "Total lamp flux", instrume)) {
00650 fors_sumflux_exit("Cannot write total lamp flux to QC log file");
00651 }
00652
00653 if (fors_qc_write_qc_double(qclist, flux_err, "QC.LAMP.FLUXERR",
00654 "ADU/s*pixel",
00655 "Error on lamp flux", instrume)) {
00656 fors_sumflux_exit("Cannot write error on lamp flux to QC log file");
00657 }
00658
00659 fors_qc_end_group();
00660
00661 cpl_free(instrume); instrume = NULL;
00662
00663 if (dfs_save_image(frameset, exposure, flux_tag, qclist,
00664 parlist, recipe, version))
00665 fors_sumflux_exit(NULL);
00666
00667 cpl_image_delete(exposure); exposure = NULL;
00668 cpl_propertylist_delete(qclist); qclist = NULL;
00669
00670 return 0;
00671
00672 }