00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028
00029
00030
00031 #include <string.h>
00032 #include <strings.h>
00033 #include <cpl.h>
00034
00035 #include "muse_flat_z.h"
00036
00037
00069
00072
00073
00074
00075 static const char *muse_flat_help =
00076 "This recipe combines several separate flat-field images into one master flat-field file and traces the location of the slices on the CCD. The master flat contains the combined pixel values of the raw flat exposures, with respect to the image combination method used, normalized to the mean flux. The trace table contains polynomials defining the location of the slices on the CCD. Processing trims the raw data and records the overscan statistics, subtracts the bias (taking account of the overscan, if --overscan is not &none&), and optionally, the dark from each raw input image, converts them from adu to count, scales them according to their exposure time, and combines the exposures using input parameters. To trace the position of the slices on the CCD, their edges are located using a threshold method. The edge detection is repeated at given intervals thereby tracing the central position (the mean of both edges) and width of each slit vertically across the CCD. Deviant positions of detections on CCD rows can be detected and excluded before fitting a polynomial to all positions measured for one slice. The polynomial parameters for each slice are saved in the output trace table. Finally, the area between the now known slice edges is searched for dark (and bright) pixels, using statistics in each row of the master flat.";
00077
00078 static const char *muse_flat_help_esorex =
00079 "\n\nInput frames for raw frame tag \"FLAT\":\n"
00080 "\n Frame tag Type Req #Fr Description"
00081 "\n -------------------- ---- --- --- ------------"
00082 "\n FLAT raw Y >=3 Raw flat"
00083 "\n MASTER_BIAS calib Y 1 Master bias"
00084 "\n MASTER_DARK calib . 1 Master dark"
00085 "\n BADPIX_TABLE calib . 1 Bad pixel table"
00086 "\n\nProduct frames for raw frame tag \"FLAT\":\n"
00087 "\n Frame tag Level Description"
00088 "\n -------------------- -------- ------------"
00089 "\n MASTER_FLAT final Master flat"
00090 "\n TRACE_TABLE final Trace table"
00091 "\n TRACE_SAMPLES final Table containing all tracing sample points, if --samples=true";
00092
00093
00101
00102 static cpl_recipeconfig *
00103 muse_flat_new_recipeconfig(void)
00104 {
00105 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
00106
00107 cpl_recipeconfig_set_tag(recipeconfig, "FLAT", 3, -1);
00108 cpl_recipeconfig_set_input(recipeconfig, "FLAT", "MASTER_BIAS", 1, 1);
00109 cpl_recipeconfig_set_input(recipeconfig, "FLAT", "MASTER_DARK", -1, 1);
00110 cpl_recipeconfig_set_input(recipeconfig, "FLAT", "BADPIX_TABLE", -1, 1);
00111 cpl_recipeconfig_set_output(recipeconfig, "FLAT", "MASTER_FLAT");
00112 cpl_recipeconfig_set_output(recipeconfig, "FLAT", "TRACE_TABLE");
00113 cpl_recipeconfig_set_output(recipeconfig, "FLAT", "TRACE_SAMPLES");
00114
00115 return recipeconfig;
00116 }
00117
00118
00128
00129 static cpl_error_code
00130 muse_flat_prepare_header(const char *aFrametag, cpl_propertylist *aHeader)
00131 {
00132 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
00133 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
00134 if (!strcmp(aFrametag, "MASTER_FLAT")) {
00135 muse_processing_prepare_property(aHeader, "ESO QC FLAT INPUT[0-9]+ MEDIAN",
00136 CPL_TYPE_FLOAT,
00137 "Median value of raw flat i in input list");
00138 muse_processing_prepare_property(aHeader, "ESO QC FLAT INPUT[0-9]+ MEAN",
00139 CPL_TYPE_FLOAT,
00140 "Mean value of raw flat i in input list");
00141 muse_processing_prepare_property(aHeader, "ESO QC FLAT INPUT[0-9]+ STDEV",
00142 CPL_TYPE_FLOAT,
00143 "Standard deviation of raw flat i in input list");
00144 muse_processing_prepare_property(aHeader, "ESO QC FLAT INPUT[0-9]+ MIN",
00145 CPL_TYPE_FLOAT,
00146 "Minimum value of raw flat i in input list");
00147 muse_processing_prepare_property(aHeader, "ESO QC FLAT INPUT[0-9]+ MAX",
00148 CPL_TYPE_FLOAT,
00149 "Maximum value of raw flat i in input list");
00150 muse_processing_prepare_property(aHeader, "ESO QC FLAT INPUT[0-9]+ NSATURATED",
00151 CPL_TYPE_INT,
00152 "Number of saturated pixels in raw flat i in input list");
00153 muse_processing_prepare_property(aHeader, "ESO QC FLAT MASTER MEDIAN",
00154 CPL_TYPE_FLOAT,
00155 "Median value of the master flat before normalization");
00156 muse_processing_prepare_property(aHeader, "ESO QC FLAT MASTER MEAN",
00157 CPL_TYPE_FLOAT,
00158 "Mean value of the master flat before normalization");
00159 muse_processing_prepare_property(aHeader, "ESO QC FLAT MASTER STDEV",
00160 CPL_TYPE_FLOAT,
00161 "Standard deviation of the master flat before normalization");
00162 muse_processing_prepare_property(aHeader, "ESO QC FLAT MASTER MIN",
00163 CPL_TYPE_FLOAT,
00164 "Minimum value of the master flat before normalization");
00165 muse_processing_prepare_property(aHeader, "ESO QC FLAT MASTER MAX",
00166 CPL_TYPE_FLOAT,
00167 "Maximum value of the master flat before normalization");
00168 muse_processing_prepare_property(aHeader, "ESO QC FLAT MASTER INTFLUX",
00169 CPL_TYPE_FLOAT,
00170 "Flux value, integrated over the whole master flat field before normalization");
00171 muse_processing_prepare_property(aHeader, "ESO QC FLAT MASTER NSATURATED",
00172 CPL_TYPE_INT,
00173 "Number of saturated pixels in output data");
00174 muse_processing_prepare_property(aHeader, "ESO QC FLAT MASTER SLICE[0-9]+ MEAN",
00175 CPL_TYPE_FLOAT,
00176 "Mean value around the vertical center of slice j before normalization");
00177 muse_processing_prepare_property(aHeader, "ESO QC FLAT MASTER SLICE[0-9]+ STDEV",
00178 CPL_TYPE_FLOAT,
00179 "Standard deviation around the vertical center of slice j before normalization");
00180 } else if (!strcmp(aFrametag, "TRACE_TABLE")) {
00181 muse_processing_prepare_property(aHeader, "ESO QC TRACE SLICE_L XPOS",
00182 CPL_TYPE_FLOAT,
00183 "[pix] Location of midpoint of leftmost slice");
00184 muse_processing_prepare_property(aHeader, "ESO QC TRACE SLICE_L TILT",
00185 CPL_TYPE_FLOAT,
00186 "[deg] Tilt of leftmost slice, measured as angle from vertical direction");
00187 muse_processing_prepare_property(aHeader, "ESO QC TRACE SLICE_R XPOS",
00188 CPL_TYPE_FLOAT,
00189 "[pix] Location of midpoint of rightmost slice");
00190 muse_processing_prepare_property(aHeader, "ESO QC TRACE SLICE_R TILT",
00191 CPL_TYPE_FLOAT,
00192 "[deg] Tilt of rightmost slice, measured as angle from vertical direction");
00193 muse_processing_prepare_property(aHeader, "ESO QC TRACE SLICE[0-9]+ MAXSLOPE",
00194 CPL_TYPE_FLOAT,
00195 "The maximum slope of the derived tracing functions of slice j within the CCD.");
00196 muse_processing_prepare_property(aHeader, "ESO QC TRACE SLICE10 WIDTH",
00197 CPL_TYPE_FLOAT,
00198 "[pix] Width of top left slice in the IFU (10 on CCD)");
00199 muse_processing_prepare_property(aHeader, "ESO QC TRACE SLICE46 WIDTH",
00200 CPL_TYPE_FLOAT,
00201 "[pix] Width of top right slice in the IFU (46 on CCD)");
00202 muse_processing_prepare_property(aHeader, "ESO QC TRACE SLICE3 WIDTH",
00203 CPL_TYPE_FLOAT,
00204 "[pix] Width of bottom left slice in the IFU (3 on CCD)");
00205 muse_processing_prepare_property(aHeader, "ESO QC TRACE SLICE39 WIDTH",
00206 CPL_TYPE_FLOAT,
00207 "[pix] Width of bottom right slice in the IFU (39 on CCD)");
00208 muse_processing_prepare_property(aHeader, "ESO QC TRACE WIDTHS MEDIAN",
00209 CPL_TYPE_FLOAT,
00210 "[pix] Median width of slices");
00211 muse_processing_prepare_property(aHeader, "ESO QC TRACE WIDTHS MEAN",
00212 CPL_TYPE_FLOAT,
00213 "[pix] Mean width of slices");
00214 muse_processing_prepare_property(aHeader, "ESO QC TRACE WIDTHS STDEV",
00215 CPL_TYPE_FLOAT,
00216 "[pix] Standard deviation of widths of slices");
00217 muse_processing_prepare_property(aHeader, "ESO QC TRACE WIDTHS MIN",
00218 CPL_TYPE_FLOAT,
00219 "[pix] Minimum width of slices");
00220 muse_processing_prepare_property(aHeader, "ESO QC TRACE WIDTHS MAX",
00221 CPL_TYPE_FLOAT,
00222 "[pix] Maximum width of slices");
00223 muse_processing_prepare_property(aHeader, "ESO QC TRACE GAPS MEDIAN",
00224 CPL_TYPE_FLOAT,
00225 "[pix] Median of gaps between slices");
00226 muse_processing_prepare_property(aHeader, "ESO QC TRACE GAPS MEAN",
00227 CPL_TYPE_FLOAT,
00228 "[pix] Mean of gaps between slices");
00229 muse_processing_prepare_property(aHeader, "ESO QC TRACE GAPS STDEV",
00230 CPL_TYPE_FLOAT,
00231 "[pix] Standard deviation of gaps between slices");
00232 muse_processing_prepare_property(aHeader, "ESO QC TRACE GAPS MIN",
00233 CPL_TYPE_FLOAT,
00234 "[pix] Minimum of gap between slices");
00235 muse_processing_prepare_property(aHeader, "ESO QC TRACE GAPS MAX",
00236 CPL_TYPE_FLOAT,
00237 "[pix] Maximum gap between slices");
00238 } else if (!strcmp(aFrametag, "TRACE_SAMPLES")) {
00239 } else {
00240 cpl_msg_warning(__func__, "Frame tag %s is not defined", aFrametag);
00241 return CPL_ERROR_ILLEGAL_INPUT;
00242 }
00243 return CPL_ERROR_NONE;
00244 }
00245
00246
00255
00256 static cpl_frame_level
00257 muse_flat_get_frame_level(const char *aFrametag)
00258 {
00259 if (!aFrametag) {
00260 return CPL_FRAME_LEVEL_NONE;
00261 }
00262 if (!strcmp(aFrametag, "MASTER_FLAT")) {
00263 return CPL_FRAME_LEVEL_FINAL;
00264 }
00265 if (!strcmp(aFrametag, "TRACE_TABLE")) {
00266 return CPL_FRAME_LEVEL_FINAL;
00267 }
00268 if (!strcmp(aFrametag, "TRACE_SAMPLES")) {
00269 return CPL_FRAME_LEVEL_FINAL;
00270 }
00271 return CPL_FRAME_LEVEL_NONE;
00272 }
00273
00274
00283
00284 static muse_frame_mode
00285 muse_flat_get_frame_mode(const char *aFrametag)
00286 {
00287 if (!aFrametag) {
00288 return MUSE_FRAME_MODE_ALL;
00289 }
00290 if (!strcmp(aFrametag, "MASTER_FLAT")) {
00291 return MUSE_FRAME_MODE_MASTER;
00292 }
00293 if (!strcmp(aFrametag, "TRACE_TABLE")) {
00294 return MUSE_FRAME_MODE_MASTER;
00295 }
00296 if (!strcmp(aFrametag, "TRACE_SAMPLES")) {
00297 return MUSE_FRAME_MODE_MASTER;
00298 }
00299 return MUSE_FRAME_MODE_ALL;
00300 }
00301
00302
00312
00313 static int
00314 muse_flat_create(cpl_plugin *aPlugin)
00315 {
00316
00317 cpl_recipe *recipe;
00318 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
00319 recipe = (cpl_recipe *)aPlugin;
00320 } else {
00321 return -1;
00322 }
00323
00324
00325
00326 muse_processinginfo_register(recipe,
00327 muse_flat_new_recipeconfig(),
00328 muse_flat_prepare_header,
00329 muse_flat_get_frame_level,
00330 muse_flat_get_frame_mode);
00331
00332
00333
00334 if (muse_cplframework() == MUSE_CPLFRAMEWORK_ESOREX) {
00335 cpl_msg_set_time_on();
00336 }
00337
00338
00339 recipe->parameters = cpl_parameterlist_new();
00340
00341 cpl_parameter *p;
00342
00343
00344 p = cpl_parameter_new_range("muse.muse_flat.nifu",
00345 CPL_TYPE_INT,
00346 "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
00347 "muse.muse_flat",
00348 (int)0,
00349 (int)-1,
00350 (int)24);
00351 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nifu");
00352 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nifu");
00353
00354 cpl_parameterlist_append(recipe->parameters, p);
00355
00356
00357 p = cpl_parameter_new_value("muse.muse_flat.overscan",
00358 CPL_TYPE_STRING,
00359 "If this is \"none\", stop when detecting discrepant overscan levels (see ovscsigma), for \"offset\" it assumes that the mean overscan level represents the real offset in the bias levels of the exposures involved, and adjusts the data accordingly; for \"vpoly\", a polynomial is fit to the vertical overscan and subtracted from the whole quadrant.",
00360 "muse.muse_flat",
00361 (const char *)"vpoly");
00362 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "overscan");
00363 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "overscan");
00364
00365 cpl_parameterlist_append(recipe->parameters, p);
00366
00367
00368 p = cpl_parameter_new_value("muse.muse_flat.ovscreject",
00369 CPL_TYPE_STRING,
00370 "This influences how values are rejected when computing overscan statistics. Either no rejection at all (\"none\"), rejection using the DCR algorithm (\"dcr\"), or rejection using an iterative constant fit (\"fit\").",
00371 "muse.muse_flat",
00372 (const char *)"dcr");
00373 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscreject");
00374 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscreject");
00375
00376 cpl_parameterlist_append(recipe->parameters, p);
00377
00378
00379 p = cpl_parameter_new_value("muse.muse_flat.ovscsigma",
00380 CPL_TYPE_DOUBLE,
00381 "If the deviation of mean overscan levels between a raw input image and the reference image is higher than |ovscsigma x stdev|, stop the processing. If overscan=\"vpoly\", this is used as sigma rejection level for the iterative polynomial fit (the level comparison is then done afterwards with |100 x stdev| to guard against incompatible settings). Has no effect for overscan=\"offset\".",
00382 "muse.muse_flat",
00383 (double)30.);
00384 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscsigma");
00385 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscsigma");
00386
00387 cpl_parameterlist_append(recipe->parameters, p);
00388
00389
00390 p = cpl_parameter_new_value("muse.muse_flat.ovscignore",
00391 CPL_TYPE_INT,
00392 "The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits.",
00393 "muse.muse_flat",
00394 (int)3);
00395 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscignore");
00396 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscignore");
00397
00398 cpl_parameterlist_append(recipe->parameters, p);
00399
00400
00401 p = cpl_parameter_new_enum("muse.muse_flat.combine",
00402 CPL_TYPE_STRING,
00403 "Type of combination to use",
00404 "muse.muse_flat",
00405 (const char *)"sigclip",
00406 4,
00407 (const char *)"average",
00408 (const char *)"median",
00409 (const char *)"minmax",
00410 (const char *)"sigclip");
00411 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "combine");
00412 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "combine");
00413
00414 cpl_parameterlist_append(recipe->parameters, p);
00415
00416
00417 p = cpl_parameter_new_value("muse.muse_flat.nlow",
00418 CPL_TYPE_INT,
00419 "Number of minimum pixels to reject with minmax",
00420 "muse.muse_flat",
00421 (int)1);
00422 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nlow");
00423 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nlow");
00424
00425 cpl_parameterlist_append(recipe->parameters, p);
00426
00427
00428 p = cpl_parameter_new_value("muse.muse_flat.nhigh",
00429 CPL_TYPE_INT,
00430 "Number of maximum pixels to reject with minmax",
00431 "muse.muse_flat",
00432 (int)1);
00433 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nhigh");
00434 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nhigh");
00435
00436 cpl_parameterlist_append(recipe->parameters, p);
00437
00438
00439 p = cpl_parameter_new_value("muse.muse_flat.nkeep",
00440 CPL_TYPE_INT,
00441 "Number of pixels to keep with minmax",
00442 "muse.muse_flat",
00443 (int)1);
00444 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nkeep");
00445 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nkeep");
00446
00447 cpl_parameterlist_append(recipe->parameters, p);
00448
00449
00450 p = cpl_parameter_new_value("muse.muse_flat.lsigma",
00451 CPL_TYPE_DOUBLE,
00452 "Low sigma for pixel rejection with sigclip",
00453 "muse.muse_flat",
00454 (double)3);
00455 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lsigma");
00456 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lsigma");
00457
00458 cpl_parameterlist_append(recipe->parameters, p);
00459
00460
00461 p = cpl_parameter_new_value("muse.muse_flat.hsigma",
00462 CPL_TYPE_DOUBLE,
00463 "High sigma for pixel rejection with sigclip",
00464 "muse.muse_flat",
00465 (double)3);
00466 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "hsigma");
00467 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "hsigma");
00468
00469 cpl_parameterlist_append(recipe->parameters, p);
00470
00471
00472 p = cpl_parameter_new_value("muse.muse_flat.scale",
00473 CPL_TYPE_BOOL,
00474 "Scale the individual images to a common exposure time before combining them.",
00475 "muse.muse_flat",
00476 (int)TRUE);
00477 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "scale");
00478 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scale");
00479
00480 cpl_parameterlist_append(recipe->parameters, p);
00481
00482
00483 p = cpl_parameter_new_value("muse.muse_flat.normalize",
00484 CPL_TYPE_BOOL,
00485 "Normalize the master flat to the average flux",
00486 "muse.muse_flat",
00487 (int)TRUE);
00488 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "normalize");
00489 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "normalize");
00490
00491 cpl_parameterlist_append(recipe->parameters, p);
00492
00493
00494 p = cpl_parameter_new_value("muse.muse_flat.trace",
00495 CPL_TYPE_BOOL,
00496 "Trace the position of the slices on the master flat",
00497 "muse.muse_flat",
00498 (int)TRUE);
00499 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "trace");
00500 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "trace");
00501
00502 cpl_parameterlist_append(recipe->parameters, p);
00503
00504
00505 p = cpl_parameter_new_value("muse.muse_flat.nsum",
00506 CPL_TYPE_INT,
00507 "Number of lines over which to average when tracing",
00508 "muse.muse_flat",
00509 (int)32);
00510 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nsum");
00511 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nsum");
00512
00513 cpl_parameterlist_append(recipe->parameters, p);
00514
00515
00516 p = cpl_parameter_new_value("muse.muse_flat.order",
00517 CPL_TYPE_INT,
00518 "Order of polynomial fit to the trace",
00519 "muse.muse_flat",
00520 (int)5);
00521 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "order");
00522 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "order");
00523
00524 cpl_parameterlist_append(recipe->parameters, p);
00525
00526
00527 p = cpl_parameter_new_value("muse.muse_flat.edgefrac",
00528 CPL_TYPE_DOUBLE,
00529 "Fractional change required to identify edge when tracing",
00530 "muse.muse_flat",
00531 (double)0.5);
00532 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "edgefrac");
00533 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "edgefrac");
00534
00535 cpl_parameterlist_append(recipe->parameters, p);
00536
00537
00538 p = cpl_parameter_new_value("muse.muse_flat.losigmabadpix",
00539 CPL_TYPE_DOUBLE,
00540 "Low sigma to find dark pixels in the master flat",
00541 "muse.muse_flat",
00542 (double)5.);
00543 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "losigmabadpix");
00544 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "losigmabadpix");
00545
00546 cpl_parameterlist_append(recipe->parameters, p);
00547
00548
00549 p = cpl_parameter_new_value("muse.muse_flat.hisigmabadpix",
00550 CPL_TYPE_DOUBLE,
00551 "High sigma to find bright pixels in the master flat",
00552 "muse.muse_flat",
00553 (double)5.);
00554 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "hisigmabadpix");
00555 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "hisigmabadpix");
00556
00557 cpl_parameterlist_append(recipe->parameters, p);
00558
00559
00560 p = cpl_parameter_new_value("muse.muse_flat.samples",
00561 CPL_TYPE_BOOL,
00562 "Create a table containing all tracing sample points.",
00563 "muse.muse_flat",
00564 (int)FALSE);
00565 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "samples");
00566 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "samples");
00567
00568 cpl_parameterlist_append(recipe->parameters, p);
00569
00570
00571 p = cpl_parameter_new_value("muse.muse_flat.merge",
00572 CPL_TYPE_BOOL,
00573 "Merge output products from different IFUs into a common file.",
00574 "muse.muse_flat",
00575 (int)FALSE);
00576 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "merge");
00577 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "merge");
00578
00579 cpl_parameterlist_append(recipe->parameters, p);
00580
00581 return 0;
00582 }
00583
00584
00595
00596 static int
00597 muse_flat_params_fill(muse_flat_params_t *aParams, cpl_parameterlist *aParameters)
00598 {
00599 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
00600 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
00601 cpl_parameter *p;
00602
00603 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.nifu");
00604 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00605 aParams->nifu = cpl_parameter_get_int(p);
00606
00607 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.overscan");
00608 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00609 aParams->overscan = cpl_parameter_get_string(p);
00610
00611 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.ovscreject");
00612 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00613 aParams->ovscreject = cpl_parameter_get_string(p);
00614
00615 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.ovscsigma");
00616 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00617 aParams->ovscsigma = cpl_parameter_get_double(p);
00618
00619 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.ovscignore");
00620 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00621 aParams->ovscignore = cpl_parameter_get_int(p);
00622
00623 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.combine");
00624 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00625 aParams->combine_s = cpl_parameter_get_string(p);
00626 aParams->combine =
00627 (!strcasecmp(aParams->combine_s, "average")) ? MUSE_FLAT_PARAM_COMBINE_AVERAGE :
00628 (!strcasecmp(aParams->combine_s, "median")) ? MUSE_FLAT_PARAM_COMBINE_MEDIAN :
00629 (!strcasecmp(aParams->combine_s, "minmax")) ? MUSE_FLAT_PARAM_COMBINE_MINMAX :
00630 (!strcasecmp(aParams->combine_s, "sigclip")) ? MUSE_FLAT_PARAM_COMBINE_SIGCLIP :
00631 MUSE_FLAT_PARAM_COMBINE_INVALID_VALUE;
00632 cpl_ensure_code(aParams->combine != MUSE_FLAT_PARAM_COMBINE_INVALID_VALUE,
00633 CPL_ERROR_ILLEGAL_INPUT);
00634
00635 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.nlow");
00636 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00637 aParams->nlow = cpl_parameter_get_int(p);
00638
00639 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.nhigh");
00640 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00641 aParams->nhigh = cpl_parameter_get_int(p);
00642
00643 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.nkeep");
00644 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00645 aParams->nkeep = cpl_parameter_get_int(p);
00646
00647 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.lsigma");
00648 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00649 aParams->lsigma = cpl_parameter_get_double(p);
00650
00651 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.hsigma");
00652 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00653 aParams->hsigma = cpl_parameter_get_double(p);
00654
00655 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.scale");
00656 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00657 aParams->scale = cpl_parameter_get_bool(p);
00658
00659 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.normalize");
00660 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00661 aParams->normalize = cpl_parameter_get_bool(p);
00662
00663 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.trace");
00664 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00665 aParams->trace = cpl_parameter_get_bool(p);
00666
00667 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.nsum");
00668 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00669 aParams->nsum = cpl_parameter_get_int(p);
00670
00671 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.order");
00672 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00673 aParams->order = cpl_parameter_get_int(p);
00674
00675 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.edgefrac");
00676 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00677 aParams->edgefrac = cpl_parameter_get_double(p);
00678
00679 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.losigmabadpix");
00680 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00681 aParams->losigmabadpix = cpl_parameter_get_double(p);
00682
00683 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.hisigmabadpix");
00684 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00685 aParams->hisigmabadpix = cpl_parameter_get_double(p);
00686
00687 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.samples");
00688 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00689 aParams->samples = cpl_parameter_get_bool(p);
00690
00691 p = cpl_parameterlist_find(aParameters, "muse.muse_flat.merge");
00692 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00693 aParams->merge = cpl_parameter_get_bool(p);
00694
00695 return 0;
00696 }
00697
00698
00705
00706 static int
00707 muse_flat_exec(cpl_plugin *aPlugin)
00708 {
00709 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
00710 return -1;
00711 }
00712 muse_processing_recipeinfo(aPlugin);
00713 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
00714 cpl_msg_set_threadid_on();
00715
00716 cpl_frameset *usedframes = cpl_frameset_new(),
00717 *outframes = cpl_frameset_new();
00718 muse_flat_params_t params;
00719 muse_flat_params_fill(¶ms, recipe->parameters);
00720
00721 cpl_errorstate prestate = cpl_errorstate_get();
00722
00723 if (params.nifu < -1 || params.nifu > kMuseNumIFUs) {
00724 cpl_msg_error(__func__, "Please specify a valid IFU number (between 1 and "
00725 "%d), 0 (to process all IFUs consecutively), or -1 (to "
00726 "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
00727 return -1;
00728 }
00729
00730 cpl_boolean donotmerge = CPL_FALSE;
00731 int rc = 0;
00732 if (params.nifu > 0) {
00733 muse_processing *proc = muse_processing_new("muse_flat",
00734 recipe);
00735 rc = muse_flat_compute(proc, ¶ms);
00736 cpl_frameset_join(usedframes, proc->usedframes);
00737 cpl_frameset_join(outframes, proc->outframes);
00738 muse_processing_delete(proc);
00739 donotmerge = CPL_TRUE;
00740 } else if (params.nifu < 0) {
00741 int *rcs = cpl_calloc(kMuseNumIFUs, sizeof(int));
00742 int nifu;
00743 #pragma omp parallel for default(none) \
00744 shared(outframes, params, rcs, recipe, usedframes)
00745 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
00746 muse_processing *proc = muse_processing_new("muse_flat",
00747 recipe);
00748 muse_flat_params_t *pars = cpl_malloc(sizeof(muse_flat_params_t));
00749 memcpy(pars, ¶ms, sizeof(muse_flat_params_t));
00750 pars->nifu = nifu;
00751 int *rci = rcs + (nifu - 1);
00752 *rci = muse_flat_compute(proc, pars);
00753 if (rci && (int)cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
00754 *rci = 0;
00755 }
00756 cpl_free(pars);
00757 #pragma omp critical(muse_processing_used_frames)
00758 cpl_frameset_join(usedframes, proc->usedframes);
00759 #pragma omp critical(muse_processing_output_frames)
00760 cpl_frameset_join(outframes, proc->outframes);
00761 muse_processing_delete(proc);
00762 }
00763
00764
00765 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
00766 if (rcs[nifu-1] != 0) {
00767 rc = rcs[nifu-1];
00768 }
00769 }
00770 cpl_free(rcs);
00771 } else {
00772 for (params.nifu = 1; params.nifu <= kMuseNumIFUs && !rc; params.nifu++) {
00773 muse_processing *proc = muse_processing_new("muse_flat",
00774 recipe);
00775 rc = muse_flat_compute(proc, ¶ms);
00776 if (rc && (int)cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
00777 rc = 0;
00778 }
00779 cpl_frameset_join(usedframes, proc->usedframes);
00780 cpl_frameset_join(outframes, proc->outframes);
00781 muse_processing_delete(proc);
00782 }
00783 }
00784 UNUSED_ARGUMENT(donotmerge);
00785
00786 if (!cpl_errorstate_is_equal(prestate)) {
00787
00788 cpl_errorstate_dump(prestate, CPL_FALSE, muse_cplerrorstate_dump_some);
00789
00790 cpl_msg_set_level(CPL_MSG_INFO);
00791 }
00792
00793 muse_cplframeset_erase_duplicate(usedframes);
00794 muse_cplframeset_erase_duplicate(outframes);
00795
00796
00797 if (params.merge && !donotmerge) {
00798 muse_utils_frameset_merge_frames(outframes, CPL_TRUE);
00799 }
00800
00801
00802
00803
00804
00805 muse_cplframeset_erase_all(recipe->frames);
00806 cpl_frameset_join(recipe->frames, usedframes);
00807 cpl_frameset_join(recipe->frames, outframes);
00808 cpl_frameset_delete(usedframes);
00809 cpl_frameset_delete(outframes);
00810 return rc;
00811 }
00812
00813
00820
00821 static int
00822 muse_flat_destroy(cpl_plugin *aPlugin)
00823 {
00824
00825 cpl_recipe *recipe;
00826 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
00827 recipe = (cpl_recipe *)aPlugin;
00828 } else {
00829 return -1;
00830 }
00831
00832
00833 cpl_parameterlist_delete(recipe->parameters);
00834 muse_processinginfo_delete(recipe);
00835 return 0;
00836 }
00837
00838
00848
00849 int
00850 cpl_plugin_get_info(cpl_pluginlist *aList)
00851 {
00852 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00853 cpl_plugin *plugin = &recipe->interface;
00854
00855 char *helptext;
00856 if (muse_cplframework() == MUSE_CPLFRAMEWORK_ESOREX) {
00857 helptext = cpl_sprintf("%s%s", muse_flat_help,
00858 muse_flat_help_esorex);
00859 } else {
00860 helptext = cpl_sprintf("%s", muse_flat_help);
00861 }
00862
00863
00864 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
00865 CPL_PLUGIN_TYPE_RECIPE,
00866 "muse_flat",
00867 "Combine several separate flat images into one master flat file, trace slice locations, and locate dark pixels.",
00868 helptext,
00869 "Peter Weilbacher (based on Joris Gerssen's draft)",
00870 "usd-help@eso.org",
00871 muse_get_license(),
00872 muse_flat_create,
00873 muse_flat_exec,
00874 muse_flat_destroy);
00875 cpl_pluginlist_append(aList, plugin);
00876 cpl_free(helptext);
00877
00878 return 0;
00879 }
00880