CRIRES Pipeline Reference Manual  2.3.15
crires_win_dark.c
1 /* $Id: crires_win_dark.c,v 1.4 2012-09-19 14:52:00 yjung Exp $
2  *
3  * This file is part of the CRIRES Pipeline
4  * Copyright (C) 2002,2003 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: yjung $
23  * $Date: 2012-09-19 14:52:00 $
24  * $Revision: 1.4 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 
36 #include "crires_recipe.h"
37 #include "irplib_utils.h"
38 
39 /*-----------------------------------------------------------------------------
40  Define
41  -----------------------------------------------------------------------------*/
42 
43 #define RECIPE_STRING "crires_win_dark"
44 
45 /*-----------------------------------------------------------------------------
46  Functions prototypes
47  -----------------------------------------------------------------------------*/
48 
49 static double crires_win_dark_ron(const cpl_image *, const cpl_image *, int) ;
50 static int crires_win_dark_save(const cpl_imagelist *,
51  const cpl_parameterlist *, cpl_frameset *) ;
52 
53 static char crires_win_dark_description[] =
54 "crires_win_dark -- Dark recipe in Windowing Mode\n"
55 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
56 "raw-file.fits "CRIRES_WIN_DARK_RAW".\n" ;
57 
58 CRIRES_RECIPE_DEFINE(crires_win_dark,
59  CRIRES_PARAM_RON_SAMPLES |
60  CRIRES_PARAM_RON_SZ,
61  "Dark recipe in Windowing Mode",
62  crires_win_dark_description) ;
63 
64 /*-----------------------------------------------------------------------------
65  Static variables
66  -----------------------------------------------------------------------------*/
67 
68 static struct {
69  /* Inputs */
70  int hsize ;
71  int nsamples ;
72  /* Outputs */
73  double dark_med[CRIRES_NB_DETECTORS] ;
74  double dark_stdev[CRIRES_NB_DETECTORS] ;
75  double ron1[CRIRES_NB_DETECTORS] ;
76  double ron2[CRIRES_NB_DETECTORS] ;
77 } crires_win_dark_config ;
78 
79 /*-----------------------------------------------------------------------------
80  Functions code
81  -----------------------------------------------------------------------------*/
82 
83 /*----------------------------------------------------------------------------*/
90 /*----------------------------------------------------------------------------*/
91 static int crires_win_dark(
92  cpl_frameset * frameset,
93  const cpl_parameterlist * parlist)
94 {
95  cpl_frameset * rawframes ;
96  cpl_frame * ref_frame ;
97  cpl_propertylist * plist ;
98  double dit ;
99  int ndit ;
100  cpl_imagelist * darks ;
101  cpl_imagelist * darks_chip ;
102  cpl_image * dark[CRIRES_NB_DETECTORS] ;
103  cpl_vector * medians ;
104  double med ;
105  int i, j ;
106 
107  /* Initialise */
108  rawframes = NULL ;
109  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
110  crires_win_dark_config.ron1[i] = -1.0 ;
111  crires_win_dark_config.ron2[i] = -1.0 ;
112  crires_win_dark_config.dark_med[i] = -1.0 ;
113  crires_win_dark_config.dark_stdev[i] = -1.0 ;
114  dark[i] = NULL ;
115  }
116 
117  /* Retrieve input parameters */
118  crires_win_dark_config.hsize = crires_parameterlist_get_int(parlist,
119  RECIPE_STRING, CRIRES_PARAM_RON_SZ) ;
120  crires_win_dark_config.nsamples = crires_parameterlist_get_int(parlist,
121  RECIPE_STRING, CRIRES_PARAM_RON_SAMPLES) ;
122 
123  /* Identify the RAW and CALIB frames in the input frameset */
124  if (crires_dfs_set_groups(frameset, "crires_win_dark")) {
125  cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
126  return -1 ;
127  }
128 
129  /* Retrieve raw frames */
130  if ((rawframes = crires_extract_frameset(frameset,
131  CRIRES_WIN_DARK_RAW)) == NULL) {
132  cpl_msg_error(__func__, "No raw frame in input") ;
133  return -1 ;
134  }
135 
136  /* At least 3 frames */
137  if (cpl_frameset_get_size(rawframes) < 3) {
138  cpl_msg_error(__func__, "Not enough input frames");
139  cpl_frameset_delete(rawframes) ;
140  return -1 ;
141  }
142 
143  /* Get DIT / NDIT from the header */
144  ref_frame = cpl_frameset_get_position(rawframes, 0) ;
145  if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
146  0)) == NULL) {
147  cpl_msg_error(__func__, "Cannot get header from frame");
148  cpl_msg_indent_less() ;
149  cpl_frameset_delete(rawframes) ;
150  return -1 ;
151  }
152  dit = crires_pfits_get_dit(plist) ;
153  ndit = crires_pfits_get_ndit(plist) ;
154  cpl_propertylist_delete(plist) ;
155  if (cpl_error_get_code() != CPL_ERROR_NONE) {
156  cpl_msg_error(__func__, "Cannot get the DIT/NDIT from the header") ;
157  cpl_msg_indent_less() ;
158  cpl_frameset_delete(rawframes) ;
159  return -1 ;
160  }
161  cpl_msg_info(__func__, "DIT value: %g sec.", dit) ;
162  cpl_msg_info(__func__, "NDIT value: %d", ndit) ;
163 
164  /* Loop on the chips */
165  cpl_msg_info(__func__, "Dark computation") ;
166  cpl_msg_indent_more() ;
167  for (i=1 ; i<CRIRES_NB_DETECTORS-1 ; i++) {
168 
169  /* Load the chips */
170  cpl_msg_info(__func__, "Load chip number %d", i+1) ;
171  if ((darks_chip = crires_load_frameset(rawframes,
172  CRIRES_ILLUM_FULL_DETECTOR, i+1,
173  CPL_TYPE_FLOAT)) == NULL) {
174  cpl_msg_error(__func__, "Cannot load chip number %d", i+1) ;
175  cpl_msg_indent_less() ;
176  cpl_frameset_delete(rawframes) ;
177  for (j=1 ; j<i ; j++)
178  cpl_image_delete(dark[j]) ;
179  return -1 ;
180  }
181  /* Compute the current dark */
182  cpl_msg_info(__func__, "Collapse images for chip number %d", i+1) ;
183  if ((dark[i] = cpl_imagelist_collapse_create(darks_chip)) == NULL) {
184  cpl_msg_error(__func__, "Cannot average for chip number %d", i+1) ;
185  cpl_msg_indent_less() ;
186  cpl_frameset_delete(rawframes) ;
187  for (j=1 ; j<i ; j++)
188  cpl_image_delete(dark[j]) ;
189  cpl_imagelist_delete(darks_chip) ;
190  return -1 ;
191  }
192 
193  /* Compute the dark_med and stdev */
194  medians = cpl_vector_new(cpl_imagelist_get_size(darks_chip));
195  for (j=0 ; j<cpl_imagelist_get_size(darks_chip) ; j++) {
196  med = cpl_image_get_median(cpl_imagelist_get(darks_chip, j)) ;
197  cpl_vector_set(medians, j, med) ;
198  }
199  crires_win_dark_config.dark_med[i] = cpl_vector_get_mean(medians) ;
200  crires_win_dark_config.dark_stdev[i] = cpl_vector_get_stdev(medians) ;
201  cpl_vector_delete(medians) ;
202 
203  /* Compute the RONs */
204  crires_win_dark_config.ron1[i] = crires_win_dark_ron(
205  cpl_imagelist_get(darks_chip, 0),
206  cpl_imagelist_get(darks_chip, 1),
207  ndit) ;
208  crires_win_dark_config.ron2[i] = crires_win_dark_ron(
209  cpl_imagelist_get(darks_chip, 1),
210  cpl_imagelist_get(darks_chip, 2),
211  ndit) ;
212  cpl_imagelist_delete(darks_chip) ;
213  }
214  cpl_frameset_delete(rawframes) ;
215  cpl_msg_indent_less() ;
216 
217  /* Reconstruct chips (windowing mode) using detector 2 */
218  if (dark[1] != NULL) {
219  dark[0] = cpl_image_duplicate(dark[1]) ;
220  cpl_image_multiply_scalar(dark[0], 0.0) ;
221  dark[CRIRES_NB_DETECTORS-1] = cpl_image_duplicate(dark[0]) ;
222  }
223 
224  /* Reconstruct the darks imagelist */
225  darks = cpl_imagelist_new() ;
226  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++)
227  cpl_imagelist_set(darks, dark[i], i) ;
228 
229  /* Divide by DIT */
230  cpl_msg_info(__func__, "Division by DIT") ;
231  cpl_imagelist_divide_scalar(darks, dit) ;
232 
233  /* Save the product */
234  cpl_msg_info(__func__, "Save the product") ;
235  cpl_msg_indent_more() ;
236  if (crires_win_dark_save(darks, parlist, frameset)) {
237  cpl_msg_error(__func__, "Cannot save the product") ;
238  cpl_imagelist_delete(darks) ;
239  cpl_msg_indent_less() ;
240  return -1 ;
241  }
242  cpl_imagelist_delete(darks) ;
243  cpl_msg_indent_less() ;
244 
245  /* Return */
246  if (cpl_error_get_code()) return -1 ;
247  else return 0 ;
248 }
249 
250 /*----------------------------------------------------------------------------*/
258 /*----------------------------------------------------------------------------*/
259 static double crires_win_dark_ron(
260  const cpl_image * ima1,
261  const cpl_image * ima2,
262  int ndit)
263 {
264  cpl_image * ima ;
265  double norm ;
266  double ron ;
267 
268  /* Test entries */
269  if (ima1 == NULL) return -1.0 ;
270  if (ima2 == NULL) return -1.0 ;
271  if (ndit < 1) return -1.0 ;
272 
273  /* Compute norm */
274  norm = 0.5 * ndit ;
275  norm = sqrt(norm) ;
276 
277  /* Subtraction */
278  if ((ima = cpl_image_subtract_create(ima2, ima1)) == NULL) return -1.0 ;
279 
280  /* RON measurement */
281  cpl_flux_get_noise_window(ima, NULL, crires_win_dark_config.hsize,
282  crires_win_dark_config.nsamples, &ron, NULL) ;
283  cpl_image_delete(ima) ;
284  return norm*ron ;
285 }
286 
287 /*----------------------------------------------------------------------------*/
295 /*----------------------------------------------------------------------------*/
296 static int crires_win_dark_save(
297  const cpl_imagelist * dark,
298  const cpl_parameterlist * parlist,
299  cpl_frameset * set)
300 {
301  cpl_propertylist ** qclists ;
302  const cpl_frame * ref_frame ;
303  cpl_propertylist * inputlist ;
304  const char * recipe_name = "crires_win_dark" ;
305  int i ;
306 
307  /* Get the reference frame */
308  ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW) ;
309 
310  /* Create the QC lists */
311  qclists = cpl_malloc(CRIRES_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
312  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
313  qclists[i] = cpl_propertylist_new() ;
314  cpl_propertylist_append_double(qclists[i], "ESO QC RON1",
315  crires_win_dark_config.ron1[i]) ;
316  cpl_propertylist_append_double(qclists[i], "ESO QC RON2",
317  crires_win_dark_config.ron2[i]) ;
318  cpl_propertylist_append_double(qclists[i], "ESO QC DARKMED",
319  crires_win_dark_config.dark_med[i]) ;
320  cpl_propertylist_append_double(qclists[i], "ESO QC DARKSTDEV",
321  crires_win_dark_config.dark_stdev[i]) ;
322 
323  /* Propagate some keywords from input raw frame extensions */
324  inputlist = cpl_propertylist_load_regexp(
325  cpl_frame_get_filename(ref_frame), i+1,
326  CRIRES_HEADER_EXT_FORWARD, 0) ;
327  cpl_propertylist_copy_property_regexp(qclists[i], inputlist,
328  CRIRES_HEADER_EXT_FORWARD, 0) ;
329  cpl_propertylist_delete(inputlist) ;
330  }
331 
332  /* Write the combined image */
333  crires_image_save(set,
334  parlist,
335  set,
336  dark,
337  recipe_name,
338  CRIRES_CALPRO_DARK_WIN,
339  CRIRES_PROTYPE_DARK,
340  CRIRES_ILLUM_FULL_DETECTOR,
341  NULL,
342  (const cpl_propertylist**)qclists,
343  PACKAGE "/" PACKAGE_VERSION,
344  "crires_win_dark.fits") ;
345 
346  /* Remove the keywords for the FITS extensions */
347  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
348  cpl_propertylist_erase_regexp(qclists[i], CRIRES_HEADER_EXT_FORWARD, 0);
349  }
350 
351  /* Free and return */
352  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
353  cpl_propertylist_delete(qclists[i]) ;
354  }
355  cpl_free(qclists) ;
356  return 0;
357 }
358