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_dark_z.h"
00036
00037
00058
00061
00062
00063
00064 static const char *muse_dark_help =
00065 "This recipe combines several separate dark images into one master dark file. The master dark contains the combined pixel values of the raw dark exposures, with respect to the image combination method used and normalization time specified. Processing trims the raw data and records the overscan statistics, subtracts the bias (taking account of the overscan, if --overscan is not &none&) from each raw input image, converts them from adu to count, scales them according to their exposure time, and combines them using input parameters. Hot pixels are then identified using image statistics and marked in the data quality extension. The combined image is normalized to the specified exposure time. QC statistics are computed on the output master dark.";
00066
00067 static const char *muse_dark_help_esorex =
00068 "\n\nInput frames for raw frame tag \"DARK\":\n"
00069 "\n Frame tag Type Req #Fr Description"
00070 "\n -------------------- ---- --- --- ------------"
00071 "\n DARK raw Y >=3 Raw dark"
00072 "\n MASTER_BIAS calib Y 1 Master bias"
00073 "\n BADPIX_TABLE calib . 1 Bad pixel table"
00074 "\n\nProduct frames for raw frame tag \"DARK\":\n"
00075 "\n Frame tag Level Description"
00076 "\n -------------------- -------- ------------"
00077 "\n MASTER_DARK final Master dark";
00078
00079
00087
00088 static cpl_recipeconfig *
00089 muse_dark_new_recipeconfig(void)
00090 {
00091 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
00092
00093 cpl_recipeconfig_set_tag(recipeconfig, "DARK", 3, -1);
00094 cpl_recipeconfig_set_input(recipeconfig, "DARK", "MASTER_BIAS", 1, 1);
00095 cpl_recipeconfig_set_input(recipeconfig, "DARK", "BADPIX_TABLE", -1, 1);
00096 cpl_recipeconfig_set_output(recipeconfig, "DARK", "MASTER_DARK");
00097
00098 return recipeconfig;
00099 }
00100
00101
00111
00112 static cpl_error_code
00113 muse_dark_prepare_header(const char *aFrametag, cpl_propertylist *aHeader)
00114 {
00115 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
00116 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
00117 if (!strcmp(aFrametag, "MASTER_DARK")) {
00118 muse_processing_prepare_property(aHeader, "ESO QC DARK INPUT[0-9]+ NSATURATED",
00119 CPL_TYPE_INT,
00120 "Number of saturated pixels in raw dark i in input list");
00121 muse_processing_prepare_property(aHeader, "ESO QC DARK MASTER NBADPIX",
00122 CPL_TYPE_INT,
00123 "Number of bad pixels determined from master dark");
00124 muse_processing_prepare_property(aHeader, "ESO QC DARK MASTER MEDIAN",
00125 CPL_TYPE_FLOAT,
00126 "Median value of the master dark");
00127 muse_processing_prepare_property(aHeader, "ESO QC DARK MASTER MEAN",
00128 CPL_TYPE_FLOAT,
00129 "Mean value of the master dark");
00130 muse_processing_prepare_property(aHeader, "ESO QC DARK MASTER STDEV",
00131 CPL_TYPE_FLOAT,
00132 "Standard deviation of the master dark");
00133 muse_processing_prepare_property(aHeader, "ESO QC DARK MASTER MIN",
00134 CPL_TYPE_FLOAT,
00135 "Minimum value of the master dark");
00136 muse_processing_prepare_property(aHeader, "ESO QC DARK MASTER MAX",
00137 CPL_TYPE_FLOAT,
00138 "Maximum value of the master dark");
00139 muse_processing_prepare_property(aHeader, "ESO QC DARK MASTER DC",
00140 CPL_TYPE_FLOAT,
00141 "[count/pix/h] Dark current measured on master dark in randomly placed windows");
00142 muse_processing_prepare_property(aHeader, "ESO QC DARK MASTER DCERR",
00143 CPL_TYPE_FLOAT,
00144 "[count/pix/h] Dark current error measured on master dark in randomly placed windows");
00145 muse_processing_prepare_property(aHeader, "ESO QC DARK MASTER NSATURATED",
00146 CPL_TYPE_INT,
00147 "Number of saturated pixels in output data");
00148 } else {
00149 cpl_msg_warning(__func__, "Frame tag %s is not defined", aFrametag);
00150 return CPL_ERROR_ILLEGAL_INPUT;
00151 }
00152 return CPL_ERROR_NONE;
00153 }
00154
00155
00164
00165 static cpl_frame_level
00166 muse_dark_get_frame_level(const char *aFrametag)
00167 {
00168 if (!aFrametag) {
00169 return CPL_FRAME_LEVEL_NONE;
00170 }
00171 if (!strcmp(aFrametag, "MASTER_DARK")) {
00172 return CPL_FRAME_LEVEL_FINAL;
00173 }
00174 return CPL_FRAME_LEVEL_NONE;
00175 }
00176
00177
00186
00187 static muse_frame_mode
00188 muse_dark_get_frame_mode(const char *aFrametag)
00189 {
00190 if (!aFrametag) {
00191 return MUSE_FRAME_MODE_ALL;
00192 }
00193 if (!strcmp(aFrametag, "MASTER_DARK")) {
00194 return MUSE_FRAME_MODE_MASTER;
00195 }
00196 return MUSE_FRAME_MODE_ALL;
00197 }
00198
00199
00209
00210 static int
00211 muse_dark_create(cpl_plugin *aPlugin)
00212 {
00213
00214 cpl_recipe *recipe;
00215 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
00216 recipe = (cpl_recipe *)aPlugin;
00217 } else {
00218 return -1;
00219 }
00220
00221
00222
00223 muse_processinginfo_register(recipe,
00224 muse_dark_new_recipeconfig(),
00225 muse_dark_prepare_header,
00226 muse_dark_get_frame_level,
00227 muse_dark_get_frame_mode);
00228
00229
00230
00231 if (muse_cplframework() == MUSE_CPLFRAMEWORK_ESOREX) {
00232 cpl_msg_set_time_on();
00233 }
00234
00235
00236 recipe->parameters = cpl_parameterlist_new();
00237
00238 cpl_parameter *p;
00239
00240
00241 p = cpl_parameter_new_range("muse.muse_dark.nifu",
00242 CPL_TYPE_INT,
00243 "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
00244 "muse.muse_dark",
00245 (int)0,
00246 (int)-1,
00247 (int)24);
00248 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nifu");
00249 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nifu");
00250
00251 cpl_parameterlist_append(recipe->parameters, p);
00252
00253
00254 p = cpl_parameter_new_value("muse.muse_dark.overscan",
00255 CPL_TYPE_STRING,
00256 "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.",
00257 "muse.muse_dark",
00258 (const char *)"vpoly");
00259 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "overscan");
00260 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "overscan");
00261
00262 cpl_parameterlist_append(recipe->parameters, p);
00263
00264
00265 p = cpl_parameter_new_value("muse.muse_dark.ovscreject",
00266 CPL_TYPE_STRING,
00267 "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\").",
00268 "muse.muse_dark",
00269 (const char *)"dcr");
00270 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscreject");
00271 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscreject");
00272
00273 cpl_parameterlist_append(recipe->parameters, p);
00274
00275
00276 p = cpl_parameter_new_value("muse.muse_dark.ovscsigma",
00277 CPL_TYPE_DOUBLE,
00278 "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\".",
00279 "muse.muse_dark",
00280 (double)30.);
00281 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscsigma");
00282 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscsigma");
00283
00284 cpl_parameterlist_append(recipe->parameters, p);
00285
00286
00287 p = cpl_parameter_new_value("muse.muse_dark.ovscignore",
00288 CPL_TYPE_INT,
00289 "The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits.",
00290 "muse.muse_dark",
00291 (int)3);
00292 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscignore");
00293 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscignore");
00294
00295 cpl_parameterlist_append(recipe->parameters, p);
00296
00297
00298 p = cpl_parameter_new_enum("muse.muse_dark.combine",
00299 CPL_TYPE_STRING,
00300 "Type of image combination to use.",
00301 "muse.muse_dark",
00302 (const char *)"sigclip",
00303 4,
00304 (const char *)"average",
00305 (const char *)"median",
00306 (const char *)"minmax",
00307 (const char *)"sigclip");
00308 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "combine");
00309 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "combine");
00310
00311 cpl_parameterlist_append(recipe->parameters, p);
00312
00313
00314 p = cpl_parameter_new_value("muse.muse_dark.nlow",
00315 CPL_TYPE_INT,
00316 "Number of minimum pixels to reject with minmax.",
00317 "muse.muse_dark",
00318 (int)1);
00319 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nlow");
00320 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nlow");
00321
00322 cpl_parameterlist_append(recipe->parameters, p);
00323
00324
00325 p = cpl_parameter_new_value("muse.muse_dark.nhigh",
00326 CPL_TYPE_INT,
00327 "Number of maximum pixels to reject with minmax.",
00328 "muse.muse_dark",
00329 (int)1);
00330 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nhigh");
00331 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nhigh");
00332
00333 cpl_parameterlist_append(recipe->parameters, p);
00334
00335
00336 p = cpl_parameter_new_value("muse.muse_dark.nkeep",
00337 CPL_TYPE_INT,
00338 "Number of pixels to keep with minmax.",
00339 "muse.muse_dark",
00340 (int)1);
00341 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nkeep");
00342 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nkeep");
00343
00344 cpl_parameterlist_append(recipe->parameters, p);
00345
00346
00347 p = cpl_parameter_new_value("muse.muse_dark.lsigma",
00348 CPL_TYPE_DOUBLE,
00349 "Low sigma for pixel rejection with sigclip.",
00350 "muse.muse_dark",
00351 (double)3);
00352 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lsigma");
00353 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lsigma");
00354
00355 cpl_parameterlist_append(recipe->parameters, p);
00356
00357
00358 p = cpl_parameter_new_value("muse.muse_dark.hsigma",
00359 CPL_TYPE_DOUBLE,
00360 "High sigma for pixel rejection with sigclip.",
00361 "muse.muse_dark",
00362 (double)3);
00363 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "hsigma");
00364 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "hsigma");
00365
00366 cpl_parameterlist_append(recipe->parameters, p);
00367
00368
00369 p = cpl_parameter_new_value("muse.muse_dark.scale",
00370 CPL_TYPE_BOOL,
00371 "Scale the individual images to a common exposure time before combining them.",
00372 "muse.muse_dark",
00373 (int)TRUE);
00374 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "scale");
00375 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scale");
00376
00377 cpl_parameterlist_append(recipe->parameters, p);
00378
00379
00380 p = cpl_parameter_new_value("muse.muse_dark.normalize",
00381 CPL_TYPE_DOUBLE,
00382 "Normalize the master dark to this exposure time (in seconds). To disable normalization, set this to a negative value.",
00383 "muse.muse_dark",
00384 (double)3600.);
00385 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "normalize");
00386 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "normalize");
00387
00388 cpl_parameterlist_append(recipe->parameters, p);
00389
00390
00391 p = cpl_parameter_new_value("muse.muse_dark.hotsigma",
00392 CPL_TYPE_DOUBLE,
00393 "Sigma level, in terms of median deviation above the median dark level, above which a pixel is detected and marked as 'hot'.",
00394 "muse.muse_dark",
00395 (double)5);
00396 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "hotsigma");
00397 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "hotsigma");
00398
00399 cpl_parameterlist_append(recipe->parameters, p);
00400
00401
00402 p = cpl_parameter_new_value("muse.muse_dark.merge",
00403 CPL_TYPE_BOOL,
00404 "Merge output products from different IFUs into a common file.",
00405 "muse.muse_dark",
00406 (int)FALSE);
00407 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "merge");
00408 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "merge");
00409
00410 cpl_parameterlist_append(recipe->parameters, p);
00411
00412 return 0;
00413 }
00414
00415
00426
00427 static int
00428 muse_dark_params_fill(muse_dark_params_t *aParams, cpl_parameterlist *aParameters)
00429 {
00430 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
00431 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
00432 cpl_parameter *p;
00433
00434 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.nifu");
00435 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00436 aParams->nifu = cpl_parameter_get_int(p);
00437
00438 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.overscan");
00439 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00440 aParams->overscan = cpl_parameter_get_string(p);
00441
00442 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.ovscreject");
00443 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00444 aParams->ovscreject = cpl_parameter_get_string(p);
00445
00446 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.ovscsigma");
00447 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00448 aParams->ovscsigma = cpl_parameter_get_double(p);
00449
00450 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.ovscignore");
00451 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00452 aParams->ovscignore = cpl_parameter_get_int(p);
00453
00454 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.combine");
00455 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00456 aParams->combine_s = cpl_parameter_get_string(p);
00457 aParams->combine =
00458 (!strcasecmp(aParams->combine_s, "average")) ? MUSE_DARK_PARAM_COMBINE_AVERAGE :
00459 (!strcasecmp(aParams->combine_s, "median")) ? MUSE_DARK_PARAM_COMBINE_MEDIAN :
00460 (!strcasecmp(aParams->combine_s, "minmax")) ? MUSE_DARK_PARAM_COMBINE_MINMAX :
00461 (!strcasecmp(aParams->combine_s, "sigclip")) ? MUSE_DARK_PARAM_COMBINE_SIGCLIP :
00462 MUSE_DARK_PARAM_COMBINE_INVALID_VALUE;
00463 cpl_ensure_code(aParams->combine != MUSE_DARK_PARAM_COMBINE_INVALID_VALUE,
00464 CPL_ERROR_ILLEGAL_INPUT);
00465
00466 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.nlow");
00467 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00468 aParams->nlow = cpl_parameter_get_int(p);
00469
00470 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.nhigh");
00471 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00472 aParams->nhigh = cpl_parameter_get_int(p);
00473
00474 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.nkeep");
00475 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00476 aParams->nkeep = cpl_parameter_get_int(p);
00477
00478 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.lsigma");
00479 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00480 aParams->lsigma = cpl_parameter_get_double(p);
00481
00482 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.hsigma");
00483 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00484 aParams->hsigma = cpl_parameter_get_double(p);
00485
00486 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.scale");
00487 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00488 aParams->scale = cpl_parameter_get_bool(p);
00489
00490 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.normalize");
00491 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00492 aParams->normalize = cpl_parameter_get_double(p);
00493
00494 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.hotsigma");
00495 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00496 aParams->hotsigma = cpl_parameter_get_double(p);
00497
00498 p = cpl_parameterlist_find(aParameters, "muse.muse_dark.merge");
00499 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
00500 aParams->merge = cpl_parameter_get_bool(p);
00501
00502 return 0;
00503 }
00504
00505
00512
00513 static int
00514 muse_dark_exec(cpl_plugin *aPlugin)
00515 {
00516 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
00517 return -1;
00518 }
00519 muse_processing_recipeinfo(aPlugin);
00520 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
00521 cpl_msg_set_threadid_on();
00522
00523 cpl_frameset *usedframes = cpl_frameset_new(),
00524 *outframes = cpl_frameset_new();
00525 muse_dark_params_t params;
00526 muse_dark_params_fill(¶ms, recipe->parameters);
00527
00528 cpl_errorstate prestate = cpl_errorstate_get();
00529
00530 if (params.nifu < -1 || params.nifu > kMuseNumIFUs) {
00531 cpl_msg_error(__func__, "Please specify a valid IFU number (between 1 and "
00532 "%d), 0 (to process all IFUs consecutively), or -1 (to "
00533 "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
00534 return -1;
00535 }
00536
00537 cpl_boolean donotmerge = CPL_FALSE;
00538 int rc = 0;
00539 if (params.nifu > 0) {
00540 muse_processing *proc = muse_processing_new("muse_dark",
00541 recipe);
00542 rc = muse_dark_compute(proc, ¶ms);
00543 cpl_frameset_join(usedframes, proc->usedframes);
00544 cpl_frameset_join(outframes, proc->outframes);
00545 muse_processing_delete(proc);
00546 donotmerge = CPL_TRUE;
00547 } else if (params.nifu < 0) {
00548 int *rcs = cpl_calloc(kMuseNumIFUs, sizeof(int));
00549 int nifu;
00550 #pragma omp parallel for default(none) \
00551 shared(outframes, params, rcs, recipe, usedframes)
00552 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
00553 muse_processing *proc = muse_processing_new("muse_dark",
00554 recipe);
00555 muse_dark_params_t *pars = cpl_malloc(sizeof(muse_dark_params_t));
00556 memcpy(pars, ¶ms, sizeof(muse_dark_params_t));
00557 pars->nifu = nifu;
00558 int *rci = rcs + (nifu - 1);
00559 *rci = muse_dark_compute(proc, pars);
00560 if (rci && (int)cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
00561 *rci = 0;
00562 }
00563 cpl_free(pars);
00564 #pragma omp critical(muse_processing_used_frames)
00565 cpl_frameset_join(usedframes, proc->usedframes);
00566 #pragma omp critical(muse_processing_output_frames)
00567 cpl_frameset_join(outframes, proc->outframes);
00568 muse_processing_delete(proc);
00569 }
00570
00571
00572 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
00573 if (rcs[nifu-1] != 0) {
00574 rc = rcs[nifu-1];
00575 }
00576 }
00577 cpl_free(rcs);
00578 } else {
00579 for (params.nifu = 1; params.nifu <= kMuseNumIFUs && !rc; params.nifu++) {
00580 muse_processing *proc = muse_processing_new("muse_dark",
00581 recipe);
00582 rc = muse_dark_compute(proc, ¶ms);
00583 if (rc && (int)cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
00584 rc = 0;
00585 }
00586 cpl_frameset_join(usedframes, proc->usedframes);
00587 cpl_frameset_join(outframes, proc->outframes);
00588 muse_processing_delete(proc);
00589 }
00590 }
00591 UNUSED_ARGUMENT(donotmerge);
00592
00593 if (!cpl_errorstate_is_equal(prestate)) {
00594
00595 cpl_errorstate_dump(prestate, CPL_FALSE, muse_cplerrorstate_dump_some);
00596
00597 cpl_msg_set_level(CPL_MSG_INFO);
00598 }
00599
00600 muse_cplframeset_erase_duplicate(usedframes);
00601 muse_cplframeset_erase_duplicate(outframes);
00602
00603
00604 if (params.merge && !donotmerge) {
00605 muse_utils_frameset_merge_frames(outframes, CPL_TRUE);
00606 }
00607
00608
00609
00610
00611
00612 muse_cplframeset_erase_all(recipe->frames);
00613 cpl_frameset_join(recipe->frames, usedframes);
00614 cpl_frameset_join(recipe->frames, outframes);
00615 cpl_frameset_delete(usedframes);
00616 cpl_frameset_delete(outframes);
00617 return rc;
00618 }
00619
00620
00627
00628 static int
00629 muse_dark_destroy(cpl_plugin *aPlugin)
00630 {
00631
00632 cpl_recipe *recipe;
00633 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
00634 recipe = (cpl_recipe *)aPlugin;
00635 } else {
00636 return -1;
00637 }
00638
00639
00640 cpl_parameterlist_delete(recipe->parameters);
00641 muse_processinginfo_delete(recipe);
00642 return 0;
00643 }
00644
00645
00655
00656 int
00657 cpl_plugin_get_info(cpl_pluginlist *aList)
00658 {
00659 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00660 cpl_plugin *plugin = &recipe->interface;
00661
00662 char *helptext;
00663 if (muse_cplframework() == MUSE_CPLFRAMEWORK_ESOREX) {
00664 helptext = cpl_sprintf("%s%s", muse_dark_help,
00665 muse_dark_help_esorex);
00666 } else {
00667 helptext = cpl_sprintf("%s", muse_dark_help);
00668 }
00669
00670
00671 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
00672 CPL_PLUGIN_TYPE_RECIPE,
00673 "muse_dark",
00674 "Combine several separate dark images into one master dark file and locate hot pixels.",
00675 helptext,
00676 "Peter Weilbacher",
00677 "usd-help@eso.org",
00678 muse_get_license(),
00679 muse_dark_create,
00680 muse_dark_exec,
00681 muse_dark_destroy);
00682 cpl_pluginlist_append(aList, plugin);
00683 cpl_free(helptext);
00684
00685 return 0;
00686 }
00687