|
HAWKI Pipeline Reference Manual 1.8.1
|
00001 /* $Id: hawki_cal_flat.c,v 1.23 2010/08/10 09:39:39 cgarcia Exp $ 00002 * 00003 * This file is part of the HAWKI 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: cgarcia $ 00023 * $Date: 2010/08/10 09:39:39 $ 00024 * $Revision: 1.23 $ 00025 * $Name: hawki-1_8_1 $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 /*----------------------------------------------------------------------------- 00033 Includes 00034 -----------------------------------------------------------------------------*/ 00035 00036 #include <math.h> 00037 #include <string.h> 00038 #include <cpl.h> 00039 00040 #include "irplib_utils.h" 00041 00042 #include "hawki_utils.h" 00043 #include "hawki_image_stats.h" 00044 #include "hawki_load.h" 00045 #include "hawki_save.h" 00046 #include "hawki_pfits.h" 00047 #include "hawki_dfs.h" 00048 00049 /*----------------------------------------------------------------------------- 00050 Functions prototypes 00051 -----------------------------------------------------------------------------*/ 00052 00053 static int hawki_cal_flat_create(cpl_plugin *) ; 00054 static int hawki_cal_flat_exec(cpl_plugin *) ; 00055 static int hawki_cal_flat_destroy(cpl_plugin *) ; 00056 static int hawki_cal_flat(cpl_parameterlist *, cpl_frameset *) ; 00057 00058 static int hawki_cal_flat_retrieve_input_param 00059 (cpl_parameterlist * parlist); 00060 static cpl_imagelist ** hawki_cal_flat_reduce( 00061 cpl_frameset * flatframes, 00062 const char * dark_file, 00063 cpl_table ** raw_flat_stats, 00064 cpl_table ** raw_flat_odd_column_stats, 00065 cpl_table ** raw_flat_even_column_stats, 00066 cpl_table ** raw_flat_odd_row_stats, 00067 cpl_table ** raw_flat_even_row_stats, 00068 cpl_vector ** selected); 00069 static int hawki_cal_flat_clean_outliers(cpl_image *, cpl_imagelist *, 00070 cpl_imagelist *, cpl_vector *, cpl_image **) ; 00071 static int hawki_cal_flat_save 00072 (cpl_imagelist ** flat, 00073 cpl_table ** raw_flat_stats, 00074 cpl_table ** raw_flat_odd_column_stats, 00075 cpl_table ** raw_flat_even_column_stats, 00076 cpl_table ** raw_flat_odd_row_stats, 00077 cpl_table ** raw_flat_even_row_stats, 00078 cpl_vector ** raw_selected, 00079 int set_nb, 00080 const cpl_frame * bpmdark, 00081 cpl_frameset * flatframes, 00082 cpl_frameset * calibframes, 00083 cpl_parameterlist * parlist, 00084 cpl_frameset * set_tot); 00085 static int hawki_cal_flat_compare(const cpl_frame *, const cpl_frame *) ; 00086 static cpl_imagelist * hawki_cal_flat_merge_bpms 00087 (const cpl_frame * bpm_orig, 00088 cpl_imagelist * bpm_to_add); 00089 static int hawki_cal_flat_select 00090 (cpl_vector * meds, 00091 cpl_vector * rms, 00092 int auto_flag, 00093 int auto_max_bins, 00094 double min_level, 00095 double max_level, 00096 double max_rms, 00097 int min_nframes, 00098 cpl_vector * selection); 00099 static cpl_vector * hawki_cal_flat_extract_vector(cpl_vector *, 00100 cpl_vector *) ; 00101 00102 /*----------------------------------------------------------------------------- 00103 Static variables 00104 -----------------------------------------------------------------------------*/ 00105 00106 static struct { 00107 /* Inputs */ 00108 int llx ; 00109 int lly ; 00110 int urx ; 00111 int ury ; 00112 int normalise ; 00113 int second_pass ; 00114 double sigma_badres ; 00115 double sigma_bpm ; 00116 double lowval_bpm ; 00117 double highval_bpm ; 00118 int select_auto ; 00119 int select_auto_max_bins; 00120 double select_min_level[HAWKI_NB_DETECTORS]; 00121 double select_max_level[HAWKI_NB_DETECTORS]; 00122 double select_max_rms[HAWKI_NB_DETECTORS]; 00123 int select_min_nframes ; 00124 int extra_stats; 00125 } hawki_cal_flat_config ; 00126 00127 static struct { 00128 /* Outputs */ 00129 int nb_badpix[HAWKI_NB_DETECTORS]; 00130 double norm[HAWKI_NB_DETECTORS]; 00131 double med_stdev[HAWKI_NB_DETECTORS]; 00132 double med_avg[HAWKI_NB_DETECTORS]; 00133 double med_med[HAWKI_NB_DETECTORS]; 00134 double med_min[HAWKI_NB_DETECTORS]; 00135 double med_max[HAWKI_NB_DETECTORS]; 00136 } hawki_cal_flat_outputs; 00137 00138 static char hawki_cal_flat_description[] = 00139 "hawki_cal_flat -- HAWKĪI imaging flat-field creation from twillight images.\n" 00140 "The input of the recipe files listed in the Set Of Frames (sof-file)\n" 00141 "must be tagged as:\n" 00142 "raw-file.fits "HAWKI_CAL_FLAT_RAW" or\n" 00143 "Optional inputs are:\n" 00144 "bpmdark-file.fits "HAWKI_CALPRO_BPM_HOT"\n" 00145 "dark-file.fits "HAWKI_CALPRO_DARK"\n" 00146 "dark_err-file.fits "HAWKI_CALPRO_DARK_ERR"\n" 00147 "The recipe creates as an output:\n" 00148 "hawki_cal_flat_setxx.fits ("HAWKI_CALPRO_FLAT"): Master flat for filter xx\n" 00149 "hawki_cal_flat_err_setxx.fits ("HAWKI_CALPRO_FLAT_ERRMAP"): Master flat residuals\n" 00150 "hawki_cal_flat_bpmflat_setxx.fits ("HAWKI_CALPRO_BPM_COLD"): BPM from the flat\n" 00151 "hawki_cal_flat_stats_setxx.fits ("HAWKI_CALPRO_FLAT_STATS"): Stats of the individual flats\n" 00152 "Optionally it also creates:\n" 00153 "hawki_cal_flat_bpm_setxx.fits ("HAWKI_CALPRO_BPM"): Bad pixel mask combining bpm from dark and flat\n" 00154 "hawki_cal_flat_stats_ec_setxx.fits ("HAWKI_CALPRO_FLAT_STATS_EVEN_COL"): Stats of the individual flats for even columns\n" 00155 "hawki_cal_flat_stats_oc_setxx.fits ("HAWKI_CALPRO_FLAT_STATS_ODD_COL"): Stats of the individual flats for odd columns\n" 00156 "hawki_cal_flat_stats_er_setxx.fits ("HAWKI_CALPRO_FLAT_STATS_EVEN_ROW"): Stats of the individual flats for even rows\n" 00157 "hawki_cal_flat_stats_or_setxx.fits ("HAWKI_CALPRO_FLAT_STATS_ODD_ROW"): Stats of the individual flats for odd rows\n" 00158 "Return code:\n" 00159 "esorex exits with an error code of 0 if the recipe completes successfully\n" 00160 "or 1 otherwise"; 00161 00162 00163 00164 00165 00166 /*----------------------------------------------------------------------------- 00167 Functions code 00168 -----------------------------------------------------------------------------*/ 00169 00170 /*----------------------------------------------------------------------------*/ 00178 /*----------------------------------------------------------------------------*/ 00179 int cpl_plugin_get_info(cpl_pluginlist * list) 00180 { 00181 cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ; 00182 cpl_plugin * plugin = &recipe->interface ; 00183 00184 cpl_plugin_init(plugin, 00185 CPL_PLUGIN_API, 00186 HAWKI_BINARY_VERSION, 00187 CPL_PLUGIN_TYPE_RECIPE, 00188 "hawki_cal_flat", 00189 "Twillight flat recipe", 00190 hawki_cal_flat_description, 00191 "Cesar Enrique Garcia Dabo", 00192 PACKAGE_BUGREPORT, 00193 hawki_get_license(), 00194 hawki_cal_flat_create, 00195 hawki_cal_flat_exec, 00196 hawki_cal_flat_destroy) ; 00197 00198 cpl_pluginlist_append(list, plugin) ; 00199 00200 return 0; 00201 } 00202 00203 /*----------------------------------------------------------------------------*/ 00212 /*----------------------------------------------------------------------------*/ 00213 static int hawki_cal_flat_create(cpl_plugin * plugin) 00214 { 00215 cpl_recipe * recipe ; 00216 cpl_parameter * p ; 00217 00218 /* Get the recipe out of the plugin */ 00219 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00220 recipe = (cpl_recipe *)plugin ; 00221 else return -1 ; 00222 00223 /* Create the parameters list in the cpl_recipe object */ 00224 recipe->parameters = cpl_parameterlist_new() ; 00225 00226 /* Fill the parameters list */ 00227 /* --zone */ 00228 p = cpl_parameter_new_value("hawki.hawki_cal_flat.zone", 00229 CPL_TYPE_STRING, 00230 "Stats zone", 00231 "hawki.hawki_cal_flat", 00232 "1,1,2048,2048") ; 00233 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "zone") ; 00234 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00235 cpl_parameterlist_append(recipe->parameters, p) ; 00236 00237 /* --normalise */ 00238 p = cpl_parameter_new_value("hawki.hawki_cal_flat.normalise", 00239 CPL_TYPE_BOOL, "Flag to apply the normalisation", 00240 "hawki.hawki_cal_flat", FALSE) ; 00241 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "normalise") ; 00242 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00243 cpl_parameterlist_append(recipe->parameters, p) ; 00244 00245 /* --second_pass */ 00246 p = cpl_parameter_new_value("hawki.hawki_cal_flat.second_pass", 00247 CPL_TYPE_BOOL, "Flag to apply a second pass computation", 00248 "hawki.hawki_cal_flat", TRUE) ; 00249 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "second_pass") ; 00250 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00251 cpl_parameterlist_append(recipe->parameters, p) ; 00252 00253 /* --sigma_badres */ 00254 p = cpl_parameter_new_value("hawki.hawki_cal_flat.sigma_badres", 00255 CPL_TYPE_DOUBLE, "sigma for detection of bad flat results", 00256 "hawki.hawki_cal_flat", 1.0) ; 00257 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sigma_badres") ; 00258 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00259 cpl_parameterlist_append(recipe->parameters, p) ; 00260 00261 /* --sigma_bpm */ 00262 p = cpl_parameter_new_value("hawki.hawki_cal_flat.sigma_bpm", 00263 CPL_TYPE_DOUBLE, "sigma for detection of bad pixels", 00264 "hawki.hawki_cal_flat", 10.0) ; 00265 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sigma_bpm") ; 00266 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00267 cpl_parameterlist_append(recipe->parameters, p) ; 00268 00269 /* --lowval_bpm */ 00270 p = cpl_parameter_new_value("hawki.hawki_cal_flat.lowval_bpm", 00271 CPL_TYPE_DOUBLE, "values of the flat below this will be included " 00272 "in the bpm. In units of final flat (normalised if normalise is on)", 00273 "hawki.hawki_cal_flat", .1) ; 00274 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lowval_bpm") ; 00275 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00276 cpl_parameterlist_append(recipe->parameters, p) ; 00277 00278 /* --highval_bpm */ 00279 p = cpl_parameter_new_value("hawki.hawki_cal_flat.highval_bpm", 00280 CPL_TYPE_DOUBLE, "values of the flat above this will be included " 00281 "in the bpm. In units of final flat (normalized if normalise is on)", 00282 "hawki.hawki_cal_flat", 10.0) ; 00283 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "highval_bpm") ; 00284 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00285 cpl_parameterlist_append(recipe->parameters, p) ; 00286 00287 /* --select_auto */ 00288 p = cpl_parameter_new_value("hawki.hawki_cal_flat.select_auto", 00289 CPL_TYPE_BOOL, "Flag to automatically select the good input frames", 00290 "hawki.hawki_cal_flat", TRUE); 00291 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "select_auto") ; 00292 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00293 cpl_parameterlist_append(recipe->parameters, p) ; 00294 00295 /* --select_auto_max_bins */ 00296 p = cpl_parameter_new_value("hawki.hawki_cal_flat.select_auto_max_bins", 00297 CPL_TYPE_INT, "Maximum number of frames requested", 00298 "hawki.hawki_cal_flat", 10) ; 00299 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "select_auto_max_bins"); 00300 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00301 cpl_parameterlist_append(recipe->parameters, p) ; 00302 00303 /* --select_min_level */ 00304 p = cpl_parameter_new_value("hawki.hawki_cal_flat.select_min_level", 00305 CPL_TYPE_STRING, "Minimum ADU level for frames selection", 00306 "hawki.hawki_cal_flat", "-1.0") ; 00307 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "select_min_level") ; 00308 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00309 cpl_parameterlist_append(recipe->parameters, p) ; 00310 00311 /* --select_max_level */ 00312 p = cpl_parameter_new_value("hawki.hawki_cal_flat.select_max_level", 00313 CPL_TYPE_STRING, "Maximum ADU level for frames selection", 00314 "hawki.hawki_cal_flat", "25000"); 00315 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "select_max_level"); 00316 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00317 cpl_parameterlist_append(recipe->parameters, p); 00318 00319 /* --select_max_rms */ 00320 p = cpl_parameter_new_value("hawki.hawki_cal_flat.select_max_rms", 00321 CPL_TYPE_STRING, "Maximum RMS for frames selection", 00322 "hawki.hawki_cal_flat", "4000"); 00323 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "select_max_rms"); 00324 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00325 cpl_parameterlist_append(recipe->parameters, p); 00326 00327 /* --select_min_nframes */ 00328 p = cpl_parameter_new_value("hawki.hawki_cal_flat.select_min_nframes", 00329 CPL_TYPE_INT, "Minimum number of frames requested", 00330 "hawki.hawki_cal_flat", 3); 00331 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "select_min_nframes") ; 00332 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00333 cpl_parameterlist_append(recipe->parameters, p) ; 00334 00335 /* --extra_stats */ 00336 p = cpl_parameter_new_value("hawki.hawki_cal_flat.extra_stats", 00337 CPL_TYPE_BOOL, "Request for even/odd column/rows statistics", 00338 "hawki.hawki_cal_flat", FALSE) ; 00339 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extra_stats") ; 00340 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV) ; 00341 cpl_parameterlist_append(recipe->parameters, p) ; 00342 00343 /* Return */ 00344 return 0; 00345 } 00346 00347 /*----------------------------------------------------------------------------*/ 00353 /*----------------------------------------------------------------------------*/ 00354 static int hawki_cal_flat_exec(cpl_plugin * plugin) 00355 { 00356 cpl_recipe * recipe ; 00357 00358 /* Get the recipe out of the plugin */ 00359 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00360 recipe = (cpl_recipe *)plugin ; 00361 else return -1 ; 00362 00363 /* Issue a banner */ 00364 hawki_print_banner(); 00365 00366 return hawki_cal_flat(recipe->parameters, recipe->frames) ; 00367 } 00368 00369 /*----------------------------------------------------------------------------*/ 00375 /*----------------------------------------------------------------------------*/ 00376 static int hawki_cal_flat_destroy(cpl_plugin * plugin) 00377 { 00378 cpl_recipe * recipe ; 00379 00380 /* Get the recipe out of the plugin */ 00381 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00382 recipe = (cpl_recipe *)plugin ; 00383 else return -1 ; 00384 00385 cpl_parameterlist_delete(recipe->parameters) ; 00386 return 0 ; 00387 } 00388 00389 /*----------------------------------------------------------------------------*/ 00396 /*----------------------------------------------------------------------------*/ 00397 static int hawki_cal_flat( 00398 cpl_parameterlist * parlist, 00399 cpl_frameset * framelist) 00400 { 00401 int * labels ; 00402 int nlabels ; 00403 cpl_frameset * flatframes ; 00404 int nflats; 00405 const char * dark ; 00406 const char * dark_err; 00407 const cpl_frame * bpmdark ; 00408 cpl_imagelist ** twflat ; 00409 cpl_table ** raw_flat_stats; 00410 cpl_table ** raw_flat_odd_column_stats = NULL; 00411 cpl_table ** raw_flat_even_column_stats = NULL; 00412 cpl_table ** raw_flat_odd_row_stats = NULL; 00413 cpl_table ** raw_flat_even_row_stats = NULL; 00414 cpl_vector ** raw_selected; 00415 int i, j ; 00416 cpl_errorstate error_prevstate = cpl_errorstate_get(); 00417 00418 /* Retrieve input parameters */ 00419 if(hawki_cal_flat_retrieve_input_param(parlist)) 00420 { 00421 cpl_msg_error(__func__, "Wrong parameters"); 00422 return -1; 00423 } 00424 00425 /* Identify the RAW and CALIB frames in the input frameset */ 00426 if (hawki_dfs_set_groups(framelist)) { 00427 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ; 00428 return -1; 00429 } 00430 00431 /* Retrieve raw frames */ 00432 if ((flatframes = hawki_extract_frameset(framelist, 00433 HAWKI_CAL_FLAT_RAW)) == NULL) { 00434 cpl_msg_error(__func__, "Cannot find flat frames in the input list (%s)", 00435 HAWKI_CAL_FLAT_RAW); 00436 return -1 ; 00437 } 00438 00439 /* Retrieve calibration frames */ 00440 bpmdark = cpl_frameset_find_const(framelist, HAWKI_CALPRO_BPM_HOT); 00441 dark = hawki_extract_first_filename(framelist, HAWKI_CALPRO_DARK); 00442 dark_err = hawki_extract_first_filename(framelist, HAWKI_CALPRO_DARK_ERR); 00443 00444 /* Labelise all input flat frames */ 00445 labels = cpl_frameset_labelise(flatframes, hawki_cal_flat_compare, 00446 &nlabels); 00447 if (labels == NULL) { 00448 cpl_msg_error(__func__, "Cannot labelise input frames") ; 00449 cpl_frameset_delete(flatframes); 00450 return -1; 00451 } 00452 00453 /* Extract sets and reduce each of them */ 00454 for (i=0 ; i<nlabels ; i++) 00455 { 00456 cpl_frameset * this_filter_flats; 00457 00458 /* Reduce data set nb i */ 00459 cpl_msg_info(__func__, "Reduce data set no %d out of %d", i+1, nlabels); 00460 cpl_msg_indent_more() ; 00461 this_filter_flats = cpl_frameset_extract(flatframes, labels, i) ; 00462 nflats = cpl_frameset_get_size(this_filter_flats); 00463 00464 /* Allocate and initialize statistics */ 00465 raw_flat_stats = cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_table*)); 00466 raw_selected = cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_vector*)); 00467 for (j=0 ; j<HAWKI_NB_DETECTORS ; j++) 00468 { 00469 raw_selected[j] = cpl_vector_new(nflats); 00470 raw_flat_stats[j] = cpl_table_new(nflats); 00471 } 00472 /* Initialize the statistics table */ 00473 hawki_image_stats_initialize(raw_flat_stats); 00474 if(hawki_cal_flat_config.extra_stats) 00475 { 00476 raw_flat_odd_column_stats = 00477 cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_table*)); 00478 raw_flat_even_column_stats = 00479 cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_table*)); 00480 raw_flat_odd_row_stats = 00481 cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_table*)); 00482 raw_flat_even_row_stats = 00483 cpl_malloc(HAWKI_NB_DETECTORS*sizeof(cpl_table*)); 00484 for (j=0 ; j<HAWKI_NB_DETECTORS ; j++) 00485 { 00486 raw_flat_odd_column_stats[j] = cpl_table_new(nflats); 00487 raw_flat_even_column_stats[j] = cpl_table_new(nflats); 00488 raw_flat_odd_row_stats[j] = cpl_table_new(nflats); 00489 raw_flat_even_row_stats[j] = cpl_table_new(nflats); 00490 } 00491 /* Initialize the statistics table */ 00492 hawki_image_stats_initialize(raw_flat_odd_column_stats); 00493 hawki_image_stats_initialize(raw_flat_even_column_stats); 00494 hawki_image_stats_initialize(raw_flat_odd_row_stats); 00495 hawki_image_stats_initialize(raw_flat_even_row_stats); 00496 } 00497 00498 /* Reduce */ 00499 if ((twflat = hawki_cal_flat_reduce 00500 (this_filter_flats, 00501 dark, 00502 raw_flat_stats, 00503 raw_flat_odd_column_stats, 00504 raw_flat_even_column_stats, 00505 raw_flat_odd_row_stats, 00506 raw_flat_even_row_stats, 00507 raw_selected)) == NULL) 00508 { 00509 for (j=0 ; j<HAWKI_NB_DETECTORS ; j++) 00510 { 00511 cpl_table_delete(raw_flat_stats[j]); 00512 cpl_vector_delete(raw_selected[j]); 00513 } 00514 cpl_free(raw_flat_stats); 00515 cpl_free(raw_selected); 00516 if(hawki_cal_flat_config.extra_stats) 00517 { 00518 for (j=0 ; j<HAWKI_NB_DETECTORS ; j++) 00519 { 00520 cpl_table_delete(raw_flat_odd_column_stats[j]); 00521 cpl_table_delete(raw_flat_even_column_stats[j]); 00522 cpl_table_delete(raw_flat_odd_row_stats[j]); 00523 cpl_table_delete(raw_flat_even_row_stats[j]); 00524 } 00525 cpl_free(raw_flat_odd_column_stats); 00526 cpl_free(raw_flat_even_column_stats); 00527 cpl_free(raw_flat_odd_row_stats); 00528 cpl_free(raw_flat_even_row_stats); 00529 } 00530 cpl_frameset_delete(this_filter_flats); 00531 cpl_frameset_delete(flatframes); 00532 cpl_free(labels); 00533 cpl_msg_error(__func__, "Cannot reduce set nb %d", i+1) ; 00534 return 1; 00535 00536 } else { 00537 /* Save the products */ 00538 cpl_frameset * calib_frames; 00539 00540 cpl_msg_info(__func__, "Save the products") ; 00541 calib_frames = cpl_frameset_new(); 00542 if(bpmdark) 00543 cpl_frameset_insert(calib_frames, cpl_frame_duplicate(bpmdark)); 00544 if(dark) 00545 cpl_frameset_insert(calib_frames, 00546 cpl_frame_duplicate(cpl_frameset_find_const(framelist, 00547 HAWKI_CALPRO_DARK))); 00548 if(dark_err) 00549 cpl_frameset_insert(calib_frames, 00550 cpl_frame_duplicate(cpl_frameset_find_const(framelist, 00551 HAWKI_CALPRO_DARK_ERR))); 00552 hawki_cal_flat_save 00553 (twflat, raw_flat_stats, 00554 raw_flat_odd_column_stats, 00555 raw_flat_even_column_stats, 00556 raw_flat_odd_row_stats, 00557 raw_flat_even_row_stats, 00558 raw_selected, 00559 i+1, bpmdark, this_filter_flats, calib_frames, 00560 parlist, framelist); 00561 cpl_imagelist_delete(twflat[0]); 00562 cpl_imagelist_delete(twflat[1]); 00563 cpl_imagelist_delete(twflat[2]); 00564 if (hawki_cal_flat_config.second_pass) 00565 cpl_imagelist_delete(twflat[3]); 00566 cpl_free(twflat); 00567 for (j=0 ; j<HAWKI_NB_DETECTORS ; j++) 00568 { 00569 cpl_table_delete(raw_flat_stats[j]); 00570 cpl_vector_delete(raw_selected[j]); 00571 } 00572 cpl_free(raw_flat_stats); 00573 cpl_free(raw_selected); 00574 if(hawki_cal_flat_config.extra_stats) 00575 { 00576 for (j=0 ; j<HAWKI_NB_DETECTORS ; j++) 00577 { 00578 cpl_table_delete(raw_flat_odd_column_stats[j]); 00579 cpl_table_delete(raw_flat_even_column_stats[j]); 00580 cpl_table_delete(raw_flat_odd_row_stats[j]); 00581 cpl_table_delete(raw_flat_even_row_stats[j]); 00582 } 00583 cpl_free(raw_flat_odd_column_stats); 00584 cpl_free(raw_flat_even_column_stats); 00585 cpl_free(raw_flat_odd_row_stats); 00586 cpl_free(raw_flat_even_row_stats); 00587 } 00588 cpl_frameset_delete(calib_frames); 00589 } 00590 cpl_msg_indent_less(); 00591 cpl_frameset_delete(this_filter_flats); 00592 } 00593 00594 if(!cpl_errorstate_is_equal(error_prevstate)) 00595 cpl_msg_warning(__func__,"Probably some data could not be saved. " 00596 "Check permisions or disk space"); 00597 00598 00599 /* Free and return */ 00600 cpl_frameset_delete(flatframes); 00601 cpl_free(labels); 00602 00603 /* Return */ 00604 if (cpl_error_get_code()) return -1 ; 00605 else return 0; 00606 } 00607 00608 /*----------------------------------------------------------------------------*/ 00619 /*----------------------------------------------------------------------------*/ 00620 static cpl_imagelist ** hawki_cal_flat_reduce( 00621 cpl_frameset * flatframes, 00622 const char * dark_file, 00623 cpl_table ** raw_flat_stats, 00624 cpl_table ** raw_flat_odd_column_stats, 00625 cpl_table ** raw_flat_even_column_stats, 00626 cpl_table ** raw_flat_odd_row_stats, 00627 cpl_table ** raw_flat_even_row_stats, 00628 cpl_vector ** selected) 00629 { 00630 int nima ; 00631 cpl_image * ima_cur ; 00632 cpl_image * big_ima ; 00633 cpl_image * big_badres ; 00634 cpl_vector * medians[HAWKI_NB_DETECTORS]; 00635 cpl_vector * stdevs[HAWKI_NB_DETECTORS]; 00636 cpl_vector * sub_medians ; 00637 cpl_imagelist * in_quad ; 00638 cpl_imagelist ** results ; 00639 cpl_imagelist * res_quad[4] ; 00640 cpl_image * err_quad[4] ; 00641 cpl_image * badres_mask[4] ; 00642 cpl_image * flat_image ; 00643 cpl_image * dark ; 00644 cpl_propertylist * plist; 00645 double gradient ; 00646 double flat_dit; 00647 cpl_image * bpmflat; 00648 int j, k ; 00649 int idet; 00650 00651 /* Test entries */ 00652 if (flatframes == NULL) return NULL ; 00653 00654 /* Initialise */ 00655 nima = cpl_frameset_get_size(flatframes) ; 00656 if (nima < 3) { 00657 cpl_msg_error(__func__, "Not enough frames (%d)", nima) ; 00658 return NULL ; 00659 } 00660 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 00661 hawki_cal_flat_outputs.norm[idet] = 1.0 ; 00662 00663 /* Compute statistics */ 00664 cpl_msg_info(__func__, "Compute statistics") ; 00665 cpl_msg_indent_more() ; 00666 /* Loop on the HAWKI_NB_DETECTORS chips */ 00667 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) 00668 { 00669 00670 /* Compute some stats on input images */ 00671 cpl_msg_info(__func__, "Chip number %d", idet+1) ; 00672 cpl_msg_info(__func__, "image min max med rms") ; 00673 cpl_msg_info(__func__, "--------------------------------------------") ; 00674 medians[idet] = cpl_vector_new(nima); 00675 stdevs[idet] = cpl_vector_new(nima); 00676 for (j=0 ; j<nima ; j++) 00677 { 00678 /* Load the image */ 00679 ima_cur = hawki_load_image(flatframes, j, idet+1, CPL_TYPE_FLOAT) ; 00680 00681 /* Compute the stats */ 00682 if(hawki_image_stats_fill_from_image 00683 (raw_flat_stats, 00684 ima_cur, 00685 hawki_cal_flat_config.llx, 00686 hawki_cal_flat_config.lly, 00687 hawki_cal_flat_config.urx, 00688 hawki_cal_flat_config.ury, 00689 idet, 00690 j) !=0 ) 00691 { 00692 cpl_msg_error(__func__, "Cannot compute stats on image %d",j+1); 00693 cpl_msg_indent_less() ; 00694 cpl_image_delete(ima_cur); 00695 for (k=0 ; k<=idet ; k++) cpl_vector_delete(medians[k]) ; 00696 for (k=0 ; k<=idet ; k++) cpl_vector_delete(stdevs[k]) ; 00697 return NULL ; 00698 } 00699 00700 if(hawki_cal_flat_config.extra_stats) 00701 { 00702 if(hawki_image_stats_odd_even_column_row_fill_from_image 00703 (raw_flat_odd_column_stats, 00704 raw_flat_even_column_stats, 00705 raw_flat_odd_row_stats, 00706 raw_flat_even_row_stats, 00707 ima_cur, 00708 idet, 00709 j) !=0 ) 00710 { 00711 cpl_msg_error(__func__, "Cannot compute extra stats"); 00712 cpl_msg_indent_less() ; 00713 cpl_image_delete(ima_cur); 00714 for (k=0 ; k<=idet ; k++) cpl_vector_delete(medians[k]) ; 00715 for (k=0 ; k<=idet ; k++) cpl_vector_delete(stdevs[k]) ; 00716 return NULL ; 00717 } 00718 } 00719 cpl_vector_set(medians[idet], j, cpl_table_get_double 00720 (raw_flat_stats[idet],HAWKI_COL_STAT_MED,j,NULL )) ; 00721 cpl_vector_set(stdevs[idet], j, cpl_table_get_double 00722 (raw_flat_stats[idet],HAWKI_COL_STAT_RMS,j,NULL )) ; 00723 cpl_msg_info(__func__, "%02d %10.2f %10.2f %10.2f %10.2f", 00724 j+1, 00725 cpl_table_get_double(raw_flat_stats[idet], 00726 HAWKI_COL_STAT_MIN,j,NULL ), 00727 cpl_table_get_double(raw_flat_stats[idet], 00728 HAWKI_COL_STAT_MAX,j,NULL ), 00729 cpl_table_get_double(raw_flat_stats[idet], 00730 HAWKI_COL_STAT_MED,j,NULL ), 00731 cpl_table_get_double(raw_flat_stats[idet], 00732 HAWKI_COL_STAT_RMS,j,NULL )); 00733 if (cpl_table_get_double 00734 (raw_flat_stats[idet],HAWKI_COL_STAT_MED,j,NULL ) < 1e-6) 00735 { 00736 cpl_msg_error(__func__, "image %d has negative flux: aborting", 00737 j+1) ; 00738 cpl_msg_indent_less() ; 00739 for (k=0 ; k<=idet ; k++) cpl_vector_delete(medians[k]) ; 00740 for (k=0 ; k<=idet ; k++) cpl_vector_delete(stdevs[k]) ; 00741 return NULL ; 00742 } 00743 cpl_image_delete(ima_cur); 00744 } 00745 cpl_msg_info(__func__, "--------------------------------------------") ; 00746 00747 /* Compute min max stdev and mean of the medians */ 00748 hawki_cal_flat_outputs.med_min[idet] = 00749 cpl_vector_get_min(medians[idet]); 00750 hawki_cal_flat_outputs.med_max[idet] = 00751 cpl_vector_get_max(medians[idet]); 00752 hawki_cal_flat_outputs.med_avg[idet] = 00753 cpl_vector_get_mean(medians[idet]); 00754 hawki_cal_flat_outputs.med_med[idet] = 00755 cpl_vector_get_median_const(medians[idet]); 00756 hawki_cal_flat_outputs.med_stdev[idet] = 00757 cpl_vector_get_stdev(medians[idet]); 00758 00759 /* See if flux gradient is large enough for a correct fit */ 00760 gradient=fabs(hawki_cal_flat_outputs.med_max[idet]/ 00761 hawki_cal_flat_outputs.med_min[idet]) ; 00762 if (gradient < 4.0) { 00763 /* cpl_msg_warning(__func__, "Low flux gradient: %g", gradient) ;*/ 00764 } 00765 } 00766 cpl_msg_indent_less() ; 00767 00768 /* Allocate for results */ 00769 results = cpl_malloc(4 * sizeof(cpl_imagelist*)) ; 00770 results[0] = cpl_imagelist_new() ; 00771 results[1] = cpl_imagelist_new() ; 00772 results[2] = cpl_imagelist_new() ; 00773 if (hawki_cal_flat_config.second_pass) results[3] = cpl_imagelist_new() ; 00774 else results[3] = NULL ; 00775 00776 cpl_msg_info(__func__, "Compute the flat") ; 00777 cpl_msg_indent_more() ; 00778 /* Loop on the HAWKI_NB_DETECTORS chips */ 00779 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) { 00780 cpl_msg_info(__func__, "Chip number %d", idet+1) ; 00781 cpl_msg_indent_more() ; 00782 00783 /* Frames selection */ 00784 cpl_msg_info(__func__, "Apply the frames selection"); 00785 if ((hawki_cal_flat_select(medians[idet], 00786 stdevs[idet], 00787 hawki_cal_flat_config.select_auto, 00788 hawki_cal_flat_config.select_auto_max_bins, 00789 hawki_cal_flat_config.select_min_level[idet], 00790 hawki_cal_flat_config.select_max_level[idet], 00791 hawki_cal_flat_config.select_max_rms[idet], 00792 hawki_cal_flat_config.select_min_nframes, 00793 selected[idet])) == -1) 00794 { 00795 cpl_msg_error(__func__, "Cannot apply the frames selection") ; 00796 cpl_imagelist_delete(results[0]) ; 00797 cpl_imagelist_delete(results[1]) ; 00798 cpl_imagelist_delete(results[2]) ; 00799 if (hawki_cal_flat_config.second_pass) 00800 cpl_imagelist_delete(results[3]) ; 00801 cpl_free(results) ; 00802 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00803 cpl_vector_delete(medians[k]) ; 00804 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00805 cpl_vector_delete(stdevs[k]) ; 00806 return NULL ; 00807 } 00808 00809 /* Apply the medians subselection */ 00810 sub_medians = hawki_cal_flat_extract_vector 00811 (medians[idet], selected[idet]) ; 00812 00813 /* Loop on the 4 quadrants */ 00814 for (j=0 ; j<4 ; j++) { 00815 /* Load input image chips */ 00816 if ((in_quad = hawki_load_quadrants(flatframes, idet+1, j+1, 00817 CPL_TYPE_FLOAT))==NULL) { 00818 cpl_msg_error(__func__, "Cannot load the raw quadrants") ; 00819 cpl_imagelist_delete(results[0]) ; 00820 cpl_imagelist_delete(results[1]) ; 00821 cpl_imagelist_delete(results[2]) ; 00822 if (hawki_cal_flat_config.second_pass) 00823 cpl_imagelist_delete(results[3]) ; 00824 cpl_free(results) ; 00825 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00826 cpl_vector_delete(medians[k]) ; 00827 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00828 cpl_vector_delete(stdevs[k]) ; 00829 cpl_vector_delete(sub_medians) ; 00830 return NULL ; 00831 } 00832 00833 /* Apply subselection of the frames */ 00834 cpl_imagelist_erase(in_quad, selected[idet]); 00835 00836 /* Apply dark correction to all planes if requested */ 00837 if (dark_file) { 00838 if (j==0) cpl_msg_info(__func__, "Subtracting dark") ; 00839 /* Load dark */ 00840 if ((dark = hawki_load_quadrant_from_file(dark_file, 00841 idet+1, j+1, CPL_TYPE_FLOAT)) == NULL) { 00842 cpl_msg_error(__func__, "Cannot load the dark quadrants") ; 00843 cpl_imagelist_delete(in_quad) ; 00844 cpl_imagelist_delete(results[0]) ; 00845 cpl_imagelist_delete(results[1]) ; 00846 cpl_imagelist_delete(results[2]) ; 00847 if (hawki_cal_flat_config.second_pass) 00848 cpl_imagelist_delete(results[3]) ; 00849 cpl_free(results) ; 00850 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00851 cpl_vector_delete(medians[k]) ; 00852 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00853 cpl_vector_delete(stdevs[k]) ; 00854 cpl_vector_delete(sub_medians) ; 00855 return NULL ; 00856 } 00857 00858 /* Multiply by the dit */ 00859 if ((plist=cpl_propertylist_load 00860 (cpl_frame_get_filename 00861 (cpl_frameset_get_first_const(flatframes)), 0)) == NULL) 00862 { 00863 cpl_msg_error(__func__, "Cannot get header from frame"); 00864 cpl_imagelist_delete(in_quad) ; 00865 cpl_imagelist_delete(results[0]) ; 00866 cpl_imagelist_delete(results[1]) ; 00867 cpl_imagelist_delete(results[2]) ; 00868 if (hawki_cal_flat_config.second_pass) 00869 cpl_imagelist_delete(results[3]) ; 00870 cpl_free(results) ; 00871 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00872 cpl_vector_delete(medians[k]) ; 00873 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00874 cpl_vector_delete(stdevs[k]) ; 00875 cpl_vector_delete(sub_medians) ; 00876 cpl_image_delete(dark); 00877 return NULL ; 00878 } 00879 flat_dit = hawki_pfits_get_dit(plist); 00880 cpl_image_multiply_scalar(dark, flat_dit); 00881 cpl_propertylist_delete(plist); 00882 00883 /* Dark correction */ 00884 cpl_imagelist_subtract_image(in_quad, dark) ; 00885 cpl_image_delete(dark) ; 00886 if (cpl_error_get_code() != CPL_ERROR_NONE) { 00887 cpl_msg_warning(__func__,"Cannot subtract the dark frame"); 00888 cpl_error_reset() ; 00889 } 00890 } 00891 00892 /* Fit slopes */ 00893 err_quad[j] = cpl_image_duplicate(cpl_imagelist_get(in_quad, 0)) ; 00894 res_quad[j] = cpl_fit_imagelist_polynomial(sub_medians, in_quad, 00895 0, 1, CPL_FALSE, CPL_TYPE_FLOAT, err_quad[j]) ; 00896 if (res_quad[j] == NULL) { 00897 cpl_msg_error(__func__, "Cannot create twilight flat-field") ; 00898 cpl_imagelist_delete(results[0]) ; 00899 cpl_imagelist_delete(results[1]) ; 00900 cpl_imagelist_delete(results[2]) ; 00901 if (hawki_cal_flat_config.second_pass) 00902 cpl_imagelist_delete(results[3]) ; 00903 cpl_free(results) ; 00904 cpl_imagelist_delete(in_quad) ; 00905 for (k=0 ; k<j ; k++) cpl_imagelist_delete(res_quad[k]) ; 00906 for (k=0 ; k<=j ; k++) cpl_image_delete(err_quad[k]) ; 00907 for (k=0 ; k<j ; k++) 00908 if (badres_mask[k]) cpl_image_delete(badres_mask[k]) ; 00909 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00910 cpl_vector_delete(medians[k]) ; 00911 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00912 cpl_vector_delete(stdevs[k]) ; 00913 cpl_vector_delete(sub_medians) ; 00914 return NULL ; 00915 } 00916 00917 /* Handle the pixels with a high error */ 00918 badres_mask[j] = NULL ; 00919 if (hawki_cal_flat_config.second_pass) { 00920 if (j==0) cpl_msg_info(__func__, 00921 "Second pass to clean the outliers") ; 00922 if (hawki_cal_flat_clean_outliers(err_quad[j], res_quad[j], 00923 in_quad, sub_medians, &(badres_mask[j])) == -1) { 00924 cpl_msg_error(__func__, "Cannot clean the outliers") ; 00925 cpl_imagelist_delete(results[0]) ; 00926 cpl_imagelist_delete(results[1]) ; 00927 cpl_imagelist_delete(results[2]) ; 00928 cpl_imagelist_delete(results[3]) ; 00929 cpl_free(results) ; 00930 cpl_imagelist_delete(in_quad) ; 00931 for (k=0 ; k<=j ; k++) cpl_imagelist_delete(res_quad[k]) ; 00932 for (k=0 ; k<=j ; k++) cpl_image_delete(err_quad[k]) ; 00933 for (k=0 ; k<=j ; k++) cpl_image_delete(badres_mask[k]) ; 00934 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00935 cpl_vector_delete(medians[k]) ; 00936 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00937 cpl_vector_delete(stdevs[k]) ; 00938 cpl_vector_delete(sub_medians) ; 00939 cpl_msg_indent_less() ; 00940 return NULL ; 00941 } 00942 } 00943 cpl_imagelist_delete(in_quad) ; 00944 } 00945 cpl_vector_delete(sub_medians) ; 00946 00947 /* Rebuild the quadrants and put in results */ 00948 /* Rebuild RESULTS */ 00949 big_ima = hawki_rebuild_quadrants( 00950 cpl_imagelist_get(res_quad[0],1), 00951 cpl_imagelist_get(res_quad[1],1), 00952 cpl_imagelist_get(res_quad[2],1), 00953 cpl_imagelist_get(res_quad[3],1)) ; 00954 for (j=0 ; j<4 ; j++) cpl_imagelist_delete(res_quad[j]) ; 00955 cpl_imagelist_set(results[0], big_ima, idet) ; 00956 if (big_ima == NULL) { 00957 cpl_msg_error(__func__, "Cannot rebuild the image") ; 00958 cpl_imagelist_delete(results[0]) ; 00959 cpl_imagelist_delete(results[1]) ; 00960 cpl_imagelist_delete(results[2]) ; 00961 if (hawki_cal_flat_config.second_pass) 00962 cpl_imagelist_delete(results[3]) ; 00963 cpl_free(results) ; 00964 for (j=0 ; j<4 ; j++) cpl_image_delete(err_quad[j]) ; 00965 for (j=0 ; j<4 ; j++) 00966 if (badres_mask[j]) cpl_image_delete(badres_mask[j]) ; 00967 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00968 cpl_vector_delete(medians[k]) ; 00969 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00970 cpl_vector_delete(stdevs[k]) ; 00971 return NULL ; 00972 } 00973 00974 /* Rebuild ERROR */ 00975 big_ima = hawki_rebuild_quadrants(err_quad[0], err_quad[1], 00976 err_quad[2], err_quad[3]) ; 00977 for (j=0 ; j<4 ; j++) cpl_image_delete(err_quad[j]) ; 00978 if (big_ima == NULL) { 00979 cpl_msg_error(__func__, "Cannot rebuild the image") ; 00980 cpl_imagelist_delete(results[0]) ; 00981 cpl_imagelist_delete(results[1]) ; 00982 cpl_imagelist_delete(results[2]) ; 00983 if (hawki_cal_flat_config.second_pass) 00984 cpl_imagelist_delete(results[3]) ; 00985 cpl_free(results) ; 00986 for (j=0 ; j<4 ; j++) 00987 if (badres_mask[j]) cpl_image_delete(badres_mask[j]) ; 00988 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00989 cpl_vector_delete(medians[k]) ; 00990 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 00991 cpl_vector_delete(stdevs[k]) ; 00992 return NULL ; 00993 } 00994 cpl_imagelist_set(results[1], big_ima, idet) ; 00995 00996 /* Rebuild BADRES_MASK */ 00997 big_badres = hawki_rebuild_quadrants(badres_mask[0], badres_mask[1], 00998 badres_mask[2], badres_mask[3]) ; 00999 if (hawki_cal_flat_config.second_pass) { 01000 for (j=0 ; j<4 ; j++) cpl_image_delete(badres_mask[j]) ; 01001 cpl_imagelist_set(results[3], big_badres, idet) ; 01002 } 01003 01004 if (hawki_cal_flat_config.normalise) { 01005 /* Normalize gain */ 01006 cpl_msg_info(__func__, "Normalise the flat") ; 01007 flat_image = cpl_imagelist_get(results[0], idet) ; 01008 hawki_cal_flat_outputs.norm[idet] = 01009 cpl_image_get_median(flat_image) ; 01010 cpl_image_divide_scalar 01011 (flat_image, hawki_cal_flat_outputs.norm[idet]); 01012 if (cpl_error_get_code()) { 01013 cpl_msg_error(__func__, "Cannot normalise") ; 01014 cpl_imagelist_delete(results[0]) ; 01015 cpl_imagelist_delete(results[1]) ; 01016 cpl_imagelist_delete(results[2]) ; 01017 if (hawki_cal_flat_config.second_pass) 01018 cpl_imagelist_delete(results[3]) ; 01019 cpl_free(results) ; 01020 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 01021 cpl_vector_delete(medians[k]) ; 01022 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) 01023 cpl_vector_delete(stdevs[k]) ; 01024 return NULL ; 01025 } 01026 } 01027 01028 /* BPM from the flat */ 01029 cpl_msg_info(__func__, "Compute the BPM from the flat") ; 01030 bpmflat=hawki_compute_flatbpm(cpl_imagelist_get(results[0],idet), 01031 hawki_cal_flat_config.sigma_bpm, 01032 hawki_cal_flat_config.lowval_bpm, 01033 hawki_cal_flat_config.highval_bpm); 01034 01035 cpl_imagelist_set(results[2], bpmflat, idet) ; 01036 hawki_cal_flat_outputs.nb_badpix[idet]= 01037 (int)cpl_image_get_flux(bpmflat); 01038 01039 cpl_msg_indent_less() ; 01040 } 01041 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) cpl_vector_delete(medians[k]) ; 01042 for (k=0 ; k<HAWKI_NB_DETECTORS ; k++) cpl_vector_delete(stdevs[k]) ; 01043 cpl_msg_indent_less() ; 01044 01045 return results ; 01046 } 01047 01048 /*----------------------------------------------------------------------------*/ 01058 /*----------------------------------------------------------------------------*/ 01059 static int hawki_cal_flat_clean_outliers( 01060 cpl_image * error, 01061 cpl_imagelist * fit_res, 01062 cpl_imagelist * raw, 01063 cpl_vector * medians, 01064 cpl_image ** recomp_mask) 01065 { 01066 cpl_mask * recompute ; 01067 cpl_binary * precompute ; 01068 double med, stdev, threshold1, threshold2 ; 01069 int nx, ny, pos, nbad, nima, out, ind, pix ; 01070 cpl_image * cur_ima ; 01071 float * pimaf ; 01072 double val, fit_val, a, b, max ; 01073 cpl_vector * z_pix ; 01074 double * pz_pix ; 01075 cpl_image * onepix ; 01076 cpl_vector * med_purged ; 01077 cpl_imagelist * raw_purged ; 01078 cpl_imagelist * fit_one ; 01079 cpl_image * err_one ; 01080 int i, j, k ; 01081 01082 /* Check entries */ 01083 if (error == NULL) return -1 ; 01084 if (fit_res == NULL) return -1 ; 01085 if (raw == NULL) return -1 ; 01086 01087 /* Initialise */ 01088 if (recomp_mask) *recomp_mask = NULL ; 01089 01090 /* Identify the places to recompute */ 01091 med = cpl_image_get_median_dev(error, &stdev) ; 01092 threshold1 = med - hawki_cal_flat_config.sigma_badres * stdev ; 01093 threshold2 = med + hawki_cal_flat_config.sigma_badres * stdev ; 01094 recompute = cpl_mask_threshold_image_create(error,threshold1,threshold2) ; 01095 cpl_mask_not(recompute) ; 01096 01097 if ((nbad=cpl_mask_count(recompute)) == 0) { 01098 if (recomp_mask) 01099 *recomp_mask = cpl_image_new_from_mask(recompute) ; 01100 cpl_mask_delete(recompute) ; 01101 return 0 ; 01102 } 01103 nx = cpl_image_get_size_x(error) ; 01104 ny = cpl_image_get_size_y(error) ; 01105 nima = cpl_imagelist_get_size(raw) ; 01106 01107 /* Get access to the mask */ 01108 precompute = cpl_mask_get_data(recompute) ; 01109 for (j=0 ; j<ny ; j++) { 01110 for (i=0 ; i<nx ; i++) { 01111 pos = i + j*nx ; 01112 /* The pixel has to be recomputed */ 01113 if (precompute[pos] == CPL_BINARY_1) { 01114 /* Get the pix_val-fit in a vector */ 01115 z_pix = cpl_vector_new(nima) ; 01116 for (k=0 ; k<nima ; k++) { 01117 cur_ima = cpl_imagelist_get(fit_res, 0) ; 01118 pimaf = cpl_image_get_data_float(cur_ima) ; 01119 a = pimaf[pos] ; 01120 cur_ima = cpl_imagelist_get(fit_res, 1) ; 01121 pimaf = cpl_image_get_data_float(cur_ima) ; 01122 b = pimaf[pos] ; 01123 med = cpl_vector_get(medians, k) ; 01124 fit_val = a + b * med ; 01125 cur_ima = cpl_imagelist_get(raw, k) ; 01126 pimaf = cpl_image_get_data_float(cur_ima) ; 01127 cpl_vector_set(z_pix, k, (double)(pimaf[pos]-fit_val)) ; 01128 } 01129 01130 /* Identify the outlier */ 01131 out = -1 ; 01132 max = -1.0 ; 01133 pz_pix = cpl_vector_get_data(z_pix) ; 01134 for (k=0 ; k<nima ; k++) { 01135 if (fabs(pz_pix[k]) > max) { 01136 max = fabs(pz_pix[k]) ; 01137 out = k ; 01138 } 01139 } 01140 cpl_vector_delete(z_pix) ; 01141 01142 /* Create 1-pixel purged image list and the purged medians */ 01143 med_purged = cpl_vector_new(nima-1) ; 01144 raw_purged = cpl_imagelist_new() ; 01145 ind = 0 ; 01146 for (k=0 ; k<nima ; k++) { 01147 if (k != out) { 01148 /* Fill raw_purged */ 01149 cur_ima = cpl_imagelist_get(raw, k) ; 01150 onepix=cpl_image_extract(cur_ima, i+1, j+1, i+1, j+1) ; 01151 cpl_imagelist_set(raw_purged, onepix, ind) ; 01152 /* Fill med_purged */ 01153 cpl_vector_set(med_purged, ind, 01154 cpl_vector_get(medians, k)) ; 01155 ind ++; 01156 } 01157 } 01158 01159 /* Perform the fit */ 01160 err_one = cpl_image_duplicate(cpl_imagelist_get(raw_purged,0)); 01161 fit_one = cpl_fit_imagelist_polynomial(med_purged, raw_purged, 01162 0, 1, CPL_FALSE, CPL_TYPE_FLOAT, err_one) ; 01163 if (fit_one == NULL) { 01164 cpl_msg_error(__func__, "Cannot fit in second pass") ; 01165 cpl_mask_delete(recompute) ; 01166 cpl_vector_delete(med_purged) ; 01167 cpl_imagelist_delete(raw_purged) ; 01168 cpl_image_delete(err_one) ; 01169 return -1 ; 01170 } 01171 cpl_vector_delete(med_purged) ; 01172 cpl_imagelist_delete(raw_purged) ; 01173 01174 /* Write the result in the input */ 01175 val = cpl_image_get(err_one, 1, 1, &pix) ; 01176 cpl_image_set(error, i+1, j+1, val) ; 01177 cpl_image_delete(err_one) ; 01178 01179 cur_ima = cpl_imagelist_get(fit_one, 0) ; 01180 val = cpl_image_get(cur_ima, 1, 1, &pix) ; 01181 cur_ima = cpl_imagelist_get(fit_res, 0) ; 01182 cpl_image_set(cur_ima, i+1, j+1, val) ; 01183 01184 cur_ima = cpl_imagelist_get(fit_one, 1) ; 01185 val = cpl_image_get(cur_ima, 1, 1, &pix) ; 01186 cur_ima = cpl_imagelist_get(fit_res, 1) ; 01187 cpl_image_set(cur_ima, i+1, j+1, val) ; 01188 cpl_imagelist_delete(fit_one) ; 01189 } 01190 } 01191 } 01192 if (recomp_mask) 01193 *recomp_mask = cpl_image_new_from_mask(recompute) ; 01194 cpl_mask_delete(recompute) ; 01195 01196 /* Return */ 01197 if (cpl_error_get_code()) return -1 ; 01198 else return 0 ; 01199 } 01200 01201 /*----------------------------------------------------------------------------*/ 01213 /*----------------------------------------------------------------------------*/ 01214 static int hawki_cal_flat_save 01215 (cpl_imagelist ** flat, 01216 cpl_table ** raw_flat_stats, 01217 cpl_table ** raw_flat_odd_column_stats, 01218 cpl_table ** raw_flat_even_column_stats, 01219 cpl_table ** raw_flat_odd_row_stats, 01220 cpl_table ** raw_flat_even_row_stats, 01221 cpl_vector ** raw_selected, 01222 int set_nb, 01223 const cpl_frame * bpmdark, 01224 cpl_frameset * flat_frames, 01225 cpl_frameset * calib_frames, 01226 cpl_parameterlist * parlist, 01227 cpl_frameset * set_tot) 01228 { 01229 cpl_propertylist ** qclists ; 01230 cpl_imagelist * bpm ; 01231 const cpl_frame * ref_frame ; 01232 cpl_frameset * used_frames; 01233 char * filename ; 01234 cpl_propertylist * inputlist ; 01235 int ext_nb ; 01236 const char * recipe_name = "hawki_cal_flat" ; 01237 int i ; 01238 int iflat; 01239 int nflat; 01240 int nused; 01241 char key_name[72]; 01242 01243 /* Get the reference frame */ 01244 ref_frame = irplib_frameset_get_first_from_group(flat_frames, CPL_FRAME_GROUP_RAW) ; 01245 01246 /* Create the QC lists */ 01247 qclists = cpl_malloc(HAWKI_NB_DETECTORS * sizeof(cpl_propertylist*)) ; 01248 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) { 01249 qclists[i] = cpl_propertylist_new() ; 01250 01251 /* Add the raw flat selection keywords */ 01252 nflat = cpl_vector_get_size(raw_selected[i]); 01253 nused = 0; 01254 for(iflat = 0; iflat < nflat; ++iflat) 01255 { 01256 snprintf(key_name, 72, "ESO QC RAW%02d USED", iflat + 1); 01257 cpl_propertylist_append_bool 01258 (qclists[i], key_name, 01259 (cpl_vector_get(raw_selected[i], iflat) + 1) / 2); 01260 cpl_table_set_int 01261 (raw_flat_stats[i],HAWKI_COL_STAT_USED, iflat, 01262 cpl_vector_get(raw_selected[i], iflat)); 01263 if(hawki_cal_flat_config.extra_stats) 01264 { 01265 cpl_table_set_int 01266 (raw_flat_odd_column_stats[i],HAWKI_COL_STAT_USED, iflat, 01267 cpl_vector_get(raw_selected[i], iflat)); 01268 cpl_table_set_int 01269 (raw_flat_even_column_stats[i],HAWKI_COL_STAT_USED, iflat, 01270 cpl_vector_get(raw_selected[i], iflat)); 01271 cpl_table_set_int 01272 (raw_flat_odd_row_stats[i],HAWKI_COL_STAT_USED, iflat, 01273 cpl_vector_get(raw_selected[i], iflat)); 01274 cpl_table_set_int 01275 (raw_flat_even_row_stats[i],HAWKI_COL_STAT_USED, iflat, 01276 cpl_vector_get(raw_selected[i], iflat)); 01277 } 01278 if(cpl_vector_get(raw_selected[i], iflat) == 1) 01279 nused++; 01280 } 01281 01282 /* Add the master flat statistics keywords */ 01283 cpl_propertylist_append_int(qclists[i], "ESO QC FLAT NBADPIX", 01284 hawki_cal_flat_outputs.nb_badpix[i]); 01285 cpl_propertylist_append_double(qclists[i], "ESO QC FLAT NORM", 01286 hawki_cal_flat_outputs.norm[i]) ; 01287 cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDMEAN", 01288 hawki_cal_flat_outputs.med_avg[i]) ; 01289 cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDMED", 01290 hawki_cal_flat_outputs.med_med[i]) ; 01291 cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDSTDEV", 01292 hawki_cal_flat_outputs.med_stdev[i]) ; 01293 cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDMIN", 01294 hawki_cal_flat_outputs.med_min[i]) ; 01295 cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDMAX", 01296 hawki_cal_flat_outputs.med_max[i]) ; 01297 cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDRANG", 01298 hawki_cal_flat_outputs.med_max[i] - 01299 hawki_cal_flat_outputs.med_min[i]); 01300 cpl_propertylist_append_double(qclists[i], "ESO QC FLAT MEDNRANG", 01301 (hawki_cal_flat_outputs.med_max[i] - 01302 hawki_cal_flat_outputs.med_min[i]) / 01303 hawki_cal_flat_outputs.med_med[i]); 01304 cpl_propertylist_append_int(qclists[i], "ESO QC DATANCOM", 01305 nused) ; 01306 01307 /* Propagate some keywords from input raw frame extensions */ 01308 ext_nb = hawki_get_ext_from_detector( 01309 cpl_frame_get_filename(ref_frame), i+1); 01310 inputlist = cpl_propertylist_load_regexp( 01311 cpl_frame_get_filename(ref_frame), ext_nb, 01312 HAWKI_HEADER_EXT_FORWARD, 0) ; 01313 cpl_propertylist_append(qclists[i], inputlist) ; 01314 01315 /* Cleaning */ 01316 cpl_propertylist_delete(inputlist) ; 01317 } 01318 /* Statistics of the raw images in the QC */ 01319 hawki_image_stats_stats(raw_flat_stats, qclists); 01320 01321 /* Get the used frames */ 01322 used_frames = cpl_frameset_duplicate(flat_frames); 01323 for(i = 0; i< cpl_frameset_get_size(calib_frames); ++i) 01324 cpl_frameset_insert(used_frames, 01325 cpl_frame_duplicate(cpl_frameset_get_frame(calib_frames, i))); 01326 01327 /* Write the flat image */ 01328 filename = cpl_sprintf("hawki_cal_flat_set%02d.fits", set_nb) ; 01329 hawki_imagelist_save(set_tot, 01330 parlist, 01331 used_frames, 01332 flat[0], 01333 recipe_name, 01334 HAWKI_CALPRO_FLAT, 01335 HAWKI_PROTYPE_FLAT, 01336 NULL, 01337 (const cpl_propertylist**)qclists, 01338 filename) ; 01339 cpl_free(filename) ; 01340 01341 /* Write the error map */ 01342 filename = cpl_sprintf("hawki_cal_flat_err_set%02d.fits", set_nb) ; 01343 hawki_imagelist_save(set_tot, 01344 parlist, 01345 used_frames, 01346 flat[1], 01347 recipe_name, 01348 HAWKI_CALPRO_FLAT_ERRMAP, 01349 HAWKI_PROTYPE_ERRMAP, 01350 NULL, 01351 (const cpl_propertylist**)qclists, 01352 filename) ; 01353 cpl_free(filename) ; 01354 01355 /* Write the Cold pixels map */ 01356 filename = cpl_sprintf("hawki_cal_flat_bpmflat_set%02d.fits", set_nb) ; 01357 hawki_imagelist_save(set_tot, 01358 parlist, 01359 used_frames, 01360 flat[2], 01361 recipe_name, 01362 HAWKI_CALPRO_BPM_COLD, 01363 HAWKI_PROTYPE_BPM, 01364 NULL, 01365 (const cpl_propertylist**)qclists, 01366 filename) ; 01367 cpl_free(filename) ; 01368 01369 if (flat[3] != NULL) { 01370 /* Write the recomputed map */ 01371 filename=cpl_sprintf("hawki_cal_flat_recomputed_set%02d.fits", set_nb) ; 01372 hawki_imagelist_save(set_tot, 01373 parlist, 01374 used_frames, 01375 flat[3], 01376 recipe_name, 01377 HAWKI_CALPRO_FLAT_RECOMPUTED, 01378 HAWKI_PROTYPE_FLAT, 01379 NULL, 01380 (const cpl_propertylist**)qclists, 01381 filename) ; 01382 cpl_free(filename) ; 01383 } 01384 01385 /* If the HOT pixel map is passed, merge with the COLD one */ 01386 if (bpmdark != NULL) { 01387 if ((bpm = hawki_cal_flat_merge_bpms(bpmdark, flat[2])) == NULL) { 01388 cpl_msg_error(__func__, "Cannot merge bad pixel maps") ; 01389 } else { 01390 filename=cpl_sprintf("hawki_cal_flat_bpm_set%02d.fits", set_nb) ; 01391 /* Get the used frames for statistics */ 01392 hawki_imagelist_save(set_tot, 01393 parlist, 01394 used_frames, 01395 bpm, 01396 recipe_name, 01397 HAWKI_CALPRO_BPM, 01398 HAWKI_PROTYPE_BPM, 01399 NULL, 01400 (const cpl_propertylist**)qclists, 01401 filename) ; 01402 cpl_free(filename) ; 01403 cpl_imagelist_delete(bpm) ; 01404 } 01405 } 01406 cpl_frameset_delete(used_frames); 01407 01408 /* Get the used frames for statistics */ 01409 used_frames = cpl_frameset_duplicate(flat_frames); 01410 01411 /* Write the table with the statistics */ 01412 filename = cpl_sprintf("hawki_cal_flat_stats_set%02d.fits", set_nb) ; 01413 hawki_tables_save(set_tot, 01414 parlist, 01415 used_frames, 01416 (const cpl_table **)raw_flat_stats, 01417 recipe_name, 01418 HAWKI_CALPRO_FLAT_STATS, 01419 HAWKI_PROTYPE_FLAT_STATS, 01420 NULL, 01421 (const cpl_propertylist **)qclists, 01422 filename) ; 01423 cpl_free(filename) ; 01424 01425 if(hawki_cal_flat_config.extra_stats) 01426 { 01427 filename = cpl_sprintf("hawki_cal_flat_stats_ec_set%02d.fits", set_nb); 01428 hawki_tables_save(set_tot, 01429 parlist, 01430 used_frames, 01431 (const cpl_table **)raw_flat_even_column_stats, 01432 recipe_name, 01433 HAWKI_CALPRO_FLAT_STATS_EVEN_COL, 01434 HAWKI_PROTYPE_FLAT_STATS_EVEN_COL, 01435 NULL, 01436 (const cpl_propertylist **)qclists, 01437 filename) ; 01438 cpl_free(filename) ; 01439 filename = cpl_sprintf("hawki_cal_flat_stats_oc_set%02d.fits", set_nb); 01440 hawki_tables_save(set_tot, 01441 parlist, 01442 used_frames, 01443 (const cpl_table **)raw_flat_odd_column_stats, 01444 recipe_name, 01445 HAWKI_CALPRO_FLAT_STATS_ODD_COL, 01446 HAWKI_PROTYPE_FLAT_STATS_ODD_COL, 01447 NULL, 01448 (const cpl_propertylist **)qclists, 01449 filename) ; 01450 cpl_free(filename) ; 01451 filename = cpl_sprintf("hawki_cal_flat_stats_er_set%02d.fits", set_nb); 01452 hawki_tables_save(set_tot, 01453 parlist, 01454 used_frames, 01455 (const cpl_table **)raw_flat_even_row_stats, 01456 recipe_name, 01457 HAWKI_CALPRO_FLAT_STATS_EVEN_ROW, 01458 HAWKI_PROTYPE_FLAT_STATS_EVEN_ROW, 01459 NULL, 01460 (const cpl_propertylist **)qclists, 01461 filename) ; 01462 cpl_free(filename) ; 01463 filename = cpl_sprintf("hawki_cal_flat_stats_or_set%02d.fits", set_nb); 01464 hawki_tables_save(set_tot, 01465 parlist, 01466 used_frames, 01467 (const cpl_table **)raw_flat_odd_row_stats, 01468 recipe_name, 01469 HAWKI_CALPRO_FLAT_STATS_ODD_ROW, 01470 HAWKI_PROTYPE_FLAT_STATS_ODD_ROW, 01471 NULL, 01472 (const cpl_propertylist **)qclists, 01473 filename) ; 01474 cpl_free(filename) ; 01475 } 01476 cpl_frameset_delete(used_frames); 01477 01478 /* Free and return */ 01479 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) { 01480 cpl_propertylist_delete(qclists[i]) ; 01481 } 01482 cpl_free(qclists) ; 01483 if (cpl_error_get_code()) return -1 ; 01484 return 0; 01485 } 01486 01487 /*----------------------------------------------------------------------------*/ 01494 /*----------------------------------------------------------------------------*/ 01495 static int hawki_cal_flat_compare( 01496 const cpl_frame * frame1, 01497 const cpl_frame * frame2) 01498 { 01499 int comparison ; 01500 cpl_propertylist * plist1 ; 01501 cpl_propertylist * plist2 ; 01502 const char * sval1, 01503 * sval2 ; 01504 double dval1, dval2 ; 01505 01506 01507 /* Test entries */ 01508 if (frame1==NULL || frame2==NULL) return -1 ; 01509 01510 /* Get property lists */ 01511 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1), 01512 0)) == NULL) { 01513 cpl_msg_error(__func__, "getting header from reference frame"); 01514 return -1 ; 01515 } 01516 if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2), 01517 0)) == NULL) { 01518 cpl_msg_error(__func__, "getting header from reference frame"); 01519 cpl_propertylist_delete(plist1) ; 01520 return -1 ; 01521 } 01522 01523 /* Test status */ 01524 if (cpl_error_get_code()) { 01525 cpl_propertylist_delete(plist1) ; 01526 cpl_propertylist_delete(plist2) ; 01527 return -1 ; 01528 } 01529 01530 comparison = 1 ; 01531 01532 /* Compare filters */ 01533 sval1 = hawki_pfits_get_filter(plist1) ; 01534 sval2 = hawki_pfits_get_filter(plist2) ; 01535 if (cpl_error_get_code()) { 01536 cpl_msg_error(__func__, "cannot get the filter"); 01537 cpl_propertylist_delete(plist1) ; 01538 cpl_propertylist_delete(plist2) ; 01539 return -1 ; 01540 } 01541 if (strcmp(sval1, sval2)) comparison = 0 ; 01542 01543 /* Compare DITs */ 01544 dval1 = hawki_pfits_get_dit(plist1) ; 01545 dval2 = hawki_pfits_get_dit(plist2) ; 01546 if (cpl_error_get_code()) { 01547 cpl_msg_error(__func__, "cannot get the DIT"); 01548 cpl_propertylist_delete(plist1) ; 01549 cpl_propertylist_delete(plist2) ; 01550 return -1 ; 01551 } 01552 if (fabs(dval1-dval2) > 1e-4) comparison = 0 ; 01553 01554 cpl_propertylist_delete(plist1) ; 01555 cpl_propertylist_delete(plist2) ; 01556 return comparison ; 01557 } 01558 01559 /*----------------------------------------------------------------------------*/ 01566 /*----------------------------------------------------------------------------*/ 01567 static cpl_imagelist * hawki_cal_flat_merge_bpms 01568 (const cpl_frame * bpm_orig, 01569 cpl_imagelist * bpm_to_merge) 01570 { 01571 cpl_imagelist * merged ; 01572 cpl_imagelist * bpm_orig_im; 01573 cpl_image * tmp ; 01574 int i ; 01575 01576 /* Test entries */ 01577 if (bpm_orig==NULL || bpm_to_merge ==NULL) return NULL ; 01578 01579 /* Create merged */ 01580 merged = cpl_imagelist_new() ; 01581 01582 /* Load the bpm_file */ 01583 bpm_orig_im = hawki_load_frame(bpm_orig, CPL_TYPE_INT); 01584 if(bpm_orig_im == NULL) 01585 { 01586 cpl_msg_error(__func__, "Cannot read existing bpm %s", 01587 cpl_frame_get_filename(bpm_orig)); 01588 cpl_imagelist_delete(merged); 01589 return NULL; 01590 } 01591 01592 /* Loop on the chips */ 01593 for (i=0 ; i<HAWKI_NB_DETECTORS ; i++) { 01594 01595 /* Merge */ 01596 tmp = cpl_image_add_create(cpl_imagelist_get(bpm_orig_im, i), 01597 cpl_imagelist_get(bpm_to_merge, i)); 01598 cpl_image_multiply(cpl_imagelist_get(bpm_orig_im, i), 01599 cpl_imagelist_get(bpm_to_merge, i)); 01600 cpl_image_subtract(tmp, cpl_imagelist_get(bpm_orig_im, i)) ; 01601 01602 /* Store */ 01603 cpl_imagelist_set(merged, tmp, i) ; 01604 } 01605 01606 /* Clean-up and return */ 01607 cpl_imagelist_delete(bpm_orig_im); 01608 return merged ; 01609 } 01610 01611 /*----------------------------------------------------------------------------*/ 01622 /*----------------------------------------------------------------------------*/ 01623 static int hawki_cal_flat_select 01624 (cpl_vector * meds, 01625 cpl_vector * rms, 01626 int auto_flag, 01627 int auto_max_bins, 01628 double min_level, 01629 double max_level, 01630 double max_rms, 01631 int min_nframes, 01632 cpl_vector * selection) 01633 { 01634 double * pselection ; 01635 double * pmeds ; 01636 double * prms ; 01637 int nvals ; 01638 int nsel ; 01639 double first_val, last_val, bin_val, dist, dist_min; 01640 double bin_low_val; 01641 double bin_up_val; 01642 int nbins, ind_closest ; 01643 int ibin; 01644 int ival; 01645 01646 /* Test entries */ 01647 if (meds == NULL) return -1; 01648 if (rms == NULL) return -1; 01649 if (selection == NULL) return -1; 01650 if(cpl_vector_get_size(meds) != cpl_vector_get_size(selection)) 01651 { 01652 cpl_msg_error(__func__, 01653 "The meds and selection vectors have not the same size"); 01654 return -1; 01655 } 01656 01657 /* Initialise. All the frames are selected by default */ 01658 nvals = cpl_vector_get_size(meds); 01659 pmeds = cpl_vector_get_data(meds); 01660 prms = cpl_vector_get_data(rms); 01661 cpl_vector_fill(selection, 1.0); 01662 01663 /* Pointer to selection */ 01664 pselection = cpl_vector_get_data(selection) ; 01665 01666 /* First select based on minimum level, if applies */ 01667 if (min_level >= 0.0) 01668 { 01669 for (ival=0 ; ival<nvals ; ival++) 01670 { 01671 if (pmeds[ival] < min_level) 01672 pselection[ival] = -1.0 ; 01673 } 01674 } 01675 01676 /* Second select based on maximum level, if applies */ 01677 if (max_level >= 0.0) 01678 { 01679 for (ival=0 ; ival<nvals ; ival++) 01680 { 01681 if (pmeds[ival] > max_level) 01682 pselection[ival] = -1.0 ; 01683 } 01684 } 01685 01686 /* Third select based on rms maximum level, if applies */ 01687 if (max_rms >= 0.0) 01688 { 01689 for (ival=0 ; ival<nvals ; ival++) 01690 { 01691 if (prms[ival] > max_rms) 01692 pselection[ival] = -1.0 ; 01693 } 01694 } 01695 01696 /* Apply the histogram selection */ 01697 if (auto_flag) 01698 { 01699 /* Automatic */ 01700 cpl_vector * auto_selection; 01701 auto_selection = cpl_vector_new(nvals); 01702 cpl_vector_fill(auto_selection, -1.0); 01703 cpl_msg_info(__func__, "Automatic dynamic range selection"); 01704 first_val = hawki_vector_get_min_select(meds, selection); 01705 last_val = hawki_vector_get_max_select(meds, selection); 01706 01707 nbins = nvals ; 01708 if (auto_max_bins > 0 && auto_max_bins < nvals) nbins = auto_max_bins; 01709 for (ibin=0 ; ibin<nbins ; ibin++) 01710 { 01711 if(ibin == 0) 01712 bin_val = first_val + (last_val-first_val)*(ibin+1)/nbins ; 01713 else if(ibin == nbins - 1) 01714 bin_val = first_val + (last_val-first_val)*(ibin)/nbins ; 01715 else 01716 bin_val = first_val + (last_val-first_val)*(ibin+0.5)/nbins ; 01717 bin_low_val = first_val + (last_val-first_val)*(ibin)/nbins ; 01718 bin_up_val = first_val + (last_val-first_val)*(ibin+1)/nbins ; 01719 01720 /* Select the closest */ 01721 dist_min = fabs(pmeds[0] - bin_val) ; 01722 ind_closest = -1; 01723 for (ival=0 ; ival<nvals ; ival++) 01724 { 01725 dist = fabs(pmeds[ival] - bin_val) ; 01726 if (dist < dist_min && pselection[ival] != -1) 01727 { 01728 dist_min = dist; 01729 ind_closest = ival; 01730 } 01731 } 01732 if(ind_closest != -1) 01733 cpl_vector_set(auto_selection, ind_closest, 1.0); 01734 } 01735 /* Use the auto_selection */ 01736 cpl_vector_copy(selection, auto_selection); 01737 cpl_vector_delete(auto_selection); 01738 } 01739 01740 /* Print and count the selected frames */ 01741 nsel = 0; 01742 cpl_msg_indent_more(); 01743 for (ival=0 ; ival<nvals ; ival++) 01744 { 01745 if(pselection[ival] != -1) 01746 { 01747 cpl_msg_info(__func__, "Selected frame %d", ival+1) ; 01748 nsel++; 01749 } 01750 } 01751 cpl_msg_indent_less(); 01752 01753 /* Check the number of selected against min_nframes */ 01754 if (nsel == 0) { 01755 cpl_msg_error(__func__, "No frame selected. Check selection criteria"); 01756 return -1; 01757 } 01758 if (min_nframes >= 0) { 01759 if (nsel < min_nframes) { 01760 cpl_msg_error(__func__, "Not enough selected frames (%d < %d)", 01761 nsel, min_nframes) ; 01762 return -1; 01763 } 01764 } 01765 01766 return 0; 01767 } 01768 01769 /*----------------------------------------------------------------------------*/ 01776 /*----------------------------------------------------------------------------*/ 01777 static cpl_vector * hawki_cal_flat_extract_vector( 01778 cpl_vector * in, 01779 cpl_vector * selection) 01780 { 01781 int nvals ; 01782 cpl_vector * selected ; 01783 double * pin ; 01784 double * pselection ; 01785 double * pselected ; 01786 int nselected ; 01787 int i ; 01788 01789 /* Test entries */ 01790 if (in == NULL) return NULL ; 01791 if (selection == NULL) return NULL ; 01792 01793 /* Initialise */ 01794 nvals = cpl_vector_get_size(in) ; 01795 nselected = 0 ; 01796 pin = cpl_vector_get_data(in) ; 01797 pselection = cpl_vector_get_data(selection) ; 01798 01799 /* Test entries */ 01800 if (nvals != cpl_vector_get_size(selection)) return NULL ; 01801 01802 /* Count the selected values */ 01803 for (i=0 ; i<nvals ; i++) { 01804 if (pselection[i] > 0.0) nselected++ ; 01805 } 01806 if (nselected == 0) return NULL ; 01807 01808 /* Create the selected vector */ 01809 selected = cpl_vector_new(nselected) ; 01810 pselected = cpl_vector_get_data(selected) ; 01811 01812 nselected = 0 ; 01813 for (i=0 ; i<nvals ; i++) { 01814 if (pselection[i] > 0.0) { 01815 pselected[nselected] = pin[i] ; 01816 nselected++ ; 01817 } 01818 } 01819 return selected ; 01820 } 01821 01822 static int hawki_cal_flat_retrieve_input_param 01823 (cpl_parameterlist * parlist) 01824 { 01825 const char * sval; 01826 cpl_parameter * par; 01827 int idet; 01828 01829 /* Initialise */ 01830 par = NULL ; 01831 for (idet=0 ; idet<HAWKI_NB_DETECTORS ; idet++) { 01832 hawki_cal_flat_outputs.nb_badpix[idet] = -1 ; 01833 hawki_cal_flat_outputs.med_stdev[idet] = -1.0 ; 01834 hawki_cal_flat_outputs.med_avg[idet] = -1.0 ; 01835 hawki_cal_flat_outputs.med_med[idet] = -1.0 ; 01836 hawki_cal_flat_outputs.med_min[idet] = -1.0 ; 01837 hawki_cal_flat_outputs.med_max[idet] = -1.0 ; 01838 } 01839 01840 /* Retrieve input parameters */ 01841 par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.zone") ; 01842 sval = cpl_parameter_get_string(par) ; 01843 if (sscanf(sval, "%d,%d,%d,%d", 01844 &hawki_cal_flat_config.llx, 01845 &hawki_cal_flat_config.lly, 01846 &hawki_cal_flat_config.urx, 01847 &hawki_cal_flat_config.ury)!=4) 01848 { 01849 return -1 ; 01850 } 01851 par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.sigma_badres") ; 01852 hawki_cal_flat_config.sigma_badres = cpl_parameter_get_double(par) ; 01853 par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.sigma_bpm") ; 01854 hawki_cal_flat_config.sigma_bpm = cpl_parameter_get_double(par) ; 01855 par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.lowval_bpm") ; 01856 hawki_cal_flat_config.lowval_bpm = cpl_parameter_get_double(par) ; 01857 par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.highval_bpm") ; 01858 hawki_cal_flat_config.highval_bpm = cpl_parameter_get_double(par) ; 01859 par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.normalise") ; 01860 hawki_cal_flat_config.normalise = cpl_parameter_get_bool(par) ; 01861 par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.second_pass") ; 01862 hawki_cal_flat_config.second_pass = cpl_parameter_get_bool(par) ; 01863 par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.select_auto") ; 01864 hawki_cal_flat_config.select_auto = cpl_parameter_get_bool(par) ; 01865 par = cpl_parameterlist_find(parlist, 01866 "hawki.hawki_cal_flat.select_auto_max_bins") ; 01867 hawki_cal_flat_config.select_auto_max_bins = cpl_parameter_get_int(par); 01868 par = cpl_parameterlist_find(parlist, 01869 "hawki.hawki_cal_flat.select_min_level") ; 01870 sval = cpl_parameter_get_string(par); 01871 if (sscanf(sval, "%lf,%lf,%lf,%lf", 01872 &hawki_cal_flat_config.select_min_level[0], 01873 &hawki_cal_flat_config.select_min_level[1], 01874 &hawki_cal_flat_config.select_min_level[2], 01875 &hawki_cal_flat_config.select_min_level[3])!=4) 01876 { 01877 if (sscanf(sval, "%f", &hawki_cal_flat_config.select_min_level[0])!=1) 01878 { 01879 return -1; 01880 } 01881 else 01882 { 01883 hawki_cal_flat_config.select_min_level[1] = 01884 hawki_cal_flat_config.select_min_level[0]; 01885 hawki_cal_flat_config.select_min_level[2] = 01886 hawki_cal_flat_config.select_min_level[0]; 01887 hawki_cal_flat_config.select_min_level[3] = 01888 hawki_cal_flat_config.select_min_level[0]; 01889 } 01890 } 01891 par = cpl_parameterlist_find(parlist, 01892 "hawki.hawki_cal_flat.select_max_level") ; 01893 sval = cpl_parameter_get_string(par); 01894 if (sscanf(sval, "%lf,%lf,%lf,%lf", 01895 &hawki_cal_flat_config.select_max_level[0], 01896 &hawki_cal_flat_config.select_max_level[1], 01897 &hawki_cal_flat_config.select_max_level[2], 01898 &hawki_cal_flat_config.select_max_level[3])!=4) 01899 { 01900 if (sscanf(sval, "%f", &hawki_cal_flat_config.select_max_level[0])!=1) 01901 { 01902 return -1; 01903 } 01904 else 01905 { 01906 hawki_cal_flat_config.select_max_level[1] = 01907 hawki_cal_flat_config.select_max_level[0]; 01908 hawki_cal_flat_config.select_max_level[2] = 01909 hawki_cal_flat_config.select_max_level[0]; 01910 hawki_cal_flat_config.select_max_level[3] = 01911 hawki_cal_flat_config.select_max_level[0]; 01912 } 01913 } 01914 par = cpl_parameterlist_find(parlist, 01915 "hawki.hawki_cal_flat.select_max_rms") ; 01916 sval = cpl_parameter_get_string(par); 01917 if (sscanf(sval, "%lf,%lf,%lf,%lf", 01918 hawki_cal_flat_config.select_max_rms, 01919 hawki_cal_flat_config.select_max_rms+1, 01920 hawki_cal_flat_config.select_max_rms+2, 01921 hawki_cal_flat_config.select_max_rms+3)!=4) 01922 { 01923 if (sscanf(sval, "%f", &hawki_cal_flat_config.select_max_rms[0])!=1) 01924 { 01925 return -1; 01926 } 01927 else 01928 { 01929 hawki_cal_flat_config.select_max_rms[1] = 01930 hawki_cal_flat_config.select_max_rms[0]; 01931 hawki_cal_flat_config.select_max_rms[2] = 01932 hawki_cal_flat_config.select_max_rms[0]; 01933 hawki_cal_flat_config.select_max_rms[3] = 01934 hawki_cal_flat_config.select_max_rms[0]; 01935 } 01936 } 01937 par = cpl_parameterlist_find(parlist, 01938 "hawki.hawki_cal_flat.select_min_nframes") ; 01939 hawki_cal_flat_config.select_min_nframes = cpl_parameter_get_int(par) ; 01940 par = cpl_parameterlist_find(parlist, "hawki.hawki_cal_flat.extra_stats") ; 01941 hawki_cal_flat_config.extra_stats = cpl_parameter_get_bool(par) ; 01942 01943 if(hawki_cal_flat_config.select_auto_max_bins != -1 && 01944 !hawki_cal_flat_config.select_auto) 01945 { 01946 cpl_msg_error(__func__,"Max bins is only allowed with select_auto"); 01947 return -1; 01948 } 01949 01950 return 0; 01951 }
1.7.3