35#include "eris_nix_lss_utils.h"
36#include "eris_nix_dfs.h"
37#include "eris_nix_utils.h"
67 if (cpl_error_get_code() != CPL_ERROR_NONE)
return cpl_error_get_code();
68 cpl_ensure_code(jitters, CPL_ERROR_NULL_INPUT);
70 cpl_msg_info(cpl_func,
"..dividing by slit response");
72 for (cpl_size j = 0; j < jitters->size; j++) {
76 cpl_image * bkg_copy = cpl_image_duplicate(
78 jitters->limages[j]->bkg));
79 cpl_image_reject_value(bkg_copy, CPL_VALUE_NOTFINITE);
85 cpl_image * bkg_collapse = cpl_image_collapse_median_create(bkg_copy,
91 double maxval = cpl_image_get_max(bkg_collapse);
92 cpl_mask_threshold_image(cpl_image_get_bpm(bkg_collapse),
97 cpl_image_fill_rejected(bkg_collapse, 0.0);
103 double medval = cpl_image_get_median(bkg_collapse);
104 cpl_image_divide_scalar(bkg_collapse, medval);
140 cpl_image_delete(bkg_collapse);
141 cpl_image_delete(bkg_copy);
144 return cpl_error_get_code();
158 cpl_image * response_1d) {
162 if (cpl_error_get_code() != CPL_ERROR_NONE)
return cpl_error_get_code();
163 cpl_ensure_code(himage_2d, CPL_ERROR_NULL_INPUT);
164 cpl_ensure_code(response_1d, CPL_ERROR_NULL_INPUT);
174 for (cpl_size i = 1; i <= nx; i++) {
176 double slit = cpl_image_get(response_1d, i, 1, &slit_ok);
177 for (cpl_size j = 1; j <= ny; j++) {
181 if (data_ok==0 && slit_ok==0) {
182 data.data = data.data / slit;
183 data.error = data.error / slit;
185 data = (hdrl_value) {0.0, 0.0};
195 return cpl_error_get_code();
242 const cpl_size slice_index,
243 const cpl_vector * guess_pos) {
245 cpl_matrix * line_pos = NULL;
246 cpl_vector * next_guess_pos = NULL;
247 cpl_vector * spectrum1d = NULL;
249 if (cpl_error_get_code() != CPL_ERROR_NONE)
return NULL;
251 cpl_ensure(spectrum2d, CPL_ERROR_NULL_INPUT, NULL);
252 cpl_ensure(guess_pos, CPL_ERROR_NULL_INPUT, NULL);
253 cpl_ensure(cpl_vector_get_size(guess_pos) > 0,
254 CPL_ERROR_ILLEGAL_INPUT, NULL);
256 cpl_size nlines = cpl_vector_get_size(guess_pos);
259 line_pos = cpl_matrix_new(nx, nlines);
260 cpl_matrix_fill(line_pos, NAN);
265 next_guess_pos = cpl_vector_duplicate(guess_pos);
267 for (cpl_size ix = slice_index; ix < nx; ix++) {
271 spectrum1d = cpl_vector_new_from_image_column(
274 for (cpl_size line_id=0; line_id < nlines; line_id++) {
275 double line_guess_pos = cpl_vector_get(next_guess_pos, line_id);
277 if (!isnan(fitted_pos)) {
283 cpl_matrix_set(line_pos, ix, line_id, fitted_pos);
284 cpl_vector_set(next_guess_pos, line_id, fitted_pos);
287 cpl_vector_delete(spectrum1d);
289 cpl_vector_delete(next_guess_pos);
293 next_guess_pos = cpl_vector_duplicate(guess_pos);
295 for (cpl_size ix = slice_index-1; ix >= 0; ix--) {
296 spectrum1d = cpl_vector_new_from_image_column(
299 for (cpl_size line_id=0; line_id < nlines; line_id++) {
300 double line_guess_pos = cpl_vector_get(next_guess_pos, line_id);
302 if (!isnan(fitted_pos)) {
303 cpl_matrix_set(line_pos, ix, line_id, fitted_pos);
304 cpl_vector_set(next_guess_pos, line_id, fitted_pos);
307 cpl_vector_delete(spectrum1d);
309 cpl_vector_delete(next_guess_pos);
313 if (cpl_error_get_code() != CPL_ERROR_NONE) {
314 cpl_matrix_delete(line_pos);
344 const double guess_pos,
345 const cpl_size half_width) {
347 if (cpl_error_get_code() != CPL_ERROR_NONE)
return NAN;
348 cpl_ensure(spectrum1d, CPL_ERROR_NULL_INPUT, NAN);
350 cpl_polynomial * line_fit = NULL;
353 cpl_size istart = (cpl_size) guess_pos - half_width;
354 cpl_size istop = (cpl_size) guess_pos + half_width;
355 cpl_size npos = istop - istart + 1;
359 cpl_matrix * pos_chunk = cpl_matrix_new(1, npos);
360 for (cpl_size i = 0; i < npos; i++) {
361 cpl_matrix_set(pos_chunk, 0, i, (
double) (i + istart));
367 cpl_vector * spectrum_chunk = cpl_vector_extract(spectrum1d,
369 const double * spectrum_chunk_data = cpl_vector_get_data_const(
372 for (cpl_size i = 0; i < npos; i++) {
374 spectrum_chunk_data[i] != 0.0 &&
375 !isnan(spectrum_chunk_data[i]);
381 line_fit = cpl_polynomial_new(1);
382 const cpl_size maxdeg1d = 2;
383 cpl_polynomial_fit(line_fit, pos_chunk, NULL, spectrum_chunk, NULL,
384 CPL_FALSE, NULL, &maxdeg1d);
391 double poly_b = cpl_polynomial_get_coeff(line_fit, &pow);
393 double poly_c = cpl_polynomial_get_coeff(line_fit, &pow);
394 result = -poly_b / (2.0 * poly_c);
400 if (fabs(result - guess_pos) > half_width) {
405 cpl_matrix_delete(pos_chunk);
406 cpl_vector_delete(spectrum_chunk);
407 cpl_polynomial_delete(line_fit);
409 if (cpl_error_get_code() != CPL_ERROR_NONE) {
433 const hdrl_image * image,
434 const cpl_image * confidence,
435 const cpl_size ntraces,
436 const cpl_polynomial * traces[ntraces],
437 const cpl_size nspectra,
438 const cpl_vector * spectra[nspectra],
439 const cpl_size nlines,
440 const cpl_polynomial * lines[nlines],
441 cpl_frameset * frameset,
442 const cpl_parameterlist * parlist,
443 const char * filename,
444 const char * recipe_name) {
448 if (cpl_error_get_code() != CPL_ERROR_NONE)
return cpl_error_get_code();
449 cpl_ensure_code(pro_catg, CPL_ERROR_NULL_INPUT);
450 cpl_ensure_code(image, CPL_ERROR_NULL_INPUT);
451 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
452 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
453 cpl_ensure_code(filename, CPL_ERROR_NULL_INPUT);
455 mef_extension_list * mefs = NULL;
456 cpl_propertylist * plist = NULL;
460 plist = cpl_propertylist_new();
461 cpl_propertylist_append_string(plist, CPL_DFS_PRO_CATG, pro_catg);
466 enu_check_error_code(
"error constructing output propertylist");
472 cpl_size nmefs = ntraces + nspectra + nlines + 1;
477 for (cpl_size i = 0; i < ntraces; i++) {
478 cpl_propertylist * mef_plist = cpl_propertylist_new();
479 cpl_propertylist_update_string(mef_plist,
"DIR",
"Y");
486 for (cpl_size i = 0; i < nspectra; i++) {
490 for (cpl_size i = 0; i < nlines; i++) {
491 cpl_propertylist * mef_plist = cpl_propertylist_new();
492 cpl_propertylist_update_string(mef_plist,
"DIR",
"X");
511 PACKAGE
"/" PACKAGE_VERSION,
516 cpl_propertylist_delete(plist);
518 return cpl_error_get_code();
539 if (cpl_error_get_code() != CPL_ERROR_NONE)
return NULL;
540 cpl_ensure(table, CPL_ERROR_NULL_INPUT, NULL);
544 cpl_polynomial * result = cpl_polynomial_new(2);
548 enu_check(cpl_table_has_column(table,
"1.dim.power"),
549 CPL_ERROR_ILLEGAL_INPUT,
550 "table does not have column '1.dim.power'");
551 enu_check(cpl_table_has_column(table,
"2.dim.power"),
552 CPL_ERROR_ILLEGAL_INPUT,
553 "table does not have column '2.dim.power'");
554 enu_check(cpl_table_has_column(table,
"coefficient"),
555 CPL_ERROR_ILLEGAL_INPUT,
556 "table does not have column 'coefficient'");
560 cpl_size nrow = cpl_table_get_nrow(table);
561 for (cpl_size row=0; row<nrow; row++) {
563 int pow1 = cpl_table_get_int(table,
"1.dim.power", row, &null1);
565 int pow2 = cpl_table_get_int(table,
"2.dim.power", row, &null2);
567 double coeff = cpl_table_get_double(table,
"coefficient", row,
569 enu_check(!(null1 || null2 || nullcoeff), CPL_ERROR_ILLEGAL_INPUT,
570 "table contains NULL values");
572 cpl_size pows[2] = {pow1, pow2};
573 cpl_polynomial_set_coeff(result, pows, coeff);
577 if (cpl_error_get_code() != CPL_ERROR_NONE) {
578 cpl_polynomial_delete(result);
601 if (cpl_error_get_code() != CPL_ERROR_NONE)
return NULL;
602 cpl_ensure(poly, CPL_ERROR_NULL_INPUT, NULL);
604 cpl_table * result = NULL;
608 const cpl_size dimension = cpl_polynomial_get_dimension(poly);
609 enu_check(dimension==1 || dimension==2, CPL_ERROR_ILLEGAL_INPUT,
610 "can only handle polynomial with dimension 1 or 2");
612 if (dimension == 1) {
614 const cpl_size degree = cpl_polynomial_get_degree(poly);
615 result = cpl_table_new(degree + 1);
619 cpl_table_new_column(result,
"1.dim.power", CPL_TYPE_INT);
620 cpl_table_new_column(result,
"coefficient", CPL_TYPE_DOUBLE);
623 for (cpl_size dim1_power=0; dim1_power<=degree; dim1_power++) {
624 double coeff = cpl_polynomial_get_coeff(poly, &dim1_power);
626 cpl_table_set_int(result,
"1.dim.power", nrows, dim1_power);
627 cpl_table_set_double(result,
"coefficient", nrows, coeff);
631 cpl_table_set_size(result, nrows);
633 }
else if (dimension == 2) {
635 const cpl_size degree = cpl_polynomial_get_degree(poly);
636 result = cpl_table_new((degree + 1) * (degree + 1));
640 cpl_table_new_column(result,
"1.dim.power", CPL_TYPE_INT);
641 cpl_table_new_column(result,
"2.dim.power", CPL_TYPE_INT);
642 cpl_table_new_column(result,
"coefficient", CPL_TYPE_DOUBLE);
645 for (
int dim2_power=0; dim2_power<=degree; dim2_power++) {
646 for (
int dim1_power=0; dim1_power<=degree; dim1_power++) {
647 cpl_size pows[2] = {dim1_power, dim2_power};
648 double coeff = cpl_polynomial_get_coeff(poly, pows);
650 cpl_table_set_int(result,
"1.dim.power", nrows, dim1_power);
651 cpl_table_set_int(result,
"2.dim.power", nrows, dim2_power);
652 cpl_table_set_double(result,
"coefficient", nrows, coeff);
657 cpl_table_set_size(result, nrows);
662 if (cpl_error_get_code() != CPL_ERROR_NONE) {
663 cpl_table_delete(result);
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.
cpl_error_code enlu_divide_slit_response_worker(hdrl_image *himage_2d, cpl_image *response_1d)
Worker function to divide a 2d image by a 1d response.
cpl_error_code enlu_divide_slit_response(located_imagelist *jitters)
Divide LSS 2d-spectra by the slit response.
double enlu_linepos_1d(const cpl_vector *spectrum1d, const double guess_pos, const cpl_size half_width)
Fit line peak.
cpl_table * enlu_warp_poly_save_to_table(const cpl_polynomial *poly)
Save an LSS polynomial to a cpl_table.
cpl_matrix * enlu_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_polynomial * enlu_warp_poly_load_from_table(const cpl_table *table)
Load a LSS warp polynomial from a cpl_table.
cpl_error_code enlu_trace_save(const char *pro_catg, const hdrl_image *image, const cpl_image *confidence, const cpl_size ntraces, const cpl_polynomial *traces[ntraces], const cpl_size nspectra, const cpl_vector *spectra[nspectra], const cpl_size nlines, const cpl_polynomial *lines[nlines], cpl_frameset *frameset, const cpl_parameterlist *parlist, const char *filename, const char *recipe_name)
Save a trace result.
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.
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.
mef_extension * enu_mef_new_vector(const char *name, const cpl_vector *vector, const cpl_propertylist *plist)
Create a mef_extension struct holding a cpl_vector.
void enu_mef_extension_list_delete(mef_extension_list *list)
Delete a mef_extension_list and its contents.
hdrl_value hdrl_image_get_pixel(const hdrl_image *self, cpl_size xpos, cpl_size ypos, int *pis_rejected)
get pixel values of hdrl_image
cpl_error_code hdrl_image_set_pixel(hdrl_image *self, cpl_size xpos, cpl_size ypos, hdrl_value value)
set pixel values of 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_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
cpl_error_code hdrl_image_reject(hdrl_image *self, cpl_size xpos, cpl_size ypos)
mark pixel as bad
const cpl_image * hdrl_image_get_image_const(const hdrl_image *himg)
get data as cpl image