39#include "casu_utils.h"
41#include "casu_stats.h"
43#include "eris_utils.h"
44#include "eris_nix_utils.h"
45#include "eris_pfits.h"
47#include "eris_nix_dfs.h"
48#include "eris_utils.h"
49#include "eris_nix_lss_utils.h"
58static const char eris_nix_lss_straighten_description[] =
59"This recipe uses a CPL warping routine to correct the wavelength and\n"
60"slit offset coordinates of the input ERIS/NIX long-slit spectra. The\n"
61"aim for the output spectra is to have slit offset along the horizontal\n"
62"axis and dispersion along the vertical.\n"
64"Areas of the detector not illuminated by the slit have their data and\n"
65"confidence values set to 0.\n"
69" DO CATG Explanation Req. #Frames\n"
70" ------- ----------- --- -------\n"
71" "ERIS_NIX_SKYSUB_OBJECT_LSS_JITTER_PRO_CATG
72 " sky-subtracted frames Y 1-n\n"
73" to be straightened.\n"
75" "ERIS_NIX_SKYSUB_STD_LSS_JITTER_PRO_CATG
76 " sky-subtracted Y 1-n\n"
79" "ERIS_NIX_MASTER_STARTRACE_PRO_CATG
80 " file containing the Y 1\n"
82" for correcting the\n"
87" DO CATG Explanation \n"
88" ------- ----------- \n"
89" "ERIS_NIX_CORRECTED_OBJECT_LSS_JITTER_PRO_CATG
90 " the straightened 2d-spectrum of the\n"
93" "ERIS_NIX_CORRECTED_STD_LSS_JITTER_PRO_CATG
94 " the straightened 2d-spectrum of the\n"
97" The output image will be in a FITS file named \n"
98" 'corrected.<first input filename>', with extensions:\n"
99" - DATA, with the corrected data.\n"
100" - ERR, with the corrected error plane.\n"
101" - DQ, with the corrected image quality\n"
102" - CONFIDENCE, with the corrected confidence plane.\n"
103" - BKG_DATA, with corrected background spectrum.\n"
104" - BKG_ERR, with the corrected background error plane.\n"
105" - BKG_CONF, with the corrected background confidence.\n"
107" Notes on the method.\n"
108" It is assumed that the jitter pattern moves the object up and\n"
109" down the slit-line. The reference position and the offset of\n"
110" each jitter from it are calculated as follows:\n"
111" 1/ The reference is jitter 0. Often this lies near the \n"
112" middle of the pattern and the object is manually \n"
113" positioned near the middle of the slit.\n"
114" 2/ Derive the slit-line PA (0 = N, increasing E) from the\n"
115" extrema of the jitter centres.\n"
116" 3/ Report how far each jitter pointing lies from the\n"
118" 4/ Estimate the offset of each jitter relative to the\n"
119" reference jitter along the slit-line.\n"
121" Correct the spectra to:\n"
122" Calibrate the wavelengths and straighten the spectrum by\n"
123" removing slit/dispersion curvature from the image.\n"
124" Shift spectra so that an object appears in the same column\n"
125" as it would in the reference jitter.\n"
127" This is done for each jitter by:\n"
128" 1/ Estimating the shift required to place the object in\n"
129" the same column as in the reference jitter.\n"
130" a/ Take a copy of the spectrum.\n"
131" b/ Apply the warp polynomials to straighten the copy.\n"
132" c/ Collapse the copy along the dispersion axis.\n"
133" d/ Find the position of the star.\n"
134" e/ Calculate the offset required to move the star to\n"
135" its position in the reference jitter.\n"
136" 2/ Modify the warp polynomials to apply the required shift\n"
137" with the straightening and wavelength calibration.\n"
138" 3/ Apply the shifted warp polynomials to:\n"
140" ..the error plane\n"
141" ..the background spectrum\n"
142" ..the confidence array\n"
144" Set the confidence to 0 outside the illuminated range\n"
145" of the shifted spectrum - to reduce edge effects when\n"
146" stacking them later.\n"
148" Save the straightened spectra. For each spectrum:\n"
149" 1/ Add FITS keywords to describe the WCS of the 2d\n"
151" 2/ Save the spectrum to FITS\n"
154 static cpl_polynomial * eris_nix_lss_shift_polynomial(
155 const cpl_polynomial * polynomial,
156 const double xshift);
159#define RECIPE_NAME "eris.eris_nix_lss_straighten"
165cpl_recipe_define(eris_nix_lss_straighten, ERIS_BINARY_VERSION,
167 PACKAGE_BUGREPORT,
"2017",
168 "Straighten and calibrate "
169 ERIS_NIX_SKYSUB_OBJECT_LSS_JITTER_PRO_CATG
171 eris_nix_lss_straighten_description);
187static cpl_error_code eris_nix_lss_straighten_fill_parameterlist(
188 cpl_parameterlist * self) {
190 if (cpl_error_get_code() != CPL_ERROR_NONE)
return cpl_error_get_code();
192 cpl_parameter * p = NULL;
194 p = cpl_parameter_new_value(RECIPE_NAME
".debug_data",
196 "write debugging data",
197 RECIPE_NAME, CPL_FALSE);
198 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"debug_data");
199 cpl_parameterlist_append(self, p);
222cpl_polynomial * eris_nix_lss_shift_polynomial(
223 const cpl_polynomial * polynomial,
224 const double xshift) {
226 if (cpl_error_get_code() != CPL_ERROR_NONE)
return NULL;
227 cpl_ensure(polynomial, CPL_ERROR_NULL_INPUT, NULL);
229 cpl_polynomial * result = cpl_polynomial_duplicate(polynomial);
231 cpl_size pows00[2] = {0, 0};
232 double coeff00 = cpl_polynomial_get_coeff(result, pows00);
233 cpl_size pows10[2] = {1, 0};
234 double coeff10 = cpl_polynomial_get_coeff(result, pows10);
235 cpl_size pows20[2] = {2, 0};
236 double coeff20 = cpl_polynomial_get_coeff(result, pows20);
238 cpl_size pows01[2] = {0, 1};
239 double coeff01 = cpl_polynomial_get_coeff(result, pows01);
240 cpl_size pows11[2] = {1, 1};
241 double coeff11 = cpl_polynomial_get_coeff(result, pows11);
242 cpl_size pows21[2] = {2, 1};
243 double coeff21 = cpl_polynomial_get_coeff(result, pows21);
245 cpl_size pows02[2] = {0, 2};
246 double coeff02 = cpl_polynomial_get_coeff(result, pows02);
247 cpl_size pows12[2] = {1, 2};
248 double coeff12 = cpl_polynomial_get_coeff(result, pows12);
249 cpl_size pows22[2] = {2, 2};
250 double coeff22 = cpl_polynomial_get_coeff(result, pows22);
252 double shift_coeff00 = coeff00 - coeff10 * xshift + coeff20 * pow(xshift,2);
253 cpl_polynomial_set_coeff(result, pows00, shift_coeff00);
254 double shift_coeff10 = coeff10 - coeff20 * 2.0 * xshift;
255 cpl_polynomial_set_coeff(result, pows10, shift_coeff10);
258 double shift_coeff01 = coeff01 - coeff11 * xshift + coeff21 * pow(xshift,2);
259 cpl_polynomial_set_coeff(result, pows01, shift_coeff01);
260 double shift_coeff11 = coeff11 - coeff21 * 2.0 * xshift;
261 cpl_polynomial_set_coeff(result, pows11, shift_coeff11);
264 double shift_coeff02 = coeff02 - coeff12 * xshift + coeff22 * pow(xshift,2);
265 cpl_polynomial_set_coeff(result, pows02, shift_coeff02);
266 double shift_coeff12 = coeff12 - coeff22 * 2.0 * xshift;
267 cpl_polynomial_set_coeff(result, pows12, shift_coeff12);
274 if (cpl_error_get_code() != CPL_ERROR_NONE) {
275 cpl_polynomial_delete(result);
291static int eris_nix_lss_straighten(cpl_frameset * frameset,
292 const cpl_parameterlist * parlist) {
294 cpl_vector * crval1_vector = NULL;
295 cpl_vector * crval2_vector = NULL;
296 located_imagelist * jitters = NULL;
297 cpl_table * jitter_table = NULL;
298 located_imagelist * object_jitters = NULL;
299 const char * out_catg = NULL;
300 const cpl_parameter * p = NULL;
301 cpl_vector * profile = NULL;
302 cpl_vector * slit_offset = NULL;
303 mef_extension_list * startrace_mefs = NULL;
304 cpl_propertylist * startrace_plist = NULL;
305 cpl_polynomial * startrace_poly_i = NULL;
306 cpl_polynomial * startrace_poly_j = NULL;
307 located_imagelist * std_jitters = NULL;
308 cpl_frameset * used = NULL;
310 enu_check_error_code(
"%s():%d: An error is already set: %s",
311 cpl_func, __LINE__, cpl_error_get_where());
315 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
316 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
320 cpl_msg_set_level_from_env();
321 cpl_msg_severity severity = cpl_msg_get_level();
322 cpl_msg_info(cpl_func,
"level %d", (
int) severity);
326 return CPL_ERROR_BAD_FILE_FORMAT;
331 p = cpl_parameterlist_find_const(parlist, RECIPE_NAME
".debug_data");
332 int debug_data = cpl_parameter_get_bool(p);
333 enu_check_error_code(
"Could not retrieve input parameters");
338 enu_check_error_code(
"Could not identify RAW and CALIB frames");
342 used = cpl_frameset_new();
344 ERIS_NIX_SKYSUB_OBJECT_LSS_JITTER_PRO_CATG, used);
346 ERIS_NIX_SKYSUB_STD_LSS_JITTER_PRO_CATG, used);
347 enu_check_error_code(
"Error loading frameset");
349 if (object_jitters->size > 0) {
350 enu_check(std_jitters->size == 0, CPL_ERROR_ILLEGAL_INPUT,
351 "SoF contains both object and std data");
352 jitters = object_jitters;
353 object_jitters = NULL;
354 out_catg = ERIS_NIX_CORRECTED_OBJECT_LSS_JITTER_PRO_CATG;
355 cpl_msg_info(cpl_func,
"Read in %d "
356 ERIS_NIX_SKYSUB_OBJECT_LSS_JITTER_PRO_CATG
"frames",
357 (
int)(jitters->size));
358 }
else if (std_jitters->size > 0) {
359 jitters = std_jitters;
361 out_catg = ERIS_NIX_CORRECTED_STD_LSS_JITTER_PRO_CATG;
362 cpl_msg_info(cpl_func,
"Read in %d "
363 ERIS_NIX_SKYSUB_STD_LSS_JITTER_PRO_CATG
"frames",
364 (
int)(jitters->size));
369 cpl_frameset_iterator * frameset_iter = cpl_frameset_iterator_new(frameset);
370 for (cpl_frame * frame = NULL;
371 (frame = cpl_frameset_iterator_get(frameset_iter)) &&
372 (cpl_error_get_code() == CPL_ERROR_NONE);
373 cpl_frameset_iterator_advance(frameset_iter, 1)) {
375 const char * tag = cpl_frame_get_tag(frame);
377 if (!strcmp(tag, ERIS_NIX_MASTER_STARTRACE_PRO_CATG)) {
378 const char * filename = cpl_frame_get_filename(frame);
381 cpl_msg_info(cpl_func,
"Read MASTER_STARTRACE %s", filename);
385 enu_check(startrace_mefs != NULL, CPL_ERROR_DATA_NOT_FOUND,
386 "SoF contains no "ERIS_NIX_MASTER_STARTRACE_PRO_CATG
394 cpl_msg_info(cpl_func,
"Finding centre of jitter pattern");
395 crval1_vector = cpl_vector_new(jitters->size);
396 crval2_vector = cpl_vector_new(jitters->size);
397 for (cpl_size i = 0; i < jitters->size; i++) {
398 double crval1 = cpl_propertylist_get_double(
399 jitters->limages[i]->plist,
401 cpl_vector_set(crval1_vector, i, crval1);
402 double crval2 = cpl_propertylist_get_double(
403 jitters->limages[i]->plist,
405 cpl_vector_set(crval2_vector, i, crval2);
406 cpl_msg_info(cpl_func,
"..jitter %d at RA=%10.7f Dec=%10.7f",
407 (
int)i, crval1, crval2);
410 cpl_size crval1_maxpos = cpl_vector_get_maxpos(crval1_vector);
411 double crval1_max = cpl_vector_get(crval1_vector, crval1_maxpos);
412 cpl_size crval1_minpos = cpl_vector_get_minpos(crval1_vector);
413 double crval1_min = cpl_vector_get(crval1_vector, crval1_minpos);
415 cpl_size crval2_maxpos = cpl_vector_get_maxpos(crval2_vector);
416 double crval2_max = cpl_vector_get(crval2_vector, crval2_maxpos);
417 cpl_size crval2_minpos = cpl_vector_get_minpos(crval2_vector);
418 double crval2_min = cpl_vector_get(crval2_vector, crval2_minpos);
422 double enda[2] = {0.0, 0.0};
423 double endb[2] = {0.0, 0.0};
424 if (fabs(crval1_max - crval1_min) > fabs(crval2_max - crval2_min)) {
425 enda[0] = crval1_min;
426 enda[1] = cpl_vector_get(crval2_vector, crval1_minpos);
427 endb[0] = crval1_max;
428 endb[1] = cpl_vector_get(crval2_vector, crval1_maxpos);
430 enda[0] = cpl_vector_get(crval1_vector, crval2_minpos);
431 enda[1] = crval2_min;
432 endb[0] = cpl_vector_get(crval1_vector, crval2_maxpos);
433 endb[1] = crval2_max;
435 cpl_msg_info(cpl_func,
"Jitter line end points (RA, DEC): "
436 "(%10.7f, %10.7f) and (%10.7f, %10.7f)",
437 enda[0], enda[1], endb[0], endb[1]);
439 double centre[2] = {0.0, 0.0};
445 centre[0] = cpl_vector_get(crval1_vector, 0);
446 centre[1] = cpl_vector_get(crval2_vector, 0);
455 cpl_msg_info(cpl_func,
"Jitter centre %f %f", centre[0], centre[1]);
456 double coslat = cos(centre[1] * CPL_MATH_PI / 180.0);
460 double slit_line[2] = {(endb[0]-enda[0]) * coslat, endb[1]-enda[1]};
461 double slit_norm = sqrt(pow(slit_line[0],2) + pow(slit_line[1],2));
462 slit_line[0] /= slit_norm;
463 slit_line[1] /= slit_norm;
464 double slit_pa = atan2(slit_line[0], slit_line[1]);
465 cpl_msg_info(cpl_func,
"..slit direction vector (long, lat) = (%f, %f)",
466 slit_line[0], slit_line[1]);
467 cpl_msg_info(cpl_func,
"..slit PA = %f deg", slit_pa * 180.0 / CPL_MATH_PI);
469 double cd1_1 = cpl_propertylist_get_double(jitters->limages[0]->
471 double cd2_1 = cpl_propertylist_get_double(jitters->limages[0]->
474 double pixsize = sqrt(cd1_1 * cd1_1 + cd2_1 * cd2_1);
475 cpl_msg_info(cpl_func,
"pixel size %f deg", pixsize);
479 slit_offset = cpl_vector_new(jitters->size);
480 for (cpl_size i = 0; i < jitters->size; i++) {
481 double offset = -1000.0;
483 if (fabs(slit_line[0]) > slit_line[1]) {
484 offset = (cpl_vector_get(crval1_vector, i) - centre[0]) *
485 coslat / slit_line[0];
487 offset = (cpl_vector_get(crval2_vector, i) - centre[1]) /
493 double distance[2] = {0.0,0.0};
494 distance[0] = ((cpl_vector_get(crval1_vector, i) - centre[0]) *
496 (offset * slit_line[0])) / pixsize;
497 distance[1] = ((cpl_vector_get(crval2_vector, i) - centre[1]) -
498 (offset * slit_line[1])) / pixsize;
502 cpl_msg_warning(cpl_func,
503 "...distance from jitter line (%f, %f) pixels",
504 distance[0], distance[1]);
506 cpl_vector_set(slit_offset, i, offset);
507 cpl_msg_info(cpl_func,
"..slit offset jitter %d %f deg",
514 cpl_vector * nominal_offset = cpl_vector_new(jitters->size);
515 for (cpl_size i = 0; i < jitters->size; i++) {
516 cpl_vector_set(nominal_offset, i,
517 cpl_vector_get(slit_offset, i) / pixsize);
519 cpl_msg_info(cpl_func,
"Nominal offset of each jitter from "
520 "reference (pixels):");
521 cpl_vector_dump(nominal_offset, NULL);
522 enu_check_error_code(
"Error calculating nominal slit offsets");
526 cpl_table * poly_table = cpl_table_duplicate(
527 (cpl_table *) startrace_mefs->mef[0]->data);
529 cpl_table_delete(poly_table);
531 poly_table = cpl_table_duplicate(
532 (cpl_table *) startrace_mefs->mef[1]->data);
534 cpl_table_delete(poly_table);
535 enu_check_error_code(
"Error reading warp polynomials");
545 profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES);
546 cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_LANCZOS,
547 CPL_KERNEL_DEF_WIDTH);
558 jitters->limages[0]->bkg));
559 cpl_image_warp_polynomial(bkg_copy,
561 jitters->limages[0]->bkg),
562 startrace_poly_i, startrace_poly_j,
563 profile, CPL_KERNEL_DEF_WIDTH,
564 profile, CPL_KERNEL_DEF_WIDTH);
565 cpl_image_reject_value(bkg_copy, CPL_VALUE_NOTFINITE);
567 cpl_image_save(bkg_copy,
"bkg_warped.fits", CPL_TYPE_UNSPECIFIED,
568 NULL, CPL_IO_CREATE);
572 cpl_image * bkg_collapse = cpl_image_collapse_median_create(
573 bkg_copy, 1, 600, 550);
574 cpl_vector * bkg_vector = cpl_vector_new_from_image_column(
576 cpl_vector_save(bkg_vector,
582 cpl_vector_delete(bkg_vector);
583 cpl_image_delete(bkg_collapse);
584 cpl_image_delete(bkg_copy);
589 double actual_offset_0 = 0.0;
591 for (cpl_size j = 0; j < jitters->size; j++) {
598 jitters->limages[j]->himage));
603 jitters->limages[j]->himage), copy_image,
604 startrace_poly_i, startrace_poly_j,
605 profile, CPL_KERNEL_DEF_WIDTH,
606 profile, CPL_KERNEL_DEF_WIDTH);
609 char* filename = cpl_sprintf(
"warp_%d.fits", (
int)j);
611 filename, CPL_TYPE_UNSPECIFIED, NULL,
620 cpl_size border = 100;
624 for(cpl_size jj=1; jj<= ny; jj++) {
625 for(cpl_size i=1; i <= border; i++) {
627 limages[j]->himage), i, jj);
630 for(cpl_size i=nx-border; i<= nx; i++) {
632 limages[j]->himage), i, jj);
637 cpl_image * collapse_image = cpl_image_collapse_create(
639 limages[j]->himage), 0);
640 cpl_vector * collapse = cpl_vector_new_from_image_row(
653 double guess = (double) cpl_vector_get_maxpos(collapse);
654 cpl_msg_debug(cpl_func,
"..maxpos %d", (
int)guess);
658 double nominal = cpl_vector_get(nominal_offset, j);
660 actual_offset_0 = actual_offset;
661 cpl_msg_info(cpl_func,
"..object in jitter 0 is at %f pixels",
664 cpl_msg_info(cpl_func,
"multiplying nominal offset by -1 as "
665 "increasing RA decreases detector column");
666 cpl_msg_info(cpl_func,
"..object slit offsets (nominal, "
668 -1.0 * nominal, actual_offset);
678 double xshift = (actual_offset_0 - actual_offset);
679 cpl_msg_info(cpl_func,
"..shift to place object at jitter 0 "
680 "position is %5.2f pixels",
683 cpl_polynomial * shifted_poly_i = eris_nix_lss_shift_polynomial(
684 startrace_poly_i, xshift);
685 cpl_polynomial * shifted_poly_j = eris_nix_lss_shift_polynomial(
686 startrace_poly_j, xshift);
691 jitters->limages[j]->himage), copy_image,
692 shifted_poly_i, shifted_poly_j,
693 profile, CPL_KERNEL_DEF_WIDTH,
694 profile, CPL_KERNEL_DEF_WIDTH);
695 cpl_image_delete(copy_image);
698 char* filename = cpl_sprintf(
"warp2_%d.fits", (
int)j);
700 filename, CPL_TYPE_UNSPECIFIED, NULL,
709 jitters->limages[j]->himage));
711 jitters->limages[j]->himage), copy_error,
712 shifted_poly_i, shifted_poly_j,
713 profile, CPL_KERNEL_DEF_WIDTH,
714 profile, CPL_KERNEL_DEF_WIDTH);
715 cpl_image_delete(copy_error);
720 jitters->limages[j]->bkg));
722 jitters->limages[j]->bkg), copy_bkg,
723 shifted_poly_i, shifted_poly_j,
724 profile, CPL_KERNEL_DEF_WIDTH,
725 profile, CPL_KERNEL_DEF_WIDTH);
726 cpl_image_delete(copy_bkg);
731 jitters->limages[j]->bkg));
733 jitters->limages[j]->bkg), copy_bkg_err,
734 shifted_poly_i, shifted_poly_j,
735 profile, CPL_KERNEL_DEF_WIDTH,
736 profile, CPL_KERNEL_DEF_WIDTH);
737 cpl_image_delete(copy_bkg_err);
741 cpl_image* copy_conf = cpl_image_duplicate(jitters->limages[j]->confidence);
742 cpl_image_warp_polynomial(jitters->limages[j]->confidence, copy_conf,
743 shifted_poly_i, shifted_poly_j,
744 profile, CPL_KERNEL_DEF_WIDTH,
745 profile, CPL_KERNEL_DEF_WIDTH);
746 cpl_image_delete(copy_conf);
750 cpl_polynomial_delete(shifted_poly_i);
751 cpl_polynomial_delete(shifted_poly_j);
752 enu_check_error_code(
"Error resampling data");
757 cpl_size left_edge = 593 + (cpl_size)xshift;
758 cpl_size right_edge = 1507 + (cpl_size)xshift;
762 if (ii > left_edge && ii < right_edge)
continue;
766 cpl_image_set(jitters->limages[j]->confidence, ii+1, jj+1,
769 (hdrl_value){0.0, 0.0});
774 enu_check_error_code(
"Error zeroing confidence outside "
780 for (cpl_size i = 0; i < jitters->size; i++) {
826 cpl_propertylist_update_int(jitters->limages[i]->plist,
"NAXIS", 3);
827 cpl_propertylist_update_string(jitters->limages[i]->plist,
"CTYPE1",
829 cpl_propertylist_update_string(jitters->limages[i]->plist,
"CTYPE2",
831 cpl_propertylist_update_string(jitters->limages[i]->plist,
"CTYPE3",
833 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CRPIX1",
835 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CRPIX2",
837 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CRPIX3",
839 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CRVAL1",
841 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CRVAL2",
843 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CRVAL3",
846 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CD1_1",
847 sin(slit_pa) * pixsize);
848 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CD1_2",
850 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CD1_3",
853 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CD2_1",
855 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CD2_2",
856 (4.107 - 3.045) / 2047);
857 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CD2_3",
860 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CD3_1",
861 cos(slit_pa) * pixsize);
862 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CD3_2",
864 cpl_propertylist_update_double(jitters->limages[i]->plist,
"CD3_3",
867 cpl_propertylist_update_string(jitters->limages[i]->plist,
"CUNIT1",
869 cpl_propertylist_update_string(jitters->limages[i]->plist,
"CUNIT2",
871 cpl_propertylist_update_string(jitters->limages[i]->plist,
"CUNIT3",
874 cpl_propertylist * applist = cpl_propertylist_new();
875 cpl_propertylist_update_string(applist, CPL_DFS_PRO_CATG, out_catg);
876 cpl_propertylist_update_string(applist,
"PRODCATG",
877 "ANCILLARY.2DSPECTRUM");
884 char* filename = cpl_sprintf(
"warp3_%d.fits", (
int)i);
886 filename, CPL_TYPE_UNSPECIFIED, NULL,
897 jitters->limages[i]->himagelist = NULL;
902 jitters->limages[i]->frame),
905 cpl_frameset * provenance = cpl_frameset_new();
906 cpl_frameset_insert(provenance, cpl_frame_duplicate(
907 jitters->limages[i]->frame));
909 cpl_msg_info(cpl_func,
"..writing %s", out_fname);
916 jitters->limages[i]->frame,
918 PACKAGE
"/" PACKAGE_VERSION,
922 cpl_frameset_delete(provenance);
923 cpl_propertylist_delete(applist);
927 cpl_vector_delete(crval1_vector);
928 cpl_vector_delete(crval2_vector);
930 cpl_table_delete(jitter_table);
932 cpl_vector_delete(profile);
933 cpl_vector_delete(slit_offset);
935 cpl_propertylist_delete(startrace_plist);
936 cpl_polynomial_delete(startrace_poly_i);
937 cpl_polynomial_delete(startrace_poly_j);
939 cpl_frameset_delete(used);
941 return (
int) cpl_error_get_code();
cpl_error_code enu_dfs_save_limage(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *provenance, const cpl_boolean prov_raw, const located_image *limage, const char *recipe, const cpl_frame *inherit, cpl_propertylist *applist, const char *pipe_id, const char *filename)
Save a located image structure to a MEF.
cpl_error_code eris_nix_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
double enlu_linepos_1d(const cpl_vector *spectrum1d, const double guess_pos, const cpl_size half_width)
Fit line peak.
cpl_polynomial * enlu_warp_poly_load_from_table(const cpl_table *table)
Load a LSS warp polynomial from a cpl_table.
void enu_located_imagelist_delete(located_imagelist *limlist)
Delete a located_imagelist and its contents.
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.
cpl_error_code enu_normalise_confidence(cpl_image *confidence)
Normalise confidence array so that mean of good pixels is 100.
char * enu_repreface(const char *filename, const char *preface)
Preface a raw filename with a string.
void enu_mef_extension_list_delete(mef_extension_list *list)
Delete a mef_extension_list and its contents.
mef_extension_list * enu_load_mef_components(const char *filename, cpl_propertylist **plist)
Load components of a multi-extension FITS file.
cpl_error_code eris_files_dont_exist(cpl_frameset *frameset)
Check if all SOF files exist.
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_image * hdrl_image_get_error(hdrl_image *himg)
get error as cpl 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
const cpl_image * hdrl_image_get_error_const(const hdrl_image *himg)
get error as cpl 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
cpl_error_code hdrl_imagelist_set(hdrl_imagelist *himlist, hdrl_image *himg, cpl_size pos)
Insert an image into an imagelist.
hdrl_imagelist * hdrl_imagelist_new(void)
Create an empty imagelist.