37#include "eris_utils.h"
38#include "eris_nix_utils.h"
39#include "eris_nix_wavecal_utils.h"
40#include "eris_pfits.h"
42#include "eris_nix_dfs.h"
43#include "eris_nix_master_bpm.h"
44#include "eris_nix_master_dark.h"
45#include "eris_nix_gain_linearity.h"
54static const char eris_nix_wave_lamp_description[] =
55"This recipe reduces a set of WAVE_LAMP_ON/WAVE_LAMP_OFF frame pairs to \n"
59"- a series of tagged WAVE_LAMP_ON / WAVE_LAMP_OFF frame pairs.\n"
60"- a tagged DETMON coefficients cube file, e.g.\n"
61"-- detmon_ir_lg_coeffs_cube.fits "ERIS_NIX_COEFFS_CUBE_PRO_CATG
"\n"
62"- a tagged MASTER_DARK for matching detector configuration.\n"
63"The output will be a fits file containing:\n"
67#define RECIPE_NAME "eris.eris_nix_wave_lamp"
73cpl_recipe_define(eris_nix_wave_lamp, ERIS_BINARY_VERSION,
"John Lightfoot",
74 PACKAGE_BUGREPORT,
"2017",
75 "Calculate a MASTER_WAVE",
76 eris_nix_wave_lamp_description);
92static cpl_error_code eris_nix_wave_lamp_fill_parameterlist(
93 cpl_parameterlist *self) {
95 if (cpl_error_get_code() != CPL_ERROR_NONE)
return cpl_error_get_code();
100 cpl_parameter * p = NULL;
101 p = cpl_parameter_new_value(RECIPE_NAME
".saturation_threshold",
102 CPL_TYPE_DOUBLE,
"frame saturation threshold", RECIPE_NAME, 5000.0);
103 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"saturation_threshold");
104 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
105 cpl_parameterlist_append(self, p);
121static int eris_nix_wave_lamp(cpl_frameset * frameset,
122 const cpl_parameterlist * parlist) {
124 cpl_image * contrib = NULL;
125 hdrl_imagelist * diff_himlist = NULL;
126 const gain_linearity * gain_lin = NULL;
127 cpl_vector * lambda_pos =NULL;
128 cpl_matrix * line_pos = NULL;
129 master_bpm * master_bpm = NULL;
130 master_dark * master_dark = NULL;
131 master_flat * master_flat_hifreq = NULL;
132 hdrl_image * master_wave = NULL;
133 mef_extension_list * mefs = NULL;
134 cpl_table * mef_table = NULL;
135 cpl_table * mef_table2 = NULL;
136 located_imagelist * off_limlist = NULL;
137 cpl_mask * old_mask = NULL;
138 located_imagelist * on_limlist = NULL;
139 cpl_frameset * used_frameset = NULL;
140 cpl_image * wave_cal_image = NULL;
141 cpl_propertylist * wave_plist = NULL;
143 enu_check_error_code(
"%s():%d: An error is already set: %s",
144 cpl_func, __LINE__, cpl_error_get_where());
148 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
149 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
153 cpl_msg_set_level_from_env();
154 cpl_msg_severity severity = cpl_msg_get_level();
155 cpl_msg_info(cpl_func,
"level %d", (
int) severity);
157 cpl_msg_info(cpl_func,
"fill_rejected parameter hardwired to True");
158 int fill_rejected = CPL_TRUE;
160 cpl_size x_probe = 1024;
161 cpl_size y_probe = 1024;
163 enu_check_error_code(
"Could not retrieve input parameters");
168 enu_check_error_code(
"Could not identify RAW and CALIB frames");
170 used_frameset = cpl_frameset_new();
174 gain_lin = engl_gain_linearity_load_from_frameset(frameset,
175 ERIS_NIX_GAIN_PRO_CATG, ERIS_NIX_COEFFS_CUBE_PRO_CATG,
176 ERIS_NIX_NL_BPM_PRO_CATG, CPL_FALSE, used_frameset);
177 enu_check_error_code(
"error trying to read gain/linearity information");
183 ERIS_NIX_MASTER_DARK_IMG_PRO_CATG, used_frameset);
184 enu_check_error_code(
"failed to read master dark from SoF");
189 master_bpm = en_master_bpm_load_from_frameset(frameset,
190 ERIS_NIX_MASTER_BPM_SKY_PRO_CATG, used_frameset, CPL_TRUE);
191 enu_check_error_code(
"failed to read master BPM from SoF");
192 master_flat_hifreq = en_master_flat_load_from_frameset(
193 frameset, ERIS_NIX_MASTER_FLAT_LSS_HIFREQ_PRO_CATG,
194 used_frameset, CPL_FALSE);
195 enu_check_error_code(
"failed to read master FLAT from SoF");
200 ERIS_NIX_RAW_WAVE_LAMP_ON_DO_CATG, used_frameset);
202 ERIS_NIX_RAW_WAVE_LAMP_OFF_DO_CATG, used_frameset);
204 enu_check(on_limlist->size > 0, CPL_ERROR_ILLEGAL_INPUT,
205 "SoF contains no WAVE_LAMP_ON data");
206 enu_check(on_limlist->size == off_limlist->size, CPL_ERROR_ILLEGAL_INPUT,
207 "SoF does not contain WAVE_LAMP_ON/WAVE_LAMP_OFF pairs");
212 cpl_msg_info(cpl_func,
"calculating lamp_on - lamp_off");
213 int flag_all_errors = ~(int)0;
215 NULL, master_bpm, flag_all_errors, fill_rejected,
218 NULL, master_bpm, flag_all_errors, fill_rejected,
220 enu_check_error_code(
"error performing basic calibration of frames");
224 for (
int on = 0; on < on_limlist->size; on++) {
226 off_limlist->limages[on]->himage);
229 limages[on]->himage),
243 cpl_size nlines = 12;
244 cpl_vector * line_guess_pos = cpl_vector_new(nlines);
245 cpl_vector * line_lambda = cpl_vector_new(nlines);
246 cpl_vector_set(line_guess_pos, 0, (
double) 71);
247 cpl_vector_set(line_lambda, 0, 20621.9);
248 cpl_vector_set(line_guess_pos, 1, (
double) 95);
249 cpl_vector_set(line_lambda, 1, 20740.0);
250 cpl_vector_set(line_guess_pos, 2, (
double) 112);
251 cpl_vector_set(line_lambda, 2, 20816.7);
252 cpl_vector_set(line_guess_pos, 3, (
double) 148);
253 cpl_vector_set(line_lambda, 3, 20991.8);
254 cpl_vector_set(line_guess_pos, 4, (
double) 220);
255 cpl_vector_set(line_lambda, 4, 21338.7);
256 cpl_vector_set(line_guess_pos, 5, (
double) 260);
257 cpl_vector_set(line_lambda, 5, 21540.1);
258 cpl_vector_set(line_guess_pos, 6, (
double) 363);
259 cpl_vector_set(line_lambda, 6, 22045.6);
260 cpl_vector_set(line_guess_pos, 7, (
double) 371);
261 cpl_vector_set(line_lambda, 7, 22083.2);
262 cpl_vector_set(line_guess_pos, 8, (
double) 583);
263 cpl_vector_set(line_lambda, 8, 23139.5);
264 cpl_vector_set(line_guess_pos, 9, (
double) 724);
265 cpl_vector_set(line_lambda, 9, 23851.5);
266 cpl_vector_set(line_guess_pos, 10, (
double) 748);
267 cpl_vector_set(line_lambda, 10, 23973.1);
268 cpl_vector_set(line_guess_pos, 11, (
double) 975);
269 cpl_vector_set(line_lambda, 11, 25132.1);
273 const cpl_size wave_cal_x = nx / 2;
281 cpl_size nsamples = 0;
282 for (cpl_size line_id = 0; line_id < nlines; line_id++) {
283 for (cpl_size ix = 0; ix < nx; ix++) {
284 double val = cpl_matrix_get(line_pos, ix, line_id);
291 cpl_matrix * line_pos_fit = cpl_matrix_new(2, nsamples);
292 lambda_pos = cpl_vector_new(nsamples);
293 cpl_size isample = 0;
294 for (cpl_size line_id = 0; line_id < nlines; line_id++) {
295 for (cpl_size ix = 0; ix < nx; ix++) {
296 double val = cpl_matrix_get(line_pos, ix, line_id);
298 cpl_matrix_set(line_pos_fit, 0, isample, val);
299 cpl_matrix_set(line_pos_fit, 1, isample, (
double) ix);
300 cpl_vector_set(lambda_pos, isample,
301 cpl_vector_get(line_lambda, line_id));
307 cpl_polynomial * wave_cal = cpl_polynomial_new(2);
308 const cpl_size maxdeg2d[] = {4, 2};
309 cpl_polynomial_fit(wave_cal, line_pos_fit, NULL, lambda_pos, NULL,
310 CPL_TRUE, NULL, maxdeg2d);
311 cpl_msg_info(cpl_func,
"The wavelength calibration polynomial:");
312 cpl_polynomial_dump(wave_cal, stdout);
316 wave_cal_image = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
317 for (cpl_size iy = 1; iy < ny+1; iy++) {
318 for (cpl_size ix = 1; ix < nx+1; ix++) {
319 cpl_vector * pos = cpl_vector_new(2);
320 cpl_vector_set(pos, 0, (
double) iy);
321 cpl_vector_set(pos, 1, (
double) ix);
322 double val = cpl_polynomial_eval(wave_cal, pos);
323 cpl_image_set(wave_cal_image, ix, iy, val);
324 cpl_vector_delete(pos);
330 cpl_vector * wave_residual = cpl_vector_new(cpl_vector_get_size(
332 cpl_vector_fill_polynomial_fit_residual(wave_residual, lambda_pos,
333 NULL, wave_cal, line_pos_fit,
335 const double residual_mad = cpl_vector_get_median_const(wave_residual);
336 cpl_msg_info(cpl_func,
"MAD of residuals = %4.2f", residual_mad);
340 wave_plist = cpl_propertylist_new();
341 cpl_propertylist_append_string(wave_plist, CPL_DFS_PRO_CATG,
342 ERIS_NIX_MASTER_WAVE_PRO_CATG);
346 cpl_propertylist_append_double(wave_plist,
"ESO QC CAL RESID",
348 enu_check_error_code(
"error constructing output propertylist");
357 master_flat_hifreq->confidence), NULL);
362 mef_table = cpl_table_new(nsamples);
363 cpl_table_new_column(mef_table,
"x", CPL_TYPE_DOUBLE);
364 cpl_table_new_column(mef_table,
"ypos", CPL_TYPE_DOUBLE);
365 cpl_table_new_column(mef_table,
"line_lambda", CPL_TYPE_DOUBLE);
366 for (cpl_size isample = 0; isample < nsamples; isample++) {
367 cpl_table_set(mef_table,
"x", isample,
368 cpl_matrix_get(line_pos_fit, 1, isample));
369 cpl_table_set(mef_table,
"ypos", isample,
370 cpl_matrix_get(line_pos_fit, 0, isample));
371 cpl_table_set(mef_table,
"line_lambda", isample,
372 cpl_vector_get(lambda_pos, isample));
380 wave_cal_image), NULL);
385 mef_table2 = cpl_table_new(nsamples);
386 cpl_table_new_column(mef_table2,
"x", CPL_TYPE_DOUBLE);
387 cpl_table_new_column(mef_table2,
"ypos", CPL_TYPE_DOUBLE);
388 cpl_table_new_column(mef_table2,
"lambda_residual", CPL_TYPE_DOUBLE);
389 for (cpl_size isample = 0; isample < nsamples; isample++) {
390 cpl_table_set(mef_table2,
"x", isample,
391 cpl_matrix_get(line_pos_fit, 1, isample));
392 cpl_table_set(mef_table2,
"ypos", isample,
393 cpl_matrix_get(line_pos_fit, 0, isample));
394 cpl_table_set(mef_table2,
"lambda_residual", isample,
395 cpl_vector_get(wave_residual, isample));
400 on_limlist->limages[0]->frame, mefs,
401 RECIPE_NAME, wave_plist, PACKAGE
"/" PACKAGE_VERSION,
404 enu_check_error_code(
"Failed to save MASTER_WAVE");
407 cpl_image_delete(contrib);
409 engl_gain_linearity_delete((gain_linearity *) gain_lin);
410 cpl_matrix_delete(line_pos);
411 cpl_vector_delete(lambda_pos);
414 en_master_flat_delete(master_flat_hifreq);
416 cpl_table_delete(mef_table);
417 cpl_table_delete(mef_table2);
419 cpl_mask_delete(old_mask);
421 cpl_frameset_delete(used_frameset);
422 cpl_image_delete(wave_cal_image);
423 cpl_propertylist_delete(wave_plist);
425 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.
cpl_error_code enu_dfs_save_himage(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *provenance, const cpl_boolean prov_raw, const hdrl_image *image, const hdrl_imagelist *imagelist, const mef_extension_list *mefs, const char *recipe, const cpl_frame *inherit_frame, const cpl_propertylist *applist, const cpl_propertylist *wcs_plist, const char *pipe_id, const char *filename)
Save an hdrl_image/imagelist as a DFS-compliant MEF pipeline product.
void en_master_bpm_delete(master_bpm *target)
Delete a 'master_bpm' struct.
master_dark * en_master_dark_load_from_frameset(const cpl_frameset *frameset, const char *tag, cpl_frameset *used)
Load a 'master_dark' struct from a frameset.
void en_master_dark_delete(master_dark *target)
Delete a 'master_dark' struct.
void enu_located_imagelist_delete(located_imagelist *limlist)
Delete a located_imagelist and its contents.
mef_extension * enu_mef_new_image(const char *name, const cpl_image *data, const cpl_propertylist *plist)
Create a mef_extension to hold a cpl_image.
cpl_error_code enu_basic_calibrate(located_image *limage, const int read_offsets, const cpl_table *refine_wcs, const master_dark *mdark, const gain_linearity *gain_lin, const master_flat *flatfield_1, const master_flat *flatfield_2, const master_bpm *mbad_pix_map, const int flag_mask, const char *fill_rejected, const double fill_value, const cpl_size x_probe, const cpl_size y_probe)
Do basic calibration of located_image (single or cube)
mef_extension * enu_mef_new_table(const char *name, const cpl_table *table, const cpl_propertylist *plist)
Create a mef_extension struct holding a cpl_table.
mef_extension_list * enu_mef_extension_list_new(cpl_size size)
Construct a new mef_extension_list.
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.
void enu_mef_extension_list_delete(mef_extension_list *list)
Delete a mef_extension_list and its contents.
cpl_matrix * enwu_linepos_2d(const hdrl_image *spectrum2d, const cpl_size slice_index, const cpl_vector *guess_pos)
Fit the line peaks of a wave calibration spectrum.
cpl_error_code hdrl_image_sub_image(hdrl_image *self, const hdrl_image *other)
Subtract two images, store the result in the first image.
hdrl_image * hdrl_image_duplicate(const hdrl_image *himg)
copy hdrl_image
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_error_code hdrl_imagelist_set(hdrl_imagelist *himlist, hdrl_image *himg, cpl_size pos)
Insert an image into an imagelist.
void hdrl_imagelist_delete(hdrl_imagelist *himlist)
Free all memory used by a hdrl_imagelist object including the images.
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
cpl_error_code hdrl_imagelist_collapse(const hdrl_imagelist *himlist, const hdrl_parameter *param, hdrl_image **out, cpl_image **contrib)
collapsing of image list
hdrl_imagelist * hdrl_imagelist_new(void)
Create an empty imagelist.