KMOS Pipeline Reference Manual  1.0.7
kmo_dark.c
00001 /* $Id: kmo_dark.c,v 1.17 2013/01/20 04:00:41 aagudo Exp $
00002  *
00003  * This file is part of the KMOS Pipeline
00004  * Copyright (C) 2002,2003 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: aagudo $
00023  * $Date: 2013/01/20 04:00:41 $
00024  * $Revision: 1.17 $
00025  * $Name: HEAD $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033  *                              Includes
00034  *----------------------------------------------------------------------------*/
00035 
00036 #include <string.h>
00037 #include <math.h>
00038 
00039 #include <cpl.h>
00040 
00041 #include "kmo_utils.h"
00042 #include "kmo_dfs.h"
00043 #include "kmo_error.h"
00044 #include "kmo_constants.h"
00045 #include "kmo_priv_dark.h"
00046 #include "kmo_priv_functions.h"
00047 #include "kmo_cpl_extensions.h"
00048 #include "kmo_debug.h"
00049 
00050 /*-----------------------------------------------------------------------------
00051  *                          Functions prototypes
00052  *----------------------------------------------------------------------------*/
00053 
00054 static int kmo_dark_create(cpl_plugin *);
00055 static int kmo_dark_exec(cpl_plugin *);
00056 static int kmo_dark_destroy(cpl_plugin *);
00057 static int kmo_dark(cpl_parameterlist *, cpl_frameset *);
00058 
00059 /*-----------------------------------------------------------------------------
00060  *                          Static variables
00061  *----------------------------------------------------------------------------*/
00062 
00063 static char kmo_dark_description[] =
00064 "This recipe calculates the master dark frame.\n"
00065 "\n"
00066 "It is recommended to provide three or more dark exposures to produce a reason-\n"
00067 "able master with associated noise.\n"
00068 "\n"
00069 "BASIC PARAMETERS\n"
00070 "----------------\n"
00071 "--pos_bad_pix_rej\n"
00072 "--neg_bad_pix_rej\n"
00073 "Bad pixels above and below defined positive/negative threshold levels will be\n"
00074 "flagged and output to the BADPIX_DARK frame (which will go into the kmo_flat\n"
00075 "recipe). The number of bad pixels is returned as a QC1 parameter. The two para-\n"
00076 "meters can be used to change these thresholds.\n"
00077 "\n"
00078 "--cmethod\n"
00079 "Following methods of frame combination are available:\n"
00080 "   * 'ksigma' (Default)\n"
00081 "   An iterative sigma clipping. For each position all pixels in the spectrum\n"
00082 "   are examined. If they deviate significantly, they will be rejected according\n"
00083 "   to the conditions:\n"
00084 "       val > mean + stdev * cpos_rej\n"
00085 "   and\n"
00086 "       val < mean - stdev * cneg_rej\n"
00087 "   where --cpos_rej, --cneg_rej and --citer are the corresponding configuration\n"
00088 "   parameters. In the first iteration median and percentile level are used.\n"
00089 "\n"
00090 "   * 'median'\n"
00091 "   At each pixel position the median is calculated.\n"
00092 "\n"
00093 "   * 'average'\n"
00094 "   At each pixel position the average is calculated.\n"
00095 "\n"
00096 "   * 'sum'\n"
00097 "   At each pixel position the sum is calculated.\n"
00098 "\n"
00099 "   * 'min_max'\n"
00100 "   The specified number of minimum and maximum pixel values will be rejected.\n"
00101 "   --cmax and --cmin apply to this method.\n"
00102 "\n"
00103 "ADVANCED PARAMETERS\n"
00104 "-------------------\n"
00105 "--cpos_rej\n"
00106 "--cneg_rej\n"
00107 "--citer\n"
00108 "see --cmethod='ksigma'\n"
00109 "\n"
00110 "--cmax\n"
00111 "--cmin\n"
00112 "see --cmethod='min_max'\n"
00113 "\n"
00114 "-------------------------------------------------------------------------------\n"
00115 "Input files:\n"
00116 "\n"
00117 "   DO                   KMOS                                                   \n"
00118 "   category             Type   Explanation                     Required #Frames\n"
00119 "   --------             -----  -----------                     -------- -------\n"
00120 "   DARK                 RAW    Dark exposures                     Y       1-n  \n"
00121 "                               (at least 3 frames recommended)                 \n"
00122 "\n"
00123 "Output files:\n"
00124 "\n"
00125 "   DO                   KMOS\n"
00126 "   category             Type   Explanation\n"
00127 "   --------             -----  -----------\n"
00128 "   MASTER_DARK          F2D    Calculated master dark frames\n"
00129 "\n"
00130 "   BADPIXEL_DARK        B2D    Associated badpixel frames\n"
00131 "\n"
00132 "-------------------------------------------------------------------------------"
00133 "\n";
00134 
00135 /*-----------------------------------------------------------------------------
00136  *                              Functions code
00137  *----------------------------------------------------------------------------*/
00138 
00155 int cpl_plugin_get_info(cpl_pluginlist *list)
00156 {
00157     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00158     cpl_plugin *plugin = &recipe->interface;
00159 
00160     cpl_plugin_init(plugin,
00161                         CPL_PLUGIN_API,
00162                         KMOS_BINARY_VERSION,
00163                         CPL_PLUGIN_TYPE_RECIPE,
00164                         "kmo_dark",
00165                         "Create master dark frame & bad pixel mask",
00166                         kmo_dark_description,
00167                         "Alex Agudo Berbel",
00168                         "agudo@mpe.mpg.de",
00169                         kmos_get_license(),
00170                         kmo_dark_create,
00171                         kmo_dark_exec,
00172                         kmo_dark_destroy);
00173 
00174     cpl_pluginlist_append(list, plugin);
00175 
00176     return 0;
00177 }
00178 
00186 static int kmo_dark_create(cpl_plugin *plugin)
00187 {
00188     cpl_recipe *recipe;
00189     cpl_parameter *p;
00190 
00191     /* Check that the plugin is part of a valid recipe */
00192     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00193         recipe = (cpl_recipe *)plugin;
00194     else
00195         return -1;
00196 
00197     /* Create the parameters list in the cpl_recipe object */
00198     recipe->parameters = cpl_parameterlist_new();
00199 
00200     /* Fill the parameters list */
00201 
00202     /* --pos_bad_pix_rej */
00203     p = cpl_parameter_new_value("kmos.kmo_dark.pos_bad_pix_rej",
00204                                 CPL_TYPE_DOUBLE,
00205                                 "The positive rejection threshold for "
00206                                 "bad pixels",
00207                                 "kmos.kmo_dark",
00208                                 50.0);
00209     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pos_bad_pix_rej");
00210     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00211     cpl_parameterlist_append(recipe->parameters, p);
00212 
00213     /* --neg_bad_pix_rej */
00214     p = cpl_parameter_new_value("kmos.kmo_dark.neg_bad_pix_rej",
00215                                 CPL_TYPE_DOUBLE,
00216                                 "The negative rejection threshold for "
00217                                 "bad pixels",
00218                                 "kmos.kmo_dark",
00219                                 50.0);
00220     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neg_bad_pix_rej");
00221     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00222     cpl_parameterlist_append(recipe->parameters, p);
00223 
00224     return kmo_combine_pars_create(recipe->parameters,
00225                                    "kmos.kmo_dark",
00226                                    DEF_REJ_METHOD,
00227                                    FALSE);
00228 }
00229 
00235 static int kmo_dark_exec(cpl_plugin *plugin)
00236 {
00237     cpl_recipe  *recipe;
00238 
00239     /* Get the recipe out of the plugin */
00240     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00241         recipe = (cpl_recipe *)plugin;
00242     else return -1;
00243 
00244     return kmo_dark(recipe->parameters, recipe->frames);
00245 }
00246 
00252 static int kmo_dark_destroy(cpl_plugin *plugin)
00253 {
00254     cpl_recipe *recipe;
00255 
00256     /* Get the recipe out of the plugin */
00257     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00258         recipe = (cpl_recipe *)plugin;
00259     else return -1 ;
00260 
00261     cpl_parameterlist_delete(recipe->parameters);
00262     return 0 ;
00263 }
00264 
00275 static int kmo_dark(cpl_parameterlist *parlist, cpl_frameset *frameset)
00276 {
00277     cpl_imagelist    *detector_in_window       = NULL;
00278 
00279     cpl_image        *img_in_window            = NULL,
00280                      *combined_data            = NULL,
00281                      *combined_data_window     = NULL,
00282                      *combined_noise           = NULL,
00283                      *combined_noise_window    = NULL,
00284                      *bad_pix_mask             = NULL,
00285                      *bad_pix_mask_window      = NULL;
00286 
00287     cpl_frame        *frame             = NULL;
00288 
00289     int              ret_val             = 0,
00290                      nr_devices          = 0,
00291                      i                   = 0,
00292                      cmax                = 0,
00293                      cmin                = 0,
00294                      citer               = 0,
00295                      nx                  = 0,
00296                      ny                  = 0,
00297                      nx_orig             = 0,
00298                      ny_orig             = 0,
00299                      nz                  = 0,
00300                      ndit                = 0;
00301 
00302     double           cpos_rej            = 0.0,
00303                      cneg_rej            = 0.0,
00304                      exptime             = 0.0,
00305                      gain                = 0.0,
00306                      pos_bad_pix_rej     = 0.0,
00307                      neg_bad_pix_rej     = 0.0,
00308                      qc_dark             = 0.0,
00309                      qc_dark_median      = 0.0,
00310                      qc_readnoise        = 0.0,
00311                      qc_readnoise_median = 0.0,
00312                      qc_bad_pix_num      = 0.0;
00313 
00314     const char       *cmethod            = NULL,
00315                      *my_method          = NULL;
00316 
00317     char             filename[256],
00318                      filename_bad[256],
00319                      *extname            = NULL;
00320 
00321     cpl_propertylist *main_header        = NULL,
00322                      *sub_header         = NULL;
00323 
00324     main_fits_desc   desc1, desc2;
00325 
00326     char             do_mode[256];
00327 
00328     KMO_TRY
00329     {
00330         kmo_init_fits_desc(&desc1);
00331         kmo_init_fits_desc(&desc2);
00332 
00333         // --- check inputs ---
00334         KMO_TRY_ASSURE((parlist != NULL) &&
00335                        (frameset != NULL),
00336                        CPL_ERROR_NULL_INPUT,
00337                        "Not all input data is provided!");
00338 
00339         if (cpl_frameset_count_tags(frameset, DARK) < 3) {
00340             cpl_msg_warning(cpl_func, "It is recommended to provide at least "
00341                                       "3 DARK frames!");
00342         }
00343 
00344         if (cpl_frameset_count_tags(frameset, DARK) >= 1) {
00345             strcpy(do_mode, DARK);
00346         } else {
00347             strcpy(do_mode, "0");
00348         }
00349 
00350         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_dark") == 1,
00351                        CPL_ERROR_ILLEGAL_INPUT,
00352                        "Cannot identify RAW and CALIB frames!");
00353 
00354         // --- get parameters ---
00355         cpl_msg_info("", "--- Parameter setup for kmo_dark ----------");
00356 
00357         pos_bad_pix_rej = kmo_dfs_get_parameter_double(parlist,
00358                                            "kmos.kmo_dark.pos_bad_pix_rej");
00359         KMO_TRY_CHECK_ERROR_STATE();
00360         KMO_TRY_EXIT_IF_ERROR(
00361             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_dark.pos_bad_pix_rej"));
00362 
00363         neg_bad_pix_rej = kmo_dfs_get_parameter_double(parlist,
00364                                            "kmos.kmo_dark.neg_bad_pix_rej");
00365         KMO_TRY_CHECK_ERROR_STATE();
00366         KMO_TRY_EXIT_IF_ERROR(
00367             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_dark.neg_bad_pix_rej"));
00368 
00369         KMO_TRY_EXIT_IF_ERROR(
00370             kmo_combine_pars_load(parlist,
00371                                   "kmos.kmo_dark",
00372                                   &cmethod,
00373                                   &cpos_rej,
00374                                   &cneg_rej,
00375                                   &citer,
00376                                   &cmin,
00377                                   &cmax,
00378                                   FALSE));
00379         
00380         cpl_msg_info("", "-------------------------------------------");
00381         cpl_msg_info("", "Detected instrument setup:");
00382         cpl_msg_info("", "   not checked here");
00383         cpl_msg_info("", "-------------------------------------------");
00384         cpl_msg_info("", "IFU status before processing:");
00385         cpl_msg_info("", "   not checked here");
00386         cpl_msg_info("", "-------------------------------------------");
00387 
00388         KMO_TRY_EXIT_IF_NULL(
00389             frame = kmo_dfs_get_frame(frameset, do_mode));
00390 
00391         i = 0;
00392         while (frame != NULL) {
00393              main_header = kmclipm_propertylist_load(
00394                                               cpl_frame_get_filename(frame), 0);
00395 
00396             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00397                 cpl_msg_error(cpl_func, "File '%s' not found",
00398                                                  cpl_frame_get_filename(frame));
00399                 KMO_TRY_CHECK_ERROR_STATE();
00400             }
00401 
00402             if (i == 0) {
00403                 exptime = cpl_propertylist_get_double(main_header, EXPTIME);
00404 
00405                 KMO_TRY_CHECK_ERROR_STATE("EXPTIME keyword in main header "
00406                                           "missing!");
00407 
00408                 ndit = cpl_propertylist_get_int(main_header, NDIT);
00409 
00410                 KMO_TRY_CHECK_ERROR_STATE("NDIT keyword in main header "
00411                                           "missing!");
00412 
00413                 strcpy(filename, MASTER_DARK);
00414                 strcpy(filename_bad, BADPIXEL_DARK);
00415 
00416                 desc1 = kmo_identify_fits_header(
00417                             cpl_frame_get_filename(frame));
00418 
00419                 KMO_TRY_CHECK_ERROR_STATE_MSG("First fits file doesn't seem to "
00420                                               "be in KMOS-format!");
00421 
00422                 KMO_TRY_ASSURE(desc1.fits_type == raw_fits,
00423                                CPL_ERROR_ILLEGAL_INPUT,
00424                                "First input file hasn't correct data type "
00425                                "(must be a raw, unprocessed file)!");
00426             } else {
00427 
00428                 desc2 = kmo_identify_fits_header(
00429                             cpl_frame_get_filename(frame));
00430                 KMO_TRY_CHECK_ERROR_STATE_MSG("Fits file doesn't seem to be "
00431                                               "in KMOS-format!");
00432 
00433                 KMO_TRY_ASSURE(desc2.fits_type == raw_fits,
00434                                CPL_ERROR_ILLEGAL_INPUT,
00435                                "An input file hasn't correct data type "
00436                                "(must be a raw, unprocessed file)!");
00437 
00438                 kmo_free_fits_desc(&desc2);
00439             }
00440 
00441             // check if all lamps are off (flat and arc lamp)
00442             KMO_TRY_ASSURE(((kmo_check_lamp(main_header, INS_LAMP1_ST) == FALSE) &&
00443                             (kmo_check_lamp(main_header, INS_LAMP2_ST) == FALSE) &&
00444                             (kmo_check_lamp(main_header, INS_LAMP3_ST) == FALSE) &&
00445                             (kmo_check_lamp(main_header, INS_LAMP4_ST) == FALSE)) ||
00446                            (((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) ||
00447                              (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE) ||
00448                              (kmo_check_lamp(main_header, INS_LAMP3_ST) == TRUE) ||
00449                              (kmo_check_lamp(main_header, INS_LAMP4_ST) == TRUE)) &&
00450                             (strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT1 ID"), "Block") == 0) &&
00451                             (strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT2 ID"), "Block") == 0) &&
00452                             (strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT3 ID"), "Block") == 0)),
00453                            CPL_ERROR_ILLEGAL_INPUT,
00454                            "All lamps must be switched off for DARK frames!");
00455 
00456             // check if EXPTIME and NDIT are the same for all frames
00457             if (cpl_propertylist_get_double(main_header, EXPTIME) != exptime) {
00458                 cpl_msg_warning(cpl_func,
00459                                 "EXPTIME isn't the same for all "
00460                                 "frames: (is %g and %g). Proceeding anyway...",
00461                                 cpl_propertylist_get_double(main_header,
00462                                                             EXPTIME),
00463                                 exptime);
00464             }
00465 
00466             if (cpl_propertylist_get_int(main_header, NDIT) != ndit) {
00467                 cpl_msg_warning(cpl_func,
00468                                 "NDIT isn't the same for all "
00469                                 "frames: (is %d and %d). Proceeding anyway...",
00470                                 cpl_propertylist_get_int(main_header, NDIT),
00471                                 ndit);
00472             }
00473 
00474             // get next DARK frame
00475             frame = kmo_dfs_get_frame(frameset, NULL);
00476             KMO_TRY_CHECK_ERROR_STATE();
00477 
00478             cpl_propertylist_delete(main_header); main_header = NULL;
00479             i++;
00480         }
00481 
00482         // --- load, update & save primary header ---
00483         KMO_TRY_EXIT_IF_NULL(
00484             frame = kmo_dfs_get_frame(frameset, do_mode));
00485 
00486         KMO_TRY_EXIT_IF_ERROR(
00487             kmo_dfs_save_main_header(frameset, filename, "", frame,
00488                                      NULL, parlist, cpl_func));
00489 
00490         KMO_TRY_EXIT_IF_ERROR(
00491             kmo_dfs_save_main_header(frameset, filename_bad, "", frame,
00492                                      NULL, parlist, cpl_func));
00493 
00494         // --- load data ---
00495         nr_devices = desc1.nr_ext;
00496 
00497         my_method = cmethod;
00498         if ((cpl_frameset_count_tags(frameset, DARK) == 1) ||
00499             (cpl_frameset_count_tags(frameset, COMMANDLINE) == 1)) {
00500             cpl_msg_warning(cpl_func, "cmethod is changed to 'average' "
00501                             "since there is only one input frame!");
00502 
00503             my_method = "average";
00504         }
00505 
00506         // get size of input frame
00507         KMO_TRY_EXIT_IF_NULL(
00508             img_in_window = kmo_dfs_load_image(frameset, do_mode, 1, FALSE, FALSE, NULL));
00509         nx_orig = cpl_image_get_size_x(img_in_window);
00510         ny_orig = cpl_image_get_size_y(img_in_window);
00511         cpl_image_delete(img_in_window); img_in_window = NULL;
00512 
00513         KMO_TRY_ASSURE((nx_orig > 2*KMOS_BADPIX_BORDER) &&
00514                        (ny_orig > 2*KMOS_BADPIX_BORDER),
00515                        CPL_ERROR_ILLEGAL_INPUT,
00516                        "Input frames must have a height and width of at "
00517                        "least 9 pixels!");
00518 
00519         // --- loop through all detectors ---
00520         for (i = 1; i <= nr_devices; i++) {
00521             cpl_msg_info("","Processing detector No. %d", i);
00522 
00523             KMO_TRY_EXIT_IF_NULL(
00524                 detector_in_window = cpl_imagelist_new());
00525 
00526             KMO_TRY_EXIT_IF_NULL(
00527                 sub_header = kmo_dfs_load_sub_header(frameset, do_mode,
00528                                                      i, FALSE));
00529 
00530             // load data of device i of all DARK frames into an imagelist
00531             KMO_TRY_EXIT_IF_NULL(
00532                 img_in_window = kmo_dfs_load_image_window(
00533                                        frameset, do_mode, i, FALSE,
00534                                        KMOS_BADPIX_BORDER+1,
00535                                        KMOS_BADPIX_BORDER+1,
00536                                        nx_orig-KMOS_BADPIX_BORDER,
00537                                        ny_orig-KMOS_BADPIX_BORDER,
00538                                        FALSE, NULL));
00539 
00540             nx = cpl_image_get_size_x(img_in_window);
00541             ny = cpl_image_get_size_y(img_in_window);
00542 
00543             nz = 0;
00544             while (img_in_window != NULL) {
00545                 cpl_imagelist_set(detector_in_window, img_in_window, nz);
00546                 KMO_TRY_CHECK_ERROR_STATE();
00547 
00548                 // load same extension of next DARK frame
00549                 img_in_window = kmo_dfs_load_image_window(
00550                                             frameset, NULL, i, FALSE,
00551                                             KMOS_BADPIX_BORDER+1,
00552                                             KMOS_BADPIX_BORDER+1,
00553                                             nx_orig-KMOS_BADPIX_BORDER,
00554                                             ny_orig-KMOS_BADPIX_BORDER,
00555                                             FALSE, NULL);
00556                 KMO_TRY_CHECK_ERROR_STATE();
00557 
00558                 if (img_in_window != NULL) {
00559                     KMO_TRY_ASSURE((nx == cpl_image_get_size_x(img_in_window)) &&
00560                                    (ny == cpl_image_get_size_y(img_in_window)),
00561                                    CPL_ERROR_ILLEGAL_INPUT,
00562                                    "Not all input frames have the "
00563                                    "same dimensions!");
00564                 }
00565                 nz++;
00566             }
00567 
00568             // combine imagelist (data only) and create noise
00569             KMO_TRY_EXIT_IF_ERROR(
00570                 kmclipm_combine_frames(detector_in_window,
00571                                        NULL,
00572                                        NULL,
00573                                        my_method,
00574                                        cpos_rej,
00575                                        cneg_rej,
00576                                        citer,
00577                                        cmax,
00578                                        cmin,
00579                                        &combined_data_window,
00580                                        &combined_noise_window,
00581                                        -1.0));
00582 
00583             if (kmclipm_omit_warning_one_slice > 10) {
00584                 cpl_msg_warning(cpl_func, "Previous warning (number of "
00585                                           "identified slices) occured %d times.",
00586                                 kmclipm_omit_warning_one_slice);
00587                 kmclipm_omit_warning_one_slice = FALSE;
00588             }
00589 
00590             // calculate preliminary mean and stdev to create the bad pixel mask
00591             qc_dark = cpl_image_get_mean(combined_data_window);
00592             KMO_TRY_CHECK_ERROR_STATE();
00593 
00594             if (nz > 2) {
00595                 qc_readnoise = cpl_image_get_mean(combined_noise_window);
00596                 KMO_TRY_CHECK_ERROR_STATE();
00597 
00598                 KMO_TRY_ASSURE(qc_readnoise != 0.0,
00599                                CPL_ERROR_ILLEGAL_INPUT,
00600                                "All frames of detector %i are exactly "
00601                                "the same!", i);
00602             } else if (nz == 2) {
00603                 qc_readnoise = cpl_image_get_stdev(combined_noise_window);
00604                 KMO_TRY_CHECK_ERROR_STATE();
00605 
00606                 KMO_TRY_ASSURE(qc_readnoise != 0.0,
00607                                CPL_ERROR_ILLEGAL_INPUT,
00608                                "All frames of detector %i are exactly "
00609                                "the same!", i);
00610             } else if (nz == 1) {
00611                 qc_readnoise = cpl_image_get_stdev(combined_data_window);
00612                 KMO_TRY_CHECK_ERROR_STATE();
00613 
00614                 KMO_TRY_ASSURE(qc_readnoise != 0.0,
00615                                CPL_ERROR_ILLEGAL_INPUT,
00616                                "The detector frame %d seems to be uniform!", i);
00617             } else {
00618                 KMO_TRY_ASSURE(1 == 0,
00619                                CPL_ERROR_ILLEGAL_INPUT,
00620                                "detector frame must have at least one frame!");
00621             }
00622 
00623             // create bad-pixel-mask
00624             qc_bad_pix_num = kmo_create_bad_pix_dark(combined_data_window,
00625                                                      qc_dark,
00626                                                      qc_readnoise,
00627                                                      pos_bad_pix_rej,
00628                                                      neg_bad_pix_rej,
00629                                                      &bad_pix_mask_window);
00630             KMO_TRY_CHECK_ERROR_STATE();
00631 
00632             KMO_TRY_EXIT_IF_ERROR(
00633                 kmclipm_update_property_int(sub_header,
00634                                             QC_NR_BAD_PIX,
00635                                             qc_bad_pix_num,
00636                                             "[] nr. of bad pixels"));
00637 
00638             //
00639             // calculate QC.DARK, QC.READNOISE, QC.DARK.MEDIAN,
00640             // QC.READNOISE.MEDIAN, QC.DARKCUR
00641 
00642             // badpixels from combined_data_window are already rejected in
00643             // kmo_create_bad_pix_dark()
00644             KMO_TRY_EXIT_IF_ERROR(
00645                 kmo_image_reject_from_mask(combined_noise_window,
00646                                            bad_pix_mask_window));
00647 
00648             qc_dark = cpl_image_get_mean(combined_data_window);
00649             KMO_TRY_CHECK_ERROR_STATE();
00650 
00651             // calculate mean and stddev of combined frames (with rejection)
00652             if (nz > 2) {
00653                 qc_readnoise = cpl_image_get_mean(combined_noise_window) * sqrt(nz);
00654             } else if (nz == 2) {
00655                 qc_readnoise =
00656                      cpl_image_get_stdev(combined_noise_window) * sqrt(2.0);
00657             } else if (nz == 1) {
00658                 qc_readnoise = cpl_image_get_stdev(combined_data_window);
00659             } else {
00660                 KMO_TRY_ASSURE(1 == 0,
00661                         CPL_ERROR_ILLEGAL_INPUT,
00662                         "detector frame must have at least one frame!");
00663             }
00664             KMO_TRY_CHECK_ERROR_STATE();
00665 
00666             qc_dark_median = cpl_image_get_median(combined_data_window);
00667             KMO_TRY_CHECK_ERROR_STATE();
00668 
00669             if (nz > 2) {
00670                 qc_readnoise_median =
00671                         cpl_image_get_median(combined_noise_window) * sqrt(nz);
00672             } else if (nz == 2) {
00673                 qc_readnoise_median =
00674                          kmo_image_get_stdev_median(combined_noise_window) *
00675                                                                   sqrt(2.0);
00676             } else if (nz == 1) {
00677                 qc_readnoise_median =
00678                            kmo_image_get_stdev_median(combined_data_window);
00679             } else {
00680                 KMO_TRY_ASSURE(1 == 0,
00681                         CPL_ERROR_ILLEGAL_INPUT,
00682                         "detector frame must have at least one frame!");
00683             }
00684             KMO_TRY_CHECK_ERROR_STATE();
00685 
00686             KMO_TRY_EXIT_IF_ERROR(
00687                 kmclipm_update_property_double(sub_header,
00688                                                QC_DARK,
00689                                                qc_dark,
00690                                               "[adu] mean of master dark"));
00691             KMO_TRY_EXIT_IF_ERROR(
00692                 kmclipm_update_property_double(sub_header,
00693                                                QC_READNOISE,
00694                                                qc_readnoise,
00695                                         "[adu] mean noise of master dark"));
00696             KMO_TRY_EXIT_IF_ERROR(
00697                 kmclipm_update_property_double(sub_header,
00698                                                QC_DARK_MEDIAN,
00699                                                qc_dark_median,
00700                                             "[adu] median of master dark"));
00701             KMO_TRY_EXIT_IF_ERROR(
00702                 kmclipm_update_property_double(sub_header,
00703                                                QC_READNOISE_MEDIAN,
00704                                                qc_readnoise_median,
00705                                       "[adu] median noise of master dark"));
00706 
00707             // load gain
00708             gain = kmo_dfs_get_property_double(sub_header, GAIN);
00709             KMO_TRY_CHECK_ERROR_STATE_MSG(
00710                                  "GAIN-keyword in fits-header is missing!");
00711 
00712             KMO_TRY_EXIT_IF_ERROR(
00713                 kmclipm_update_property_double(sub_header,
00714                                                QC_DARK_CURRENT,
00715                                                qc_dark / exptime / gain,
00716                                                "[e-/s] dark current"));
00717 
00718             // save dark frame
00719             KMO_TRY_EXIT_IF_NULL(
00720                 extname = kmo_extname_creator(detector_frame, i, EXT_DATA));
00721             KMO_TRY_EXIT_IF_ERROR(
00722                 kmclipm_update_property_string(sub_header, EXTNAME,
00723                                                extname,
00724                                                "FITS extension name"));
00725             cpl_free(extname); extname = NULL;
00726 
00727             KMO_TRY_EXIT_IF_NULL(
00728                 combined_data = kmo_add_bad_pix_border(combined_data_window,
00729                                                        TRUE));
00730 
00731             KMO_TRY_EXIT_IF_ERROR(
00732                 kmo_dfs_save_image(combined_data, filename, "", sub_header, 0./0.));
00733 
00734             // save noise frame
00735             KMO_TRY_EXIT_IF_NULL(
00736                 extname = kmo_extname_creator(detector_frame, i, EXT_NOISE));
00737             KMO_TRY_EXIT_IF_ERROR(
00738                 kmclipm_update_property_string(sub_header, EXTNAME,
00739                                                extname,
00740                                                "FITS extension name"));
00741             cpl_free(extname); extname = NULL;
00742 
00743             KMO_TRY_EXIT_IF_NULL(
00744                 combined_noise = kmo_add_bad_pix_border(combined_noise_window,
00745                                                         TRUE));
00746 
00747             KMO_TRY_EXIT_IF_ERROR(
00748                 kmo_dfs_save_image(combined_noise, filename, "", sub_header, 0./0.));
00749 
00750             // save bad_pix frame
00751             KMO_TRY_EXIT_IF_NULL(
00752                 extname = kmo_extname_creator(detector_frame, i, EXT_BADPIX));
00753             KMO_TRY_EXIT_IF_ERROR(
00754                 kmclipm_update_property_string(sub_header, EXTNAME,
00755                                                extname,
00756                                                "FITS extension name"));
00757             cpl_free(extname); extname = NULL;
00758 
00759             KMO_TRY_EXIT_IF_NULL(
00760                 bad_pix_mask = kmo_add_bad_pix_border(bad_pix_mask_window,
00761                                                       FALSE));
00762 
00763             KMO_TRY_EXIT_IF_ERROR(
00764                 kmo_dfs_save_image(bad_pix_mask, filename_bad, "", sub_header, 0.));
00765 
00766             // free memory
00767             cpl_propertylist_delete(sub_header); sub_header = NULL;
00768             cpl_imagelist_delete(detector_in_window); detector_in_window = NULL;
00769             cpl_image_delete(combined_data); combined_data = NULL;
00770             cpl_image_delete(combined_data_window); combined_data_window = NULL;
00771             cpl_image_delete(combined_noise); combined_noise = NULL;
00772             cpl_image_delete(combined_noise_window); combined_noise_window = NULL;
00773             cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL;
00774             cpl_image_delete(bad_pix_mask_window); bad_pix_mask_window = NULL;
00775         } // for i = [1, nr_devices]
00776 
00777         cpl_msg_info("", "-------------------------------------------");
00778         cpl_msg_info("", "IFU status after processing:");
00779         cpl_msg_info("", "   not checked here");
00780         cpl_msg_info("", "-------------------------------------------");
00781     }
00782     KMO_CATCH
00783     {
00784         KMO_CATCH_MSG();
00785 
00786 //        if (desc2.sub_desc != NULL) {
00787             kmo_free_fits_desc(&desc2);
00788 //        }
00789 
00790         ret_val = -1;
00791     }
00792 
00793     kmo_free_fits_desc(&desc1);
00794     cpl_propertylist_delete(main_header); main_header = NULL;
00795     cpl_propertylist_delete(sub_header); sub_header = NULL;
00796     cpl_imagelist_delete(detector_in_window); detector_in_window = NULL;
00797     cpl_image_delete(combined_data); combined_data = NULL;
00798     cpl_image_delete(combined_data_window); combined_data_window = NULL;
00799     cpl_image_delete(combined_noise); combined_noise = NULL;
00800     cpl_image_delete(combined_noise_window); combined_noise_window = NULL;
00801     cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL;
00802     cpl_image_delete(bad_pix_mask_window); bad_pix_mask_window = NULL;
00803 
00804     return ret_val;
00805 }
00806