KMOS Pipeline Reference Manual  1.0.8
kmo_dark.c
00001 /* $Id: kmo_dark.c,v 1.18 2013/02/19 10:51:08 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/02/19 10:51:08 $
00024  * $Revision: 1.18 $
00025  * $Name: kmosp_v1_0_8__20130220 $
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 "--file_extension"
00104 "Set this parameter to TRUE if the EXPTIME keyword should be appended to\n"
00105 "the output filenames.\n"
00106 "\n"
00107 "ADVANCED PARAMETERS\n"
00108 "-------------------\n"
00109 "--cpos_rej\n"
00110 "--cneg_rej\n"
00111 "--citer\n"
00112 "see --cmethod='ksigma'\n"
00113 "\n"
00114 "--cmax\n"
00115 "--cmin\n"
00116 "see --cmethod='min_max'\n"
00117 "\n"
00118 "-------------------------------------------------------------------------------\n"
00119 "Input files:\n"
00120 "\n"
00121 "   DO                   KMOS                                                   \n"
00122 "   category             Type   Explanation                     Required #Frames\n"
00123 "   --------             -----  -----------                     -------- -------\n"
00124 "   DARK                 RAW    Dark exposures                     Y       1-n  \n"
00125 "                               (at least 3 frames recommended)                 \n"
00126 "\n"
00127 "Output files:\n"
00128 "\n"
00129 "   DO                   KMOS\n"
00130 "   category             Type   Explanation\n"
00131 "   --------             -----  -----------\n"
00132 "   MASTER_DARK          F2D    Calculated master dark frames\n"
00133 "\n"
00134 "   BADPIXEL_DARK        B2D    Associated badpixel frames\n"
00135 "\n"
00136 "-------------------------------------------------------------------------------"
00137 "\n";
00138 
00139 /*-----------------------------------------------------------------------------
00140  *                              Functions code
00141  *----------------------------------------------------------------------------*/
00142 
00159 int cpl_plugin_get_info(cpl_pluginlist *list)
00160 {
00161     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00162     cpl_plugin *plugin = &recipe->interface;
00163 
00164     cpl_plugin_init(plugin,
00165                         CPL_PLUGIN_API,
00166                         KMOS_BINARY_VERSION,
00167                         CPL_PLUGIN_TYPE_RECIPE,
00168                         "kmo_dark",
00169                         "Create master dark frame & bad pixel mask",
00170                         kmo_dark_description,
00171                         "Alex Agudo Berbel",
00172                         "agudo@mpe.mpg.de",
00173                         kmos_get_license(),
00174                         kmo_dark_create,
00175                         kmo_dark_exec,
00176                         kmo_dark_destroy);
00177 
00178     cpl_pluginlist_append(list, plugin);
00179 
00180     return 0;
00181 }
00182 
00190 static int kmo_dark_create(cpl_plugin *plugin)
00191 {
00192     cpl_recipe *recipe;
00193     cpl_parameter *p;
00194 
00195     /* Check that the plugin is part of a valid recipe */
00196     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00197         recipe = (cpl_recipe *)plugin;
00198     else
00199         return -1;
00200 
00201     /* Create the parameters list in the cpl_recipe object */
00202     recipe->parameters = cpl_parameterlist_new();
00203 
00204     /* Fill the parameters list */
00205 
00206     /* --pos_bad_pix_rej */
00207     p = cpl_parameter_new_value("kmos.kmo_dark.pos_bad_pix_rej",
00208                                 CPL_TYPE_DOUBLE,
00209                                 "The positive rejection threshold for "
00210                                 "bad pixels",
00211                                 "kmos.kmo_dark",
00212                                 50.0);
00213     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pos_bad_pix_rej");
00214     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00215     cpl_parameterlist_append(recipe->parameters, p);
00216 
00217     /* --neg_bad_pix_rej */
00218     p = cpl_parameter_new_value("kmos.kmo_dark.neg_bad_pix_rej",
00219                                 CPL_TYPE_DOUBLE,
00220                                 "The negative rejection threshold for "
00221                                 "bad pixels",
00222                                 "kmos.kmo_dark",
00223                                 50.0);
00224     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neg_bad_pix_rej");
00225     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00226     cpl_parameterlist_append(recipe->parameters, p);
00227 
00228     /* --file_extension */
00229     p = cpl_parameter_new_value("kmos.kmo_dark.file_extension",
00230                                 CPL_TYPE_BOOL,
00231                                 "Controls if EXPTIME keyword should be appended "
00232                                 "to product filenames.",
00233                                 "kmos.kmo_dark",
00234                                 FALSE);
00235     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "file_extension");
00236     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00237     cpl_parameterlist_append(recipe->parameters, p);
00238 
00239     return kmo_combine_pars_create(recipe->parameters,
00240                                    "kmos.kmo_dark",
00241                                    DEF_REJ_METHOD,
00242                                    FALSE);
00243 }
00244 
00250 static int kmo_dark_exec(cpl_plugin *plugin)
00251 {
00252     cpl_recipe  *recipe;
00253 
00254     /* Get the recipe out of the plugin */
00255     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00256         recipe = (cpl_recipe *)plugin;
00257     else return -1;
00258 
00259     return kmo_dark(recipe->parameters, recipe->frames);
00260 }
00261 
00267 static int kmo_dark_destroy(cpl_plugin *plugin)
00268 {
00269     cpl_recipe *recipe;
00270 
00271     /* Get the recipe out of the plugin */
00272     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00273         recipe = (cpl_recipe *)plugin;
00274     else return -1 ;
00275 
00276     cpl_parameterlist_delete(recipe->parameters);
00277     return 0 ;
00278 }
00279 
00290 static int kmo_dark(cpl_parameterlist *parlist, cpl_frameset *frameset)
00291 {
00292     cpl_imagelist    *detector_in_window       = NULL;
00293 
00294     cpl_image        *img_in_window            = NULL,
00295                      *combined_data            = NULL,
00296                      *combined_data_window     = NULL,
00297                      *combined_noise           = NULL,
00298                      *combined_noise_window    = NULL,
00299                      *bad_pix_mask             = NULL,
00300                      *bad_pix_mask_window      = NULL;
00301 
00302     cpl_frame        *frame             = NULL;
00303 
00304     int              ret_val             = 0,
00305                      nr_devices          = 0,
00306                      i                   = 0,
00307                      cmax                = 0,
00308                      cmin                = 0,
00309                      citer               = 0,
00310                      nx                  = 0,
00311                      ny                  = 0,
00312                      nx_orig             = 0,
00313                      ny_orig             = 0,
00314                      nz                  = 0,
00315                      ndit                = 0,
00316                      file_extension      = FALSE;
00317 
00318     double           cpos_rej            = 0.0,
00319                      cneg_rej            = 0.0,
00320                      exptime             = 0.0,
00321                      gain                = 0.0,
00322                      pos_bad_pix_rej     = 0.0,
00323                      neg_bad_pix_rej     = 0.0,
00324                      qc_dark             = 0.0,
00325                      qc_dark_median      = 0.0,
00326                      qc_readnoise        = 0.0,
00327                      qc_readnoise_median = 0.0,
00328                      qc_bad_pix_num      = 0.0;
00329 
00330     const char       *cmethod            = NULL,
00331                      *my_method          = NULL;
00332 
00333     char             *filename           = NULL,
00334                      *filename_bad       = NULL,
00335                      *extname            = NULL;
00336 
00337     cpl_propertylist *main_header        = NULL,
00338                      *sub_header         = NULL;
00339 
00340     main_fits_desc   desc1, desc2;
00341 
00342     char             do_mode[256];
00343 
00344     KMO_TRY
00345     {
00346         kmo_init_fits_desc(&desc1);
00347         kmo_init_fits_desc(&desc2);
00348 
00349         // --- check inputs ---
00350         KMO_TRY_ASSURE((parlist != NULL) &&
00351                        (frameset != NULL),
00352                        CPL_ERROR_NULL_INPUT,
00353                        "Not all input data is provided!");
00354 
00355         if (cpl_frameset_count_tags(frameset, DARK) < 3) {
00356             cpl_msg_warning(cpl_func, "It is recommended to provide at least "
00357                                       "3 DARK frames!");
00358         }
00359 
00360         if (cpl_frameset_count_tags(frameset, DARK) >= 1) {
00361             strcpy(do_mode, DARK);
00362         } else {
00363             strcpy(do_mode, "0");
00364         }
00365 
00366         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_dark") == 1,
00367                        CPL_ERROR_ILLEGAL_INPUT,
00368                        "Cannot identify RAW and CALIB frames!");
00369 
00370         // --- get parameters ---
00371         cpl_msg_info("", "--- Parameter setup for kmo_dark ----------");
00372 
00373         pos_bad_pix_rej = kmo_dfs_get_parameter_double(parlist,
00374                                            "kmos.kmo_dark.pos_bad_pix_rej");
00375         KMO_TRY_CHECK_ERROR_STATE();
00376         KMO_TRY_EXIT_IF_ERROR(
00377             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_dark.pos_bad_pix_rej"));
00378 
00379         neg_bad_pix_rej = kmo_dfs_get_parameter_double(parlist,
00380                                            "kmos.kmo_dark.neg_bad_pix_rej");
00381         KMO_TRY_CHECK_ERROR_STATE();
00382         KMO_TRY_EXIT_IF_ERROR(
00383             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_dark.neg_bad_pix_rej"));
00384 
00385         file_extension = kmo_dfs_get_parameter_bool(parlist,
00386                                                         "kmos.kmo_dark.file_extension");
00387         KMO_TRY_CHECK_ERROR_STATE();
00388         KMO_TRY_EXIT_IF_ERROR(
00389            kmo_dfs_print_parameter_help(parlist, "kmos.kmo_dark.file_extension"));
00390 
00391         KMO_TRY_ASSURE((file_extension == TRUE) ||
00392                        (file_extension == FALSE),
00393                        CPL_ERROR_ILLEGAL_INPUT,
00394                        "extension must be TRUE or FALSE!");
00395 
00396         KMO_TRY_EXIT_IF_ERROR(
00397             kmo_combine_pars_load(parlist,
00398                                   "kmos.kmo_dark",
00399                                   &cmethod,
00400                                   &cpos_rej,
00401                                   &cneg_rej,
00402                                   &citer,
00403                                   &cmin,
00404                                   &cmax,
00405                                   FALSE));
00406         
00407         cpl_msg_info("", "-------------------------------------------");
00408         cpl_msg_info("", "Detected instrument setup:");
00409         cpl_msg_info("", "   not checked here");
00410         cpl_msg_info("", "-------------------------------------------");
00411         cpl_msg_info("", "IFU status before processing:");
00412         cpl_msg_info("", "   not checked here");
00413         cpl_msg_info("", "-------------------------------------------");
00414 
00415         KMO_TRY_EXIT_IF_NULL(
00416             frame = kmo_dfs_get_frame(frameset, do_mode));
00417 
00418         i = 0;
00419         while (frame != NULL) {
00420              main_header = kmclipm_propertylist_load(
00421                                               cpl_frame_get_filename(frame), 0);
00422 
00423             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00424                 cpl_msg_error(cpl_func, "File '%s' not found",
00425                                                  cpl_frame_get_filename(frame));
00426                 KMO_TRY_CHECK_ERROR_STATE();
00427             }
00428 
00429             if (i == 0) {
00430                 exptime = cpl_propertylist_get_double(main_header, EXPTIME);
00431 
00432                 KMO_TRY_CHECK_ERROR_STATE("EXPTIME keyword in main header "
00433                                           "missing!");
00434 
00435                 ndit = cpl_propertylist_get_int(main_header, NDIT);
00436 
00437                 KMO_TRY_CHECK_ERROR_STATE("NDIT keyword in main header "
00438                                           "missing!");
00439 
00440                 if (file_extension) {
00441                     filename = cpl_sprintf("%s_%d", MASTER_DARK, (int)exptime);
00442                     filename_bad = cpl_sprintf("%s_%d", BADPIXEL_DARK, (int)exptime);
00443                 } else {
00444                     filename = cpl_sprintf("%s", MASTER_DARK);
00445                     filename_bad = cpl_sprintf("%s", BADPIXEL_DARK);
00446                 }
00447 
00448 
00449                 desc1 = kmo_identify_fits_header(
00450                             cpl_frame_get_filename(frame));
00451 
00452                 KMO_TRY_CHECK_ERROR_STATE_MSG("First fits file doesn't seem to "
00453                                               "be in KMOS-format!");
00454 
00455                 KMO_TRY_ASSURE(desc1.fits_type == raw_fits,
00456                                CPL_ERROR_ILLEGAL_INPUT,
00457                                "First input file hasn't correct data type "
00458                                "(must be a raw, unprocessed file)!");
00459             } else {
00460 
00461                 desc2 = kmo_identify_fits_header(
00462                             cpl_frame_get_filename(frame));
00463                 KMO_TRY_CHECK_ERROR_STATE_MSG("Fits file doesn't seem to be "
00464                                               "in KMOS-format!");
00465 
00466                 KMO_TRY_ASSURE(desc2.fits_type == raw_fits,
00467                                CPL_ERROR_ILLEGAL_INPUT,
00468                                "An input file hasn't correct data type "
00469                                "(must be a raw, unprocessed file)!");
00470 
00471                 kmo_free_fits_desc(&desc2);
00472             }
00473 
00474             // check if all lamps are off (flat and arc lamp)
00475             KMO_TRY_ASSURE(((kmo_check_lamp(main_header, INS_LAMP1_ST) == FALSE) &&
00476                             (kmo_check_lamp(main_header, INS_LAMP2_ST) == FALSE) &&
00477                             (kmo_check_lamp(main_header, INS_LAMP3_ST) == FALSE) &&
00478                             (kmo_check_lamp(main_header, INS_LAMP4_ST) == FALSE)) ||
00479                            (((kmo_check_lamp(main_header, INS_LAMP1_ST) == TRUE) ||
00480                              (kmo_check_lamp(main_header, INS_LAMP2_ST) == TRUE) ||
00481                              (kmo_check_lamp(main_header, INS_LAMP3_ST) == TRUE) ||
00482                              (kmo_check_lamp(main_header, INS_LAMP4_ST) == TRUE)) &&
00483                             (strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT1 ID"), "Block") == 0) &&
00484                             (strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT2 ID"), "Block") == 0) &&
00485                             (strcmp(cpl_propertylist_get_string(main_header, "ESO INS FILT3 ID"), "Block") == 0)),
00486                            CPL_ERROR_ILLEGAL_INPUT,
00487                            "All lamps must be switched off for DARK frames!");
00488 
00489             // check if EXPTIME and NDIT are the same for all frames
00490             if (cpl_propertylist_get_double(main_header, EXPTIME) != exptime) {
00491                 cpl_msg_warning(cpl_func,
00492                                 "EXPTIME isn't the same for all "
00493                                 "frames: (is %g and %g). Proceeding anyway...",
00494                                 cpl_propertylist_get_double(main_header,
00495                                                             EXPTIME),
00496                                 exptime);
00497             }
00498 
00499             if (cpl_propertylist_get_int(main_header, NDIT) != ndit) {
00500                 cpl_msg_warning(cpl_func,
00501                                 "NDIT isn't the same for all "
00502                                 "frames: (is %d and %d). Proceeding anyway...",
00503                                 cpl_propertylist_get_int(main_header, NDIT),
00504                                 ndit);
00505             }
00506 
00507             // get next DARK frame
00508             frame = kmo_dfs_get_frame(frameset, NULL);
00509             KMO_TRY_CHECK_ERROR_STATE();
00510 
00511             cpl_propertylist_delete(main_header); main_header = NULL;
00512             i++;
00513         }
00514 
00515         // --- load, update & save primary header ---
00516         KMO_TRY_EXIT_IF_NULL(
00517             frame = kmo_dfs_get_frame(frameset, do_mode));
00518 
00519         KMO_TRY_EXIT_IF_ERROR(
00520             kmo_dfs_save_main_header(frameset, filename, "", frame,
00521                                      NULL, parlist, cpl_func));
00522 
00523         KMO_TRY_EXIT_IF_ERROR(
00524             kmo_dfs_save_main_header(frameset, filename_bad, "", frame,
00525                                      NULL, parlist, cpl_func));
00526 
00527         // --- load data ---
00528         nr_devices = desc1.nr_ext;
00529 
00530         my_method = cmethod;
00531         if ((cpl_frameset_count_tags(frameset, DARK) == 1) ||
00532             (cpl_frameset_count_tags(frameset, COMMANDLINE) == 1)) {
00533             cpl_msg_warning(cpl_func, "cmethod is changed to 'average' "
00534                             "since there is only one input frame!");
00535 
00536             my_method = "average";
00537         }
00538 
00539         // get size of input frame
00540         KMO_TRY_EXIT_IF_NULL(
00541             img_in_window = kmo_dfs_load_image(frameset, do_mode, 1, FALSE, FALSE, NULL));
00542         nx_orig = cpl_image_get_size_x(img_in_window);
00543         ny_orig = cpl_image_get_size_y(img_in_window);
00544         cpl_image_delete(img_in_window); img_in_window = NULL;
00545 
00546         KMO_TRY_ASSURE((nx_orig > 2*KMOS_BADPIX_BORDER) &&
00547                        (ny_orig > 2*KMOS_BADPIX_BORDER),
00548                        CPL_ERROR_ILLEGAL_INPUT,
00549                        "Input frames must have a height and width of at "
00550                        "least 9 pixels!");
00551 
00552         // --- loop through all detectors ---
00553         for (i = 1; i <= nr_devices; i++) {
00554             cpl_msg_info("","Processing detector No. %d", i);
00555 
00556             KMO_TRY_EXIT_IF_NULL(
00557                 detector_in_window = cpl_imagelist_new());
00558 
00559             KMO_TRY_EXIT_IF_NULL(
00560                 sub_header = kmo_dfs_load_sub_header(frameset, do_mode,
00561                                                      i, FALSE));
00562 
00563             // load data of device i of all DARK frames into an imagelist
00564             KMO_TRY_EXIT_IF_NULL(
00565                 img_in_window = kmo_dfs_load_image_window(
00566                                        frameset, do_mode, i, FALSE,
00567                                        KMOS_BADPIX_BORDER+1,
00568                                        KMOS_BADPIX_BORDER+1,
00569                                        nx_orig-KMOS_BADPIX_BORDER,
00570                                        ny_orig-KMOS_BADPIX_BORDER,
00571                                        FALSE, NULL));
00572 
00573             nx = cpl_image_get_size_x(img_in_window);
00574             ny = cpl_image_get_size_y(img_in_window);
00575 
00576             nz = 0;
00577             while (img_in_window != NULL) {
00578                 cpl_imagelist_set(detector_in_window, img_in_window, nz);
00579                 KMO_TRY_CHECK_ERROR_STATE();
00580 
00581                 // load same extension of next DARK frame
00582                 img_in_window = kmo_dfs_load_image_window(
00583                                             frameset, NULL, i, FALSE,
00584                                             KMOS_BADPIX_BORDER+1,
00585                                             KMOS_BADPIX_BORDER+1,
00586                                             nx_orig-KMOS_BADPIX_BORDER,
00587                                             ny_orig-KMOS_BADPIX_BORDER,
00588                                             FALSE, NULL);
00589                 KMO_TRY_CHECK_ERROR_STATE();
00590 
00591                 if (img_in_window != NULL) {
00592                     KMO_TRY_ASSURE((nx == cpl_image_get_size_x(img_in_window)) &&
00593                                    (ny == cpl_image_get_size_y(img_in_window)),
00594                                    CPL_ERROR_ILLEGAL_INPUT,
00595                                    "Not all input frames have the "
00596                                    "same dimensions!");
00597                 }
00598                 nz++;
00599             }
00600 
00601             // combine imagelist (data only) and create noise
00602             KMO_TRY_EXIT_IF_ERROR(
00603                 kmclipm_combine_frames(detector_in_window,
00604                                        NULL,
00605                                        NULL,
00606                                        my_method,
00607                                        cpos_rej,
00608                                        cneg_rej,
00609                                        citer,
00610                                        cmax,
00611                                        cmin,
00612                                        &combined_data_window,
00613                                        &combined_noise_window,
00614                                        -1.0));
00615 
00616             if (kmclipm_omit_warning_one_slice > 10) {
00617                 cpl_msg_warning(cpl_func, "Previous warning (number of "
00618                                           "identified slices) occured %d times.",
00619                                 kmclipm_omit_warning_one_slice);
00620                 kmclipm_omit_warning_one_slice = FALSE;
00621             }
00622 
00623             // calculate preliminary mean and stdev to create the bad pixel mask
00624             qc_dark = cpl_image_get_mean(combined_data_window);
00625             KMO_TRY_CHECK_ERROR_STATE();
00626 
00627             if (nz > 2) {
00628                 qc_readnoise = cpl_image_get_mean(combined_noise_window);
00629                 KMO_TRY_CHECK_ERROR_STATE();
00630 
00631                 KMO_TRY_ASSURE(qc_readnoise != 0.0,
00632                                CPL_ERROR_ILLEGAL_INPUT,
00633                                "All frames of detector %i are exactly "
00634                                "the same!", i);
00635             } else if (nz == 2) {
00636                 qc_readnoise = cpl_image_get_stdev(combined_noise_window);
00637                 KMO_TRY_CHECK_ERROR_STATE();
00638 
00639                 KMO_TRY_ASSURE(qc_readnoise != 0.0,
00640                                CPL_ERROR_ILLEGAL_INPUT,
00641                                "All frames of detector %i are exactly "
00642                                "the same!", i);
00643             } else if (nz == 1) {
00644                 qc_readnoise = cpl_image_get_stdev(combined_data_window);
00645                 KMO_TRY_CHECK_ERROR_STATE();
00646 
00647                 KMO_TRY_ASSURE(qc_readnoise != 0.0,
00648                                CPL_ERROR_ILLEGAL_INPUT,
00649                                "The detector frame %d seems to be uniform!", i);
00650             } else {
00651                 KMO_TRY_ASSURE(1 == 0,
00652                                CPL_ERROR_ILLEGAL_INPUT,
00653                                "detector frame must have at least one frame!");
00654             }
00655 
00656             // create bad-pixel-mask
00657             qc_bad_pix_num = kmo_create_bad_pix_dark(combined_data_window,
00658                                                      qc_dark,
00659                                                      qc_readnoise,
00660                                                      pos_bad_pix_rej,
00661                                                      neg_bad_pix_rej,
00662                                                      &bad_pix_mask_window);
00663             KMO_TRY_CHECK_ERROR_STATE();
00664 
00665             KMO_TRY_EXIT_IF_ERROR(
00666                 kmclipm_update_property_int(sub_header,
00667                                             QC_NR_BAD_PIX,
00668                                             qc_bad_pix_num,
00669                                             "[] nr. of bad pixels"));
00670 
00671             //
00672             // calculate QC.DARK, QC.READNOISE, QC.DARK.MEDIAN,
00673             // QC.READNOISE.MEDIAN, QC.DARKCUR
00674 
00675             // badpixels from combined_data_window are already rejected in
00676             // kmo_create_bad_pix_dark()
00677             KMO_TRY_EXIT_IF_ERROR(
00678                 kmo_image_reject_from_mask(combined_noise_window,
00679                                            bad_pix_mask_window));
00680 
00681             qc_dark = cpl_image_get_mean(combined_data_window);
00682             KMO_TRY_CHECK_ERROR_STATE();
00683 
00684             // calculate mean and stddev of combined frames (with rejection)
00685             if (nz > 2) {
00686                 qc_readnoise = cpl_image_get_mean(combined_noise_window) * sqrt(nz);
00687             } else if (nz == 2) {
00688                 qc_readnoise =
00689                      cpl_image_get_stdev(combined_noise_window) * sqrt(2.0);
00690             } else if (nz == 1) {
00691                 qc_readnoise = cpl_image_get_stdev(combined_data_window);
00692             } else {
00693                 KMO_TRY_ASSURE(1 == 0,
00694                         CPL_ERROR_ILLEGAL_INPUT,
00695                         "detector frame must have at least one frame!");
00696             }
00697             KMO_TRY_CHECK_ERROR_STATE();
00698 
00699             qc_dark_median = cpl_image_get_median(combined_data_window);
00700             KMO_TRY_CHECK_ERROR_STATE();
00701 
00702             if (nz > 2) {
00703                 qc_readnoise_median =
00704                         cpl_image_get_median(combined_noise_window) * sqrt(nz);
00705             } else if (nz == 2) {
00706                 qc_readnoise_median =
00707                          kmo_image_get_stdev_median(combined_noise_window) *
00708                                                                   sqrt(2.0);
00709             } else if (nz == 1) {
00710                 qc_readnoise_median =
00711                            kmo_image_get_stdev_median(combined_data_window);
00712             } else {
00713                 KMO_TRY_ASSURE(1 == 0,
00714                         CPL_ERROR_ILLEGAL_INPUT,
00715                         "detector frame must have at least one frame!");
00716             }
00717             KMO_TRY_CHECK_ERROR_STATE();
00718 
00719             KMO_TRY_EXIT_IF_ERROR(
00720                 kmclipm_update_property_double(sub_header,
00721                                                QC_DARK,
00722                                                qc_dark,
00723                                               "[adu] mean of master dark"));
00724             KMO_TRY_EXIT_IF_ERROR(
00725                 kmclipm_update_property_double(sub_header,
00726                                                QC_READNOISE,
00727                                                qc_readnoise,
00728                                         "[adu] mean noise of master dark"));
00729             KMO_TRY_EXIT_IF_ERROR(
00730                 kmclipm_update_property_double(sub_header,
00731                                                QC_DARK_MEDIAN,
00732                                                qc_dark_median,
00733                                             "[adu] median of master dark"));
00734             KMO_TRY_EXIT_IF_ERROR(
00735                 kmclipm_update_property_double(sub_header,
00736                                                QC_READNOISE_MEDIAN,
00737                                                qc_readnoise_median,
00738                                       "[adu] median noise of master dark"));
00739 
00740             // load gain
00741             gain = kmo_dfs_get_property_double(sub_header, GAIN);
00742             KMO_TRY_CHECK_ERROR_STATE_MSG(
00743                                  "GAIN-keyword in fits-header is missing!");
00744 
00745             KMO_TRY_EXIT_IF_ERROR(
00746                 kmclipm_update_property_double(sub_header,
00747                                                QC_DARK_CURRENT,
00748                                                qc_dark / exptime / gain,
00749                                                "[e-/s] dark current"));
00750 
00751             // save dark frame
00752             KMO_TRY_EXIT_IF_NULL(
00753                 extname = kmo_extname_creator(detector_frame, i, EXT_DATA));
00754             KMO_TRY_EXIT_IF_ERROR(
00755                 kmclipm_update_property_string(sub_header, EXTNAME,
00756                                                extname,
00757                                                "FITS extension name"));
00758             cpl_free(extname); extname = NULL;
00759 
00760             KMO_TRY_EXIT_IF_NULL(
00761                 combined_data = kmo_add_bad_pix_border(combined_data_window,
00762                                                        TRUE));
00763 
00764             KMO_TRY_EXIT_IF_ERROR(
00765                 kmo_dfs_save_image(combined_data, filename, "", sub_header, 0./0.));
00766 
00767             // save noise frame
00768             KMO_TRY_EXIT_IF_NULL(
00769                 extname = kmo_extname_creator(detector_frame, i, EXT_NOISE));
00770             KMO_TRY_EXIT_IF_ERROR(
00771                 kmclipm_update_property_string(sub_header, EXTNAME,
00772                                                extname,
00773                                                "FITS extension name"));
00774             cpl_free(extname); extname = NULL;
00775 
00776             KMO_TRY_EXIT_IF_NULL(
00777                 combined_noise = kmo_add_bad_pix_border(combined_noise_window,
00778                                                         TRUE));
00779 
00780             KMO_TRY_EXIT_IF_ERROR(
00781                 kmo_dfs_save_image(combined_noise, filename, "", sub_header, 0./0.));
00782 
00783             // save bad_pix frame
00784             KMO_TRY_EXIT_IF_NULL(
00785                 extname = kmo_extname_creator(detector_frame, i, EXT_BADPIX));
00786             KMO_TRY_EXIT_IF_ERROR(
00787                 kmclipm_update_property_string(sub_header, EXTNAME,
00788                                                extname,
00789                                                "FITS extension name"));
00790             cpl_free(extname); extname = NULL;
00791 
00792             KMO_TRY_EXIT_IF_NULL(
00793                 bad_pix_mask = kmo_add_bad_pix_border(bad_pix_mask_window,
00794                                                       FALSE));
00795 
00796             KMO_TRY_EXIT_IF_ERROR(
00797                 kmo_dfs_save_image(bad_pix_mask, filename_bad, "", sub_header, 0.));
00798 
00799             // free memory
00800             cpl_propertylist_delete(sub_header); sub_header = NULL;
00801             cpl_imagelist_delete(detector_in_window); detector_in_window = NULL;
00802             cpl_image_delete(combined_data); combined_data = NULL;
00803             cpl_image_delete(combined_data_window); combined_data_window = NULL;
00804             cpl_image_delete(combined_noise); combined_noise = NULL;
00805             cpl_image_delete(combined_noise_window); combined_noise_window = NULL;
00806             cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL;
00807             cpl_image_delete(bad_pix_mask_window); bad_pix_mask_window = NULL;
00808         } // for i = [1, nr_devices]
00809 
00810         cpl_msg_info("", "-------------------------------------------");
00811         cpl_msg_info("", "IFU status after processing:");
00812         cpl_msg_info("", "   not checked here");
00813         cpl_msg_info("", "-------------------------------------------");
00814     }
00815     KMO_CATCH
00816     {
00817         KMO_CATCH_MSG();
00818 
00819 //        if (desc2.sub_desc != NULL) {
00820             kmo_free_fits_desc(&desc2);
00821 //        }
00822 
00823         ret_val = -1;
00824     }
00825 
00826     kmo_free_fits_desc(&desc1);
00827     cpl_free(filename); filename = NULL;
00828     cpl_free(filename_bad); filename_bad = NULL;
00829     cpl_propertylist_delete(main_header); main_header = NULL;
00830     cpl_propertylist_delete(sub_header); sub_header = NULL;
00831     cpl_imagelist_delete(detector_in_window); detector_in_window = NULL;
00832     cpl_image_delete(combined_data); combined_data = NULL;
00833     cpl_image_delete(combined_data_window); combined_data_window = NULL;
00834     cpl_image_delete(combined_noise); combined_noise = NULL;
00835     cpl_image_delete(combined_noise_window); combined_noise_window = NULL;
00836     cpl_image_delete(bad_pix_mask); bad_pix_mask = NULL;
00837     cpl_image_delete(bad_pix_mask_window); bad_pix_mask_window = NULL;
00838 
00839     return ret_val;
00840 }
00841