36 #include "naco_recipe.h"
38 #include "irplib_distortion.h"
41 #include "irplib_wlxcorr.h"
45 #include "irplib_polynomial.h"
46 #include "irplib_wavecal.h"
47 #include "irplib_distortion.h"
56 #define RECIPE_STRING "naco_spc_wavecal"
62 static cpl_error_code naco_spc_wavecal_reduce(cpl_imagelist *,
66 const irplib_framelist *,
69 const cpl_parameterlist *);
71 static cpl_error_code naco_spc_wavecal_get_slitw(
const cpl_propertylist *,
75 static cpl_error_code naco_spc_wavecal_1d(cpl_imagelist *
self,
76 cpl_propertylist * qclist,
77 const cpl_image * spec2d,
78 const cpl_propertylist * plist,
80 const cpl_polynomial * phdisp,
81 const cpl_bivector * argonlines,
82 const cpl_parameterlist* parlist);
85 cpl_error_code naco_image_fill_column_from_dispersion(cpl_image *,
int, cpl_boolean,
86 const cpl_polynomial *);
88 static cpl_error_code naco_spc_wavecal_distortion(cpl_image *,
90 const cpl_parameterlist *);
92 static cpl_error_code naco_spc_physdisp_fill(cpl_polynomial *,
const char *,
95 static cpl_error_code naco_spc_physdisp_transform(cpl_polynomial *,
double,
96 double,
int,
double,
double,
99 static cpl_error_code naco_spc_wavecal_qc(cpl_propertylist *,
101 const irplib_framelist *);
103 static cpl_error_code naco_spc_wavecal_save(cpl_frameset *,
104 const cpl_parameterlist *,
105 const cpl_propertylist *,
106 const cpl_propertylist *,
107 const cpl_imagelist *,
108 const cpl_polynomial *,
109 int,
const irplib_framelist *);
111 static cpl_error_code naco_spc_wavecal_fill_table(cpl_table *,
112 const cpl_polynomial *);
114 static cpl_error_code naco_spc_wavecal_count_lines(cpl_propertylist *,
115 const cpl_bivector *,
118 cpl_error_code naco_spc_wavecal_interpolate_rejected(cpl_image *,
119 const cpl_polynomial *);
121 static cpl_error_code naco_spc_wavecal_qc_lines(cpl_propertylist *,
123 const cpl_apertures *);
125 NACO_RECIPE_DEFINE(naco_spc_wavecal,
126 NACO_PARAM_PLOT | NACO_PARAM_FORCE,
127 "Wavelength calibration using arc lamps",
129 " -- NACO spectrocopy wavelength calibration from "
131 "The files listed in the Set Of Frames (sof-file) "
133 "NACO-raw-file.fits " NACO_SPC_LAMPWAVE_RAW
"\n"
134 "NACO-spectrum-model.fits " NACO_SPC_MODEL
" .\n"
136 NACO_SPC_MAN_MODESPLIT
"\n\n"
137 "Furthermore, each input frame must have a value of "
138 NACO_PFITS_BOOL_LAMP1
" that is false for off-frames and "
139 "true for on-frames.\n"
142 NACO_CALIB_ARC_MAP
": Primary HDU with the wavelength map, "
143 "i.e. the pixel values are wavelengths. The first extension "
144 "is a single-row table with the polynomial coefficients of "
145 "the 2D dispersion relation, lambda = P(x, y).\n"
146 NACO_CALIB_ARC_DIFF
": Primary HDU with the difference image "
147 "of the lamp-on and -off image. The first extension is the "
148 "distortion corrected image, were all the arc-lines are "
149 "straight. The dispersion in the distortion corrected image "
150 "is given by the central dispersion, lambda = P(512.5, y).");
171 static int naco_spc_wavecal(cpl_frameset * framelist,
172 const cpl_parameterlist * parlist)
174 cpl_errorstate cleanstate = cpl_errorstate_get();
175 irplib_framelist * allframes = NULL;
176 irplib_framelist * rawframes = NULL;
177 irplib_framelist * f_one = NULL;
178 const char ** taglist = NULL;
179 cpl_imagelist * lamp_wave = cpl_imagelist_new();
180 cpl_polynomial * disp2d = cpl_polynomial_new(2);
181 cpl_propertylist * qclist = cpl_propertylist_new();
182 cpl_propertylist * paflist = cpl_propertylist_new();
183 const cpl_frame * modelframe;
184 const char * modelfile;
185 cpl_table * modeltab = NULL;
186 const cpl_frame * argonframe;
187 const char * argonfile;
188 cpl_table * argontab = NULL;
189 cpl_bivector * argonlines= NULL;
190 cpl_vector * argonlinex= NULL;
191 cpl_vector * argonliney= NULL;
202 skip_if(allframes == NULL);
205 skip_if(rawframes == NULL);
210 modelframe = cpl_frameset_find_const(framelist, NACO_SPC_MODEL);
211 error_if (modelframe == NULL, CPL_ERROR_DATA_NOT_FOUND,
"No input frame "
212 "is tagged %s", NACO_SPC_MODEL);
214 modelfile = cpl_frame_get_filename(modelframe);
215 skip_if (modelfile == NULL);
217 modeltab = cpl_table_load(modelfile, 1, 0);
218 error_if (modeltab == NULL, cpl_error_get_code(),
"Could not "
219 "load the table with the model parameters");
222 argonframe = cpl_frameset_find_const(framelist, NACO_SPC_ARGON);
223 error_if (argonframe == NULL, CPL_ERROR_DATA_NOT_FOUND,
"No input frame "
224 "is tagged %s", NACO_SPC_ARGON);
226 argonfile = cpl_frame_get_filename(argonframe);
227 skip_if (argonfile == NULL);
229 argontab = cpl_table_load(argonfile, 1, 0);
230 error_if (argontab == NULL, cpl_error_get_code(),
"Could not "
231 "load the table with the argon lines");
234 nargonlines = cpl_table_get_nrow(argontab);
236 argonlinex = cpl_vector_wrap(nargonlines,
237 cpl_table_get_data_double(argontab,
239 skip_if(argonlinex == NULL);
241 argonliney = cpl_vector_wrap(nargonlines,
242 cpl_table_get_data_double(argontab,
243 NACO_SPC_LAB_INTENS));
244 skip_if(argonliney == NULL);
246 #ifdef NACO_SPC_WAVECAL_LOG
247 bug_if(cpl_vector_add_scalar(argonliney, 1.0));
248 skip_if(cpl_vector_logarithm(argonliney, exp(1.0)));
251 argonlines = cpl_bivector_wrap_vectors(argonlinex, argonliney);
252 bug_if(argonlines == NULL);
255 NACO_PFITS_REGEXP_SPCWAVE
"|"
256 NACO_PFITS_REGEXP_SPCWAVE_PAF
260 skip_if(taglist == NULL);
262 cpl_msg_info(cpl_func,
"Identified %d setting(s) in %d frames",
266 for (i=0 ; i < nsets ; i++) {
268 cpl_error_code error;
271 cpl_msg_info(cpl_func,
"Reducing data set %d of %d", i+1, nsets);
276 bug_if (f_one == NULL);
283 cpl_msg_info(cpl_func,
"Reducing frame set %d of %d (size=%d) with "
284 "setting: %s", i+1, nsets, n_one, taglist[i]);
286 error = naco_spc_wavecal_reduce(lamp_wave, disp2d, qclist, taglist[i],
287 f_one, modeltab, argonlines, parlist);
292 irplib_error_recover(cleanstate,
"Could not do the wavelength "
293 "calibration for this setting");
295 cpl_errorstate prestate = cpl_errorstate_get();
297 skip_if(naco_spc_wavecal_qc(qclist, paflist, f_one));
300 bug_if (cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
301 NACO_CALIB_ARC_MAP));
307 (void)naco_spc_wavecal_save(framelist, parlist, qclist, paflist,
308 lamp_wave, disp2d, i+1, f_one);
311 skip_if(!cpl_errorstate_is_equal(prestate));
314 cpl_image_delete(cpl_imagelist_unset(lamp_wave, 0));
315 }
while (cpl_imagelist_get_size(lamp_wave) > 0);
319 cpl_propertylist_empty(qclist);
320 cpl_propertylist_empty(paflist);
325 irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
326 "None of the %d sets could be reduced", nsets);
331 cpl_imagelist_delete(lamp_wave);
332 cpl_table_delete(modeltab);
333 cpl_bivector_unwrap_vectors(argonlines);
334 (void)cpl_vector_unwrap(argonlinex);
335 (void)cpl_vector_unwrap(argonliney);
336 cpl_table_delete(argontab);
340 cpl_propertylist_delete(qclist);
341 cpl_propertylist_delete(paflist);
342 cpl_polynomial_delete(disp2d);
344 return cpl_error_get_code();
361 static cpl_error_code naco_spc_wavecal_reduce(cpl_imagelist * imglist,
362 cpl_polynomial * disp2d,
363 cpl_propertylist * qclist,
365 const irplib_framelist * framelist,
366 const cpl_table * modeltab,
367 const cpl_bivector * argonlines,
368 const cpl_parameterlist * parlist)
370 cpl_image *
self = NULL;
371 cpl_image * corrected = NULL;
372 cpl_imagelist * difflist = cpl_imagelist_new();
373 cpl_polynomial * disp1d = NULL;
374 cpl_polynomial * collapse = cpl_polynomial_new(1);
377 const cpl_size deg0 = 0;
378 cpl_polynomial * phdisp = cpl_polynomial_new(1);
379 const cpl_propertylist * plist
381 const char * specmode
382 = irplib_pfits_get_string(plist, NACO_PFITS_STRING_SPECMODE);
384 = irplib_pfits_get_double(plist, NACO_PFITS_DOUBLE_CWLEN);
385 cpl_propertylist * lampkeys = cpl_propertylist_new();
386 cpl_stats * stats = NULL;
387 double adumin, adumax;
389 cpl_vector * center = cpl_vector_new(2);
393 bug_if (imglist == NULL);
394 bug_if (qclist == NULL);
395 bug_if (framelist == NULL);
396 bug_if (modeltab == NULL);
397 bug_if (argonlines == NULL);
398 bug_if (parlist == NULL);
399 bug_if (cpl_imagelist_get_size(imglist));
402 bug_if(cpl_propertylist_append_int(lampkeys, NACO_PFITS_BOOL_LAMP1, 1));
403 bug_if(cpl_propertylist_append_int(lampkeys, NACO_PFITS_INT_LAMP2, 0));
409 if (cpl_imagelist_get_size(difflist) > 1) {
410 cpl_msg_warning(cpl_func,
"Averaging %d difference images "
411 "into one image for setting %s",
412 (
int)cpl_imagelist_get_size(difflist), tag);
413 self = cpl_imagelist_collapse_create(difflist);
415 self = cpl_imagelist_unset(difflist, 0);
418 stats = cpl_stats_new_from_image(
self, CPL_STATS_MIN | CPL_STATS_MAX);
419 adumin = cpl_stats_get_min(stats);
420 adumax = cpl_stats_get_max(stats);
422 cpl_msg_info(cpl_func,
"Difference image for '%s' has ADUs in range: "
423 "%g -> %g", tag, adumin, adumax);
425 cpl_msg_info(cpl_func,
"Setting negative ADUs to zero");
426 bug_if(cpl_image_threshold(
self, 0.0, FLT_MAX, 0.0, FLT_MAX));
430 cpl_errorstate prestate = cpl_errorstate_get();
431 cpl_plot_image(
"",
"t 'Difference image'",
"",
self);
432 if (!cpl_errorstate_is_equal(prestate)) {
433 cpl_errorstate_set(prestate);
437 corrected = cpl_image_duplicate(
self);
438 skip_if(naco_spc_wavecal_distortion(corrected, qclist, parlist));
440 ny = cpl_image_get_size_y(
self);
444 skip_if(naco_spc_physdisp_fill(phdisp, specmode, modeltab));
446 cpl_msg_info(cpl_func,
"Wavelength range using physical model [micron]: "
448 cpl_polynomial_eval_1d(phdisp, 0.5, NULL),
449 cpl_polynomial_eval_1d(phdisp, 0.5 + ny, NULL));
453 const cpl_size idegree = 0;
455 = cpl_polynomial_eval_1d(phdisp, 0.5*(1+ny), NULL) - wlen;
457 = cpl_polynomial_get_coeff(phdisp, &idegree) - dwlen;
459 bug_if(cpl_polynomial_set_coeff(phdisp, &idegree, newval));
462 cpl_msg_info(cpl_func,
"Central Wavelength (model <=> CWLEN) [micron]: "
463 "%g <=> %g", cpl_polynomial_eval_1d(phdisp, 0.5*(1+ny), NULL),
467 skip_if(naco_spc_wavecal_1d(imglist, qclist,
self, plist, tag, phdisp,
468 argonlines, parlist));
471 cpl_imagelist_get(imglist, 0),
474 cpl_msg_info(cpl_func,
"2D-dispersion with MSE=%g for setting %s", mse, tag);
475 skip_if(cpl_polynomial_dump(disp2d, stdout));
477 skip_if(naco_spc_wavecal_interpolate_rejected(cpl_imagelist_get(imglist, 0),
480 bug_if(cpl_vector_set(center, 0, 0.5*(1+cpl_image_get_size_x(
self))));
481 bug_if(cpl_vector_set(center, 1, 0.5*(1+cpl_image_get_size_y(
self))));
483 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC WLEN",
484 cpl_polynomial_eval(disp2d, center)));
487 bug_if(cpl_polynomial_set_coeff(collapse, °0,
488 0.5 * (1+cpl_image_get_size_x(
self))));
490 disp1d = cpl_polynomial_extract(disp2d, 0, collapse);
491 cpl_msg_info(cpl_func,
"Central 1D-dispersion (at x=%g)",
492 0.5*(1+cpl_image_get_size_x(
self)));
493 skip_if(cpl_polynomial_dump(disp1d, stdout));
497 if (cpl_error_get_code()) {
498 cpl_image_delete(
self);
499 cpl_image_delete(corrected);
501 cpl_imagelist_set(imglist,
self, 1);
502 cpl_imagelist_set(imglist, corrected, 2);
505 cpl_vector_delete(center);
506 cpl_propertylist_delete(lampkeys);
507 cpl_imagelist_delete(difflist);
508 cpl_stats_delete(stats);
509 cpl_polynomial_delete(phdisp);
510 cpl_polynomial_delete(disp1d);
511 cpl_polynomial_delete(collapse);
513 return cpl_error_get_code();
531 static cpl_error_code naco_spc_wavecal_1d(cpl_imagelist *
self,
532 cpl_propertylist * qclist,
533 const cpl_image * spec2d,
534 const cpl_propertylist * plist,
536 const cpl_polynomial * phdisp,
537 const cpl_bivector * argonlines,
538 const cpl_parameterlist* parlist)
541 cpl_errorstate prestate = cpl_errorstate_get();
542 const int nx = cpl_image_get_size_x(spec2d);
543 const int ny = cpl_image_get_size_y(spec2d);
544 cpl_vector * vspec1d = NULL;
545 cpl_polynomial * disp = NULL;
546 cpl_polynomial * dispcen = NULL;
547 cpl_polynomial * phshift = cpl_polynomial_duplicate(phdisp);
548 cpl_polynomial * dispdif = cpl_polynomial_new(1);
551 = cpl_vector_wrap(cpl_bivector_get_size(argonlines),
552 cpl_calloc(cpl_bivector_get_size(argonlines),
555 const double wfwhm = 4.0;
557 double xc, xcmean, xcstdev;
560 const int plotstep = nplot > 0 ? nx / (1<<nplot) : nx + 1;
561 const int degree = cpl_polynomial_get_degree(phdisp);
562 const int fitdeg = degree > 4 ? degree : 4;
563 cpl_image * imgdisp = cpl_image_new(nx, ny, cpl_image_get_type(spec2d));
564 cpl_vector * vxcall = cpl_vector_new(nx);
567 const int hshiftmax = ny/4;
569 const double pixstep = 0.25;
570 const double pixtol = 1e-5;
571 const int istart = nx/2;
572 const int maxite = fitdeg * 100;
574 double wl2dmin = FLT_MAX;
575 double wl2dmax = 0.0;
576 cpl_boolean isfirst = CPL_TRUE;
579 bug_if(qclist == NULL);
580 bug_if(spec2d == NULL);
581 bug_if(plist == NULL);
582 bug_if(phdisp == NULL);
583 bug_if(argonlines == NULL);
586 skip_if(naco_spc_wavecal_get_slitw(plist, &slitw));
588 cpl_msg_info(cpl_func,
"Slitwidth [pixel]: %g", slitw);
590 xtrunc = 0.5 * slitw + 5.0 * wfwhm * CPL_MATH_SIG_FWHM;
592 memset(&model, 0,
sizeof(model));
595 model.xtrunc = xtrunc;
596 model.lines = argonlines;
597 model.linepix = linepix;
600 vspec1d = cpl_vector_new_from_image_column(spec2d, ispec);
601 #ifdef NACO_SPC_WAVECAL_LOG
602 bug_if(cpl_vector_add_scalar(vspec1d, 1.0));
603 skip_if(cpl_vector_logarithm(vspec1d, exp(1.0)));
607 char * title = cpl_sprintf(
"t 'Uncalibrated 1D-spectrum "
608 "using %s' w linespoints", tag);
609 cpl_vector * vphys = cpl_vector_new(ny);
610 cpl_bivector * bspec1d = cpl_bivector_wrap_vectors(vphys, vspec1d);
612 (void)cpl_vector_fill_polynomial(vphys, phdisp, 1.0, 1.0);
615 cpl_plot_bivector(
"set grid;set xlabel 'Wavelength [micron]';"
616 "set ylabel 'Intensity [ADU]';", title,
"",
619 cpl_vector_delete(vphys);
620 cpl_bivector_unwrap_vectors(bspec1d);
621 if (!cpl_errorstate_is_equal(prestate)) {
622 cpl_errorstate_set(prestate);
629 hshiftmax, nplot > 0,
637 bug_if(cpl_polynomial_subtract(dispdif, phshift, phdisp));
639 cpl_msg_info(cpl_func,
"Changes to model polynomial by XC is of degree %d",
640 (
int)cpl_polynomial_get_degree(dispdif));
641 skip_if(cpl_polynomial_dump(dispdif, stdout));
643 disp = cpl_polynomial_duplicate(phshift);
645 dispcen = cpl_polynomial_duplicate(disp);
648 for (; ispec <= nx; ispec++) {
649 const cpl_size prevcost = model.cost;
652 cpl_vector_delete(vspec1d);
653 vspec1d = cpl_vector_new_from_image_column(spec2d, ispec);
654 #ifdef NACO_SPC_WAVECAL_LOG
655 bug_if(cpl_vector_add_scalar(vspec1d, 1.0));
656 skip_if(cpl_vector_logarithm(vspec1d, exp(1.0)));
662 (disp, fitdeg, vspec1d, (
void *)&model,
665 irplib_error_recover(prestate,
"Could not calibrate column %d of "
667 cpl_polynomial_copy(disp, dispcen);
670 double wl2d = cpl_polynomial_eval_1d(disp, 0.5, NULL);
672 if (wl2d < wl2dmin) wl2dmin = wl2d;
674 wl2d = cpl_polynomial_eval_1d(disp, ny + 0.5, NULL);
675 if (wl2d > wl2dmax) wl2dmax = wl2d;
677 if (ispec % plotstep == 0) {
683 #ifdef IRPLIB_SPC_DUMP
685 if (ispec == istart) {
686 irplib_polynomial_tabulate(disp, vspec1d, (
void *)&model,
693 bug_if(cpl_vector_set(vxcall, ispec-1, xc));
695 cpl_msg_info(cpl_func,
"XC(%d): %g (cost=%u of %u)", ispec, xc,
696 (
unsigned)(model.cost-prevcost), (
unsigned)model.cost);
698 bug_if(naco_image_fill_column_from_dispersion(imgdisp, ispec, xc <= 0.0,
703 const double cwl = cpl_polynomial_eval_1d(disp, 0.5*ny + 0.5,
707 cpl_msg_info(cpl_func,
"Center of setting %s has range %g -> %g "
708 "-> %g [um], center dispersion %g [nm/pixel] and "
709 "dispersion (of degree %d):", tag,
710 cpl_polynomial_eval_1d(disp, 0.5, NULL),
712 cpl_polynomial_eval_1d(disp, ny + 0.5, NULL),
714 (
int)cpl_polynomial_get_degree(disp));
715 skip_if(cpl_polynomial_dump(disp, stdout));
717 cpl_polynomial_copy(dispcen, disp);
719 bug_if(cpl_polynomial_subtract(dispdif, disp, phshift));
721 cpl_msg_info(cpl_func,
"Changes to model polynomial by search is of"
722 " degree %d", (
int)cpl_polynomial_get_degree(dispdif));
723 skip_if(cpl_polynomial_dump(dispdif, stdout));
725 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC DISP XCORR",
731 cpl_polynomial_copy(disp, dispcen);
733 for (ispec = istart-1; ispec > 0; ispec--) {
734 const cpl_size prevcost = model.cost;
736 cpl_vector_delete(vspec1d);
737 vspec1d = cpl_vector_new_from_image_column(spec2d, ispec);
738 #ifdef NACO_SPC_WAVECAL_LOG
739 bug_if(cpl_vector_add_scalar(vspec1d, 1.0));
740 skip_if(cpl_vector_logarithm(vspec1d, exp(1.0)));
745 (disp, fitdeg, vspec1d, (
void *)&model,
747 if (ispec == 1 && wl2dmin >= wl2dmax) {
748 error_if (0, cpl_error_get_code(),
749 "None of the columns could be calibrated");
752 irplib_error_recover(prestate,
"Could not calibrate column %d of "
754 cpl_polynomial_copy(disp, dispcen);
756 double wl2d = cpl_polynomial_eval_1d(disp, 0.5, NULL);
758 if (wl2d < wl2dmin) wl2dmin = wl2d;
760 wl2d = cpl_polynomial_eval_1d(disp, ny + 0.5, NULL);
761 if (wl2d > wl2dmax) wl2dmax = wl2d;
763 if (ispec % plotstep == 0) {
771 bug_if(cpl_vector_set(vxcall, ispec-1, xc));
773 cpl_msg_info(cpl_func,
"XC(%d): %g (cost=%u of %u)", ispec, xc,
774 (
unsigned)(model.cost-prevcost), (
unsigned)model.cost);
776 bug_if(naco_image_fill_column_from_dispersion(imgdisp, ispec, xc <= 0.0,
781 cpl_plot_vector(
"set grid;",
"t 'XC over spatial range' w linespoints",
785 xcmean = cpl_vector_get_mean(vxcall);
786 xcstdev = cpl_vector_get_stdev(vxcall);
788 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC DISP XCORR MEAN",
790 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC DISP XCORR STDEV",
793 cpl_msg_info(cpl_func,
"Cross-correlation mean and stdev for setting %s: %g "
794 "%g", tag, xcmean, xcstdev);
795 cpl_msg_info(cpl_func,
"Total fitting cost: %u", (
unsigned)model.cost);
797 skip_if(naco_spc_wavecal_count_lines(qclist, argonlines, wl2dmin, wl2dmax));
801 if (cpl_error_get_code()) {
802 cpl_image_delete(imgdisp);
804 cpl_imagelist_set(
self, imgdisp, 0);
807 cpl_vector_delete(linepix);
808 cpl_vector_delete(vxcall);
809 cpl_polynomial_delete(dispdif);
810 cpl_polynomial_delete(disp);
811 cpl_polynomial_delete(dispcen);
812 cpl_polynomial_delete(phshift);
813 cpl_vector_delete(vspec1d);
815 return cpl_error_get_code();
829 static cpl_error_code naco_spc_physdisp_fill(cpl_polynomial *
self,
831 const cpl_table * modeltab)
835 const int nrows = cpl_table_get_nrow(modeltab);
836 const char ** smode = cpl_table_get_data_string_const(modeltab,
839 bug_if(
self == NULL);
840 bug_if(mode == NULL);
841 bug_if(modeltab == NULL);
842 bug_if(cpl_polynomial_get_dimension(
self) != 1);
844 skip_if (smode == NULL);
846 for (imode = 0; imode < nrows; imode++) {
848 skip_if(smode[imode] == NULL);
850 if (!strcmp(mode, smode[imode]))
break;
853 error_if (imode == nrows, CPL_ERROR_UNSUPPORTED_MODE,
"Unsupported value "
854 "'%s' for " NACO_PFITS_STRING_SPECMODE, mode);
856 cpl_msg_info(cpl_func,
"Finding dispersion relation for spectrum mode "
857 "%d/%d: %s ", imode, nrows, mode);
859 skip_if(naco_spc_physdisp_transform
861 cpl_table_get_double(modeltab, NACO_SPC_LAB_XMIN, imode, NULL),
862 cpl_table_get_double(modeltab, NACO_SPC_LAB_XMAX, imode, NULL),
863 cpl_table_get_int (modeltab, NACO_SPC_LAB_ORDER, imode, NULL),
864 cpl_table_get_double(modeltab, NACO_SPC_LAB_C1, imode, NULL),
865 cpl_table_get_double(modeltab, NACO_SPC_LAB_C2, imode, NULL),
866 cpl_table_get_double(modeltab, NACO_SPC_LAB_C3, imode, NULL),
867 cpl_table_get_double(modeltab, NACO_SPC_LAB_C4, imode, NULL)));
869 #ifdef NACO_SPC_WAVECAL_S54_3_SH
870 if (!strcmp(
"S54_3_SH", mode)) {
872 double p1 = 0.000165591;
873 double p2 = 2.86676e-07;
876 bug_if(cpl_polynomial_set_coeff(
self, °ree, p0));
878 bug_if(cpl_polynomial_set_coeff(
self, °ree, p1));
880 bug_if(cpl_polynomial_set_coeff(
self, °ree, p2));
882 bug_if(cpl_polynomial_set_coeff(
self, °ree, 0.0));
884 bug_if(cpl_polynomial_set_coeff(
self, °ree, 0.0));
886 cpl_msg_warning(cpl_func,
"Changing phdisp to simple fit:");
887 skip_if(cpl_polynomial_dump(
self, stdout));
893 return cpl_error_get_code();
913 static cpl_error_code naco_spc_physdisp_transform(cpl_polynomial *
self,
914 double xmin,
double xmax,
916 double c1,
double c2,
917 double c3,
double c4)
920 const double alpha = 2.0/(xmax - xmin);
921 const double beta = -(xmax + xmin) / (xmax - xmin);
923 double lambdamin1, lambdamax1;
924 double lambdamin2, lambdamax2;
927 bug_if(
self == NULL);
928 bug_if(cpl_polynomial_get_dimension(
self) != 1);
931 skip_if(xmin >= xmax);
933 value = 1e-4 * (c1 - 0.5 * c3);
935 bug_if(cpl_polynomial_set_coeff(
self, °ree, value));
937 value = 1e-4 * (c2 - 1.5 * c4);
939 bug_if(cpl_polynomial_set_coeff(
self, °ree, value));
942 value = 1e-4 * 1.5 * c3;
944 bug_if(cpl_polynomial_set_coeff(
self, °ree, value));
947 value = 1e-4 * 2.5 * c4;
949 bug_if(cpl_polynomial_set_coeff(
self, °ree, value));
951 skip_if(fit_order > 4);
954 skip_if(fit_order < 2);
958 lambdamin1 = cpl_polynomial_eval_1d(
self, -1.0, NULL);
959 lambdamax1 = cpl_polynomial_eval_1d(
self, 1.0, NULL);
966 bug_if(cpl_polynomial_shift_1d(
self, 0, beta));
969 value = cpl_polynomial_get_coeff(
self, °ree) * alpha;
970 bug_if(cpl_polynomial_set_coeff(
self, °ree, value));
974 value = cpl_polynomial_get_coeff(
self, °ree) * alpha * alpha;
975 bug_if(cpl_polynomial_set_coeff(
self, °ree, value));
979 value = cpl_polynomial_get_coeff(
self, °ree) * alpha * alpha
981 bug_if(cpl_polynomial_set_coeff(
self, °ree, value));
985 lambdamin2 = cpl_polynomial_eval_1d(
self, xmin, NULL);
986 lambdamax2 = cpl_polynomial_eval_1d(
self, xmax, NULL);
988 skip_if(cpl_polynomial_get_degree(
self) != fit_order - 1);
990 skip_if(cpl_polynomial_dump(
self, stdout));
992 cpl_msg_debug(cpl_func,
"Interpolation minimum=%g: %g (%g)", xmin,
993 lambdamin1, lambdamin2-lambdamin1);
994 cpl_msg_debug(cpl_func,
"Interpolation maximum=%g: %g (%g)", xmax,
995 lambdamax1, lambdamax2-lambdamax1);
999 return cpl_error_get_code();
1014 static cpl_error_code naco_spc_wavecal_get_slitw(
const cpl_propertylist *
self,
1017 const char * sslitw;
1023 bug_if(
self == NULL);
1024 bug_if(pslitw == NULL);
1026 sslitw = irplib_pfits_get_string(
self, NACO_PFITS_STRING_SLITNAME);
1027 skip_if(sslitw == NULL);
1029 nvals = sscanf(sslitw,
"Slit_%u", &uslitw);
1031 error_if(nvals != 1, CPL_ERROR_UNSUPPORTED_MODE,
"Unsupported value of '"
1032 NACO_PFITS_STRING_SLITNAME
": %s", sslitw);
1034 pixscale = irplib_pfits_get_double(
self, NACO_PFITS_DOUBLE_PIXSCALE);
1036 error_if(pixscale <= 0.0, CPL_ERROR_ILLEGAL_INPUT,
"Non-positive value of '"
1037 NACO_PFITS_DOUBLE_PIXSCALE
": %g", pixscale);
1039 *pslitw = (double)uslitw/(1000.0*pixscale);
1043 return cpl_error_get_code();
1058 static cpl_error_code
1059 naco_image_fill_column_from_dispersion(cpl_image *
self,
1060 int ispec, cpl_boolean is_bad,
1061 const cpl_polynomial * disp)
1064 const int ny = cpl_image_get_size_y(
self);
1067 bug_if(
self == NULL);
1068 bug_if(disp == NULL);
1069 bug_if(cpl_polynomial_get_dimension(disp) != 1);
1070 bug_if(cpl_polynomial_get_degree(disp) < 1);
1072 for (i = 1; i <= ny; i++) {
1073 const double value = cpl_polynomial_eval_1d(disp, (
double)i, NULL);
1074 cpl_image_set(
self, ispec, i, value);
1075 if (is_bad) cpl_image_reject(
self, ispec, i);
1080 return cpl_error_get_code();
1095 cpl_error_code naco_spc_wavecal_distortion(cpl_image *
self,
1096 cpl_propertylist * qclist,
1097 const cpl_parameterlist * parlist)
1100 const int fitdeg = 2;
1101 cpl_image * copy = NULL;
1102 const int nx = cpl_image_get_size_x(
self);
1103 const int ny = cpl_image_get_size_y(
self);
1104 cpl_apertures * lines = NULL;
1105 cpl_polynomial* distortion = NULL;
1106 cpl_polynomial* yid2d = cpl_polynomial_new(2);
1107 cpl_vector * profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES);
1108 cpl_size power[] = {0, 1};
1111 cpl_polynomial* center = cpl_polynomial_new(1);
1112 cpl_polynomial* dist1d = NULL;
1113 cpl_vector * dist1dfix = NULL;
1114 const cpl_size i0 = 0;
1115 const cpl_size i1 = 1;
1116 const double xcent = 0.5*(nx + 1);
1117 const double ycent = 0.5*(ny + 1);
1120 bug_if(
self == NULL);
1121 bug_if(qclist == NULL);
1122 bug_if(parlist == NULL);
1126 bug_if(cpl_image_turn(
self, 1));
1128 distortion = irplib_distortion_estimate(
self, 1, 1, nx, ny,
1131 0.33, fitdeg, &lines);
1133 error_if(distortion == NULL, cpl_error_get_code(),
"Curvature estimation "
1136 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
1137 skip_if(cpl_polynomial_dump(distortion, stdout));
1138 cpl_apertures_dump(lines, stdout);
1141 skip_if(naco_spc_wavecal_qc_lines(qclist,
self, lines));
1144 bug_if(cpl_polynomial_set_coeff(yid2d, power, 1.0));
1147 bug_if(cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_DEFAULT,
1148 CPL_KERNEL_DEF_WIDTH));
1151 copy = cpl_image_duplicate(
self);
1152 error_if (cpl_image_warp_polynomial(
self, copy, distortion, yid2d, profile,
1153 CPL_KERNEL_DEF_WIDTH, profile,
1154 CPL_KERNEL_DEF_WIDTH),
1155 cpl_error_get_code(),
"Distortion correction failed");
1158 bug_if(cpl_image_turn(
self, -1));
1161 cpl_errorstate prestate = cpl_errorstate_get();
1162 cpl_plot_image(
"",
"t 'Distortion corrected image'",
"",
self);
1163 if (!cpl_errorstate_is_equal(prestate)) {
1164 cpl_errorstate_set(prestate);
1168 (void)cpl_image_turn(copy, -1);
1170 (void)cpl_image_subtract(copy,
self);
1172 cpl_plot_image(
"",
"t 'Distortion correction'",
"", copy);
1173 if (!cpl_errorstate_is_equal(prestate)) {
1174 cpl_errorstate_set(prestate);
1179 skip_if(cpl_polynomial_dump(distortion, stdout));
1182 bug_if(cpl_polynomial_set_coeff(center, &i0, xcent));
1184 dist1d = cpl_polynomial_extract(distortion, 1, center);
1187 bug_if(cpl_polynomial_set_coeff(center, &i1, 1.0));
1188 bug_if(cpl_polynomial_set_coeff(center, &i0, 0.0));
1191 bug_if(cpl_polynomial_subtract(center, dist1d, center));
1193 if (cpl_polynomial_get_degree(center) > 0) {
1194 const cpl_size ndist1d = cpl_polynomial_get_degree(dist1d);
1195 cpl_size dist1dnreal;
1197 cpl_msg_info(cpl_func,
"On the center column (x=%g) the distortion poly"
1198 "nomial should be P(y)=y, its deviation from that has deg"
1199 "ree %d:", xcent, (
int)cpl_polynomial_get_degree(center));
1200 skip_if(cpl_polynomial_dump(center, stdout));
1203 cpl_errorstate prestate = cpl_errorstate_get();
1204 dist1dfix = cpl_vector_new(ndist1d);
1208 irplib_error_recover(prestate,
"Could not compute fix-points for "
1209 "%d-degree polynomial", (
int)ndist1d);
1215 if (dist1dnreal > 0) {
1216 cpl_vector * dist1dfixreal = dist1dnreal == ndist1d ? dist1dfix
1217 : cpl_vector_wrap(dist1dnreal, cpl_vector_get_data(dist1dfix));
1218 cpl_msg_info(cpl_func,
"The distortion correction has %d fix-"
1219 "point(s) on the center column:", (
int)dist1dnreal);
1220 cpl_vector_dump(dist1dfixreal, stdout);
1221 if (dist1dfixreal != dist1dfix)
1222 (void)cpl_vector_unwrap(dist1dfixreal);
1223 }
else if (cpl_polynomial_get_coeff(dist1d, &i0) != 0.0) {
1225 cpl_msg_info(cpl_func,
"The distortion correction has "
1226 "no fix-points on the center column");
1229 cpl_msg_info(cpl_func,
"The distortion correction has "
1230 "no fix-points on the center column");
1233 cpl_msg_info(cpl_func,
"The distortion correction moves the detector "
1234 "center at (%g,%g) by (%g,%g)", xcent, ycent, 0.0,
1235 cpl_polynomial_eval_1d(dist1d, ycent, NULL)-ycent);
1236 }
else if (cpl_polynomial_get_coeff(center, &i0) != 0.0) {
1237 cpl_msg_info(cpl_func,
"The distortion correction has no fix-points "
1238 "on the center column, their Y-offset are [pixel]: %g",
1239 cpl_polynomial_get_coeff(center, &i0));
1241 cpl_msg_info(cpl_func,
"The distortion correction has all points "
1242 "on the center column (at x=%g) as fix-points", xcent);
1246 power[0] = power[1] = 0;
1247 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC DIST1",
1248 cpl_polynomial_get_coeff(distortion,
1251 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC DISTY",
1252 cpl_polynomial_get_coeff(distortion,
1255 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC DISTYY",
1256 cpl_polynomial_get_coeff(distortion,
1259 power[0] = power[1] = 1;
1260 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC DISTXY",
1261 cpl_polynomial_get_coeff(distortion,
1264 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC DISTX",
1265 cpl_polynomial_get_coeff(distortion,
1268 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC DISTXX",
1269 cpl_polynomial_get_coeff(distortion,
1276 cpl_image_delete(copy);
1277 cpl_apertures_delete(lines);
1278 cpl_vector_delete(profile);
1279 cpl_vector_delete(dist1dfix);
1280 cpl_polynomial_delete(distortion);
1281 cpl_polynomial_delete(yid2d);
1282 cpl_polynomial_delete(center);
1283 cpl_polynomial_delete(dist1d);
1285 return cpl_error_get_code();
1297 static cpl_error_code naco_spc_wavecal_qc(cpl_propertylist * qclist,
1298 cpl_propertylist * paflist,
1299 const irplib_framelist * rawframes)
1302 const cpl_propertylist * reflist
1304 const char pafcopy[] =
"^(" NACO_PFITS_REGEXP_SPCWAVE_PAF
")$";
1311 skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
1313 skip_if (cpl_propertylist_append(paflist, qclist));
1315 bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist,
"^("
1316 IRPLIB_PFITS_REGEXP_RECAL_LAMP
1320 return cpl_error_get_code();
1336 static cpl_error_code naco_spc_wavecal_fill_table(cpl_table *
self,
1337 const cpl_polynomial * disp2d)
1340 const int degree = cpl_polynomial_get_degree(disp2d);
1341 const char * lunit =
"micron";
1344 bug_if (
self == NULL);
1345 bug_if (cpl_polynomial_get_dimension(disp2d) != 2);
1346 bug_if (degree < 1);
1348 bug_if(cpl_table_set_size(
self, 1));
1350 for (i=0; i <= degree; i++) {
1351 for (j = 0; j <= i; j++) {
1352 const cpl_size powers[2] = {i-j, j};
1353 const double value = cpl_polynomial_get_coeff(disp2d, powers);
1354 char * label = cpl_sprintf(
"DISP2D_%d_%d", i-j, j);
1355 char * unit = i > 1 ? cpl_sprintf(
"%s/pixel^%d", lunit, i)
1356 : cpl_sprintf(i ?
"%s/pixel" :
"%s", lunit);
1358 cpl_table_new_column(
self, label, CPL_TYPE_DOUBLE);
1359 cpl_table_set_column_unit(
self, label, unit);
1360 cpl_table_set_double(
self, label, 0, value);
1370 return cpl_error_get_code();
1387 static cpl_error_code naco_spc_wavecal_save(cpl_frameset * set_tot,
1388 const cpl_parameterlist * parlist,
1389 const cpl_propertylist * qclist,
1390 const cpl_propertylist * paflist,
1391 const cpl_imagelist * lamp_wave,
1392 const cpl_polynomial * disp2d,
1394 const irplib_framelist * rawframes)
1397 cpl_table * table2d = cpl_table_new(1);
1398 char * filename = NULL;
1399 cpl_propertylist * xtlist = cpl_propertylist_new();
1401 bug_if(cpl_propertylist_append_string(xtlist,
"EXTNAME",
1402 "Wavelength calibration"));
1405 filename = cpl_sprintf(RECIPE_STRING
"_set%02d" CPL_DFS_FITS, set_nb);
1407 cpl_imagelist_get_const(lamp_wave, 0),
1408 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
1409 NACO_CALIB_ARC_MAP, qclist, NULL,
1410 naco_pipe_id, filename));
1412 bug_if(naco_spc_wavecal_fill_table(table2d, disp2d));
1414 skip_if(cpl_table_save(table2d, NULL, xtlist, filename, CPL_IO_EXTEND));
1418 filename = cpl_sprintf(RECIPE_STRING
"_set%02d_diff" CPL_DFS_FITS, set_nb);
1420 cpl_imagelist_get_const(lamp_wave, 1),
1421 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
1422 NACO_CALIB_ARC_DIFF, qclist, NULL,
1423 naco_pipe_id, filename));
1425 bug_if(cpl_propertylist_set_string(xtlist,
"EXTNAME",
1426 "Difference Image"));
1427 skip_if (cpl_image_save(cpl_imagelist_get_const(lamp_wave, 2), filename,
1428 CPL_BPP_IEEE_FLOAT, xtlist, CPL_IO_EXTEND));
1430 #ifdef NACO_SAVE_PAF
1432 filename = cpl_sprintf(RECIPE_STRING
"_set%02d" CPL_DFS_PAF, set_nb);
1433 skip_if (cpl_dfs_save_paf(
"NACO", RECIPE_STRING, paflist, filename));
1435 bug_if(paflist == NULL);
1440 cpl_table_delete(table2d);
1442 cpl_frameset_delete(proframes);
1443 cpl_propertylist_delete(xtlist);
1445 return cpl_error_get_code();
1460 static cpl_error_code naco_spc_wavecal_count_lines(cpl_propertylist *
self,
1461 const cpl_bivector * lines,
1466 const cpl_vector * xlines = cpl_bivector_get_x_const(lines);
1467 const double * dxlines = cpl_vector_get_data_const(xlines);
1468 int minline, maxline;
1472 bug_if (
self == NULL);
1473 bug_if (lines == NULL);
1475 bug_if (wlmin < 0.0);
1476 bug_if (wlmax < wlmin);
1479 minline = cpl_vector_find(xlines, wlmin);
1482 if (dxlines[minline] < wlmin) minline++;
1485 maxline = cpl_vector_find(xlines, wlmax);
1488 if (dxlines[maxline] > wlmax) maxline--;
1490 clines = maxline >= minline ? maxline - minline : 0;
1492 bug_if(cpl_propertylist_append_int(
self,
"ESO QC DISP NUMCAT", clines));
1496 return cpl_error_get_code();
1508 static cpl_error_code
1509 naco_spc_wavecal_interpolate_rejected(cpl_image *
self,
1510 const cpl_polynomial * disp2d)
1513 const int nz = cpl_image_count_rejected(
self);
1514 const int nx = cpl_image_get_size_x(
self);
1515 const int ny = cpl_image_get_size_y(
self);
1517 cpl_vector * vpower = cpl_vector_wrap(2, power);
1521 bug_if(
self == NULL);
1522 bug_if(disp2d == NULL);
1524 if (nz > 0) cpl_msg_info(cpl_func,
"Interpolating %d poorly calibrated "
1525 "pixels in the wavelength map", nz);
1527 for (i = 1; i <= nx && k > 0; i++) {
1528 for (j = 1; j <= ny && k > 0; j++) {
1529 if (cpl_image_is_rejected(
self, i, j)) {
1530 power[0] = (double)i;
1531 power[1] = (double)j;
1532 cpl_image_set(
self, i, j, cpl_polynomial_eval(disp2d, vpower));
1533 cpl_image_reject(
self, i, j);
1541 cpl_vector_unwrap(vpower);
1543 return cpl_error_get_code();
1557 static cpl_error_code naco_spc_wavecal_qc_lines(cpl_propertylist *
self,
1558 const cpl_image * spec2d,
1559 const cpl_apertures * lines)
1562 const int nlines = cpl_apertures_get_size(lines);
1563 const int ny = cpl_image_get_size_y(spec2d);
1564 const double ycen = 0.5 * (ny + 1);
1566 char * label = NULL;
1567 cpl_vector * vmedian = cpl_vector_new(nlines);
1570 bug_if(
self == NULL);
1571 bug_if(spec2d == NULL);
1572 bug_if(lines == NULL);
1574 bug_if(cpl_propertylist_append_int(
self,
"ESO QC ARCS NUM", nlines));
1577 for(i = 1; i <= nlines; i++) {
1578 cpl_errorstate prestate = cpl_errorstate_get();
1579 const double flux = cpl_apertures_get_flux(lines, i);
1580 const double xcen = cpl_apertures_get_centroid_x(lines, i);
1581 double fwhm_x, fwhm_y;
1583 if (cpl_image_get_fwhm(spec2d, xcen, ycen, &fwhm_x, &fwhm_y)) {
1584 irplib_error_recover(prestate,
"Could not compute the FWHM for "
1585 "aperture %d of %d (with xcentroid=%g, flux=%g",
1586 i, nlines, xcen, flux);
1591 cpl_vector_set(vmedian, igood++, fwhm_x);
1595 label = cpl_sprintf(
"ESO QC ARCS%d XPOS", i);
1596 cpl_propertylist_append_double(
self, label, xcen);
1599 label = cpl_sprintf(
"ESO QC ARCS%d FWHM", i);
1601 cpl_propertylist_append_double(
self, label, fwhm_x);
1604 label = cpl_sprintf(
"ESO QC ARCS%d FLUX", i);
1606 cpl_propertylist_append_double(
self, label, flux);
1610 bug_if(cpl_propertylist_append_int(
self,
"ESO QC ARCS NUMGOOD", igood));
1613 bug_if(cpl_vector_set_size(vmedian, igood));
1614 median = cpl_vector_get_median(vmedian);
1619 bug_if(cpl_propertylist_append_double(
self,
"ESO QC FWHM MED", median));
1623 cpl_vector_delete(vmedian);
1626 return cpl_error_get_code();
cpl_frameset * irplib_frameset_cast(const irplib_framelist *self)
Create a CPL frameset from an irplib_framelist.
cpl_error_code irplib_vector_fill_line_spectrum(cpl_vector *self, const cpl_polynomial *disp, irplib_base_spectrum_model *lsslamp)
Generate a 1D spectrum from a model and a dispersion relation.
cpl_error_code irplib_framelist_set_tag_all(irplib_framelist *self, const char *tag)
Set the tag of all frames in the list.
char * naco_spc_make_tag(const cpl_frame *self, const cpl_propertylist *plist, int dummy)
Create a string suitable for frame comparison in spectroscopy.
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
cpl_error_code irplib_framelist_set(irplib_framelist *self, cpl_frame *frame, int pos)
Add a frame to a framelist.
cpl_error_code irplib_polynomial_shift_1d_from_correlation(cpl_polynomial *self, const cpl_vector *obs, irplib_base_spectrum_model *model, cpl_error_code(*filler)(cpl_vector *, const cpl_polynomial *, irplib_base_spectrum_model *), int hsize, cpl_boolean doplot, double *pxc)
Shift self by the amount that maximizes the cross-correlation.
cpl_error_code irplib_polynomial_find_1d_from_correlation(cpl_polynomial *self, int maxdeg, const cpl_vector *obs, irplib_base_spectrum_model *model, cpl_error_code(*filler)(cpl_vector *, const cpl_polynomial *, irplib_base_spectrum_model *), double pixtol, double pixstep, int hsize, int maxite, double *pxc)
Modify self by maximizing the cross-correlation.
cpl_error_code irplib_polynomial_fit_2d_dispersion(cpl_polynomial *self, const cpl_image *imgwave, int fitdeg, double *presid)
Fit a 2D-dispersion from an image of wavelengths.
int naco_parameterlist_get_int(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO integer parameter.
const cpl_propertylist * irplib_framelist_get_propertylist_const(const irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
void irplib_framelist_empty(irplib_framelist *self)
Erase all frames from a framelist.
cpl_error_code irplib_dfs_save_image(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_image *image, cpl_type_bpp bpp, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save an image as a DFS-compliant pipeline product.
cpl_error_code irplib_polynomial_solve_1d_all(const cpl_polynomial *self, cpl_vector *roots, cpl_size *preal)
Compute all n roots of p(x) = 0, where p(x) is of degree n, n > 0.
cpl_error_code irplib_framelist_load_propertylist_all(irplib_framelist *self, int ind, const char *regexp, cpl_boolean invert)
Load the propertylists of all frames in the framelist.
cpl_frame * irplib_framelist_unset(irplib_framelist *self, int pos, cpl_propertylist **plist)
Erase a frame from a framelist and return it to the caller.
cpl_boolean naco_parameterlist_get_bool(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO boolean parameter.
cpl_error_code irplib_plot_spectrum_and_model(const cpl_vector *self, const cpl_polynomial *disp1d, irplib_base_spectrum_model *model, cpl_error_code(*filler)(cpl_vector *, const cpl_polynomial *, irplib_base_spectrum_model *))
Plot a 1D spectrum and one from a model.
irplib_framelist * irplib_framelist_extract(const irplib_framelist *self, const char *tag)
Extract the frames with the given tag from a framelist.
const char ** naco_framelist_set_tag(irplib_framelist *self, char *(*pftag)(const cpl_frame *, const cpl_propertylist *, int), int *pntags)
Retag a framelist according to the given tagging function.
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
cpl_error_code naco_imagelist_load_diff(cpl_imagelist *self, const irplib_framelist *onofflist, const cpl_propertylist *onoffkeys)
Fill the list of difference images from on/off frames.
irplib_framelist * irplib_framelist_cast(const cpl_frameset *frameset)
Create an irplib_framelist from a cpl_framelist.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.