KMOS Pipeline Reference Manual 4.5.10
kmos_dark.c
1/*
2 * This file is part of the KMOS Pipeline
3 * Copyright (C) 2002,2003 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 * Includes
26 *----------------------------------------------------------------------------*/
27
28#include <string.h>
29#include <math.h>
30
31#include <cpl.h>
32
33#include "kmo_utils.h"
34#include "kmos_pfits.h"
35#include "kmo_dfs.h"
36#include "kmo_error.h"
37#include "kmo_constants.h"
38#include "kmo_priv_dark.h"
39#include "kmo_priv_combine.h"
40#include "kmo_priv_functions.h"
41#include "kmo_cpl_extensions.h"
42#include "kmo_debug.h"
43#include "kmos_oscan.h"
44
45/*-----------------------------------------------------------------------------
46 * Functions prototypes
47 *----------------------------------------------------------------------------*/
48
49static int kmos_dark_check_inputs(cpl_frameset *, int *, int *, int *, int *,
50 double *);
51
52static int kmos_dark_create(cpl_plugin *);
53static int kmos_dark_exec(cpl_plugin *);
54static int kmos_dark_destroy(cpl_plugin *);
55static int kmos_dark(cpl_parameterlist *, cpl_frameset *);
56
57/*-----------------------------------------------------------------------------
58 * Static variables
59 *----------------------------------------------------------------------------*/
60
61static char kmos_dark_description[] =
62"This recipe calculates the master dark frame.\n"
63"\n"
64"It is recommended to provide three or more dark exposures to produce a\n"
65"reasonable master with associated noise.\n"
66"\n"
67"---------------------------------------------------------------------------\n"
68"Input files:\n"
69" DO CATG Type Explanation Required #Frames\n"
70" ------- ----- ----------- -------- -------\n"
71" DARK RAW Dark exposures Y 1-n \n"
72" (at least 3 frames recommended) \n"
73"\n"
74"Output files:\n"
75" DO CATG Type Explanation\n"
76" ------- ----- -----------\n"
77" MASTER_DARK F2D Calculated master dark frames\n"
78" BADPIXEL_DARK B2D Associated badpixel frames\n"
79"---------------------------------------------------------------------------"
80"\n";
81
82/*----------------------------------------------------------------------------*/
86/*----------------------------------------------------------------------------*/
87
90/*-----------------------------------------------------------------------------
91 * Functions code
92 *----------------------------------------------------------------------------*/
93
94/*----------------------------------------------------------------------------*/
103/*----------------------------------------------------------------------------*/
104int cpl_plugin_get_info(cpl_pluginlist *list)
105{
106 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
107 cpl_plugin *plugin = &recipe->interface;
108
109 cpl_plugin_init(plugin,
110 CPL_PLUGIN_API,
111 KMOS_BINARY_VERSION,
112 CPL_PLUGIN_TYPE_RECIPE,
113 "kmos_dark",
114 "Create master dark frame & bad pixel mask",
115 kmos_dark_description,
116 "Alex Agudo Berbel, Yves Jung",
117 "https://support.eso.org/",
118 kmos_get_license(),
119 kmos_dark_create,
120 kmos_dark_exec,
121 kmos_dark_destroy);
122
123 cpl_pluginlist_append(list, plugin);
124
125 return 0;
126}
127
128/*----------------------------------------------------------------------------*/
136/*----------------------------------------------------------------------------*/
137static int kmos_dark_create(cpl_plugin *plugin)
138{
139 cpl_recipe *recipe;
140 cpl_parameter *p;
141
142 /* Check that the plugin is part of a valid recipe */
143 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
144 recipe = (cpl_recipe *)plugin;
145 else
146 return -1;
147
148 /* Create the parameters list in the cpl_recipe object */
149 recipe->parameters = cpl_parameterlist_new();
150
151 /* Fill the parameters list */
152
153 /* --lcmethod (level correction method) */
154 p = cpl_parameter_new_value("kmos.kmos_dark.lcmethod", CPL_TYPE_STRING,
155 "Method to use for the level correction "
156 "[\"NONE\" (no correction), "
157 "\"OSCAN\" (overscan)]",
158 "kmos.kmos_dark", "OSCAN");
159 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lcmethod");
160 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
161 cpl_parameterlist_append(recipe->parameters, p);
162
163 /* --pos_bad_pix_rej */
164 p = cpl_parameter_new_value("kmos.kmos_dark.pos_bad_pix_rej",
165 CPL_TYPE_DOUBLE, "The positive rejection threshold for bad pixels",
166 "kmos.kmos_dark", 50.0);
167 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pos_bad_pix_rej");
168 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
169 cpl_parameterlist_append(recipe->parameters, p);
170
171 /* --neg_bad_pix_rej */
172 p = cpl_parameter_new_value("kmos.kmos_dark.neg_bad_pix_rej",
173 CPL_TYPE_DOUBLE, "The negative rejection threshold for bad pixels",
174 "kmos.kmos_dark", 50.0);
175 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neg_bad_pix_rej");
176 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
177 cpl_parameterlist_append(recipe->parameters, p);
178
179 /* --file_extension */
180 p = cpl_parameter_new_value("kmos.kmos_dark.file_extension", CPL_TYPE_BOOL,
181 "Controls if EXPTIME should be appended to product filenames",
182 "kmos.kmos_dark", FALSE);
183 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "file_extension");
184 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
185 cpl_parameterlist_append(recipe->parameters, p);
186
187 return kmos_combine_pars_create(recipe->parameters, "kmos.kmos_dark",
188 DEF_REJ_METHOD, FALSE);
189}
190
191/*----------------------------------------------------------------------------*/
197/*----------------------------------------------------------------------------*/
198static int kmos_dark_exec(cpl_plugin *plugin)
199{
200 cpl_recipe *recipe;
201
202 /* Get the recipe out of the plugin */
203 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
204 recipe = (cpl_recipe *)plugin;
205 else return -1;
206
207 return kmos_dark(recipe->parameters, recipe->frames);
208}
209
210/*----------------------------------------------------------------------------*/
216/*----------------------------------------------------------------------------*/
217static int kmos_dark_destroy(cpl_plugin *plugin)
218{
219 cpl_recipe *recipe;
220
221 /* Get the recipe out of the plugin */
222 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
223 recipe = (cpl_recipe *)plugin;
224 else return -1 ;
225
226 cpl_parameterlist_delete(recipe->parameters);
227 return 0 ;
228}
229
230/*----------------------------------------------------------------------------*/
240/*----------------------------------------------------------------------------*/
241static int kmos_dark(cpl_parameterlist * parlist, cpl_frameset * frameset)
242{
243 const cpl_parameter * par ;
244 int nx, ny, nz, next, ndit ;
245 const char * cmethod ;
246 const char * lcmethod ;
247 const char * my_method ;
248 cpl_frame * frame ;
249 int file_extension, citer, cmin, cmax ;
250 double pos_bad_pix_rej, neg_bad_pix_rej, cneg_rej,
251 cpos_rej, exptime, gain;
252 char * filename ;
253 char * filename_bad ;
254 char * extname ;
255 char * exptimeStr ;
256 cpl_imagelist * detector_in_window ;
257 cpl_image * img_in ;
258 cpl_image * img_in_oscan ;
259 cpl_image * img_in_window ;
260 cpl_image * combined_data_window ;
261 cpl_image * combined_data ;
262 cpl_image * combined_noise_window ;
263 cpl_image * combined_noise ;
264 cpl_image * bad_pix_mask_window ;
265 cpl_image * bad_pix_mask ;
266 cpl_propertylist * header; //new for QC
267 cpl_propertylist * header_bad; //new for QC
268 cpl_propertylist * sub_header ;
269 int i ;
270
271 char * filename_final;
272 char * filename_bad_final;
273 char * dark_file;
274 char * bad_pixel_file;
275
276 /* Check initial Entries */
277 if (kmos_check_and_set_groups(frameset) != CPL_ERROR_NONE) {
278 return cpl_error_get_code();
279 }
280
281 /* Inistialise */
282 nx = ny = next = -1 ;
283 exptime = -1.0 ;
284
285 /* Get Parameters */
286 par = cpl_parameterlist_find_const(parlist, "kmos.kmos_dark.lcmethod");
287 lcmethod = cpl_parameter_get_string(par) ;
288 par=cpl_parameterlist_find_const(parlist, "kmos.kmos_dark.pos_bad_pix_rej");
289 pos_bad_pix_rej = cpl_parameter_get_double(par);
290 par=cpl_parameterlist_find_const(parlist, "kmos.kmos_dark.neg_bad_pix_rej");
291 neg_bad_pix_rej = cpl_parameter_get_double(par);
292 par = cpl_parameterlist_find_const(parlist,"kmos.kmos_dark.file_extension");
293 file_extension = cpl_parameter_get_bool(par);
294 kmos_combine_pars_load(parlist, "kmos.kmos_dark", &cmethod, &cpos_rej,
295 &cneg_rej, &citer, &cmin, &cmax, FALSE);
296
297 /* Check the inputs consistency */
298 if (kmos_dark_check_inputs(frameset, &nx, &ny, &ndit, &next,&exptime) != 1){
299 cpl_msg_error(__func__, "Input frameset is not consistent") ;
300 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
301 return -1 ;
302 }
303 if (strcmp(lcmethod, "OSCAN") && strcmp(lcmethod, "NONE")) {
304 cpl_msg_error(__func__,
305 "lcmethod must be 'OSCAN' or 'NONE'") ;
306 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
307 return -1 ;
308 }
309
310 /* Use average method in case there is only 1 input */
311 my_method = cmethod;
312 if (cpl_frameset_count_tags(frameset, DARK) == 1) {
313 cpl_msg_warning(cpl_func,
314 "cmethod is set to 'average' since there is only 1 input");
315 my_method = "average";
316 }
317
318 /* Compute output file names */
319 if (file_extension) {
320 /* Delete trailing zeros */
321 /* If zero right after decimal point,delete point as well */
322 exptimeStr = cpl_sprintf("%g", exptime);
323 char *p = 0;
324 for(p=exptimeStr; *p; ++p) {
325 if('.' == *p) {
326 while(*++p);
327 while('0'==*--p) *p = '\0';
328 if(*p == '.') *p = '\0';
329 break;
330 }
331 }
332 filename_final = cpl_sprintf("%s_%s", MASTER_DARK, exptimeStr);
333 filename_bad_final = cpl_sprintf("%s_%s", BADPIXEL_DARK, exptimeStr);
334
335 filename = cpl_sprintf("%s_%s_tmp", MASTER_DARK, exptimeStr);
336 filename_bad = cpl_sprintf("%s_%s_tmp", BADPIXEL_DARK, exptimeStr);
337 cpl_free(exptimeStr);
338
339 } else {
340 filename_final = cpl_sprintf("%s", MASTER_DARK);
341 filename_bad_final = cpl_sprintf("%s", BADPIXEL_DARK);
342
343 filename = cpl_sprintf("%s_tmp", MASTER_DARK);
344 filename_bad = cpl_sprintf("%s_tmp", BADPIXEL_DARK);
345 }
346
347 dark_file = cpl_sprintf("%s.fits",filename) ;
348 bad_pixel_file = cpl_sprintf("%s.fits",filename_bad) ;
349
350 cpl_msg_info(cpl_func, "filenames %s and %s ", dark_file, bad_pixel_file);
351
352
353 /* Create primary header products */
354 frame = kmo_dfs_get_frame(frameset, DARK);
355
356 header = kmo_dfs_load_primary_header(frameset, DARK); //new for QC
357 header_bad = kmo_dfs_load_primary_header(frameset, DARK); //new for QC
358
359 /*cpl_frame * master_tmp = cpl_frame_new();
360 cpl_frame_set_filename(master_tmp, filename);
361 cpl_frame_set_tag(master_tmp, MASTER_DARK);
362 cpl_frame_set_type(master_tmp, CPL_FRAME_TYPE_ANY);
363 cpl_frame_set_group(master_tmp, CPL_FRAME_GROUP_PRODUCT);
364 cpl_frame_set_level(master_tmp, CPL_FRAME_LEVEL_INTERMEDIATE);
365
366 cpl_frame * bad_tmp = cpl_frame_new();
367 cpl_frame_set_filename(bad_tmp, filename_bad);
368 cpl_frame_set_tag(bad_tmp, BADPIXEL_DARK);
369 cpl_frame_set_type(bad_tmp, CPL_FRAME_TYPE_ANY);
370 cpl_frame_set_group(bad_tmp, CPL_FRAME_GROUP_PRODUCT);
371 cpl_frame_set_level(bad_tmp, CPL_FRAME_LEVEL_INTERMEDIATE); */
372
373 cpl_propertylist_save(header, dark_file, CPL_IO_CREATE);
374 cpl_propertylist_save(header_bad, bad_pixel_file, CPL_IO_CREATE);
375
376 /*kmo_dfs_save_main_header(frameset, filename, "", frame, NULL, parlist,
377 cpl_func);
378 kmo_dfs_save_main_header(frameset, filename_bad, "", frame, NULL, parlist,
379 cpl_func); */
380
381 double qc_dark_avg =0.0 , qc_dark_median_avg = 0.0;
382 double qc_readnoise_avg =0.0, qc_readnoise_median_avg =0.0, qc_bad_pix_num_arr_avg =0.0;
383
384 double qc_dark_rms =0.0, qc_dark_median_rms =0.0;
385 double qc_readnoise_rms=0.0 , qc_readnoise_median_rms =0.0, qc_bad_pix_num_arr_rms =0.0;
386 double qc_dark_curr_arr_avg =0.0, qc_dark_curr_arr_rms = 0.0;
387
388 cpl_vector * qc_dark_arr = cpl_vector_new(next);
389 cpl_vector * qc_dark_median_arr = cpl_vector_new(next);
390 cpl_vector * qc_readnoise_arr = cpl_vector_new(next);
391 cpl_vector * qc_readnoise_median_arr = cpl_vector_new(next);
392 cpl_vector * qc_median_median_arr = cpl_vector_new(next);
393 cpl_vector * qc_bad_pix_num_arr = cpl_vector_new(next);
394 cpl_vector * qc_dark_curr_arr = cpl_vector_new(next);
395
396 /* Loop on detectors */
397 for (i = 1; i <= next ; i++) {
398 cpl_msg_indent_more() ;
399
400 detector_in_window = cpl_imagelist_new();
401 frame = kmo_dfs_get_frame(frameset, DARK);
402 nz = 0;
403 cpl_vector_set(qc_bad_pix_num_arr,i-1,0);
404
405 while (frame != NULL) {
406 /* Load current detector DARK frames into an imagelist */
407 img_in = cpl_image_load(cpl_frame_get_filename(frame),
408 CPL_TYPE_FLOAT, 0, i) ;
409 if (img_in == NULL) {
410 cpl_free(filename) ;
411 cpl_free(filename_bad) ;
412 cpl_imagelist_delete(detector_in_window) ;
413 cpl_msg_error(__func__, "Cannot load frame %d", nz+1) ;
414 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
415 cpl_msg_indent_less() ;
416 return -1 ;
417 }
418
419 /* Overscan Correction */
420 if (!strcmp(lcmethod, "OSCAN")) {
421 img_in_oscan = kmos_oscan_correct(img_in) ;
422 if (img_in_oscan == NULL) {
423 cpl_free(filename) ;
424 cpl_free(filename_bad) ;
425 cpl_imagelist_delete(detector_in_window) ;
426 cpl_image_delete(img_in);
427 cpl_msg_error(__func__, "Cannot correct Overscan") ;
428 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
429 cpl_msg_indent_less() ;
430 return -1 ;
431 }
432 cpl_image_delete(img_in) ;
433 img_in = img_in_oscan ;
434 }
435
436 /* Cut the borderѕ */
437 img_in_window = cpl_image_extract(img_in, KMOS_BADPIX_BORDER+1,
438 KMOS_BADPIX_BORDER+1, nx-KMOS_BADPIX_BORDER,
439 ny-KMOS_BADPIX_BORDER) ;
440 cpl_image_delete(img_in) ;
441
442 cpl_imagelist_set(detector_in_window, img_in_window, nz);
443 nz++;
444
445 /* Get next DARK frame */
446 frame = kmo_dfs_get_frame(frameset, NULL);
447 }
448
449 /* Combine imagelist and create noise */
450 kmos_combine_frames(detector_in_window, my_method,
451 cpos_rej, cneg_rej, citer, cmax, cmin, &combined_data_window,
452 &combined_noise_window, -1.0);
453 cpl_imagelist_delete(detector_in_window) ;
454
455 if (kmclipm_omit_warning_one_slice > 10)
456 kmclipm_omit_warning_one_slice = FALSE;
457
458 /* Calculate preliminary mean and stdev to create the BPM */
459 cpl_vector_set(qc_dark_arr, (cpl_size)i-1 ,cpl_image_get_mean(combined_data_window));
460
461 /* Check the noise frame (NULL or ALL pixels are bad) */
462 if (combined_noise_window == NULL ||
463 cpl_image_count_rejected(combined_noise_window) ==
464 cpl_image_get_size_x(combined_noise_window)*
465 cpl_image_get_size_y(combined_noise_window)) {
466 cpl_vector_set(qc_readnoise_arr, i-1, cpl_image_get_stdev(combined_data_window));
467 cpl_msg_info(cpl_func, "vectors, %f ", cpl_image_get_stdev(combined_data_window) );
468 } else {
469 if (nz > 2)
470 cpl_vector_set(qc_readnoise_arr, i-1, cpl_image_get_mean(combined_noise_window));
471 else if (nz == 2)
472 cpl_vector_set(qc_readnoise_arr, i, cpl_image_get_stdev(combined_noise_window));
473 else if (nz == 1)
474 cpl_vector_set(qc_readnoise_arr, i-1, cpl_image_get_stdev(combined_data_window));
475 else {
476 cpl_msg_error(__func__, "Not enough frames: %d", nz) ;
477 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
478 cpl_free(filename) ;
479 cpl_free(filename_bad) ;
480 cpl_image_delete(combined_data_window);
481 cpl_image_delete(combined_noise_window);
482 cpl_msg_indent_less() ;
483 return -1 ;
484 }
485 }
486
487 /* Create bad-pixel-mask */
488 cpl_vector_set(qc_bad_pix_num_arr,i-1, kmo_create_bad_pix_dark(combined_data_window,
489 cpl_vector_get(qc_dark_arr,i-1), cpl_vector_get(qc_readnoise_arr,i-1), pos_bad_pix_rej, neg_bad_pix_rej,
490 &bad_pix_mask_window));
491
492 sub_header = kmo_dfs_load_sub_header(frameset, DARK, i, FALSE);
493 kmclipm_update_property_int(sub_header, QC_NR_BAD_PIX, cpl_vector_get(qc_bad_pix_num_arr,i-1),
494 "[] nr. of bad pixels");
495
496 /* Calculate QC.DARK, QC.READNOISE, QC.DARK.MEDIAN, */
497 /* QC.READNOISE.MEDIAN, QC.DARKCUR */
498
499 /* Badpixels from combined_data_window are already rejected */
500 /* by kmo_create_bad_pix_dark() */
501 kmo_image_reject_from_mask(combined_noise_window, bad_pix_mask_window);
502 cpl_vector_set(qc_dark_arr, i-1, cpl_image_get_mean(combined_data_window));
503 cpl_vector_set(qc_dark_median_arr, i-1, cpl_image_get_median(combined_data_window));
504
505 /* Check the noise frame (NULL or ALL pixels are bad) */
506 /* Calculate mean and stddev of combined frames (with rejection) */
507 if (combined_noise_window == NULL ||
508 cpl_image_count_rejected(combined_noise_window) ==
509 cpl_image_get_size_x(combined_noise_window)*
510 cpl_image_get_size_y(combined_noise_window)) {
511 cpl_vector_set(qc_readnoise_arr, i-1, cpl_image_get_stdev(combined_data_window));
512 cpl_vector_set(qc_readnoise_median_arr,i-1,
513 kmo_image_get_stdev_median(combined_data_window));
514 } else {
515 if (nz > 2) {
516 cpl_vector_set(qc_readnoise_arr,i-1,
517 cpl_image_get_mean(combined_noise_window) * sqrt(nz)) ;
518 cpl_vector_set(qc_readnoise_median_arr, i-1,
519 cpl_image_get_median(combined_noise_window) * sqrt(nz));
520 } else if (nz == 2) {
521 cpl_vector_set(qc_readnoise_arr, i-1,
522 cpl_image_get_stdev(combined_noise_window) * sqrt(nz)) ;
523 cpl_vector_set(qc_readnoise_median_arr,i-1, sqrt(nz) *
524 kmo_image_get_stdev_median(combined_noise_window) );
525 } else if (nz == 1) {
526 cpl_vector_set(qc_readnoise_arr,i-1, cpl_image_get_stdev(combined_data_window));
527 cpl_vector_set(qc_readnoise_median_arr, i-1,
528 kmo_image_get_stdev_median(combined_data_window));
529 } else {
530 cpl_msg_error(__func__, "Not enough frames: %d", nz) ;
531 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
532 cpl_free(filename) ;
533 cpl_free(filename_bad) ;
534 cpl_image_delete(combined_data_window);
535 cpl_image_delete(combined_noise_window);
536 cpl_image_delete(bad_pix_mask_window);
537 cpl_propertylist_delete(sub_header);
538 cpl_msg_indent_less() ;
539 return -1 ;
540 }
541 }
542
543 kmclipm_update_property_double(sub_header, QC_DARK, cpl_vector_get(qc_dark_arr,i-1),
544 "[adu] mean of master dark");
545 kmclipm_update_property_double(sub_header, QC_READNOISE, cpl_vector_get(qc_readnoise_arr,i-1),
546 "[adu] mean noise of master dark");
547 kmclipm_update_property_double(sub_header, QC_DARK_MEDIAN,
548 cpl_vector_get(qc_dark_median_arr, i-1), "[adu] median of master dark");
549 kmclipm_update_property_double(sub_header, QC_READNOISE_MEDIAN,
550 cpl_vector_get(qc_readnoise_median_arr,i-1), "[adu] median noise of master dark");
551
552 /* Load gain */
553 gain = kmo_dfs_get_property_double(sub_header, GAIN);
554 if (cpl_error_get_code() != CPL_ERROR_NONE) {
555 cpl_msg_error(__func__, "GAIN is missing in header") ;
556 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
557 cpl_free(filename) ;
558 cpl_free(filename_bad) ;
559 cpl_image_delete(combined_data_window);
560 cpl_image_delete(combined_noise_window);
561 cpl_image_delete(bad_pix_mask_window);
562 cpl_propertylist_delete(sub_header);
563 cpl_msg_indent_less() ;
564 return -1 ;
565 }
566
567 cpl_vector_set(qc_dark_curr_arr, i-1, (cpl_vector_get(qc_dark_arr,i-1) / exptime / gain));
568
569 kmclipm_update_property_double(sub_header, QC_DARK_CURRENT,
570 cpl_vector_get(qc_dark_curr_arr,i-1), "[e-/s] dark current");
571
572 /* Save dark frame */
573 extname = kmo_extname_creator(detector_frame, i, EXT_DATA);
574 kmclipm_update_property_string(sub_header, EXTNAME, extname,
575 "FITS extension name");
576 cpl_free(extname);
577
578 combined_data = kmo_add_bad_pix_border(combined_data_window, TRUE);
579 cpl_image_delete(combined_data_window);
580
581 //NEW
582 kmclipm_image_save(combined_data, dark_file, CPL_BPP_IEEE_FLOAT, sub_header,
583 CPL_IO_EXTEND, 0./0.);
584 //kmo_dfs_save_image(combined_data, filename, "", sub_header, 0./0.);
585 cpl_image_delete(combined_data);
586
587 /* Save noise frame */
588 extname = kmo_extname_creator(detector_frame, i, EXT_NOISE);
589 kmclipm_update_property_string(sub_header, EXTNAME, extname,
590 "FITS extension name");
591 cpl_free(extname);
592
593 combined_noise = kmo_add_bad_pix_border(combined_noise_window, TRUE);
594 cpl_image_delete(combined_noise_window);
595
596 //NEW
597 kmclipm_image_save(combined_noise, dark_file, CPL_BPP_IEEE_FLOAT, sub_header,
598 CPL_IO_EXTEND, 0./0.);
599 //kmo_dfs_save_image(combined_noise, filename, "", sub_header, 0./0.);
600 cpl_image_delete(combined_noise);
601
602 /* Save bad_pix frame */
603 extname = kmo_extname_creator(detector_frame, i, EXT_BADPIX);
604 kmclipm_update_property_string(sub_header, EXTNAME, extname,
605 "FITS extension name");
606 cpl_free(extname);
607
608 bad_pix_mask = kmo_add_bad_pix_border(bad_pix_mask_window, FALSE);
609 cpl_image_delete(bad_pix_mask_window);
610
611 //NEW
612 kmclipm_image_save(bad_pix_mask, bad_pixel_file, CPL_BPP_IEEE_FLOAT, sub_header,
613 CPL_IO_EXTEND, 0./0.);
614 //kmo_dfs_save_image(bad_pix_mask, filename_bad, "", sub_header, 0.);
615 cpl_image_delete(bad_pix_mask);
616
617 cpl_propertylist_delete(sub_header);
618
619 cpl_msg_indent_less() ;
620 }
621
622 //Calculating QC params -
623 qc_dark_avg = cpl_vector_get_mean(qc_dark_arr);
624 qc_dark_rms = cpl_vector_get_stdev(qc_dark_arr);
625 qc_dark_median_avg = cpl_vector_get_mean(qc_dark_median_arr);
626 qc_dark_median_rms = cpl_vector_get_stdev(qc_dark_median_arr);
627 qc_readnoise_avg = cpl_vector_get_mean(qc_readnoise_arr);
628 qc_readnoise_rms = cpl_vector_get_stdev(qc_readnoise_arr);
629 qc_readnoise_median_avg = cpl_vector_get_mean(qc_readnoise_median_arr);
630 qc_readnoise_median_rms = cpl_vector_get_stdev(qc_readnoise_median_arr);
631 qc_bad_pix_num_arr_avg = cpl_vector_get_mean(qc_bad_pix_num_arr);
632 qc_bad_pix_num_arr_rms = cpl_vector_get_stdev(qc_bad_pix_num_arr);
633 qc_dark_curr_arr_avg = cpl_vector_get_mean(qc_dark_curr_arr);
634 qc_dark_curr_arr_rms = cpl_vector_get_stdev(qc_dark_curr_arr);
635
636
637 kmclipm_update_property_double(header, QC_DARK_AVG, qc_dark_avg,
638 "[adu] avg of master dark");
639 kmclipm_update_property_double(header, QC_READNOISE_AVG, qc_readnoise_avg,
640 "[adu] avg noise of master dark");
641 kmclipm_update_property_double(header, QC_DARK_MEDIAN_AVG,
642 qc_dark_median_avg, "[adu] avg median of master dark");
643 kmclipm_update_property_double(header, QC_READNOISE_MEDIAN_AVG,
644 qc_readnoise_median_avg, "[adu] avg median noise of master dark");
645
646 kmclipm_update_property_double(header, QC_DARK_RMS, qc_dark_rms,
647 "[adu] stdev of master dark");
648 kmclipm_update_property_double(header, QC_READNOISE_RMS, qc_readnoise_rms,
649 "[adu] stdev noise of master dark");
650 kmclipm_update_property_double(header, QC_DARK_MEDIAN_RMS,
651 qc_dark_median_rms, "[adu] stdev of master dark");
652 kmclipm_update_property_double(header, QC_READNOISE_MEDIAN_RMS,
653 qc_readnoise_median_rms, "[adu] stdev noise of master dark");
654
655 kmclipm_update_property_double(header, QC_DARK_CURRENT_AVG, qc_dark_curr_arr_avg,
656 "[adu] avg of dark current");
657 kmclipm_update_property_double(header, QC_DARK_CURRENT_RMS, qc_dark_curr_arr_rms,
658 "[adu] stdev noise of dark current");
659 kmclipm_update_property_double(header, QC_NR_BAD_PIX_AVG,
660 qc_bad_pix_num_arr_avg, "[adu] avg bad pixel number");
661 kmclipm_update_property_double(header, QC_NR_BAD_PIX_RMS,
662 qc_bad_pix_num_arr_rms, "[adu] stdev bad pixel number");
663
664 kmclipm_update_property_double(header_bad, QC_DARK_AVG, qc_dark_avg,
665 "[adu] avg of master dark");
666 kmclipm_update_property_double(header_bad, QC_READNOISE_AVG, qc_readnoise_avg,
667 "[adu] avg noise of master dark");
668 kmclipm_update_property_double(header_bad, QC_DARK_MEDIAN_AVG,
669 qc_dark_median_avg, "[adu] avg median of master dark");
670 kmclipm_update_property_double(header_bad, QC_READNOISE_MEDIAN_AVG,
671 qc_readnoise_median_avg, "[adu] avg median noise of master dark");
672
673 kmclipm_update_property_double(header_bad, QC_DARK_RMS, qc_dark_rms,
674 "[adu] stdev of master dark");
675 kmclipm_update_property_double(header_bad, QC_READNOISE_RMS, qc_readnoise_rms,
676 "[adu] stdev noise of master dark");
677 kmclipm_update_property_double(header_bad, QC_DARK_MEDIAN_RMS,
678 qc_dark_median_rms, "[adu] stev median of master dark");
679 kmclipm_update_property_double(header_bad, QC_READNOISE_MEDIAN_RMS,
680 qc_readnoise_median_rms, "[adu] stdev median noise of master dark");
681
682 kmclipm_update_property_double(header_bad, QC_DARK_CURRENT_AVG, qc_dark_curr_arr_avg,
683 "[adu] avg of dark current");
684 kmclipm_update_property_double(header_bad, QC_DARK_CURRENT_RMS, qc_dark_curr_arr_rms,
685 "[adu] stdev noise of dark current");
686 kmclipm_update_property_double(header_bad, QC_NR_BAD_PIX_AVG,
687 qc_bad_pix_num_arr_avg, "[adu] avg bad pixel number");
688 kmclipm_update_property_double(header_bad, QC_NR_BAD_PIX_RMS,
689 qc_bad_pix_num_arr_rms, "[adu] stdev bad pixel number");
690
691 kmo_dfs_save_main_header(frameset, filename_final, "", frame, header, parlist, cpl_func);
692 kmo_dfs_save_main_header(frameset, filename_bad_final, "", frame, header_bad, parlist, cpl_func);
693
694
695 int j =0;
696
697 for (i = 1; i <= next; i++) {
698
699 cpl_image * saved_im;
700 cpl_image * saved_im_noise;
701 cpl_image * saved_im_bad;
702
703 cpl_propertylist * sub_header_fin;
704 cpl_propertylist * sub_header_noise_fin;
705 cpl_propertylist * sub_header_bad_fin;
706 j= i*2;
707
708 saved_im = kmclipm_image_load(dark_file, CPL_TYPE_FLOAT, 0, j-1);
709 saved_im_noise = kmclipm_image_load(dark_file, CPL_TYPE_FLOAT, 0, j);
710 saved_im_bad = kmclipm_image_load(bad_pixel_file, CPL_TYPE_FLOAT, 0, i);
711
712 sub_header_fin= kmclipm_propertylist_load(dark_file,j-1);
713 sub_header_noise_fin= kmclipm_propertylist_load(dark_file,j);
714 sub_header_bad_fin= kmclipm_propertylist_load(bad_pixel_file,i);
715
716 kmo_dfs_save_image(saved_im, filename_final, "", sub_header_fin, 0.);
717 kmo_dfs_save_image(saved_im_noise, filename_final, "", sub_header_noise_fin, 0.);
718 kmo_dfs_save_image(saved_im_bad, filename_bad_final, "", sub_header_bad_fin, 0.);
719
720 cpl_image_delete(saved_im);
721 cpl_image_delete(saved_im_noise);
722 cpl_image_delete(saved_im_bad);
723
724 cpl_propertylist_delete(sub_header_fin);
725 cpl_propertylist_delete(sub_header_noise_fin);
726 cpl_propertylist_delete(sub_header_bad_fin);
727
728 }
729
730 //cpl_frame_set_level(frame, CPL_FRAME_LEVEL_FINAL);
731
732 unlink(dark_file);
733 unlink(bad_pixel_file);
734 cpl_vector_delete(qc_dark_arr );
735 cpl_vector_delete(qc_dark_median_arr);
736 cpl_vector_delete(qc_readnoise_arr);
737 cpl_vector_delete(qc_readnoise_median_arr);
738 cpl_vector_delete(qc_median_median_arr);
739 cpl_vector_delete(qc_bad_pix_num_arr);
740 cpl_vector_delete(qc_dark_curr_arr);
741
742 cpl_propertylist_delete(header);
743 cpl_propertylist_delete(header_bad);
744
745 /*cpl_frame_delete(master_tmp);
746 cpl_frame_delete(bad_tmp);*/
747
748 cpl_free(dark_file);
749 cpl_free(bad_pixel_file);
750
751 /* Free and Return */
752 cpl_free(filename_final);
753 cpl_free(filename_bad_final);
754 return CPL_ERROR_NONE;
755}
756
759/*----------------------------------------------------------------------------*/
770/*----------------------------------------------------------------------------*/
771static int kmos_dark_check_inputs(
772 cpl_frameset * frameset,
773 int * nx,
774 int * ny,
775 int * ndit,
776 int * next,
777 double * exptime)
778{
779 cpl_frame * frame ;
780 cpl_propertylist * eh ;
781 cpl_propertylist * main_header ;
782 int nx_cur, ny_cur, ndit_cur, ne_cur ;
783 double exptime_cur ;
784 int i, j ;
785
786 /* Check Entries */
787 if (nx == NULL || ny == NULL || frameset == NULL || exptime == NULL ||
788 ndit == NULL || next == NULL) {
789 return -1;
790 }
791
792 /* More than 3 frames is recommended */
793 if (cpl_frameset_count_tags(frameset, DARK) < 3) {
794 cpl_msg_warning(cpl_func, "3 DARK frames or more are recommended");
795 }
796
797 /* Loop on the frames - Check Main Headers consistency */
798 i = 0;
799 frame = kmo_dfs_get_frame(frameset, DARK);
800 while (frame != NULL) {
801 /* Get Frame nb of extensions */
802 ne_cur = cpl_frame_get_nextensions(frame);
803
804 /* Read Frame header */
805 main_header = cpl_propertylist_load(cpl_frame_get_filename(frame),0);
806 ndit_cur = kmos_pfits_get_ndit(main_header) ;
807 exptime_cur = kmos_pfits_get_exptime(main_header) ;
808 cpl_propertylist_delete(main_header) ;
809
810 if (cpl_error_get_code() != CPL_ERROR_NONE) {
811 cpl_msg_error(__func__, "Cannot retrieve keywords from header") ;
812 return -1 ;
813 }
814
815 if (i == 0) {
816 *exptime = exptime_cur ;
817 *ndit = ndit_cur ;
818 *next = ne_cur ;
819 } else {
820 if (ndit_cur != *ndit || ne_cur != *next ||
821 fabs(exptime_cur-(*exptime)) >1e-3) {
822 cpl_msg_error(__func__, "Header keywords are inconsistent") ;
823 return -1 ;
824 }
825 }
826
827 /* Get next DARK frame */
828 frame = kmo_dfs_get_frame(frameset, NULL);
829 i++;
830 }
831
832 /* Loop on the frames - Check Extension Headers consistency */
833 i = 0;
834 frame = kmo_dfs_get_frame(frameset, DARK);
835 while (frame != NULL) {
836 /* Loop on extensions */
837 for (j=1 ; j<=*next ; j++) {
838 /* Read extension header */
839 eh = cpl_propertylist_load(cpl_frame_get_filename(frame), j);
840 nx_cur = kmos_pfits_get_naxis1(eh) ;
841 ny_cur = kmos_pfits_get_naxis2(eh) ;
842 cpl_propertylist_delete(eh) ;
843 if (cpl_error_get_code() != CPL_ERROR_NONE) {
844 cpl_msg_error(__func__, "Cannot retrieve keywords from header");
845 return -1 ;
846 }
847
848 if (i == 0 && j == 1) {
849 *nx = nx_cur ;
850 *ny = ny_cur ;
851 } else {
852 if (nx_cur != *nx || ny_cur != *ny) {
853 cpl_msg_error(__func__, "Header keywords are inconsistent");
854 return -1 ;
855 }
856 }
857 }
858
859 /* Get next DARK frame */
860 frame = kmo_dfs_get_frame(frameset, NULL);
861 i++;
862 }
863
864 /* Check Sizeѕ */
865 if (*nx <= 2*KMOS_BADPIX_BORDER || *ny <= 2*KMOS_BADPIX_BORDER) {
866 cpl_msg_error(__func__, "Input frames x/y size must be > 9 pixels");
867 return -1 ;
868 }
869
870 /* Return */
871 return 1 ;
872}
873
874
875
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.
Definition: kmos_dark.c:104