31#include "cr2res_utils.h"
32#include "cr2res_pfits.h"
33#include "cr2res_dfs.h"
35#include "cr2res_trace.h"
36#include "cr2res_wave.h"
42#define RECIPE_STRING "cr2res_util_trace"
48int cpl_plugin_get_info(cpl_pluginlist * list);
54static cpl_frameset * cr2res_util_trace_find_RAW(
const cpl_frameset * in) ;
55static int cr2res_util_trace_create(cpl_plugin *);
56static int cr2res_util_trace_exec(cpl_plugin *);
57static int cr2res_util_trace_destroy(cpl_plugin *);
58static int cr2res_util_trace(cpl_frameset *,
const cpl_parameterlist *);
64static char cr2res_util_trace_description[] =
"\
66 This utility detects the traces, fits polynomials on their edges \n\
67 (Upper and Lower) and in their centers (All), and stores these \n\
68 informations in the TRACE_WAVE file. \n\
69 Each trace is uniquely identified by its Order/TraceNb values. \n\
70 The Order values refer to the keywords indices (e.g. HIERARCH ESO INS \n\
71 WLEN CENY4) in the product headers. \n\
72 The TraceNb starts with 1, identifies traces within the same order. \n\
73 The additional columns : \n\
74 "CR2RES_COL_WAVELENGTH
" \n\
75 "CR2RES_COL_WAVELENGTH_ERROR
" \n\
76 "CR2RES_COL_SLIT_CURV_A
" \n\
77 "CR2RES_COL_SLIT_CURV_B
" \n\
78 "CR2RES_COL_SLIT_CURV_C
" \n\
79 "CR2RES_COL_SLIT_FRACTION
" \n\
80 are filled with default values. \n\
83 raw.fits " CR2RES_FLAT_RAW
" [1 to n] \n\
84 or " CR2RES_UTIL_CALIB_PROCATG
" \n\
87 <input_name>_tw.fits " CR2RES_UTIL_TRACE_TW_PROCATG
" \n\
90 loop on input raw frames f: \n\
91 loop on detectors d: \n\
92 Use cr2res_trace(--degree, --min_cluster, --smooth, --opening) \n\
93 to measure the traces \n\
94 if --split_traces, call cr2res_trace_split_traces() to split \n\
96 Use cr2res_trace_add_extra_columns() to add the additional \n\
97 columns (slit fraction, wl, slit curvature) \n\
98 Save the trace wave table \n\
100 Library functions used \n\
101 cr2res_io_load_image() \n\
103 cr2res_trace_add_extra_columns() \n\
104 cr2res_trace_split_traces() \n\
105 cr2res_io_save_TRACE_WAVE() \n\
123int cpl_plugin_get_info(cpl_pluginlist * list)
125 cpl_recipe * recipe = cpl_calloc(1,
sizeof *recipe );
126 cpl_plugin * plugin = &recipe->interface;
128 if (cpl_plugin_init(plugin,
130 CR2RES_BINARY_VERSION,
131 CPL_PLUGIN_TYPE_RECIPE,
134 cr2res_util_trace_description,
135 CR2RES_PIPELINE_AUTHORS,
138 cr2res_util_trace_create,
139 cr2res_util_trace_exec,
140 cr2res_util_trace_destroy)) {
141 cpl_msg_error(cpl_func,
"Plugin initialization failed");
142 (void)cpl_error_set_where(cpl_func);
146 if (cpl_pluginlist_append(list, plugin)) {
147 cpl_msg_error(cpl_func,
"Error adding plugin to list");
148 (void)cpl_error_set_where(cpl_func);
163static int cr2res_util_trace_create(cpl_plugin * plugin)
169 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
170 recipe = (cpl_recipe *)plugin;
175 recipe->parameters = cpl_parameterlist_new();
178 p = cpl_parameter_new_value(
"cr2res.cr2res_util_trace.degree",
179 CPL_TYPE_INT,
"polynomial degree for the fit to the orders",
180 "cr2res.cr2res_util_trace", 2);
181 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"degree");
182 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
183 cpl_parameterlist_append(recipe->parameters, p);
185 p = cpl_parameter_new_value(
"cr2res.cr2res_util_trace.min_cluster",
186 CPL_TYPE_INT,
"size in pixels of the smallest allowed cluster",
187 "cr2res.cr2res_util_trace", 200000);
188 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"min_cluster");
189 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
190 cpl_parameterlist_append(recipe->parameters, p);
192 p = cpl_parameter_new_value(
"cr2res.cr2res_util_trace.smooth_x",
193 CPL_TYPE_INT,
"Length of the smoothing kernel in x",
194 "cr2res.cr2res_util_trace", 111);
195 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"smooth_x");
196 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
197 cpl_parameterlist_append(recipe->parameters, p);
199 p = cpl_parameter_new_value(
"cr2res.cr2res_util_trace.smooth_y",
200 CPL_TYPE_INT,
"Length of the smoothing kernel in y",
201 "cr2res.cr2res_util_trace", 401);
202 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"smooth_y");
203 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
204 cpl_parameterlist_append(recipe->parameters, p);
206 p = cpl_parameter_new_value(
"cr2res.cr2res_util_trace.threshold",
207 CPL_TYPE_DOUBLE,
"Detection Threshold",
208 "cr2res.cr2res_util_trace", 3.0);
209 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"threshold");
210 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
211 cpl_parameterlist_append(recipe->parameters, p);
222 p = cpl_parameter_new_value(
"cr2res.cr2res_util_trace.opening",
223 CPL_TYPE_BOOL,
"Use a morphological opening to rejoin clusters",
224 "cr2res.cr2res_util_trace", TRUE);
225 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"opening");
226 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
227 cpl_parameterlist_append(recipe->parameters, p);
229 p = cpl_parameter_new_value(
"cr2res.cr2res_util_trace.split_traces",
230 CPL_TYPE_INT,
"Split the full slit traces",
231 "cr2res.cr2res_util_trace", 0);
232 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"split_traces");
233 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
234 cpl_parameterlist_append(recipe->parameters, p);
236 p = cpl_parameter_new_value(
"cr2res.cr2res_util_trace.detector",
237 CPL_TYPE_INT,
"Only reduce the specified detector",
238 "cr2res.cr2res_util_trace", 0);
239 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"detector");
240 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
241 cpl_parameterlist_append(recipe->parameters, p);
253static int cr2res_util_trace_exec(cpl_plugin * plugin)
258 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
259 recipe = (cpl_recipe *)plugin;
262 return cr2res_util_trace(recipe->frames, recipe->parameters);
272static int cr2res_util_trace_destroy(cpl_plugin * plugin)
277 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
278 recipe = (cpl_recipe *)plugin;
281 cpl_parameterlist_delete(recipe->parameters);
293static int cr2res_util_trace(
294 cpl_frameset * frameset,
295 const cpl_parameterlist * parlist)
297 const cpl_parameter * param;
298 int min_cluster, degree, opening, reduce_det,
299 split_traces, smooth_x, smooth_y, trace_filter ;
301 cpl_frameset * rawframes ;
302 cpl_frameset * cur_fset ;
304 hdrl_image * flat_ima ;
305 cpl_image * debug_ima ;
306 int det_nr, zp_order ;
307 cpl_propertylist * plist ;
308 cpl_table * filtered_traces ;
310 cpl_table * traces_tmp ;
311 cpl_table * traces[CR2RES_NB_DETECTORS] ;
312 cpl_propertylist * ext_plist[CR2RES_NB_DETECTORS] ;
316 param = cpl_parameterlist_find_const(parlist,
317 "cr2res.cr2res_util_trace.min_cluster");
318 min_cluster = cpl_parameter_get_int(param);
319 param = cpl_parameterlist_find_const(parlist,
320 "cr2res.cr2res_util_trace.degree");
321 degree = cpl_parameter_get_int(param);
322 param = cpl_parameterlist_find_const(parlist,
323 "cr2res.cr2res_util_trace.smooth_x");
324 smooth_x = cpl_parameter_get_int(param);
325 param = cpl_parameterlist_find_const(parlist,
326 "cr2res.cr2res_util_trace.smooth_y");
327 smooth_y = cpl_parameter_get_int(param);
328 param = cpl_parameterlist_find_const(parlist,
329 "cr2res.cr2res_util_trace.threshold");
330 threshold = cpl_parameter_get_double(param);
331 param = cpl_parameterlist_find_const(parlist,
332 "cr2res.cr2res_util_trace.opening");
333 opening = cpl_parameter_get_bool(param);
340 param = cpl_parameterlist_find_const(parlist,
341 "cr2res.cr2res_util_trace.split_traces");
342 split_traces = cpl_parameter_get_int(param);
343 param = cpl_parameterlist_find_const(parlist,
344 "cr2res.cr2res_util_trace.detector");
345 reduce_det = cpl_parameter_get_int(param);
351 cpl_msg_error(__func__,
"Cannot identify RAW and CALIB frames") ;
352 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
359 rawframes = cr2res_util_trace_find_RAW(frameset) ;
360 if (rawframes==NULL || cpl_frameset_get_size(rawframes) <= 0) {
361 cpl_msg_error(__func__,
"Cannot find any RAW file") ;
362 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND) ;
367 for (i = 0; i < cpl_frameset_get_size(rawframes); i++) {
368 const cpl_frame *cur_frame;
369 const char *cur_fname;
371 cur_frame = cpl_frameset_get_position(rawframes, i) ;
372 cur_fname = cpl_frame_get_filename(cur_frame) ;
373 cpl_msg_info(__func__,
"Reduce Frame %s", cur_fname) ;
374 cpl_msg_indent_more() ;
377 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
380 traces[det_nr-1] = NULL ;
383 ext_plist[det_nr-1] = cpl_propertylist_load(cur_fname,
387 if (reduce_det != 0 && det_nr != reduce_det) continue ;
389 cpl_msg_info(__func__,
"Process detector number %d", det_nr) ;
390 cpl_msg_indent_more() ;
393 cpl_msg_info(__func__,
"Load the Image") ;
395 cpl_msg_warning(__func__,
396 "Cannot load the image - skip detector");
398 cpl_msg_indent_less() ;
403 cpl_msg_info(__func__,
"Compute the traces") ;
404 cpl_msg_indent_more() ;
406 smooth_x, smooth_y, threshold, opening, degree,
407 min_cluster)) == NULL) {
408 cpl_msg_warning(__func__,
409 "Cannot compute trace - skip detector");
412 cpl_msg_indent_less() ;
413 cpl_msg_indent_less() ;
416 cpl_msg_indent_less() ;
420 cur_fname, det_nr) != 0) {
421 cpl_msg_warning(__func__,
422 "Cannot complete the trace table - skip detector");
425 cpl_table_delete(traces[det_nr-1]) ;
426 traces[det_nr-1] = NULL ;
427 cpl_msg_indent_less() ;
433 cpl_msg_info(__func__,
"Filter out the traces") ;
434 cpl_msg_indent_more() ;
437 plist = cpl_propertylist_load(cur_fname, 0) ;
439 zp_order = cr2res_pfits_get_order_zp(plist) ;
440 cpl_propertylist_delete(plist) ;
442 setting_id, zp_order) ;
443 cpl_free(setting_id) ;
444 cpl_table_delete(traces[det_nr-1]) ;
445 traces[det_nr-1] = filtered_traces ;
446 cpl_msg_indent_less() ;
447 if (cpl_table_get_nrow(traces[det_nr-1]) == 0) {
448 cpl_msg_error(__func__,
"All traces are filtered out") ;
450 cpl_table_delete(traces[det_nr-1]) ;
451 traces[det_nr-1] = NULL ;
452 cpl_msg_indent_less() ;
459 cpl_msg_info(__func__,
460 "Split the full slit traces in %d traces",
464 split_traces)) == NULL) {
465 cpl_msg_warning(__func__,
466 "Failed splitting the traces - skip detector") ;
469 cpl_table_delete(traces[det_nr-1]) ;
470 traces[det_nr-1] = NULL ;
471 cpl_msg_indent_less() ;
474 cpl_table_delete(traces[det_nr-1]) ;
475 traces[det_nr-1] = traces_tmp ;
481 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
485 out_file = cpl_sprintf(
"debug_%s_trace_map_%d.fits",
488 cpl_image_save(debug_ima, out_file, CPL_BPP_IEEE_DOUBLE, NULL,
491 cpl_image_delete(debug_ima) ;
494 cpl_msg_indent_less() ;
496 cpl_msg_indent_less() ;
499 out_file = cpl_sprintf(
"%s_tw.fits",
501 cur_fset = cpl_frameset_new() ;
502 cpl_frameset_insert(cur_fset, cpl_frame_duplicate(cur_frame)) ;
504 NULL, ext_plist, CR2RES_UTIL_TRACE_TW_PROCATG, RECIPE_STRING);
505 cpl_frameset_delete(cur_fset) ;
509 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
510 if (ext_plist[det_nr-1] != NULL)
511 cpl_propertylist_delete(ext_plist[det_nr-1]) ;
512 if (traces[det_nr-1] != NULL)
513 cpl_table_delete(traces[det_nr-1]) ;
516 cpl_frameset_delete(rawframes) ;
517 return (
int)cpl_error_get_code();
529static cpl_frameset * cr2res_util_trace_find_RAW(
const cpl_frameset * in)
534 if (in == NULL)
return NULL ;
cpl_error_code cr2res_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
int cr2res_io_save_TRACE_WAVE(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, cpl_table **tables, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a TRACE_WAVE.
int cr2res_io_get_ext_idx(const char *filename, int detector, int data)
Get the wished extension number for a detector.
hdrl_image * cr2res_io_load_image(const char *in, int detector)
Load an hdrl image from a image file.
const char * cr2res_pfits_get_wlen_id(const cpl_propertylist *plist)
find out the Setting
cpl_table * cr2res_trace_filter(const cpl_table *tw, const char *setting, int zp_order)
Only keep the predefined orders of the setting.
cpl_image * cr2res_trace_gen_image(cpl_table *trace, int nx, int ny)
Make an image out of the trace solution.
cpl_table * cr2res_trace_split(cpl_table *trace_wave, int order_idx, int nb_subtraces)
Splits full slit traces into several sub traces.
cpl_table * cr2res_trace(cpl_image *ima, int smooth_x, int smooth_y, double threshold, int opening, int degree, int min_cluster)
Main function for running all parts of the trace algorithm.
int cr2res_trace_add_extra_columns(cpl_table *traces, const char *infile, int det_nr)
Add extra columns to the plain trace table.
char * cr2res_get_root_name(const char *filename)
Find out the root part of a basename (name without extension).
cpl_frameset * cr2res_extract_frameset(const cpl_frameset *in, const char *tag)
Extract the frames with the given tag from a frameset.
char * cr2res_get_base_name(const char *filename)
Find out the base name of a file (i.e. without prefix path)
const char * cr2res_get_license(void)
Get the pipeline copyright and license.
cpl_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
cpl_size hdrl_image_get_size_x(const hdrl_image *self)
return size of X dimension of image
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image