ERIS Pipeline Reference Manual 1.9.2
eris_nix_img_stack.c
1/* $Id$
2 *
3 * This file is part of the ERIS Pipeline
4 * Copyright (C) 2017 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/*
22 * $Author$
23 * $Date$
24 * $Revision$
25 */
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31/*-----------------------------------------------------------------------------
32 Includes
33 -----------------------------------------------------------------------------*/
34
35#include <libgen.h>
36#include <math.h>
37#include <string.h>
38
39#include "casu_utils.h"
40#include "casu_mods.h"
41
42#include "eris_nix_utils.h"
43#include "eris_nix_casu_utils.h"
44#include "eris_nix_dfs.h"
45#include <hdrl.h>
46
47#include <cpl.h>
48
49/*-----------------------------------------------------------------------------
50 Static variables
51 -----------------------------------------------------------------------------*/
52
53static const char eris_nix_img_stack_description[] =
54"This recipe rebins a set of calibrated ERIS/NIX jitter frames to a\n"
55"common grid and stacks them.\n"
56"\n"
57"Input files:\n"
58"\n"
59" DO CATG Explanation Req. #Frames\n"
60" ------- ----------- --- -------\n"
61" "ERIS_NIX_CAL_PHOT_OBJECT_JITTER_PRO_CATG
62 " calibrated frames Y 1-n\n"
63" to be stacked.\n"
64" or\n"
65" "ERIS_NIX_CAL_PHOT_STD_JITTER_PRO_CATG
66 " calibrated standard Y 1-n\n"
67" frames to be stacked.\n"
68"\n"
69"Output files:\n"
70"\n"
71" DO CATG Explanation \n"
72" ------- ----------- \n"
73" "ERIS_NIX_IMG_OBS_COMBINED_PRO_CATG
74 " the stacked image of the target.\n"
75" or\n"
76" "ERIS_NIX_IMG_STD_COMBINED_PRO_CATG
77 " the stacked image of the standard.\n"
78"\n"
79" The output will be FITS files named 'stack.<first input filename>',\n"
80" containing extensions:\n"
81" - DATA, with the stacked target or standard data.\n"
82" - ERR, with the error plane.\n"
83" - DQ, with the stacked image quality\n"
84" - CONFIDENCE, with the target confidence plane.\n"
85"\n"
86" The output file can be split into smaller components, see\n"
87" param --split-output-file.\n"
88"\n"
89"Notes on the method.\n"
90" The stacking is done by a CASU routine, the relevant part\n"
91" of whose description is:\n"
92" 'A list of frames is given. A mean image is stacked by using the\n"
93" given WCS to work out the shift of an input pixel relative to the\n"
94" grid defined by the first image in the list. At first all are\n"
95" stacked using a nearest neighbour algorithm. Any discordant pixels\n"
96" are marked at this stage. If a different stacking algorithm is\n"
97" required, then the images are restacked, but with the discordant\n"
98" pixels found earlier removed.\n"
99"\n";
100
101#define RECIPE_NAME "eris.eris_nix_img_stack"
102
103/*-----------------------------------------------------------------------------
104 Private function prototypes
105 -----------------------------------------------------------------------------*/
106
107cpl_recipe_define(eris_nix_img_stack, ERIS_BINARY_VERSION, "John Lightfoot",
108 PACKAGE_BUGREPORT, "2017",
109 "Stack calibrated ERIS/NIX jitter frames",
110 eris_nix_img_stack_description);
111
112/*-----------------------------------------------------------------------------
113 Function code
114 -----------------------------------------------------------------------------*/
115
116/*----------------------------------------------------------------------------*/
124/*----------------------------------------------------------------------------*/
125
126static cpl_error_code eris_nix_img_stack_fill_parameterlist(
127 cpl_parameterlist * self) {
128
129 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
130
131 hdrl_parameter * catalogue_defaults = NULL;
132 cpl_parameterlist * catalogue_parlist = NULL;
133 cpl_parameter * p = NULL;
134
135 /* The lower rejection threshold to be used during stacking */
136
137 p = cpl_parameter_new_range(RECIPE_NAME".stk_lthr", CPL_TYPE_DOUBLE,
138 "Low rejection threshold", RECIPE_NAME,
139 5.0, 1.0e-6, 1.0e10);
140 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "stk-lthr");
141 cpl_parameterlist_append(self, p);
142
143 /* The upper rejection threshold to be used during stacking */
144
145 p = cpl_parameter_new_range(RECIPE_NAME".stk_hthr", CPL_TYPE_DOUBLE,
146 "Upper rejection threshold", RECIPE_NAME,
147 5.0, 1.0e-6, 1.0e10);
148 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "stk-hthr");
149 cpl_parameterlist_append(self, p);
150
151 /* Stacking method */
152
153 p = cpl_parameter_new_enum(RECIPE_NAME".stk_method", CPL_TYPE_STRING,
154 "The interpolation method", RECIPE_NAME,
155 "bi-linear", 2, "nearest neighbour",
156 "bi-linear");
157 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "stk-method");
158 cpl_parameterlist_append(self, p);
159
160 /* Stacking speed method */
161
162 p = cpl_parameter_new_enum(RECIPE_NAME".stk_fast", CPL_TYPE_STRING,
163 "Use fast stacking? The fast algorithm "
164 "uses much more memory", RECIPE_NAME,
165 "auto", 3, "fast", "slow", "auto");
166 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "stk-fast");
167 cpl_parameterlist_append(self, p);
168
169 /* Number of frames above which we use the slow algorithm in auto mode */
170
171 p = cpl_parameter_new_value(RECIPE_NAME".stk_nfst", CPL_TYPE_INT,
172 "nframes limit beyond which 'slow' "
173 "stacking is enforced", RECIPE_NAME, 30);
174 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "stk-nfst");
175 cpl_parameterlist_append(self, p);
176
177 /* tidy up */
178
179 hdrl_parameter_delete(catalogue_defaults);
180 cpl_parameterlist_delete(catalogue_parlist);
181
182 return 0;
183}
184
185/*----------------------------------------------------------------------------*/
192/*----------------------------------------------------------------------------*/
193
194static int eris_nix_img_stack(cpl_frameset * frameset,
195 const cpl_parameterlist * parlist) {
196
197 located_imagelist * cal_jitters = NULL;
198 located_imagelist * cal_object_jitters = NULL;
199 located_imagelist * cal_std_jitters = NULL;
200 hdrl_parameter * cat_params = NULL;
201 const char * funcid = "eris_nix_img_stack";
202 mef_extension_list * mefs = NULL;
203 const cpl_parameter * p = NULL;
204 located_image * stack = NULL;
205 hdrl_image * stack_image = NULL;
206 cpl_frameset * used = NULL;
207
208 enu_check_error_code("%s():%d: An error is already set: %s",
209 cpl_func, __LINE__, cpl_error_get_where());
210
211 /* Check input parameters */
212
213 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
214 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
215
216 /* Set the msg verbosity level from environment variable CPL_MSG_LEVEL
217 - not working, so set manually for now */
218
219 cpl_msg_set_level_from_env();
220 cpl_msg_severity severity = cpl_msg_get_level();
221 cpl_msg_info(funcid, "level %d", (int) severity);
222
223 /* Retrieve input parameters */
224
225 p = cpl_parameterlist_find_const(parlist, RECIPE_NAME".stk_lthr");
226 const double stk_lthr = cpl_parameter_get_double(p);
227 p = cpl_parameterlist_find_const(parlist, RECIPE_NAME".stk_hthr");
228 const double stk_hthr = cpl_parameter_get_double(p);
229 p = cpl_parameterlist_find_const(parlist, RECIPE_NAME".stk_method");
230 const char * stk_method = cpl_parameter_get_string(p);
231 p = cpl_parameterlist_find_const(parlist, RECIPE_NAME".stk_fast");
232 const char * stk_fast_setting = cpl_parameter_get_string(p);
233 p = cpl_parameterlist_find_const(parlist, RECIPE_NAME".stk_nfst");
234 const int stk_nfst = cpl_parameter_get_int(p);
235 enu_check_error_code("Could not retrieve input parameters");
236
237 /* Identify the RAW and CALIB frames in the input frameset */
238
239 eris_nix_dfs_set_groups(frameset);
240 enu_check_error_code("Could not identify RAW and CALIB frames");
241
242 /* read the input frameset */
243
244 used = cpl_frameset_new();
245 cal_object_jitters = enu_limlist_load_from_frameset(frameset,
246 ERIS_NIX_CAL_PHOT_OBJECT_JITTER_PRO_CATG, used);
247 cpl_msg_info(funcid, "read %d %s frames", (int) cal_object_jitters->size,
248 ERIS_NIX_CAL_PHOT_OBJECT_JITTER_PRO_CATG);
249 cal_std_jitters = enu_limlist_load_from_frameset(frameset,
250 ERIS_NIX_CAL_PHOT_STD_JITTER_PRO_CATG, used);
251 cpl_msg_info(funcid, "read %d %s frames", (int) cal_std_jitters->size,
252 ERIS_NIX_CAL_PHOT_STD_JITTER_PRO_CATG);
253
254 /* is this a target object or standard? */
255
256 enu_check(!(cal_object_jitters->size > 0 && cal_std_jitters->size > 0),
257 CPL_ERROR_ILLEGAL_INPUT,
258 "SoF cannot contain data for both target and standard");
259 enu_check(!(cal_object_jitters->size == 0 && cal_std_jitters->size == 0),
260 CPL_ERROR_DATA_NOT_FOUND,
261 "SoF contains no data");
262 if(cal_object_jitters->size > 0) {
263 cal_jitters = cal_object_jitters;
264 } else {
265 cal_jitters = cal_std_jitters;
266 }
267
268 /* Set CASU stk_fast parameter appropriately */
269
270 int stk_fast = 1;
271 if (!strcmp(stk_fast_setting, "auto") && cal_jitters->size > stk_nfst) {
272 stk_fast = 0;
273 } else if (!strcmp(stk_fast_setting, "slow")) {
274 stk_fast = 0;
275 }
276
277 /* Stack the jitter images */
278
279 enu_stack(cal_jitters, stk_lthr, stk_hthr, stk_method, stk_fast,
280 &stack);
281 enu_check_error_code("error set after image stacking");
282
283 /* generate name of file with stacked image */
284
285 char * proto = cpl_strdup(cpl_frame_get_filename((cal_jitters->limages[0])->
286 frame);
287 char * stack_fname = cpl_sprintf("stack.%s", basename(proto_copy));
288
289 /* construct provenance frameset */
290
291 cpl_frameset * provenance = cpl_frameset_new();
292 for (cpl_size j=0; j<cal_jitters->size; j++) {
293 cpl_frameset_insert(provenance, cpl_frame_duplicate(
294 cal_jitters->limages[j]->frame));
295 }
296
297 /* update PRO.CATG and stack info */
298
299 const char * out_tag = NULL;
300 if (cal_object_jitters->size >0) {
301 out_tag = ERIS_NIX_IMG_OBS_COMBINED_PRO_CATG;
302 } else {
303 out_tag = ERIS_NIX_IMG_STD_COMBINED_PRO_CATG;
304 }
305 cpl_propertylist_update_string(stack->plist, CPL_DFS_PRO_CATG, out_tag);
306
307 int ncombine = cal_jitters->size;
308 double total_exptime = 100.0;
309 double mjd_start = 10000.0;
310 double mjd_end = 11000.0;
311 cpl_vector * obsid = cpl_vector_new(cal_jitters->size);
312 for (cpl_size j=0; j < cal_jitters->size; j++) {
313 cpl_vector_set(obsid, j, (double)j);
314 }
315 cpl_propertylist_update_int(stack->plist, "NCOMBINE", ncombine);
316 cpl_propertylist_update_double(stack->plist, "TEXPTIME", total_exptime);
317 cpl_propertylist_update_double(stack->plist, "MJD-OBS", mjd_start);
318 cpl_propertylist_update_double(stack->plist, "MJD-END", mjd_end);
319 for (cpl_size j = 0; j < cal_jitters->size; ++j) {
320 char * pname = cpl_sprintf("OBID%.0i", (int)(j+1));
321 cpl_msg_info(cpl_func, "%d %s", (int)j, pname);
322 cpl_propertylist_update_int(stack->plist, pname,
323 (int)cpl_vector_get(obsid, j));
324 cpl_free(pname);
325 }
326
327 enu_limage_save(stack_fname,
328 CPL_TRUE,
329 stack,
330 stack->frame,
331 stack->plist,
332 frameset,
333 RECIPE_NAME,
334 parlist,
335 used,
336 provenance);
337
338 cpl_free(proto);
339 cpl_free(stack_fname);
340 cpl_frameset_delete(provenance);
341
342cleanup:
343 enu_located_imagelist_delete(cal_jitters);
344 hdrl_parameter_delete(cat_params);
346 hdrl_image_delete(stack_image);
347 cpl_frameset_delete(used);
348
349 return (int)cpl_error_get_code();
350}
cpl_error_code eris_nix_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: eris_nix_dfs.c:58
void enu_located_imagelist_delete(located_imagelist *limlist)
Delete a located_imagelist and its contents.
located_imagelist * enu_limlist_load_from_frameset(cpl_frameset *frameset, const char *tag, cpl_frameset *used)
Load tagged data from a frameset into a located_imagelist.
cpl_error_code enu_stack(located_imagelist *limages, const double stk_lthr, const double stk_hthr, const char *stk_method, const int stk_fast, located_image **result)
Stack a set of images.
void enu_mef_extension_list_delete(mef_extension_list *list)
Delete a mef_extension_list and its contents.
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
Definition: hdrl_image.c:379
void hdrl_parameter_delete(hdrl_parameter *obj)
shallow delete of a parameter