CRIRES Pipeline Reference Manual 2.3.19
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
49static double crires_win_dark_ron(const cpl_image *, const cpl_image *, int) ;
50static int crires_win_dark_save(const cpl_imagelist *,
51 const cpl_parameterlist *, cpl_frameset *) ;
52
53static 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
58CRIRES_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
68static 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/*----------------------------------------------------------------------------*/
91static 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/*----------------------------------------------------------------------------*/
259static 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/*----------------------------------------------------------------------------*/
296static 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