ERIS Pipeline Reference Manual 1.9.1
eris_nix_img_supersky.c
1/* $Id$
2 *
3 * This file is part of the ERIS/NIX Pipeline
4 * Copyright (C) 2025 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
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20
21/*-----------------------------------------------------------------------------
22 Includes
23 -----------------------------------------------------------------------------*/
24
25#include "eris_utils.h"
26#include "eris_pfits.h"
27#include "eris_dfs.h"
28#include "eris_nix_dfs.h"
29#include "eris_nix_utils.h"
30#include "eris_nix_img_supersky.h"
31
32#include <cpl.h>
33#include <hdrl.h>
34#include <math.h>
35
36/*-----------------------------------------------------------------------------
37 Static variables
38 -----------------------------------------------------------------------------*/
39#define RECIPE_NAME "eris.eris_nix_img_supersky"
40
41static const char eris_nix_img_supersky_description[] =
42"Creates and applies super-sky flat for mid-infrared (M-IR) imaging data\n"
43"to correct for highly variable sky emission in Short-Lp, Lp, and Mp filters.\n"
44"\n"
45"Input files:\n"
46" NIX_SCIENCE_REDUCED: Detector-corrected science exposures (REQUIRED, multiple)\n"
47" MASTER_BPM: Master bad pixel map (REQUIRED, single)\n"
48"\n"
49"Output files:\n"
50" MASTER_SKYFLAT: Final super-sky flat\n"
51" SKYSUB_OBJECT_JITTER: Sky-subtracted science frames (if save-skysub=TRUE)\n"
52"\n"
53"Algorithm:\n"
54"1. Create first-pass super-sky by sigma-clipped combination of all frames\n"
55"2. Subtract scaled super-sky from each frame\n"
56"3. Detect and mask sources in corrected frames using local background\n"
57"4. Create final super-sky with source masks applied\n"
58"5. Subtract scaled final super-sky from original frames\n"
59"\n"
60"The recipe handles both point-source (default) and extended-source observations.\n"
61"For extended sources, use OFF-SOURCE frames as input.\n";
62
63static const char eris_nix_img_supersky_name[] = "eris_nix_img_supersky";
64
65/*-----------------------------------------------------------------------------
66 Private function prototypes
67 -----------------------------------------------------------------------------*/
68
69cpl_recipe_define(eris_nix_img_supersky, ERIS_BINARY_VERSION, "ESO Pipeline Team",
70 PACKAGE_BUGREPORT, "2025",
71 "Create and apply super-sky flat for M-IR imaging",
72 eris_nix_img_supersky_description);
73
74/*-----------------------------------------------------------------------------
75 Functions
76 -----------------------------------------------------------------------------*/
77
78/*----------------------------------------------------------------------------*/
84/*----------------------------------------------------------------------------*/
85static cpl_error_code eris_nix_img_supersky_fill_parameterlist(
86 cpl_parameterlist *self)
87{
88 cpl_errorstate prestate = cpl_errorstate_get();
89 cpl_parameter* p;
90
91 /* Combination method */
92 p = cpl_parameter_new_enum("eris.eris_nix_img_supersky.combine_method",
93 CPL_TYPE_STRING,
94 "Method to combine frames",
95 "eris.eris_nix_img_supersky",
96 "sigmaclip", 2,
97 "median", "sigmaclip");
98 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "combine-method");
99 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
100 cpl_parameterlist_append(self, p);
101
102 /* Sigma clipping threshold */
103 p = cpl_parameter_new_value("eris.eris_nix_img_supersky.sigma_clip",
104 CPL_TYPE_DOUBLE,
105 "Sigma threshold for clipping",
106 "eris.eris_nix_img_supersky", 2.0); //2.5
107 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sigma-clip");
108 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
109 cpl_parameterlist_append(self, p);
110
111 /* Maximum iterations for sigma clipping */
112 p = cpl_parameter_new_value("eris.eris_nix_img_supersky.max_iter",
113 CPL_TYPE_INT,
114 "Maximum iterations for sigma clipping",
115 "eris.eris_nix_img_supersky", 5);
116 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "max-iter");
117 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
118 cpl_parameterlist_append(self, p);
119
120 /* Source detection threshold */
121 p = cpl_parameter_new_value("eris.eris_nix_img_supersky.detect_threshold",
122 CPL_TYPE_DOUBLE,
123 "Detection threshold in sigma above background",
124 "eris.eris_nix_img_supersky", 3.0);//5.0
125 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "detect-threshold");
126 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
127 cpl_parameterlist_append(self, p);
128
129 /* Source FWHM */
130 p = cpl_parameter_new_value("eris.eris_nix_img_supersky.source_fwhm",
131 CPL_TYPE_DOUBLE,
132 "Stellar FWHM in pixels",
133 "eris.eris_nix_img_supersky", 5.0);
134 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "source-fwhm");
135 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
136 cpl_parameterlist_append(self, p);
137
138 /* Minimum source area */
139 p = cpl_parameter_new_value("eris.eris_nix_img_supersky.min_area",
140 CPL_TYPE_INT,
141 "Minimum connected pixels for source detection",
142 "eris.eris_nix_img_supersky", 500); //20
143 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "min-area");
144 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
145 cpl_parameterlist_append(self, p);
146
147 /* Mask dilation */
148 p = cpl_parameter_new_value("eris.eris_nix_img_supersky.mask_dilate",
149 CPL_TYPE_INT,
150 "Source mask dilation radius in pixels",
151 "eris.eris_nix_img_supersky", 10);
152 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "mask-dilate");
153 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
154 cpl_parameterlist_append(self, p);
155
156 /* Save sky-subtracted frames */
157 p = cpl_parameter_new_value("eris.eris_nix_img_supersky.save_skysub",
158 CPL_TYPE_BOOL,
159 "Save individual sky-subtracted frames",
160 "eris.eris_nix_img_supersky", TRUE);
161 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "save-skysub");
162 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
163 cpl_parameterlist_append(self, p);
164
165
166
167 /* parameters to mask objects */
168
169
170
171 /* Get default parameters in the recipe */
172 /* Default values of the hdrl_parameter in the hdrl_catalogue */
173 int obj_min_pixels = 300; //4
174 double obj_threshold = 3.0; //2.5
175 cpl_boolean obj_deblending = CPL_TRUE;
176 double obj_core_radius = 30.;//5.
177 cpl_boolean bkg_estimate = CPL_TRUE;
178 int bkg_mesh_size = 64;
179 double bkg_smooth_fwhm = 2.;
180 double det_eff_gain = 3.;
181 double det_saturation = HDRL_SATURATION_INIT;
182 hdrl_catalogue_options resulttype = HDRL_CATALOGUE_BKG;
183
184
185
186 /* Create a parameter list */
187 hdrl_parameter *c_def = hdrl_catalogue_parameter_create(
188 obj_min_pixels, obj_threshold, obj_deblending, obj_core_radius,
189 bkg_estimate, bkg_mesh_size, bkg_smooth_fwhm,
190 det_eff_gain, det_saturation, resulttype);
191
192
193 cpl_parameterlist *s_param = hdrl_catalogue_parameter_create_parlist(RECIPE_NAME, "", c_def);
194 hdrl_parameter_delete(c_def) ;
195
196
197 /* Duplicate in the input/output parameterlist the parameters in the catalogue */
198 for (cpl_parameter *p = cpl_parameterlist_get_first(s_param); p != NULL;
199 p = cpl_parameterlist_get_next(s_param) ) {
200 cpl_parameterlist_append(self, cpl_parameter_duplicate(p));
201 }
202 cpl_parameterlist_delete(s_param);
203
204 cpl_parameter *par;
205
206 /* --hdrldemo_bpm_2d.post-filter-x */
207 par = cpl_parameter_new_value(RECIPE_NAME".post-filter-x", CPL_TYPE_INT,
208 "X Size of the post filtering kernel.", RECIPE_NAME, 21);//3
209 cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI, "pfx");
210 cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
211 cpl_parameterlist_append(self, par);
212
213 /* --hdrldemo_bpm_2d.post-filter-y */
214 par = cpl_parameter_new_value(RECIPE_NAME".post-filter-y", CPL_TYPE_INT,
215 "Y Size of the post filtering kernel.", RECIPE_NAME, 21);//3
216 cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI, "pfy");
217 cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
218 cpl_parameterlist_append(self, par);
219
220 /* --hdrldemo_bpm_2d.post-filter-mode */
221 par = cpl_parameter_new_enum(RECIPE_NAME".post-filter-mode",
222 CPL_TYPE_STRING, "Post filtering mode.", RECIPE_NAME,
223 "dilation", 2, "closing", "dilation");//closing
224 cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI, "pfm");
225 cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
226 cpl_parameterlist_append(self, par);
227
228
229
230
231 return cpl_errorstate_is_equal(prestate) ? CPL_ERROR_NONE
232 : cpl_error_set_where(cpl_func);
233}
234
235/*----------------------------------------------------------------------------*/
242/*----------------------------------------------------------------------------*/
243static int eris_nix_img_supersky(cpl_frameset * frameset,
244 const cpl_parameterlist * parlist)
245{
246 const cpl_parameter * param;
247 const char * combine_method;
248 double sigma_clip;
249 int max_iter;
250 double detect_threshold;
251 double source_fwhm;
252 int min_area;
253 int mask_dilate;
254 cpl_boolean save_skysub;
255 cpl_frameset * product_frames = NULL;
256 cpl_error_code error;
257
258 /* Retrieve input parameters */
259 param = cpl_parameterlist_find_const(parlist,
260 "eris.eris_nix_img_supersky.combine_method");
261 combine_method = cpl_parameter_get_string(param);
262
263 param = cpl_parameterlist_find_const(parlist,
264 "eris.eris_nix_img_supersky.sigma_clip");
265 sigma_clip = cpl_parameter_get_double(param);
266
267 param = cpl_parameterlist_find_const(parlist,
268 "eris.eris_nix_img_supersky.max_iter");
269 max_iter = cpl_parameter_get_int(param);
270
271 param = cpl_parameterlist_find_const(parlist,
272 "eris.eris_nix_img_supersky.detect_threshold");
273 detect_threshold = cpl_parameter_get_double(param);
274
275 param = cpl_parameterlist_find_const(parlist,
276 "eris.eris_nix_img_supersky.source_fwhm");
277 source_fwhm = cpl_parameter_get_double(param);
278
279 param = cpl_parameterlist_find_const(parlist,
280 "eris.eris_nix_img_supersky.min_area");
281 min_area = cpl_parameter_get_int(param);
282
283 param = cpl_parameterlist_find_const(parlist,
284 "eris.eris_nix_img_supersky.mask_dilate");
285 mask_dilate = cpl_parameter_get_int(param);
286
287 param = cpl_parameterlist_find_const(parlist,
288 "eris.eris_nix_img_supersky.save_skysub");
289 save_skysub = cpl_parameter_get_bool(param);
290
291 cpl_msg_info(cpl_func, "Recipe parameters:");
292 cpl_msg_info(cpl_func, " combine_method = %s", combine_method);
293 cpl_msg_info(cpl_func, " sigma_clip = %.2f", sigma_clip);
294 cpl_msg_info(cpl_func, " max_iter = %d", max_iter);
295 cpl_msg_info(cpl_func, " detect_threshold = %.2f", detect_threshold);
296 cpl_msg_info(cpl_func, " source_fwhm = %.2f", source_fwhm);
297 cpl_msg_info(cpl_func, " min_area = %d", min_area);
298 cpl_msg_info(cpl_func, " mask_dilate = %d", mask_dilate);
299 cpl_msg_info(cpl_func, " save_skysub = %s", save_skysub ? "TRUE" : "FALSE");
300
301 /* Identify the RAW and CALIB frames in the input frameset */
302 cpl_ensure_code(eris_nix_dfs_set_groups(frameset) == CPL_ERROR_NONE,
303 cpl_error_get_code());
304
305 /* Call the main processing function */
306 error = eris_nix_img_supersky_run(frameset, parlist, RECIPE_NAME, &product_frames);
307
308 if (error != CPL_ERROR_NONE) {
309 cpl_msg_error(cpl_func, "Super-sky creation failed");
310 if (product_frames) cpl_frameset_delete(product_frames);
311 return (int)cpl_error_set_where(cpl_func);
312 }
313
314 cpl_msg_info(cpl_func, "Recipe completed successfully. Generated %lld products",
315 product_frames ? cpl_frameset_get_size(product_frames) : 0);
316
317 if (product_frames) cpl_frameset_delete(product_frames);
318
319 return (int)cpl_error_get_code();
320}
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
hdrl_parameter * hdrl_catalogue_parameter_create(int obj_min_pixels, double obj_threshold, cpl_boolean obj_deblending, double obj_core_radius, cpl_boolean bkg_estimate, int bkg_mesh_size, double bkg_smooth_fwhm, double det_eff_gain, double det_saturation, hdrl_catalogue_options resulttype)
Creates catalogue Parameters object.
cpl_parameterlist * hdrl_catalogue_parameter_create_parlist(const char *base_context, const char *prefix, hdrl_parameter *defaults)
Create parameter list for the catalogue computation.
void hdrl_parameter_delete(hdrl_parameter *obj)
shallow delete of a parameter