25#include "eris_utils.h"
26#include "eris_pfits.h"
28#include "eris_nix_dfs.h"
29#include "eris_nix_utils.h"
30#include "eris_nix_img_supersky.h"
39#define RECIPE_NAME "eris.eris_nix_img_supersky"
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"
46" NIX_SCIENCE_REDUCED: Detector-corrected science exposures (REQUIRED, multiple)\n"
47" MASTER_BPM: Master bad pixel map (REQUIRED, single)\n"
50" MASTER_SKYFLAT: Final super-sky flat\n"
51" SKYSUB_OBJECT_JITTER: Sky-subtracted science frames (if save-skysub=TRUE)\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"
60"The recipe handles both point-source (default) and extended-source observations.\n"
61"For extended sources, use OFF-SOURCE frames as input.\n";
67cpl_recipe_define(eris_nix_img_supersky, ERIS_BINARY_VERSION,
"ESO Pipeline Team",
68 PACKAGE_BUGREPORT,
"2025",
69 "Create and apply super-sky flat for M-IR imaging",
70 eris_nix_img_supersky_description);
83static cpl_error_code eris_nix_img_supersky_fill_parameterlist(
84 cpl_parameterlist *self)
86 cpl_errorstate prestate = cpl_errorstate_get();
90 p = cpl_parameter_new_enum(
"eris.eris_nix_img_supersky.combine_method",
92 "Method to combine frames",
93 "eris.eris_nix_img_supersky",
95 "median",
"sigmaclip");
96 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"combine-method");
97 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
98 cpl_parameterlist_append(self, p);
101 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.sigma_clip",
103 "Sigma threshold for clipping",
104 "eris.eris_nix_img_supersky", 2.0);
105 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"sigma-clip");
106 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
107 cpl_parameterlist_append(self, p);
110 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.max_iter",
112 "Maximum iterations for sigma clipping",
113 "eris.eris_nix_img_supersky", 5);
114 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"max-iter");
115 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
116 cpl_parameterlist_append(self, p);
119 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.detect_threshold",
121 "Detection threshold in sigma above background",
122 "eris.eris_nix_img_supersky", 3.0);
123 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"detect-threshold");
124 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
125 cpl_parameterlist_append(self, p);
128 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.source_fwhm",
130 "Stellar FWHM in pixels",
131 "eris.eris_nix_img_supersky", 5.0);
132 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"source-fwhm");
133 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
134 cpl_parameterlist_append(self, p);
137 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.min_area",
139 "Minimum connected pixels for source detection",
140 "eris.eris_nix_img_supersky", 500);
141 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"min-area");
142 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
143 cpl_parameterlist_append(self, p);
146 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.mask_dilate",
148 "Source mask dilation radius in pixels",
149 "eris.eris_nix_img_supersky", 10);
150 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"mask-dilate");
151 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
152 cpl_parameterlist_append(self, p);
155 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.save_skysub",
157 "Save individual sky-subtracted frames",
158 "eris.eris_nix_img_supersky", TRUE);
159 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"save-skysub");
160 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
161 cpl_parameterlist_append(self, p);
164 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.debug_data",
166 "Save individual sky-subtracted frames",
167 "eris.eris_nix_img_supersky", TRUE);
168 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"debug-data");
169 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
170 cpl_parameterlist_append(self, p);
181 int obj_min_pixels = 300;
182 double obj_threshold = 3.0;
183 cpl_boolean obj_deblending = CPL_TRUE;
184 double obj_core_radius = 30.;
185 cpl_boolean bkg_estimate = CPL_TRUE;
186 int bkg_mesh_size = 64;
187 double bkg_smooth_fwhm = 2.;
188 double det_eff_gain = 3.;
189 double det_saturation = HDRL_SATURATION_INIT;
190 hdrl_catalogue_options resulttype = HDRL_CATALOGUE_BKG;
196 obj_min_pixels, obj_threshold, obj_deblending, obj_core_radius,
197 bkg_estimate, bkg_mesh_size, bkg_smooth_fwhm,
198 det_eff_gain, det_saturation, resulttype);
206 for (p = cpl_parameterlist_get_first(s_param); p != NULL;
207 p = cpl_parameterlist_get_next(s_param) ) {
208 cpl_parameterlist_append(self, cpl_parameter_duplicate(p));
210 cpl_parameterlist_delete(s_param);
215 par = cpl_parameter_new_value(RECIPE_NAME
".post-filter-x", CPL_TYPE_INT,
216 "X Size of the post filtering kernel.", RECIPE_NAME, 21);
217 cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI,
"pfx");
218 cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
219 cpl_parameterlist_append(self, par);
222 par = cpl_parameter_new_value(RECIPE_NAME
".post-filter-y", CPL_TYPE_INT,
223 "Y Size of the post filtering kernel.", RECIPE_NAME, 21);
224 cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI,
"pfy");
225 cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
226 cpl_parameterlist_append(self, par);
229 par = cpl_parameter_new_enum(RECIPE_NAME
".post-filter-mode",
230 CPL_TYPE_STRING,
"Post filtering mode.", RECIPE_NAME,
231 "dilation", 2,
"closing",
"dilation");
232 cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI,
"pfm");
233 cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
234 cpl_parameterlist_append(self, par);
239 return cpl_errorstate_is_equal(prestate) ? CPL_ERROR_NONE
240 : cpl_error_set_where(cpl_func);
251static int eris_nix_img_supersky(cpl_frameset * frameset,
252 const cpl_parameterlist * parlist)
254 const cpl_parameter * param;
255 const char * combine_method;
258 double detect_threshold;
262 cpl_boolean save_skysub;
263 cpl_frameset * product_frames = NULL;
264 cpl_error_code error;
267 param = cpl_parameterlist_find_const(parlist,
268 "eris.eris_nix_img_supersky.combine_method");
269 combine_method = cpl_parameter_get_string(param);
271 param = cpl_parameterlist_find_const(parlist,
272 "eris.eris_nix_img_supersky.sigma_clip");
273 sigma_clip = cpl_parameter_get_double(param);
275 param = cpl_parameterlist_find_const(parlist,
276 "eris.eris_nix_img_supersky.max_iter");
277 max_iter = cpl_parameter_get_int(param);
280 param = cpl_parameterlist_find_const(parlist,
281 "eris.eris_nix_img_supersky.source_fwhm");
282 source_fwhm = cpl_parameter_get_double(param);
284 param = cpl_parameterlist_find_const(parlist,
285 "eris.eris_nix_img_supersky.catalogue.obj.min-pixels");
286 min_area = cpl_parameter_get_int(param);
288 param = cpl_parameterlist_find_const(parlist,
289 "eris.eris_nix_img_supersky.catalogue.obj.threshold");
290 detect_threshold = cpl_parameter_get_double(param);
292 param = cpl_parameterlist_find_const(parlist,
293 "eris.eris_nix_img_supersky.mask_dilate");
294 mask_dilate = cpl_parameter_get_int(param);
296 param = cpl_parameterlist_find_const(parlist,
297 "eris.eris_nix_img_supersky.save_skysub");
298 save_skysub = cpl_parameter_get_bool(param);
300 cpl_msg_info(cpl_func,
"Recipe parameters:");
301 cpl_msg_info(cpl_func,
" combine_method = %s", combine_method);
302 cpl_msg_info(cpl_func,
" sigma_clip = %.2f", sigma_clip);
303 cpl_msg_info(cpl_func,
" max_iter = %d", max_iter);
304 cpl_msg_info(cpl_func,
" detect_threshold = %.2f", detect_threshold);
305 cpl_msg_info(cpl_func,
" source_fwhm = %.2f", source_fwhm);
306 cpl_msg_info(cpl_func,
" min_area = %d", min_area);
307 cpl_msg_info(cpl_func,
" mask_dilate = %d", mask_dilate);
308 cpl_msg_info(cpl_func,
" save_skysub = %s", save_skysub ?
"TRUE" :
"FALSE");
312 cpl_error_get_code());
315 error = eris_nix_img_supersky_run(frameset, parlist, RECIPE_NAME, &product_frames);
317 if (error != CPL_ERROR_NONE) {
318 cpl_msg_error(cpl_func,
"Super-sky creation failed");
319 if (product_frames) cpl_frameset_delete(product_frames);
320 return (
int)cpl_error_set_where(cpl_func);
323 cpl_msg_info(cpl_func,
"Recipe completed successfully. Generated %lld products",
324 product_frames ? cpl_frameset_get_size(product_frames) : 0);
326 if (product_frames) cpl_frameset_delete(product_frames);
328 return (
int)cpl_error_get_code();
cpl_error_code eris_nix_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
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