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";
63static const char eris_nix_img_supersky_name[] =
"eris_nix_img_supersky";
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);
85static cpl_error_code eris_nix_img_supersky_fill_parameterlist(
86 cpl_parameterlist *self)
88 cpl_errorstate prestate = cpl_errorstate_get();
92 p = cpl_parameter_new_enum(
"eris.eris_nix_img_supersky.combine_method",
94 "Method to combine frames",
95 "eris.eris_nix_img_supersky",
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);
103 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.sigma_clip",
105 "Sigma threshold for clipping",
106 "eris.eris_nix_img_supersky", 2.0);
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);
112 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.max_iter",
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);
121 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.detect_threshold",
123 "Detection threshold in sigma above background",
124 "eris.eris_nix_img_supersky", 3.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);
130 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.source_fwhm",
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);
139 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.min_area",
141 "Minimum connected pixels for source detection",
142 "eris.eris_nix_img_supersky", 500);
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);
148 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.mask_dilate",
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);
157 p = cpl_parameter_new_value(
"eris.eris_nix_img_supersky.save_skysub",
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);
173 int obj_min_pixels = 300;
174 double obj_threshold = 3.0;
175 cpl_boolean obj_deblending = CPL_TRUE;
176 double obj_core_radius = 30.;
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;
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);
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));
202 cpl_parameterlist_delete(s_param);
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);
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);
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);
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);
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");
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);
231 return cpl_errorstate_is_equal(prestate) ? CPL_ERROR_NONE
232 : cpl_error_set_where(cpl_func);
243static int eris_nix_img_supersky(cpl_frameset * frameset,
244 const cpl_parameterlist * parlist)
246 const cpl_parameter * param;
247 const char * combine_method;
250 double detect_threshold;
254 cpl_boolean save_skysub;
255 cpl_frameset * product_frames = NULL;
256 cpl_error_code error;
259 param = cpl_parameterlist_find_const(parlist,
260 "eris.eris_nix_img_supersky.combine_method");
261 combine_method = cpl_parameter_get_string(param);
263 param = cpl_parameterlist_find_const(parlist,
264 "eris.eris_nix_img_supersky.sigma_clip");
265 sigma_clip = cpl_parameter_get_double(param);
267 param = cpl_parameterlist_find_const(parlist,
268 "eris.eris_nix_img_supersky.max_iter");
269 max_iter = cpl_parameter_get_int(param);
271 param = cpl_parameterlist_find_const(parlist,
272 "eris.eris_nix_img_supersky.detect_threshold");
273 detect_threshold = cpl_parameter_get_double(param);
275 param = cpl_parameterlist_find_const(parlist,
276 "eris.eris_nix_img_supersky.source_fwhm");
277 source_fwhm = cpl_parameter_get_double(param);
279 param = cpl_parameterlist_find_const(parlist,
280 "eris.eris_nix_img_supersky.min_area");
281 min_area = cpl_parameter_get_int(param);
283 param = cpl_parameterlist_find_const(parlist,
284 "eris.eris_nix_img_supersky.mask_dilate");
285 mask_dilate = cpl_parameter_get_int(param);
287 param = cpl_parameterlist_find_const(parlist,
288 "eris.eris_nix_img_supersky.save_skysub");
289 save_skysub = cpl_parameter_get_bool(param);
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");
303 cpl_error_get_code());
306 error = eris_nix_img_supersky_run(frameset, parlist, RECIPE_NAME, &product_frames);
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);
314 cpl_msg_info(cpl_func,
"Recipe completed successfully. Generated %lld products",
315 product_frames ? cpl_frameset_get_size(product_frames) : 0);
317 if (product_frames) cpl_frameset_delete(product_frames);
319 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