CRIRES Pipeline Reference Manual  2.3.15
crires_spec_dark.c
1 /* $Id: crires_spec_dark.c,v 1.32 2011-02-09 10:45:01 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: 2011-02-09 10:45:01 $
24  * $Revision: 1.32 $
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_spec_dark"
44 
45 /*-----------------------------------------------------------------------------
46  Functions prototypes
47  -----------------------------------------------------------------------------*/
48 
49 static double crires_spec_dark_ron(const cpl_image *, const cpl_image *, int) ;
50 static int crires_spec_dark_save(const cpl_imagelist *,
51  const cpl_parameterlist *, cpl_frameset *) ;
52 
53 static char crires_spec_dark_description[] =
54 "crires_spec_dark -- Dark recipe\n"
55 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
56 "raw-file.fits "CRIRES_SPEC_DARK_RAW".\n" ;
57 
58 CRIRES_RECIPE_DEFINE(crires_spec_dark,
59  CRIRES_PARAM_RON_SAMPLES |
60  CRIRES_PARAM_RON_SZ,
61  "Dark recipe",
62  crires_spec_dark_description) ;
63 
64 /*-----------------------------------------------------------------------------
65  Static variables
66  -----------------------------------------------------------------------------*/
67 
68 static struct {
69  /* Inputs */
70  int hsize ;
71  int nsamples ;
72  /* Outputs */
73  crires_illum_period period ;
74  double dark_med[CRIRES_NB_DETECTORS] ;
75  double dark_stdev[CRIRES_NB_DETECTORS] ;
76  double ron1[CRIRES_NB_DETECTORS] ;
77  double ron2[CRIRES_NB_DETECTORS] ;
78 } crires_spec_dark_config ;
79 
80 /*-----------------------------------------------------------------------------
81  Functions code
82  -----------------------------------------------------------------------------*/
83 
84 /*----------------------------------------------------------------------------*/
91 /*----------------------------------------------------------------------------*/
92 static int crires_spec_dark(
93  cpl_frameset * frameset,
94  const cpl_parameterlist * parlist)
95 {
96  cpl_frameset * rawframes ;
97  cpl_frame * ref_frame ;
98  cpl_propertylist * plist ;
99  double dit ;
100  int ndit, ly, uy, ysize ;
101  cpl_imagelist * darks ;
102  cpl_imagelist * darks_chip ;
103  cpl_image * tmp_dark ;
104  cpl_vector * medians ;
105  double med ;
106  int i, j ;
107 
108  /* Initialise */
109  rawframes = NULL ;
110  uy = ly = -1 ;
111  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
112  crires_spec_dark_config.ron1[i] = -1.0 ;
113  crires_spec_dark_config.ron2[i] = -1.0 ;
114  crires_spec_dark_config.dark_med[i] = -1.0 ;
115  crires_spec_dark_config.dark_stdev[i] = -1.0 ;
116  }
117 
118  /* Retrieve input parameters */
119  crires_spec_dark_config.hsize = crires_parameterlist_get_int(parlist,
120  RECIPE_STRING, CRIRES_PARAM_RON_SZ) ;
121  crires_spec_dark_config.nsamples = crires_parameterlist_get_int(parlist,
122  RECIPE_STRING, CRIRES_PARAM_RON_SAMPLES) ;
123 
124  /* Identify the RAW and CALIB frames in the input frameset */
125  if (crires_dfs_set_groups(frameset, "crires_spec_dark")) {
126  cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
127  return -1 ;
128  }
129 
130  /* Retrieve raw frames */
131  if ((rawframes = crires_extract_frameset(frameset,
132  CRIRES_SPEC_DARK_RAW)) == NULL) {
133  cpl_msg_error(__func__, "No raw frame in input") ;
134  return -1 ;
135  }
136 
137  /* At least 3 frames */
138  if (cpl_frameset_get_size(rawframes) < 3) {
139  cpl_msg_error(__func__, "Not enough input frames");
140  cpl_frameset_delete(rawframes) ;
141  return -1 ;
142  }
143 
144  /* Get the detector illumination period */
145  crires_spec_dark_config.period =
146  crires_get_detector_illum_period(
147  cpl_frame_get_filename(cpl_frameset_get_position(rawframes, 0))) ;
148  if (crires_spec_dark_config.period == CRIRES_ILLUM_UNKNOWN) {
149  cpl_msg_error(__func__,
150  "Cannot determine the detector illumination period") ;
151  cpl_frameset_delete(rawframes) ;
152  return -1 ;
153  } else {
154  crires_display_detector_illum(crires_spec_dark_config.period) ;
155  }
156 
157  /* Get DIT / NDIT from the header */
158  ref_frame = cpl_frameset_get_position(rawframes, 0) ;
159  if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
160  0)) == NULL) {
161  cpl_msg_error(__func__, "Cannot get header from frame");
162  cpl_msg_indent_less() ;
163  cpl_frameset_delete(rawframes) ;
164  return -1 ;
165  }
166  dit = crires_pfits_get_dit(plist) ;
167  ndit = crires_pfits_get_ndit(plist) ;
168  cpl_propertylist_delete(plist) ;
169  if (cpl_error_get_code() != CPL_ERROR_NONE) {
170  cpl_msg_error(__func__, "Cannot get the DIT/NDIT from the header") ;
171  cpl_msg_indent_less() ;
172  cpl_frameset_delete(rawframes) ;
173  return -1 ;
174  }
175  cpl_msg_info(__func__, "DIT value: %g sec.", dit) ;
176  cpl_msg_info(__func__, "NDIT value: %d", ndit) ;
177 
178  /* Loop on the chips */
179  darks = cpl_imagelist_new() ;
180  cpl_msg_info(__func__, "Dark computation") ;
181  cpl_msg_indent_more() ;
182  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
183  /* Get the illumination zone */
184  if (i==0) {
185  ly=crires_get_detector_ly1(crires_spec_dark_config.period);
186  uy=crires_get_detector_uy1(crires_spec_dark_config.period);
187  } else if (i==1) {
188  ly=crires_get_detector_ly2(crires_spec_dark_config.period);
189  uy=crires_get_detector_uy2(crires_spec_dark_config.period);
190  } else if (i==2) {
191  ly=crires_get_detector_ly3(crires_spec_dark_config.period);
192  uy=crires_get_detector_uy3(crires_spec_dark_config.period);
193  } else if (i==3) {
194  ly=crires_get_detector_ly4(crires_spec_dark_config.period);
195  uy=crires_get_detector_uy4(crires_spec_dark_config.period);
196  }
197  ysize = uy - ly + 1;
198  if (128-ly <= 0) ly = 1 ;
199  else ly = 128-ly+1 ;
200  if (ly+256 >= ysize) uy = ysize ;
201  else uy = ly+256 ;
202 
203  /* Load the chips */
204  cpl_msg_info(__func__, "Load chip number %d", i+1) ;
205  if ((darks_chip = crires_load_frameset(rawframes,
206  crires_spec_dark_config.period, i+1,
207  CPL_TYPE_FLOAT)) == NULL) {
208  cpl_msg_error(__func__, "Cannot load chip number %d", i+1) ;
209  cpl_msg_indent_less() ;
210  cpl_imagelist_delete(darks) ;
211  cpl_frameset_delete(rawframes) ;
212  return -1 ;
213  }
214  /* Compute the current dark */
215  cpl_msg_info(__func__, "Collapse images for chip number %d", i+1) ;
216  if ((tmp_dark = cpl_imagelist_collapse_create(darks_chip)) == NULL) {
217  cpl_msg_error(__func__, "Cannot average for chip number %d", i+1) ;
218  cpl_msg_indent_less() ;
219  cpl_imagelist_delete(darks) ;
220  cpl_frameset_delete(rawframes) ;
221  cpl_imagelist_delete(darks_chip) ;
222  return -1 ;
223  }
224  /* Put the result in the image list */
225  cpl_imagelist_set(darks, tmp_dark, i) ;
226 
227  /* Compute the dark_med and stdev */
228  medians = cpl_vector_new(cpl_imagelist_get_size(darks_chip));
229  for (j=0 ; j<cpl_imagelist_get_size(darks_chip) ; j++) {
230  med = cpl_image_get_median_window(cpl_imagelist_get(darks_chip, j),
231  256, ly, 768, uy) ;
232  cpl_vector_set(medians, j, med) ;
233  }
234  crires_spec_dark_config.dark_med[i] = cpl_vector_get_mean(medians) ;
235  crires_spec_dark_config.dark_stdev[i] = cpl_vector_get_stdev(medians) ;
236  cpl_vector_delete(medians) ;
237 
238  /* Compute the RONs */
239  crires_spec_dark_config.ron1[i] = crires_spec_dark_ron(
240  cpl_imagelist_get(darks_chip, 0),
241  cpl_imagelist_get(darks_chip, 1),
242  ndit) ;
243  crires_spec_dark_config.ron2[i] = crires_spec_dark_ron(
244  cpl_imagelist_get(darks_chip, 1),
245  cpl_imagelist_get(darks_chip, 2),
246  ndit) ;
247  cpl_imagelist_delete(darks_chip) ;
248  }
249  cpl_frameset_delete(rawframes) ;
250  cpl_msg_indent_less() ;
251 
252  /* Divide by DIT */
253  cpl_msg_info(__func__, "Division by DIT") ;
254  cpl_imagelist_divide_scalar(darks, dit) ;
255 
256  /* Save the product */
257  cpl_msg_info(__func__, "Save the product") ;
258  cpl_msg_indent_more() ;
259  if (crires_spec_dark_save(darks, parlist, frameset)) {
260  cpl_msg_error(__func__, "Cannot save the product") ;
261  cpl_imagelist_delete(darks) ;
262  cpl_msg_indent_less() ;
263  return -1 ;
264  }
265  cpl_imagelist_delete(darks) ;
266  cpl_msg_indent_less() ;
267 
268  /* Return */
269  if (cpl_error_get_code()) return -1 ;
270  else return 0 ;
271 }
272 
273 /*----------------------------------------------------------------------------*/
281 /*----------------------------------------------------------------------------*/
282 static double crires_spec_dark_ron(
283  const cpl_image * ima1,
284  const cpl_image * ima2,
285  int ndit)
286 {
287  cpl_image * ima ;
288  double norm ;
289  double ron ;
290 
291  /* Test entries */
292  if (ima1 == NULL) return -1.0 ;
293  if (ima2 == NULL) return -1.0 ;
294  if (ndit < 1) return -1.0 ;
295 
296  /* Compute norm */
297  norm = 0.5 * ndit ;
298  norm = sqrt(norm) ;
299 
300  /* Subtraction */
301  if ((ima = cpl_image_subtract_create(ima2, ima1)) == NULL) return -1.0 ;
302 
303  /* RON measurement */
304  cpl_flux_get_noise_window(ima, NULL, crires_spec_dark_config.hsize,
305  crires_spec_dark_config.nsamples, &ron, NULL) ;
306  cpl_image_delete(ima) ;
307  return norm*ron ;
308 }
309 
310 /*----------------------------------------------------------------------------*/
318 /*----------------------------------------------------------------------------*/
319 static int crires_spec_dark_save(
320  const cpl_imagelist * dark,
321  const cpl_parameterlist * parlist,
322  cpl_frameset * set)
323 {
324  cpl_propertylist ** qclists ;
325  const cpl_frame * ref_frame ;
326  cpl_propertylist * inputlist ;
327  const char * recipe_name = "crires_spec_dark" ;
328  int i ;
329 
330  /* Get the reference frame */
331  ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW) ;
332 
333  /* Create the QC lists */
334  qclists = cpl_malloc(CRIRES_NB_DETECTORS * sizeof(cpl_propertylist*)) ;
335  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
336  qclists[i] = cpl_propertylist_new() ;
337  cpl_propertylist_append_double(qclists[i], "ESO QC RON1",
338  crires_spec_dark_config.ron1[i]) ;
339  cpl_propertylist_append_double(qclists[i], "ESO QC RON2",
340  crires_spec_dark_config.ron2[i]) ;
341  cpl_propertylist_append_double(qclists[i], "ESO QC DARKMED",
342  crires_spec_dark_config.dark_med[i]) ;
343  cpl_propertylist_append_double(qclists[i], "ESO QC DARKSTDEV",
344  crires_spec_dark_config.dark_stdev[i]) ;
345 
346  /* Propagate some keywords from input raw frame extensions */
347  inputlist = cpl_propertylist_load_regexp(
348  cpl_frame_get_filename(ref_frame), i+1,
349  CRIRES_HEADER_EXT_FORWARD, 0) ;
350  cpl_propertylist_copy_property_regexp(qclists[i], inputlist,
351  CRIRES_HEADER_EXT_FORWARD, 0) ;
352  cpl_propertylist_delete(inputlist) ;
353  }
354 
355  /* Write the combined image */
356  crires_image_save(set,
357  parlist,
358  set,
359  dark,
360  recipe_name,
361  CRIRES_CALPRO_DARK,
362  CRIRES_PROTYPE_DARK,
363  crires_spec_dark_config.period,
364  NULL,
365  (const cpl_propertylist**)qclists,
366  PACKAGE "/" PACKAGE_VERSION,
367  "crires_spec_dark.fits") ;
368 
369  /* Remove the keywords for the FITS extensions */
370  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
371  cpl_propertylist_erase_regexp(qclists[i], CRIRES_HEADER_EXT_FORWARD, 0);
372  }
373 
374  /* Free and return */
375  for (i=0 ; i<CRIRES_NB_DETECTORS ; i++) {
376  cpl_propertylist_delete(qclists[i]) ;
377  }
378  cpl_free(qclists) ;
379  return 0;
380 }
381