38 #include "irplib_plugin.h"
39 #include "irplib_utils.h"
40 #include "irplib_stdstar.h"
41 #include "irplib_spectrum.h"
43 #include "isaac_utils.h"
44 #include "isaac_wavelength.h"
45 #include "isaac_physicalmodel.h"
46 #include "isaac_pfits.h"
47 #include "isaac_dfs.h"
56 #define RECIPE_STRING "isaac_spc_jitter"
58 #define ISAAC_SPC_JITTER_OFFSET_ERR 10
62 #define CENT_WL_BAND_Z 0.9
63 #define CENT_WL_BAND_SZ 1.06
64 #define CENT_WL_BAND_J 1.25
65 #define CENT_WL_BAND_H 1.65
66 #define CENT_WL_BAND_K 2.2
67 #define CENT_WL_BAND_SL 3.78
68 #define CENT_WL_BAND_M 4.78
70 #define ISAAC_MIN(A,B) ((A) < (B) ? (A) : (B))
72 #define isaac_plot_manpage \
73 "The recipe can produce a number of predefined plots. " \
74 "Zero means that none of the plots are produced, while " \
75 "increasing values (e.g. 1 or 2) increases the number " \
76 "of plots produced. If the plotting fails a warning is " \
77 "produced, and the recipe continues. " \
78 "The default behaviour of the plotting is to use " \
79 "gnuplot (with option -persist). The recipe currently " \
80 "produces 1D-plots using gnuplot commands. The recipe " \
81 "user can control the actual plotting-command used by " \
82 "the recipe to create the plot by setting the " \
83 "environment variable CPL_PLOTTER. Currently, if " \
85 "is set it must contain the string 'gnuplot'. Setting " \
86 "it to 'cat > my_gnuplot_$$.txt' causes a number of " \
87 "ASCII-files to be created, which each produce a plot " \
88 "when given as standard input to gnuplot (e.g. later " \
89 "or on a different computer). A finer control of the " \
90 "plotting options can be obtained by writing an " \
91 "executable script, e.g. my_gnuplot.pl, that " \
92 "executes gnuplot after setting the desired gnuplot " \
93 "options (e.g. set terminal pslatex color) " \
94 "and then setting CPL_PLOTTER to my_gnuplot.pl. " \
95 "The predefined plots include plotting of images. " \
96 "Images can be plotted not only with gnuplot, but also " \
97 "using the pnm format. This is controlled with the " \
98 "environment variable CPL_IMAGER. If CPL_IMAGER " \
99 "is set to a string that does not contain the word " \
100 "gnuplot, the recipe will generate the plot in pnm " \
101 "format. E.g. setting CPL_IMAGER to " \
102 "'display - &' will produce a gray-scale image " \
103 "using the image viewer display."
111 static cpl_image ** isaac_spc_jitter_combine(
const cpl_frameset *,
const char *,
112 const char *,
const char *,
const char *);
113 static cpl_imagelist * isaac_spc_jitter_load(
const cpl_frameset *);
114 static cpl_vector * isaac_spc_jitter_get_offsets(
const cpl_frameset *);
115 static int * isaac_spc_jitter_classif(
const cpl_vector *,
int *);
116 static int off_comp(
double,
double,
double);
117 static cpl_imagelist * isaac_spc_jitter_saa_groups(cpl_imagelist *,
118 cpl_vector *,
int *,
int, cpl_vector **);
119 static int isaac_spc_jitter_wavecal(
const char *,
const cpl_image *,
120 const char *,
const cpl_frameset *);
121 static cpl_imagelist * isaac_spc_jitter_nodded(cpl_imagelist *, cpl_vector *,
123 static cpl_imagelist * isaac_spc_jitter_distor(cpl_imagelist *,
const char *,
125 static double isaac_spc_jitter_refine_offset(
const cpl_image *,
127 static cpl_table * isaac_spc_jitter_extract(
const cpl_image *);
128 static int isaac_spc_jitter_std(
const char *,
const char *,
const cpl_frame *,
129 cpl_table *,
double);
130 static cpl_error_code isaac_spc_jitter_flat(cpl_imagelist *,
const char *);
131 static cpl_error_code isaac_spc_jitter_save(cpl_frameset *,
const cpl_image *,
134 const cpl_parameterlist *);
136 cpl_recipe_define(isaac_spc_jitter, ISAAC_BINARY_VERSION,
137 "Lars Lundin", PACKAGE_BUGREPORT,
"2002,2003, 2008",
138 "ISAAC Spectro jitter recipe",
139 RECIPE_STRING
" -- ISAAC spectro jitter recipe\n"
140 "The files listed in the Set Of Frames (sof-file) "
142 "Observation in nodding mode:\n"
143 "\traw-file.fits "ISAAC_SPC_JITTER_NODOBJ_RAW
" or\n"
144 "\traw-file.fits "ISAAC_SPC_JITTER_NODSKY_RAW
"\n"
145 "Observation in chopping mode:\n"
146 "\traw-file.fits "ISAAC_SPC_JITTER_CHOP_RAW
" or\n"
147 "Calibration (standard star) in nodding mode:\n"
148 "\traw-file.fits "ISAAC_SPC_RESPFUNC_RAW
" or\n"
149 "\traw-file.fits "ISAAC_SPC_RESPFUNC_OBJ_RAW
" or\n"
150 "\traw-file.fits "ISAAC_SPC_RESPFUNC_SKY_RAW
"\n"
151 "\traw-file.fits "ISAAC_SPC_RESPFUNC_FLUX_RAW
"\n"
152 "Calibration (standard star) in chopping mode:\n"
153 "\traw-file.fits "ISAAC_SPC_JITTER_CHOP_CAL_RAW
"\n"
154 "Calibration files:\n"
155 "\toh.fits "ISAAC_CALPRO_OH_CAT
" or\n"
156 "\tflat-file.fits "ISAAC_CALIB_SPFLAT
" or\n"
157 "\tflat-file.fits "ISAAC_CALIB_LW_SPFLAT
" or\n"
158 "\tarc-file.fits "ISAAC_CALIB_ARC
" or\n"
159 "\tarc-file.fits "ISAAC_CALIB_LW_ARC
" or\n"
160 "\tstartrace-file.fits "ISAAC_CALIB_STARTRACE
" or\n"
161 "\tstartrace-file.fits "ISAAC_CALIB_LW_STARTRACE
" or\n"
162 "\tsed-file.fits "ISAAC_CALIB_SED
" or\n"
163 "\tstdstars-file.fits "ISAAC_CALIB_STDSTARS
"\n");
176 int wavecal_rej_bottom;
178 int wavecal_rej_left;
179 int wavecal_rej_right;
186 int extr_sky_hi_width;
187 int extr_sky_lo_width;
188 int extr_sky_hi_dist;
189 int extr_sky_lo_dist;
191 double std_magnitude;
196 cpl_vector * intensities;
197 char filter[KEYSIZE];
198 char filter_ref[KEYSIZE];
207 } isaac_spc_jitter_config;
224 cpl_error_code isaac_spc_jitter_fill_parameterlist(cpl_parameterlist *
self)
226 const char * context = PACKAGE
"." RECIPE_STRING;
229 cpl_ensure_code(
self, CPL_ERROR_NULL_INPUT);
235 err = irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
236 "oddeven", CPL_FALSE, NULL, context,
237 "Flag to correct the oddeven column "
239 cpl_ensure_code(!err, err);
242 err = irplib_parameterlist_set_string(
self, PACKAGE, RECIPE_STRING,
243 "wavecal",
"sky", NULL, context,
244 "Wavelength calibration method: "
246 cpl_ensure_code(!err, err);
249 err = irplib_parameterlist_set_string(
self, PACKAGE, RECIPE_STRING,
250 "wavecal_rej",
"-1,-1,50,50",
252 "left right bottom top rejections");
253 cpl_ensure_code(!err, err);
256 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
257 "max_offset", 50, NULL, context,
258 "Maximum allowed offset from the "
259 "physical model [pixel]");
260 cpl_ensure_code(!err, err);
263 err = irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
264 "saa_refine", CPL_TRUE, NULL, context,
265 "Flag to refine the offsets");
266 cpl_ensure_code(!err, err);
269 err = irplib_parameterlist_set_string(
self, PACKAGE, RECIPE_STRING,
270 "saa_rej",
"0.1,0.1", NULL, context,
271 "Low and high rejection fractions "
273 cpl_ensure_code(!err, err);
276 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
277 "spec_pos", -1, NULL, context,
278 "Spectrum position");
279 cpl_ensure_code(!err, err);
282 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
283 "spec_width", 10, NULL, context,
285 cpl_ensure_code(!err, err);
288 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
289 "sky_hi_width", 10, NULL, context,
290 "Sky width above the spectrum");
291 cpl_ensure_code(!err, err);
294 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
295 "sky_lo_width", 10, NULL, context,
296 "Sky width below the spectrum");
297 cpl_ensure_code(!err, err);
300 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
301 "sky_hi_dist", -1, NULL, context,
302 "Sky distance above the spectrum");
303 cpl_ensure_code(!err, err);
306 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
307 "sky_lo_dist", -1, NULL, context,
308 "Sky distance below the spectrum");
309 cpl_ensure_code(!err, err);
312 err = irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
313 "display", CPL_FALSE, NULL, context,
314 "Ignored. Use --plot instead");
315 cpl_ensure_code(!err, err);
318 err = irplib_parameterlist_set_int(
self, PACKAGE, RECIPE_STRING,
319 "plot", 0, NULL, context,
321 cpl_ensure_code(!err, err);
324 err = irplib_parameterlist_set_bool(
self, PACKAGE, RECIPE_STRING,
325 "std_mode", CPL_FALSE,
"std", context,
326 "Flag for standard star");
327 cpl_ensure_code(!err, err);
330 err = irplib_parameterlist_set_double(
self, PACKAGE, RECIPE_STRING,
331 "std_magnitude", -1.0,
"mag",
332 context,
"Standard star magnitude");
333 cpl_ensure_code(!err, err);
335 return CPL_ERROR_NONE;
348 static int isaac_spc_jitter(cpl_frameset * framelist,
349 const cpl_parameterlist * parlist)
351 cpl_errorstate prestate = cpl_errorstate_get();
355 const char * startrace;
357 const char * stdstars;
359 const cpl_frame * cur_frame;
360 cpl_frameset * rawframes = NULL;
361 cpl_propertylist * plist = NULL;
362 cpl_image ** combined = NULL;
363 cpl_table * extracted = NULL;
368 isaac_spc_jitter_config.chopping = -1;
369 isaac_spc_jitter_config.wavecal_out = -1;
370 isaac_spc_jitter_config.wavecal_cc = -1.0;
371 isaac_spc_jitter_config.throws = NULL;
372 isaac_spc_jitter_config.intensities = NULL;
373 isaac_spc_jitter_config.filter[0] = (char)0;
374 isaac_spc_jitter_config.filter_ref[0] = (char)0;
375 isaac_spc_jitter_config.starname = NULL;
376 isaac_spc_jitter_config.sptype = NULL;
377 isaac_spc_jitter_config.wavecal_in = -1;
378 isaac_spc_jitter_config.arm = -1;
382 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
384 bug_if(sval == NULL);
386 if (!strcmp(sval,
"phy")) isaac_spc_jitter_config.wavecal_in = 0;
387 else if (!strcmp(sval,
"sky")) isaac_spc_jitter_config.wavecal_in = 1;
388 else if (!strcmp(sval,
"arc")) isaac_spc_jitter_config.wavecal_in = 2;
390 error_if(isaac_spc_jitter_config.wavecal_in < 0,
391 CPL_ERROR_UNSUPPORTED_MODE,
"Invalid value for wavecal option: "
395 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
397 bug_if(sval == NULL);
399 skip_if (sscanf(sval,
"%d,%d,%d,%d",
400 &isaac_spc_jitter_config.wavecal_rej_left,
401 &isaac_spc_jitter_config.wavecal_rej_right,
402 &isaac_spc_jitter_config.wavecal_rej_bottom,
403 &isaac_spc_jitter_config.wavecal_rej_top) != 4);
406 isaac_spc_jitter_config.max_offset
407 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
411 isaac_spc_jitter_config.oddeven
412 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
416 isaac_spc_jitter_config.saa_refine
417 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
421 sval = irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
423 bug_if(sval == NULL);
425 skip_if (sscanf(sval,
"%lg,%lg",
426 &isaac_spc_jitter_config.saa_rej_low,
427 &isaac_spc_jitter_config.saa_rej_high) != 2);
430 isaac_spc_jitter_config.extr_spec_pos
431 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
434 isaac_spc_jitter_config.extr_spec_width
435 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
438 isaac_spc_jitter_config.extr_sky_hi_width
439 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
442 isaac_spc_jitter_config.extr_sky_lo_width
443 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
446 isaac_spc_jitter_config.extr_sky_hi_dist
447 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
450 isaac_spc_jitter_config.extr_sky_lo_dist
451 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
454 isaac_spc_jitter_config.plot
455 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
458 isaac_spc_jitter_config.std_mode
459 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
462 isaac_spc_jitter_config.std_magnitude
463 = irplib_parameterlist_get_double(parlist, PACKAGE, RECIPE_STRING,
471 ISAAC_SPC_JITTER_CHOP_RAW)) != NULL) {
473 ISAAC_SPC_JITTER_CHOP_CAL_RAW)) != NULL) {
475 ISAAC_SPC_JITTER_NODOBJ_RAW)) != NULL) {
477 ISAAC_SPC_RESPFUNC_RAW)) != NULL) {
478 isaac_spc_jitter_config.std_mode = 1;
480 ISAAC_SPC_RESPFUNC_OBJ_RAW)) != NULL) {
481 isaac_spc_jitter_config.std_mode = 1;
483 ISAAC_SPC_RESPFUNC_FLUX_RAW)) != NULL) {
484 isaac_spc_jitter_config.std_mode = 1;
489 error_if (cpl_frameset_find_const(framelist,
490 ISAAC_SPC_JITTER_NODSKY_RAW),
491 CPL_ERROR_UNSUPPORTED_MODE,
"Cannot reduce "
492 ISAAC_SPC_JITTER_NODSKY_RAW
"-frames without object frames");
494 error_if (cpl_frameset_find_const(framelist,
495 ISAAC_SPC_RESPFUNC_SKY_RAW),
496 CPL_ERROR_UNSUPPORTED_MODE,
"Cannot reduce "
497 ISAAC_SPC_RESPFUNC_SKY_RAW
"-frames without object frames");
501 error_if (rawframes == NULL, CPL_ERROR_DATA_NOT_FOUND,
502 "Cannot find the raw frames in the input list");
505 cur_frame = cpl_frameset_get_position_const(framelist, 0);
506 skip_if(cur_frame == NULL);
507 plist = cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
508 skip_if(plist == NULL);
510 error_if (sval == NULL, CPL_ERROR_DATA_NOT_FOUND,
"cannot get the arm");
512 if (sval[0] ==
'S') isaac_spc_jitter_config.arm = 1;
513 else if (sval[0] ==
'L') isaac_spc_jitter_config.arm = 2;
515 error_if (isaac_spc_jitter_config.arm < 0, CPL_ERROR_UNSUPPORTED_MODE,
516 "Unsupported arm: %s", sval);
523 (void)strncpy(isaac_spc_jitter_config.filter, sval, KEYSIZE);
524 isaac_spc_jitter_config.filter[KEYSIZE-1] = (char)0;
526 cpl_propertylist_empty(plist);
536 if (startrace == NULL)
543 error_if (arc == NULL && isaac_spc_jitter_config.wavecal_in == 2,
544 CPL_ERROR_DATA_NOT_FOUND,
"Missing an arc file for the "
545 "arc-based wavelength calibration");
547 cpl_msg_info(cpl_func,
"Create the combined image");
548 combined = isaac_spc_jitter_combine(rawframes, oh, flat, arc,
550 skip_if (combined == NULL);
552 cpl_msg_info(cpl_func,
"Extract the spectrum");
553 extracted = isaac_spc_jitter_extract(combined[0]);
554 if (extracted == NULL || !cpl_errorstate_is_equal(prestate)) {
555 cpl_msg_warning(cpl_func,
"Cannot extract the spectrum");
556 if (!cpl_errorstate_is_equal(prestate)) {
557 cpl_errorstate_dump(prestate, CPL_FALSE,
558 irplib_errorstate_dump_warning);
559 cpl_errorstate_set(prestate);
561 }
else if (isaac_spc_jitter_config.std_mode) {
563 cpl_msg_info(cpl_func,
"Compute flux calibration");
564 cur_frame = cpl_frameset_get_position_const(framelist, 0);
565 if (isaac_spc_jitter_std(sed, stdstars, cur_frame, extracted,
566 isaac_spc_jitter_config.std_magnitude)) {
567 cpl_msg_warning(cpl_func,
"Cannot compute the flux calibration");
568 if (!cpl_errorstate_is_equal(prestate)) {
569 cpl_errorstate_dump(prestate, CPL_FALSE,
570 irplib_errorstate_dump_warning);
571 cpl_errorstate_set(prestate);
577 cpl_msg_info(cpl_func,
"Save the products");
578 skip_if (isaac_spc_jitter_save(framelist, combined[0], combined[1],
579 extracted, parlist));
583 if (combined != NULL) {
584 cpl_image_delete(combined[0]);
585 cpl_image_delete(combined[1]);
589 cpl_table_delete(extracted);
591 cpl_vector_delete(isaac_spc_jitter_config.intensities);
592 cpl_vector_delete(isaac_spc_jitter_config.throws);
594 cpl_free(isaac_spc_jitter_config.starname);
595 cpl_free(isaac_spc_jitter_config.sptype);
597 cpl_propertylist_delete(plist);
599 cpl_frameset_delete(rawframes);
601 return cpl_error_get_code();
616 static cpl_image ** isaac_spc_jitter_combine(
const cpl_frameset * rawframes,
620 const char * startrace)
623 cpl_imagelist * ilist = NULL;
624 cpl_vector * offsets = NULL;
627 cpl_imagelist * abba = NULL;
628 cpl_vector * abba_off = NULL;
629 cpl_imagelist * nodded = NULL;
630 cpl_vector * nodded_off_y = NULL;
632 cpl_vector * nodded_off_x = NULL;
633 cpl_bivector * nodded_offsets = NULL;
634 cpl_image ** combined = NULL;
638 bug_if (rawframes == NULL);
641 cpl_msg_info(cpl_func,
"Load the data");
642 ilist = isaac_spc_jitter_load(rawframes);
643 skip_if (ilist == NULL);
645 nilist = cpl_imagelist_get_size(ilist);
648 if (isaac_spc_jitter_config.oddeven) {
649 cpl_errorstate prestate = cpl_errorstate_get();
650 cpl_imagelist * corrected = cpl_imagelist_new();
652 cpl_msg_info(cpl_func,
"Apply the odd-even effect correction");
653 for (i=0; i < nilist; i++) {
657 cpl_msg_info(cpl_func,
"Correcting frame %d/%d", i+1, nilist);
659 if (cur_im == NULL)
break;
660 (void)cpl_imagelist_set(corrected, cur_im, i);
665 cpl_imagelist_delete(ilist);
668 cpl_msg_warning(cpl_func,
"Odd/even correction failed for "
669 "image %d/%d", i+1, nilist);
670 cpl_imagelist_delete(corrected);
671 if (!cpl_errorstate_is_equal(prestate)) {
672 cpl_errorstate_dump(prestate, CPL_FALSE,
673 irplib_errorstate_dump_warning);
674 cpl_errorstate_set(prestate);
680 if (isaac_spc_jitter_config.plot > 0) {
681 cpl_plot_image(
"",
"",
"", cpl_imagelist_get(ilist, 0));
686 cpl_errorstate prestate = cpl_errorstate_get();
687 cpl_msg_info(cpl_func,
"Apply the flatfield correction");
688 if (isaac_spc_jitter_flat(ilist, flat)) {
689 cpl_msg_warning(cpl_func,
"cannot apply the flat field");
690 if (!cpl_errorstate_is_equal(prestate)) {
691 cpl_errorstate_dump(prestate, CPL_FALSE,
692 irplib_errorstate_dump_warning);
693 cpl_errorstate_set(prestate);
698 if (isaac_spc_jitter_config.plot > 0) {
699 cpl_plot_image(
"",
"",
"", cpl_imagelist_get(ilist, 0));
702 cpl_msg_info(cpl_func,
"Get the %d offsets", nilist);
703 offsets = isaac_spc_jitter_get_offsets(rawframes);
705 error_if (offsets == NULL, cpl_error_get_code(),
706 "Could not get the offsets");
709 cpl_msg_info(cpl_func,
"Classify in groups");
710 groups = isaac_spc_jitter_classif(offsets, &ngroups);
711 error_if (groups == NULL, cpl_error_get_code(),
712 "Could not classify the data");
715 cpl_msg_info(cpl_func,
"Shift and add each group to one image");
716 abba = isaac_spc_jitter_saa_groups(ilist, offsets, groups,
718 error_if (abba == NULL, cpl_error_get_code(),
"Could not shift and add "
722 cpl_msg_info(cpl_func,
"Compute the wavelength calibration");
723 error_if (isaac_spc_jitter_wavecal(arc, cpl_imagelist_get(abba, 0), oh,
725 cpl_error_get_code(),
"Wavelength calibration failed");
728 cpl_msg_info(cpl_func,
"Create the nodded images");
729 nodded = isaac_spc_jitter_nodded(abba, abba_off, &nodded_off_y);
730 cpl_imagelist_delete(abba);
733 skip_if (nodded == NULL);
736 nima = cpl_imagelist_get_size(nodded);
737 isaac_spc_jitter_config.throws = cpl_vector_new(nima);
738 if (isaac_spc_jitter_config.chopping == 0) {
739 for (i=0; i<nima/2; i++) {
740 throw = fabs( (cpl_vector_get(abba_off, 2*i))-
741 (cpl_vector_get(abba_off, 2*i+1)));
742 cpl_vector_set(isaac_spc_jitter_config.throws, 2*i,
throw);
743 cpl_vector_set(isaac_spc_jitter_config.throws, 2*i+1,
throw);
746 for (i=0; i<nima; i++) {
747 throw = fabs( (cpl_vector_get(abba_off, 2*i))-
748 (cpl_vector_get(abba_off, 2*i+1)));
749 cpl_vector_set(isaac_spc_jitter_config.throws, i,
throw);
752 cpl_vector_delete(abba_off);
756 cpl_msg_info(cpl_func,
"Compute the spectra intensities");
757 cpl_msg_indent_more();
758 isaac_spc_jitter_config.intensities = cpl_vector_new(nima);
759 for (i=0; i<nima; i++) {
760 cpl_errorstate prestate = cpl_errorstate_get();
761 cpl_table * extracted
762 = isaac_spc_jitter_extract(cpl_imagelist_get(nodded, i));
766 if (extracted == NULL || !cpl_errorstate_is_equal(prestate)) {
767 cpl_msg_warning(cpl_func,
"Cannot extract the spectrum from "
768 "nodded image %d", i+1);
769 cpl_errorstate_dump(prestate, CPL_FALSE,
770 irplib_errorstate_dump_warning);
771 cpl_errorstate_set(prestate);
774 intensity = cpl_table_get_column_mean(extracted,
775 "Extracted_spectrum_value");
776 intensity *= cpl_table_get_nrow(extracted);
777 cpl_table_delete(extracted);
778 cpl_msg_info(cpl_func,
"Spectrum intensity %d: %g", i+1,
781 cpl_vector_set(isaac_spc_jitter_config.intensities, i, intensity);
783 cpl_msg_indent_less();
785 if (arc || startrace) {
786 cpl_imagelist * nodded_warped;
787 cpl_msg_info(cpl_func,
"Correct the distortion on nodded images");
788 cpl_msg_indent_more();
789 nodded_warped = isaac_spc_jitter_distor(nodded, arc, startrace);
790 cpl_msg_indent_less();
792 skip_if (nodded_warped == NULL);
794 cpl_imagelist_delete(nodded);
795 nodded = nodded_warped;
796 nima = cpl_imagelist_get_size(nodded);
801 if (isaac_spc_jitter_config.saa_refine) {
802 double * pnodded_off_y = cpl_vector_get_data(nodded_off_y);
803 cpl_msg_info(cpl_func,
"Refine the %d offsets", nima);
804 for (i=0; i < nima; i++) {
805 const double new_offset
806 = isaac_spc_jitter_refine_offset(cpl_imagelist_get(nodded, 0),
807 cpl_imagelist_get(nodded, i));
808 if (new_offset > 5000) {
809 cpl_msg_debug(cpl_func,
"cannot refine the offset - keep %g",
811 }
else if (fabs(new_offset-pnodded_off_y[i]) <
812 ISAAC_SPC_JITTER_OFFSET_ERR) {
813 cpl_msg_debug(cpl_func,
"refined offset : %g (old was %g)",
814 new_offset, pnodded_off_y[i]);
815 pnodded_off_y[i] = new_offset;
817 cpl_msg_debug(cpl_func,
818 "refined offset %g too different - keep %g",
819 new_offset, pnodded_off_y[i]);
827 nodded_off_x = cpl_vector_new(nima);
828 bug_if(cpl_vector_fill(nodded_off_x, 0.0));
829 nodded_offsets = cpl_bivector_wrap_vectors(nodded_off_x, nodded_off_y);
833 combined = cpl_malloc(2 *
sizeof(cpl_image*));
836 combined[0] = cpl_imagelist_unset(nodded, 0);
837 bug_if (combined[0] == NULL);
839 combined[1] = cpl_image_new(cpl_image_get_size_x(combined[0]),
840 cpl_image_get_size_y(combined[0]),
842 bug_if (combined[1] == NULL);
845 bug_if(cpl_image_threshold(combined[1], 1.0, 1.0, 1.0, 1.0));
849 const int nrejlo = (int)(nima * isaac_spc_jitter_config.saa_rej_low);
850 const int nrejhi = (int)(nima * isaac_spc_jitter_config.saa_rej_high);
852 cpl_msg_info(cpl_func,
"Apply the shift and add on the %d nodded "
853 "frames (Rejecting %d lowermost, %d uppermost)", nima,
855 combined = cpl_geom_img_offset_saa(nodded, nodded_offsets,
856 CPL_KERNEL_DEFAULT, nrejlo, nrejhi,
857 CPL_GEOM_FIRST, NULL, NULL);
860 skip_if(combined == NULL);
865 cpl_imagelist_delete(ilist);
866 cpl_vector_delete(offsets);
867 cpl_imagelist_delete(abba);
868 cpl_vector_delete(abba_off);
869 cpl_imagelist_delete(nodded);
870 cpl_bivector_unwrap_vectors(nodded_offsets);
871 cpl_vector_delete(nodded_off_x);
872 cpl_vector_delete(nodded_off_y);
886 static cpl_error_code isaac_spc_jitter_flat(cpl_imagelist *
self,
889 cpl_image * fim = NULL;
890 cpl_image * big_fim = NULL;
891 const int mx = cpl_image_get_size_x(cpl_imagelist_get(
self, 0));
892 const int my = cpl_image_get_size_y(cpl_imagelist_get(
self, 0));
895 bug_if (
self == NULL);
896 bug_if (flat == NULL);
899 fim = cpl_image_load(flat, CPL_TYPE_UNSPECIFIED, 0, 0);
900 error_if(fim == NULL, cpl_error_get_code(),
"Could not load the flat "
901 "field from %s", flat);
904 nx = cpl_image_get_size_x(fim);
905 ny = cpl_image_get_size_y(fim);
907 error_if(ny != my, CPL_ERROR_INCOMPATIBLE_INPUT,
"Flat field Y-size "
908 "%d is incompatible with image Y-size %d", ny, my);
912 cpl_propertylist * plist
913 = cpl_propertylist_load_regexp(flat, 0,
"ESO DET WIN STARTX", 0);
916 cpl_propertylist_delete(plist);
919 cpl_msg_info(cpl_func,
"Windowing mode: flat between pixels %d "
920 "and %d", lx, ISAAC_MIN(mx, lx + nx - 1));
922 if (lx > mx || lx < 1) {
923 cpl_msg_warning(cpl_func,
"Cannot apply out of bounds flat field, "
924 "lx=%d > mx=%d", lx, mx);
925 cpl_image_delete(fim);
930 big_fim = cpl_image_new(mx, my, cpl_image_get_type(fim));
933 bug_if(cpl_image_threshold(big_fim, 1.0, 1.0, 1.0, 1.0));
936 bug_if (cpl_image_copy(big_fim, fim, lx, 1));
938 cpl_image_delete(fim);
948 bug_if(cpl_image_threshold(fim, sqrt(FLT_MIN), sqrt(FLT_MAX),
952 error_if (cpl_imagelist_divide_image(
self, fim),
953 cpl_error_get_code(),
"Could not apply the flat field");
958 cpl_image_delete(fim);
959 cpl_image_delete(big_fim);
972 static cpl_imagelist * isaac_spc_jitter_load(
const cpl_frameset * rawframes)
975 const cpl_frame * cur_frame = cpl_frameset_get_position_const(rawframes, 0);
976 cpl_propertylist * plist
977 = cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
979 cpl_imagelist *
self = NULL;
982 skip_if (plist == NULL);
985 skip_if (sval == NULL);
987 if (!strcmp(sval,
"INT")) isaac_spc_jitter_config.chopping = 0;
988 else if (!strcmp(sval,
"CUBE1")) isaac_spc_jitter_config.chopping = 1;
990 error_if(1, CPL_ERROR_UNSUPPORTED_MODE,
"Unsupported frame type: %s",
994 cpl_propertylist_empty(plist);
997 self = cpl_imagelist_load_frameset(rawframes, CPL_TYPE_FLOAT, 1, 0);
999 if (isaac_spc_jitter_config.chopping == 1) {
1000 cpl_imagelist * self_tmp
1001 = cpl_imagelist_load_frameset(rawframes, CPL_TYPE_FLOAT, 2, 0);
1002 const cpl_error_code error = cpl_imagelist_subtract(
self, self_tmp);
1004 cpl_imagelist_delete(self_tmp);
1010 cpl_propertylist_delete(plist);
1012 if (cpl_error_get_code()) {
1013 cpl_imagelist_delete(
self);
1029 cpl_vector * isaac_spc_jitter_get_offsets(
const cpl_frameset * rawframes)
1031 const int nraw = cpl_frameset_get_size(rawframes);
1032 cpl_vector * offsets = cpl_vector_new(nraw);
1033 cpl_propertylist * plist = NULL;
1036 bug_if (rawframes == NULL);
1041 for (i=0; i < nraw; i++) {
1042 const cpl_frame * cur_frame
1043 = cpl_frameset_get_position_const(rawframes, i);
1044 const char * filename = cpl_frame_get_filename(cur_frame);
1047 skip_if(filename == NULL);
1049 cpl_propertylist_delete(plist);
1050 plist = cpl_propertylist_load_regexp(filename, 0,
1051 "ESO SEQ CUMOFFSETY", 0);
1053 any_if(
"Could not load propertylist from %s", filename);
1055 yoff = cpl_propertylist_get_double(plist,
"ESO SEQ CUMOFFSETY");
1057 any_if(
"Could not get the offset from %s", filename);
1059 bug_if(cpl_vector_set(offsets, i, yoff));
1064 cpl_propertylist_delete(plist);
1066 if (cpl_error_get_code()) {
1067 cpl_vector_delete(offsets);
1114 static int * isaac_spc_jitter_classif(
const cpl_vector * offsets,
1117 const int nraw = cpl_vector_get_size(offsets);
1118 const double * pvect = cpl_vector_get_data_const(offsets);
1119 const double offmin = cpl_vector_get_min(offsets);
1120 const double offmax = cpl_vector_get_max(offsets);
1121 const double offset_thresh = 0.5 * (offmin + offmax);
1122 int * groups = cpl_calloc(nraw,
sizeof(
int));
1127 bug_if(offsets == NULL);
1128 bug_if(pngroups == NULL);
1132 error_if (offmin >= offmax, CPL_ERROR_DATA_NOT_FOUND,
1133 "The %d offset(s) all have the same value: %g", nraw, pvect[0]);
1141 while ((i+j < nraw) &&
1142 (!off_comp(pvect[i], pvect[i+j], offset_thresh))) j++;
1144 if (i+j >= nraw) i = nraw;
1148 while ((i+j+k < nraw)
1149 && (!off_comp(pvect[i+j], pvect[i+j+k], offset_thresh))
1153 for (l=i+j+k; l<nraw; l++) {
1154 if (off_comp(pvect[i+j], pvect[l], offset_thresh)) {
1160 if (last_group == 0) {
1161 for (l=0; l<j; l++) groups[i+l] = *pngroups + 1;
1162 for (l=0; l<k; l++) groups[i+j+l] = *pngroups + 2;
1166 for (l=0; l<j; l++) groups[i+l] = *pngroups + 1;
1167 for (l=0; l<nraw - (i+j); l++) groups[i+j+l] = *pngroups + 2;
1175 error_if (*pngroups & 1, CPL_ERROR_ILLEGAL_INPUT,
"Found an odd number "
1176 "(%d) of groups in the %d offsets", *pngroups, nraw);
1180 if (cpl_error_get_code()) {
1221 static cpl_imagelist * isaac_spc_jitter_saa_groups(
1222 cpl_imagelist * ilist,
1223 cpl_vector * offsets,
1226 cpl_vector ** abba_off)
1228 cpl_imagelist * abba;
1229 cpl_imagelist * group_list;
1230 cpl_image * tmp_ima;
1231 cpl_image ** combined;
1232 cpl_bivector * group_off;
1233 double * pgroup_off;
1241 if ((ilist == NULL) || (offsets == NULL) || (groups == NULL))
return NULL;
1244 nima = cpl_imagelist_get_size(ilist);
1245 poffsets = cpl_vector_get_data(offsets);
1248 abba = cpl_imagelist_new();
1249 *abba_off = cpl_vector_new(ngroups);
1250 pabba_off = cpl_vector_get_data(*abba_off);
1253 for (i=0; i<ngroups; i++) {
1257 group_list = cpl_imagelist_new();
1259 for (j=0; j<nima; j++) {
1260 if (i+1 == groups[j]) {
1262 if (k==0) pabba_off[i] = poffsets[j];
1264 if (fabs(pabba_off[i]-poffsets[j]) > 1e-3) saa = 1;
1266 tmp_ima = cpl_image_duplicate(cpl_imagelist_get(ilist, j));
1267 cpl_imagelist_set(group_list, tmp_ima, k);
1275 group_off = cpl_bivector_new(k);
1276 cpl_vector_fill(cpl_bivector_get_x(group_off), 0.0);
1277 pgroup_off = cpl_bivector_get_y_data(group_off);
1279 for (j=0; j<nima; j++) {
1280 if (i+1 == groups[j]) {
1281 pgroup_off[k] = poffsets[j];
1285 cpl_vector_subtract_scalar(cpl_bivector_get_y(group_off),
1288 cpl_msg_debug(cpl_func,
"Apply shift-and-add for group %d", i+1);
1289 if ((combined = cpl_geom_img_offset_saa(group_list,
1290 group_off, CPL_KERNEL_DEFAULT, 0, 0,
1291 CPL_GEOM_FIRST, NULL, NULL)) == NULL) {
1292 cpl_msg_error(cpl_func,
"Cannot shift and add group nb %d", i+1);
1293 cpl_imagelist_delete(group_list);
1294 cpl_bivector_delete(group_off);
1295 cpl_imagelist_delete(abba);
1296 cpl_vector_delete(*abba_off);
1299 cpl_bivector_delete(group_off);
1300 cpl_image_delete(combined[1]);
1301 cpl_imagelist_set(abba, combined[0], i);
1305 cpl_msg_debug(cpl_func,
"Apply averaging for group %d", i+1);
1306 if ((tmp_ima = cpl_imagelist_collapse_create(group_list)) == NULL) {
1307 cpl_msg_error(cpl_func,
"Cannot average group nb %d", i+1);
1308 cpl_imagelist_delete(group_list);
1309 cpl_imagelist_delete(abba);
1310 cpl_vector_delete(*abba_off);
1313 cpl_imagelist_set(abba, tmp_ima, i);
1315 cpl_imagelist_delete(group_list);
1331 static int isaac_spc_jitter_wavecal(
const char * arc,
1332 const cpl_image * ima,
1334 const cpl_frameset * raw)
1336 cpl_table * arc_tab;
1338 const cpl_frame * cur_frame;
1339 const char * cur_fname;
1340 computed_disprel * disprel;
1345 if (isaac_spc_jitter_config.wavecal_in == 2) {
1347 cpl_msg_error(cpl_func,
1348 "Missing arc for the wavelength calibration");
1349 return CPL_ERROR_UNSPECIFIED;
1351 cpl_msg_info(cpl_func,
"Get the wavelength from the ARC file");
1352 if ((arc_tab = cpl_table_load(arc, 1, 0)) == NULL) {
1353 cpl_msg_error(cpl_func,
"Cannot load the arc table");
1354 isaac_spc_jitter_config.wavecal_out = -1;
1355 return CPL_ERROR_UNSPECIFIED;
1357 isaac_spc_jitter_config.wavecal_a0 =
1358 cpl_table_get_double(arc_tab,
"WL_coefficients", 0, NULL);
1359 isaac_spc_jitter_config.wavecal_a1 =
1360 cpl_table_get_double(arc_tab,
"WL_coefficients", 1, NULL);
1361 isaac_spc_jitter_config.wavecal_a2 =
1362 cpl_table_get_double(arc_tab,
"WL_coefficients", 2, NULL);
1363 isaac_spc_jitter_config.wavecal_a3 =
1364 cpl_table_get_double(arc_tab,
"WL_coefficients", 3, NULL);
1365 cpl_table_delete(arc_tab);
1366 isaac_spc_jitter_config.wavecal_out = 2;
1367 isaac_spc_jitter_config.wavecal_cc = -1.0;
1372 cur_frame = cpl_frameset_get_position_const(raw, 0);
1373 cur_fname = cpl_frame_get_filename(cur_frame);
1376 cpl_msg_info(cpl_func,
"Compute the physical model");
1377 cpl_msg_indent_more();
1379 cpl_msg_error(cpl_func,
"cannot compute the physical model");
1380 isaac_spc_jitter_config.wavecal_out = -1;
1381 cpl_msg_indent_less();
1382 return CPL_ERROR_UNSPECIFIED;
1384 cpl_msg_info(cpl_func,
"f(x)=%g + %g*x + %g*x^2 + %g*x^3",
1385 phdisprel[0], phdisprel[1], phdisprel[2], phdisprel[3]);
1386 isaac_spc_jitter_config.wavecal_a0 = phdisprel[0];
1387 isaac_spc_jitter_config.wavecal_a1 = phdisprel[1];
1388 isaac_spc_jitter_config.wavecal_a2 = phdisprel[2];
1389 isaac_spc_jitter_config.wavecal_a3 = phdisprel[3];
1390 isaac_spc_jitter_config.wavecal_cc = -1.0;
1391 isaac_spc_jitter_config.wavecal_out = 0;
1392 cpl_msg_indent_less();
1395 if (isaac_spc_jitter_config.wavecal_in == 1) {
1397 if ((slit_width = isaac_get_slitwidth(cur_fname)) == -1) {
1398 cpl_msg_warning(cpl_func,
"cannot get the slit width");
1399 cpl_free(phdisprel);
1403 if ((order = isaac_find_order(cur_fname)) == -1) {
1404 cpl_msg_warning(cpl_func,
"cannot get the order");
1405 cpl_free(phdisprel);
1409 cpl_msg_info(cpl_func,
"Compute the wavelength with the sky lines");
1410 cpl_msg_indent_more();
1411 if ((disprel = spectro_compute_disprel(ima,
1412 isaac_spc_jitter_config.wavecal_rej_bottom,
1413 isaac_spc_jitter_config.wavecal_rej_top,
1414 isaac_spc_jitter_config.wavecal_rej_left,
1415 isaac_spc_jitter_config.wavecal_rej_right,
1416 isaac_spc_jitter_config.max_offset,
1417 isaac_has_thermal(cur_fname) > 0,
1418 "oh", oh, NULL, NULL, slit_width, order,
1419 (
int)(cpl_msg_get_level() == CPL_MSG_DEBUG),
1420 phdisprel)) == NULL) {
1421 cpl_msg_error(cpl_func,
"cannot compute the dispersion relation");
1422 cpl_free(phdisprel);
1423 cpl_msg_indent_less();
1426 cpl_msg_info(cpl_func,
"Cross correlation factor: %g", disprel->cc);
1427 cpl_msg_info(cpl_func,
"f(x)=%g + %g*x + %g*x^2 + %g*x^3",
1428 disprel->poly[0], disprel->poly[1], disprel->poly[2],
1430 isaac_spc_jitter_config.wavecal_a0 = disprel->poly[0];
1431 isaac_spc_jitter_config.wavecal_a1 = disprel->poly[1];
1432 isaac_spc_jitter_config.wavecal_a2 = disprel->poly[2];
1433 isaac_spc_jitter_config.wavecal_a3 = disprel->poly[3];
1434 isaac_spc_jitter_config.wavecal_cc = disprel->cc;
1435 isaac_spc_jitter_config.wavecal_out = 1;
1436 if (disprel->poly != NULL) cpl_free(disprel->poly);
1438 cpl_msg_indent_less();
1440 cpl_free(phdisprel);
1478 static cpl_imagelist * isaac_spc_jitter_nodded(cpl_imagelist * abba,
1479 cpl_vector * abba_off,
1480 cpl_vector ** nodded_off)
1482 cpl_imagelist * nodded;
1483 cpl_image * tmp_ima;
1486 double * pnodded_off;
1491 if ((abba == NULL) || (abba_off == NULL))
return NULL;
1494 nima = cpl_imagelist_get_size(abba);
1496 cpl_msg_error(cpl_func,
"Number of images should be even");
1501 if (isaac_spc_jitter_config.chopping == 0) {
1503 *nodded_off = cpl_vector_duplicate(abba_off);
1505 nodded = cpl_imagelist_new();
1506 for (i=0; i<(nima/2); i++) {
1508 tmp_ima = cpl_image_duplicate(cpl_imagelist_get(abba, 2*i));
1509 cpl_image_subtract(tmp_ima, cpl_imagelist_get(abba, 2*i+1));
1510 cpl_imagelist_set(nodded, tmp_ima, 2*i);
1512 tmp_ima = cpl_image_duplicate(cpl_imagelist_get(abba, 2*i+1));
1513 cpl_image_subtract(tmp_ima, cpl_imagelist_get(abba, 2*i));
1514 cpl_imagelist_set(nodded, tmp_ima, 2*i+1);
1517 }
else if (isaac_spc_jitter_config.chopping == 1) {
1519 *nodded_off = cpl_vector_new(nima/2);
1520 pnodded_off = cpl_vector_get_data(*nodded_off);
1521 pabba_off = cpl_vector_get_data(abba_off);
1523 nodded = cpl_imagelist_new();
1524 for (i=0; i<nima/2; i++) {
1525 if ((pabba_off[0]-pabba_off[1])*(pabba_off[2*i]-pabba_off[2*i+1])
1528 pnodded_off[i] = pabba_off[2*i];
1529 tmp_ima = cpl_image_duplicate(cpl_imagelist_get(abba, 2*i));
1530 cpl_image_subtract(tmp_ima, cpl_imagelist_get(abba, 2*i+1));
1531 cpl_image_divide_scalar(tmp_ima, 2.0);
1532 cpl_imagelist_set(nodded, tmp_ima, i);
1535 pnodded_off[i] = pabba_off[2*i+1];
1536 tmp_ima = cpl_image_duplicate(cpl_imagelist_get(abba, 2*i+1));
1537 cpl_image_subtract(tmp_ima, cpl_imagelist_get(abba, 2*i));
1538 cpl_image_divide_scalar(tmp_ima, 2.0);
1539 cpl_imagelist_set(nodded, tmp_ima, i);
1543 cpl_msg_error(cpl_func,
"Unsupported chopping mode");
1548 ref_off = cpl_vector_get(*nodded_off, 0);
1549 cpl_vector_subtract_scalar(*nodded_off, ref_off);
1563 static cpl_imagelist * isaac_spc_jitter_distor(
1564 cpl_imagelist * ilist,
1566 const char * startrace)
1568 cpl_polynomial * arc_poly;
1569 cpl_polynomial * sttr_poly;
1572 cpl_vector * profile;
1573 cpl_imagelist * warped_list;
1578 if (ilist == NULL)
return NULL;
1579 if ((arc == NULL) && (startrace == NULL))
return NULL;
1582 arc_poly = cpl_polynomial_new(2);
1584 cpl_msg_info(cpl_func,
"Get the arc distortion from the file");
1585 if ((tab = cpl_table_load(arc, 1, 0)) == NULL) {
1586 cpl_msg_error(cpl_func,
"cannot load the arc table");
1587 cpl_polynomial_delete(arc_poly);
1590 for (i=0; i<cpl_table_get_nrow(tab); i++) {
1591 if (cpl_table_get_column_type(tab,
"Degree_of_x") == CPL_TYPE_INT) {
1592 power[0] = cpl_table_get_int(tab,
"Degree_of_x", i, NULL);
1593 power[1] = cpl_table_get_int(tab,
"Degree_of_y", i, NULL);
1595 power[0] = cpl_table_get_double(tab,
"Degree_of_x", i, NULL);
1596 power[1] = cpl_table_get_double(tab,
"Degree_of_y", i, NULL);
1598 cpl_polynomial_set_coeff(arc_poly, power,
1599 cpl_table_get_double(tab,
"poly2d_coef", i, NULL));
1601 cpl_table_delete(tab);
1603 cpl_msg_info(cpl_func,
"Use the ID polynomial for the arc dist");
1606 cpl_polynomial_set_coeff(arc_poly, power, 1.0);
1610 sttr_poly = cpl_polynomial_new(2);
1611 if (startrace != NULL) {
1612 cpl_msg_info(cpl_func,
"Get the startrace distortion from the file");
1613 if ((tab = cpl_table_load(startrace, 1, 0)) == NULL) {
1614 cpl_msg_error(cpl_func,
"cannot load the startrace table");
1615 cpl_polynomial_delete(arc_poly);
1616 cpl_polynomial_delete(sttr_poly);
1619 for (i=0; i<cpl_table_get_nrow(tab); i++) {
1621 if (cpl_table_get_column_type(tab,
"Degree_of_x") == CPL_TYPE_INT) {
1622 power[0] = cpl_table_get_int(tab,
"Degree_of_x", i, NULL);
1623 power[1] = cpl_table_get_int(tab,
"Degree_of_y", i, NULL);
1625 power[0] = cpl_table_get_double(tab,
"Degree_of_x", i, NULL);
1626 power[1] = cpl_table_get_double(tab,
"Degree_of_y", i, NULL);
1628 cpl_polynomial_set_coeff(sttr_poly, power,
1629 cpl_table_get_double(tab,
"poly2d_coef", i, NULL));
1631 cpl_table_delete(tab);
1633 cpl_msg_info(cpl_func,
"Use the ID polynomial for the startrace dist");
1636 cpl_polynomial_set_coeff(sttr_poly, power, 1.0);
1640 profile = cpl_vector_new(CPL_KERNEL_DEF_SAMPLES);
1641 cpl_vector_fill_kernel_profile(profile, CPL_KERNEL_DEFAULT,
1642 CPL_KERNEL_DEF_WIDTH);
1645 warped_list = cpl_imagelist_new();
1646 for (i=0; i<cpl_imagelist_get_size(ilist); i++) {
1647 warped = cpl_image_duplicate(cpl_imagelist_get(ilist, i));
1648 if (cpl_image_warp_polynomial(warped, cpl_imagelist_get(ilist, i),
1649 arc_poly, sttr_poly, profile, CPL_KERNEL_DEF_WIDTH, profile,
1650 CPL_KERNEL_DEF_WIDTH) != CPL_ERROR_NONE) {
1651 cpl_msg_error(cpl_func,
"cannot correct the distortion");
1652 cpl_image_delete(warped);
1653 cpl_polynomial_delete(arc_poly);
1654 cpl_polynomial_delete(sttr_poly);
1655 cpl_vector_delete(profile);
1658 cpl_imagelist_set(warped_list, warped, i);
1660 cpl_vector_delete(profile);
1661 cpl_polynomial_delete(arc_poly);
1662 cpl_polynomial_delete(sttr_poly);
1675 static double isaac_spc_jitter_refine_offset(
const cpl_image * ima1,
1676 const cpl_image * ima2)
1681 if (ima1 == NULL)
return 10000.0;
1682 if (ima2 == NULL)
return 10000.0;
1685 if (irplib_spectrum_find_brightest(ima1, 0.0, NO_SHADOW, 0.0, 0,
1689 if (irplib_spectrum_find_brightest(ima2, 0.0, NO_SHADOW, 0.0, 0,
1704 static cpl_table * isaac_spc_jitter_extract(
const cpl_image * combined)
1706 int lo_dist, hi_dist, lo_width, hi_width, spec_pos;
1709 int low_side, up_side;
1714 cpl_image * colfluximg;
1719 cpl_bivector * toplot;
1723 if (combined == NULL)
return NULL;
1726 nx = cpl_image_get_size_x(combined);
1727 ny = cpl_image_get_size_y(combined);
1728 lo_dist = isaac_spc_jitter_config.extr_sky_lo_dist;
1729 hi_dist = isaac_spc_jitter_config.extr_sky_hi_dist;
1730 lo_width = isaac_spc_jitter_config.extr_sky_lo_width;
1731 hi_width = isaac_spc_jitter_config.extr_sky_hi_width;
1732 spec_pos = isaac_spc_jitter_config.extr_spec_pos;
1736 const int nthrow = cpl_vector_get_size(isaac_spc_jitter_config.throws);
1739 cpl_msg_error(cpl_func,
1740 "Need a throw value to detect the spectra !!");
1741 cpl_ensure(0, CPL_ERROR_DATA_NOT_FOUND, NULL);
1744 for (i=0; i < nthrow; i++){
1745 const int throw = (int)cpl_vector_get(isaac_spc_jitter_config.throws,
1747 if (irplib_spectrum_find_brightest(combined,
throw, TWO_SHADOWS,
1748 0.0, 0, &pos) == 0)
break;
1749 if (irplib_spectrum_find_brightest(combined,
throw, ONE_SHADOW,
1750 0.0, 0, &pos) == 0)
break;
1753 cpl_msg_error(cpl_func,
"Could not detect the spectrum using %d "
1756 cpl_vector_dump(isaac_spc_jitter_config.throws, stderr);
1757 cpl_plot_image(
"",
"",
"", combined);
1759 cpl_ensure(0, CPL_ERROR_DATA_NOT_FOUND, NULL);
1761 spec_pos = (int)pos;
1762 cpl_msg_info(cpl_func,
"Spectrum detected at y = %d", spec_pos);
1768 low_side = spec_pos - (int)(isaac_spc_jitter_config.extr_spec_width/2);
1769 up_side = low_side + isaac_spc_jitter_config.extr_spec_width;
1770 if (up_side < low_side) {
1771 (void)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1772 "Spectrum zone invalid: low=%d > up=%d",
1777 (void)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1778 "Spectrum zone lower limit too low: "
1779 "%d < 1", low_side);
1783 (void)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1784 "Spectrum zone upper limit too high: "
1785 "%d > ny=%d", up_side, ny);
1790 colfluximg = cpl_image_collapse_window_create(combined, 1, low_side,
1793 if (cpl_image_count_rejected(colfluximg) == up_side - low_side + 1) {
1794 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1795 "Combined image has undefined flux "
1796 "from column %d to %d", low_side, up_side);
1797 cpl_image_delete(colfluximg);
1802 if (lo_dist < 0) lo_dist = 2*isaac_spc_jitter_config.extr_spec_width;
1803 if (hi_dist < 0) hi_dist = 2*isaac_spc_jitter_config.extr_spec_width;
1804 sky_pos[1] = spec_pos - lo_dist;
1805 sky_pos[0] = sky_pos[1] - lo_width;
1806 sky_pos[2] = spec_pos + hi_dist;
1807 sky_pos[3] = sky_pos[2] + hi_width;
1810 sky = cpl_vector_new(nx);
1811 psky = cpl_vector_get_data(sky);
1812 if (((sky_pos[0] < 1) || (lo_width == 0)) &&
1813 ((sky_pos[3] <= ny) && (hi_width > 0))) {
1814 for (i=0; i<nx; i++) {
1815 psky[i] = cpl_image_get_median_window(combined, i+1,
1816 sky_pos[2], i+1, sky_pos[3]);
1818 }
else if (((sky_pos[3] > ny) || (hi_width == 0))
1819 && ((sky_pos[0] > 0) && (lo_width > 0))) {
1820 for (i=0; i<nx; i++) {
1821 psky[i] = cpl_image_get_median_window(combined, i+1,
1822 sky_pos[0], i+1, sky_pos[1]);
1824 }
else if ((lo_width != 0) && (hi_width != 0)
1825 && (sky_pos[0] > 0) && (sky_pos[3] <= ny)) {
1826 for (i=0; i<nx; i++) {
1827 psky[i] = cpl_image_get_median_window(combined, i+1,
1828 sky_pos[2], i+1, sky_pos[3]);
1829 psky[i] += cpl_image_get_median_window(combined, i+1,
1830 sky_pos[0], i+1, sky_pos[1]);
1834 for (i=0; i<nx; i++) psky[i] = 0.0;
1838 spec = cpl_vector_new(nx);
1839 pspec = cpl_vector_get_data(spec);
1840 for (i=0; i<nx; i++) {
1842 const double colflux = cpl_image_get(colfluximg, i+1, 1, &is_bad);
1846 cpl_msg_warning(cpl_func,
"Combined image has undefined flux in "
1850 - psky[i] * isaac_spc_jitter_config.extr_spec_width;
1853 cpl_image_delete(colfluximg);
1856 wl = cpl_vector_new(nx);
1857 pwl = cpl_vector_get_data(wl);
1858 for (i=0; i<nx; i++) {
1859 pwl[i] = isaac_spc_jitter_config.wavecal_a0 +
1860 isaac_spc_jitter_config.wavecal_a1 * (i+1) +
1861 isaac_spc_jitter_config.wavecal_a2 * (i+1) * (i+1) +
1862 isaac_spc_jitter_config.wavecal_a3 * (i+1) * (i+1) * (i+1);
1866 if (isaac_spc_jitter_config.plot > 0) {
1867 toplot = cpl_bivector_wrap_vectors(wl, spec);
1868 cpl_plot_bivector(NULL,
"t 'Spectrum' w lines", NULL, toplot);
1869 cpl_bivector_unwrap_vectors(toplot);
1870 toplot = cpl_bivector_wrap_vectors(wl, sky);
1871 cpl_plot_bivector(NULL,
"t 'Sky' w lines", NULL, toplot);
1872 cpl_bivector_unwrap_vectors(toplot);
1876 out = cpl_table_new(nx);
1877 cpl_table_new_column(out,
"X_coordinate", CPL_TYPE_DOUBLE);
1878 cpl_table_new_column(out,
"Extracted_spectrum_value", CPL_TYPE_DOUBLE);
1879 cpl_table_new_column(out,
"Sky_spectrum", CPL_TYPE_DOUBLE);
1880 for (i=0; i<nx; i++) {
1881 cpl_table_set_double(out,
"X_coordinate", i, pwl[i]);
1882 cpl_table_set_double(out,
"Extracted_spectrum_value", i, pspec[i]);
1883 cpl_table_set_double(out,
"Sky_spectrum", i, psky[i]);
1885 cpl_vector_delete(wl);
1886 cpl_vector_delete(spec);
1887 cpl_vector_delete(sky);
1903 static int isaac_spc_jitter_std(
const char * seds_file,
1904 const char * stdstars,
1905 const cpl_frame * frame,
1909 double surface = CPL_MATH_PI * 400 * 400;
1910 cpl_propertylist * plist;
1911 double dit, ra, dec, magnitude, cent_wl;
1913 const int nelem = cpl_table_get_nrow(tab);
1916 cpl_bivector * spec_biv;
1918 cpl_vector * efficiency;
1919 cpl_vector * mag_zero;
1920 cpl_vector * conversion;
1924 if (seds_file == NULL)
return CPL_ERROR_UNSPECIFIED;
1925 if (stdstars == NULL)
return CPL_ERROR_UNSPECIFIED;
1926 if (frame == NULL)
return CPL_ERROR_UNSPECIFIED;
1927 if (tab == NULL)
return CPL_ERROR_UNSPECIFIED;
1928 if (cpl_error_get_code())
return CPL_ERROR_UNSPECIFIED;
1931 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(frame),0))==NULL) {
1932 cpl_msg_error(cpl_func,
"Cannot load the property list");
1933 return CPL_ERROR_UNSPECIFIED;
1938 if (cpl_error_get_code()) {
1939 cpl_msg_error(cpl_func,
"Cannot get DIT");
1940 cpl_propertylist_delete(plist);
1941 return CPL_ERROR_UNSPECIFIED;
1943 cpl_msg_info(cpl_func,
"DIT: %g", dit);
1947 == ISAAC_BAND_UNKNOWN) {
1948 cpl_msg_error(cpl_func,
"Cannot associate the filter to a BB one");
1949 cpl_propertylist_delete(plist);
1950 return CPL_ERROR_UNSPECIFIED;
1957 if (cpl_error_get_code()) {
1958 cpl_msg_error(cpl_func,
"Cannot get star position");
1959 cpl_propertylist_delete(plist);
1960 return CPL_ERROR_UNSPECIFIED;
1962 cpl_msg_info(cpl_func,
"RA: %g DEC: %g", ra, dec);
1967 if (irplib_stdstar_find_star(stdstars, ra, dec,
1970 &isaac_spc_jitter_config.starname,
1971 &isaac_spc_jitter_config.sptype,
1972 NULL, NULL, NULL, 2.0)) {
1973 cpl_msg_error(cpl_func,
"Cannot find the star in catalogs");
1974 cpl_propertylist_delete(plist);
1975 return CPL_ERROR_UNSPECIFIED;
1980 cpl_propertylist_delete(plist);
1981 (void)strncpy(isaac_spc_jitter_config.filter_ref,
1983 (isaac_spc_jitter_config.filter)),
1985 cpl_msg_info(cpl_func,
"Magnitude: %g", magnitude);
1986 isaac_spc_jitter_config.std_magnitude = magnitude;
1990 case ISAAC_BAND_Z: cent_wl = CENT_WL_BAND_Z;
break;
1991 case ISAAC_BAND_SZ: cent_wl = CENT_WL_BAND_SZ;
break;
1992 case ISAAC_BAND_J: cent_wl = CENT_WL_BAND_J;
break;
1993 case ISAAC_BAND_JBLOCK: cent_wl = CENT_WL_BAND_J;
break;
1994 case ISAAC_BAND_SH: cent_wl = CENT_WL_BAND_H;
break;
1995 case ISAAC_BAND_SK: cent_wl = CENT_WL_BAND_K;
break;
1996 case ISAAC_BAND_SL: cent_wl = CENT_WL_BAND_SL;
break;
1997 case ISAAC_BAND_M: cent_wl = CENT_WL_BAND_M;
break;
1999 cpl_msg_error(cpl_func,
"Unsupported band: %s",
2001 return CPL_ERROR_UNSPECIFIED;
2003 cpl_msg_info(cpl_func,
"Center of band : %g microns", cent_wl);
2006 sed = irplib_stdstar_get_sed(seds_file, isaac_spc_jitter_config.sptype);
2008 cpl_msg_error(cpl_func,
"Cannot get the SED");
2009 return CPL_ERROR_UNSPECIFIED;
2013 wl = cpl_vector_wrap(nelem, cpl_table_get_data_double(tab,
2015 spec = cpl_vector_wrap(nelem, cpl_table_get_data_double(tab,
2016 "Extracted_spectrum_value"));
2017 spec_biv = cpl_bivector_wrap_vectors(wl, spec);
2020 if ((conversion = irplib_stdstar_get_conversion(spec_biv, dit, surface,
2021 4.5, magnitude)) == NULL) {
2022 cpl_msg_error(cpl_func,
"Cannot get the conversion");
2023 cpl_bivector_unwrap_vectors(spec_biv);
2024 cpl_vector_unwrap(spec);
2025 cpl_vector_unwrap(wl);
2026 cpl_bivector_delete(sed);
2027 return CPL_ERROR_UNSPECIFIED;
2031 if ((mag_zero = irplib_stdstar_get_mag_zero(sed,
2032 cpl_bivector_get_x(spec_biv), cent_wl)) == NULL) {
2033 cpl_msg_error(cpl_func,
"Cannot get the 0 magnitude spectrum");
2034 cpl_bivector_unwrap_vectors(spec_biv);
2035 cpl_vector_unwrap(spec);
2036 cpl_vector_unwrap(wl);
2037 cpl_bivector_delete(sed);
2038 cpl_vector_delete(conversion);
2039 return CPL_ERROR_UNSPECIFIED;
2041 cpl_bivector_unwrap_vectors(spec_biv);
2042 cpl_vector_unwrap(spec);
2043 cpl_vector_unwrap(wl);
2044 cpl_bivector_delete(sed);
2047 for (i=0; i<cpl_vector_get_size(mag_zero); i++) {
2048 if (cpl_vector_get(mag_zero, i) < 1e-19) {
2049 cpl_vector_set(mag_zero, i, 1.0);
2054 efficiency = cpl_vector_duplicate(conversion);
2055 if (cpl_vector_divide(efficiency, mag_zero) != CPL_ERROR_NONE) {
2056 cpl_msg_error(cpl_func,
"Missing SED info in this wavelength range");
2057 cpl_vector_delete(conversion);
2058 cpl_vector_delete(mag_zero);
2059 cpl_vector_delete(efficiency);
2060 return CPL_ERROR_UNSPECIFIED;
2064 for (i=0; i<cpl_vector_get_size(mag_zero); i++) {
2065 if (cpl_vector_get(mag_zero, i) == 1.0) {
2066 cpl_vector_set(efficiency, i, 0.0);
2069 cpl_vector_delete(mag_zero);
2072 cpl_table_wrap_double(tab, cpl_vector_get_data(efficiency),
"Efficiency");
2073 cpl_table_wrap_double(tab, cpl_vector_get_data(conversion),
"Conversion");
2074 cpl_vector_unwrap(efficiency);
2075 cpl_vector_unwrap(conversion);
2078 if (isaac_spc_jitter_config.plot > 0) {
2079 wl = cpl_vector_wrap(nelem, cpl_table_get_data_double(tab,
2081 spec = cpl_vector_wrap(nelem, cpl_table_get_data_double(tab,
2083 spec_biv = cpl_bivector_wrap_vectors(wl, spec);
2084 cpl_plot_bivector(NULL,
"t 'Conversion' w lines",
2086 cpl_bivector_unwrap_vectors(spec_biv);
2087 cpl_vector_unwrap(spec);
2088 spec = cpl_vector_wrap(nelem, cpl_table_get_data_double(tab,
2090 spec_biv = cpl_bivector_wrap_vectors(wl, spec);
2091 cpl_plot_bivector(NULL,
"t 'Efficiency' w lines", NULL, spec_biv);
2092 cpl_bivector_unwrap_vectors(spec_biv);
2093 cpl_vector_unwrap(spec);
2094 cpl_vector_unwrap(wl);
2113 cpl_error_code isaac_spc_jitter_save(cpl_frameset * set,
2114 const cpl_image * ima,
2115 const cpl_image * contrib,
2116 const cpl_table * tab,
2117 const cpl_parameterlist * parlist)
2120 cpl_propertylist * qclist = cpl_propertylist_new();
2121 cpl_propertylist * paflist = NULL;
2122 const cpl_frame * ref_frame;
2123 char * qc_str = NULL;
2124 const char * procat;
2126 = cpl_vector_get_size(isaac_spc_jitter_config.intensities);
2128 cpl_propertylist * xtlist = cpl_propertylist_new();
2130 bug_if(cpl_propertylist_append_string(xtlist,
"EXTNAME",
2131 "Contribution Map"));
2132 bug_if(contrib == NULL);
2136 if (isaac_spc_jitter_config.filter[0] != (
char)0)
2137 bug_if(cpl_propertylist_append_string(qclist,
"ESO QC FILTER OBS",
2138 isaac_spc_jitter_config.filter));
2140 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC DISPCO1",
2141 isaac_spc_jitter_config.wavecal_a0));
2142 cpl_propertylist_append_double(qclist,
"ESO QC DISPCO2",
2143 isaac_spc_jitter_config.wavecal_a1);
2144 cpl_propertylist_append_double(qclist,
"ESO QC DISPCO3",
2145 isaac_spc_jitter_config.wavecal_a2);
2146 cpl_propertylist_append_double(qclist,
"ESO QC DISPCO4",
2147 isaac_spc_jitter_config.wavecal_a3);
2148 cpl_propertylist_append_double(qclist,
"ESO QC WLEN",
2149 isaac_spc_jitter_config.wavecal_a0 +
2150 isaac_spc_jitter_config.wavecal_a1 * 512 +
2151 isaac_spc_jitter_config.wavecal_a2 * 512 *
2153 isaac_spc_jitter_config.wavecal_a3 * 512 *
2155 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC DISP XCORR",
2156 isaac_spc_jitter_config.wavecal_cc));
2157 if (isaac_spc_jitter_config.wavecal_out == 0) {
2158 cpl_propertylist_append_string(qclist,
"ESO QC WLMETHOD",
2160 }
else if (isaac_spc_jitter_config.wavecal_out == 1) {
2161 cpl_propertylist_append_string(qclist,
"ESO QC WLMETHOD",
2163 }
else if (isaac_spc_jitter_config.wavecal_out == 2) {
2164 cpl_propertylist_append_string(qclist,
"ESO QC WLMETHOD",
2167 for (i = 0; i < nintens; i++) {
2169 = cpl_vector_get(isaac_spc_jitter_config.intensities, i);
2171 qc_str = cpl_sprintf(
"ESO QC SPEC INTENS%d", i+1);
2172 cpl_propertylist_append_double(qclist, qc_str, intens);
2178 if (isaac_spc_jitter_config.std_mode == 1) {
2179 bug_if(cpl_propertylist_append_string(qclist,
"ESO QC STDNAME",
2180 isaac_spc_jitter_config.starname ?
2181 isaac_spc_jitter_config.starname :
2183 bug_if(cpl_propertylist_append_string(qclist,
"ESO QC SPECTYPE",
2184 isaac_spc_jitter_config.sptype ?
2185 isaac_spc_jitter_config.sptype :
2187 cpl_propertylist_append_double(qclist,
"ESO QC STARMAG",
2188 isaac_spc_jitter_config.std_magnitude);
2189 if (isaac_spc_jitter_config.filter_ref[0] != (
char)0)
2190 cpl_propertylist_append_string(qclist,
"ESO QC FILTER REF",
2191 isaac_spc_jitter_config.filter_ref);
2195 cpl_propertylist_update_double(qclist,
"CRVAL1",
2196 isaac_spc_jitter_config.wavecal_a0);
2197 cpl_propertylist_update_double(qclist,
"CRVAL2", 1.0);
2198 cpl_propertylist_update_double(qclist,
"CRPIX1", 1.0);
2199 cpl_propertylist_update_double(qclist,
"CRPIX2", 1.0);
2200 cpl_propertylist_update_double(qclist,
"CDELT1",
2201 isaac_spc_jitter_config.wavecal_a1);
2202 cpl_propertylist_update_double(qclist,
"CDELT2", 1.0);
2203 cpl_propertylist_update_string(qclist,
"CTYPE1",
"LINEAR");
2204 cpl_propertylist_update_string(qclist,
"CTYPE2",
"LINEAR");
2205 if (cpl_propertylist_has(qclist,
"CD1_1")) {
2206 cpl_propertylist_update_double(qclist,
"CD1_1",
2207 isaac_spc_jitter_config.wavecal_a1);
2209 cpl_propertylist_insert_after_double(qclist,
"CTYPE2",
"CD1_1",
2210 isaac_spc_jitter_config.wavecal_a1);
2212 if (cpl_propertylist_has(qclist,
"CD2_2")) {
2213 cpl_propertylist_update_double(qclist,
"CD2_2", 1.0);
2215 cpl_propertylist_insert_after_double(qclist,
"CD1_1",
"CD2_2", 1.0);
2219 procat = isaac_spc_jitter_config.std_mode == 1 ?
2220 ISAAC_SPC_JITTER_COMB_STD : ISAAC_SPC_JITTER_COMB;
2222 irplib_dfs_save_image(set, parlist, set, ima, CPL_BPP_IEEE_FLOAT,
2223 RECIPE_STRING, procat, qclist, NULL,
2224 PACKAGE
"/" PACKAGE_VERSION,
2225 RECIPE_STRING
"_combined" CPL_DFS_FITS);
2228 skip_if (cpl_image_save(contrib, RECIPE_STRING
"_combined" CPL_DFS_FITS,
2229 CPL_BPP_16_UNSIGNED, xtlist, CPL_IO_EXTEND));
2233 const char * procatt = isaac_spc_jitter_config.std_mode == 1 ?
2234 ISAAC_SPC_JITTER_EXTR_STD : ISAAC_SPC_JITTER_EXTR;
2236 irplib_dfs_save_table(set, parlist, set, tab, NULL, RECIPE_STRING,
2237 procatt, qclist, NULL,
2238 PACKAGE
"/" PACKAGE_VERSION,
2239 RECIPE_STRING
"_extracted" CPL_DFS_FITS);
2243 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
2246 paflist = cpl_propertylist_load_regexp(cpl_frame_get_filename(ref_frame),
2247 0,
"^(ARCFILE|MJD-OBS|INSTRUME"
2248 "|ESO TPL ID|ESO TPL NEXP"
2249 "|ESO DPR CATG|ESO DPR TECH"
2250 "|ESO DPR TYPE|DATE-OBS"
2251 "|ESO INS GRAT NAME"
2252 "|ESO INS GRAT WLEN"
2253 "|ESO INS OPTI1 ID|ESO OBS ID"
2254 "|ESO OBS TARG NAME)$", 0);
2255 skip_if (paflist == NULL);
2258 bug_if(cpl_propertylist_append(paflist, qclist));
2259 cpl_propertylist_empty(qclist);
2262 cpl_propertylist_update_string(paflist, CPL_DFS_PRO_CATG, procat);
2265 skip_if(cpl_dfs_save_paf(
"ISAAC", RECIPE_STRING, paflist,
2266 RECIPE_STRING CPL_DFS_PAF));
2270 cpl_propertylist_delete(xtlist);
2271 cpl_propertylist_delete(paflist);
2272 cpl_propertylist_delete(qclist);
2275 return CPL_ERROR_NONE;
2288 static int off_comp(
double off1,
double off2,
double thresh)
2290 return (off1 > thresh && off2 < thresh) || (off1 < thresh && off2 > thresh)
int isaac_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
double isaac_pfits_get_win_startx(const cpl_propertylist *plist)
find out the WIN STARTX keyword
const char * isaac_pfits_get_frame_type(const cpl_propertylist *plist)
find out the frame type
double isaac_pfits_get_ra(const cpl_propertylist *plist)
find out the RA
double isaac_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
double isaac_pfits_get_dec(const cpl_propertylist *plist)
find out the DEC
const char * isaac_pfits_get_arm(const cpl_propertylist *plist)
find out the arm which is active
const char * isaac_pfits_get_filter(const cpl_propertylist *plist)
find out the filter
double * isaac_get_disprel_estimate(const char *filename, cpl_size poly_deg)
Estimate the instrument wavelength range.
const char * isaac_extract_filename(const cpl_frameset *self, const char *tag)
Extract the filename of the first frame of the given tag.
const char * isaac_std_band_name(isaac_band band)
Return a band name.
cpl_image * isaac_oddeven_correct(const cpl_image *in)
Correct the odd/even in an image.
isaac_band isaac_get_bbfilter(const char *f)
Get the broad band filter.
cpl_frameset * isaac_extract_frameset(const cpl_frameset *self, const char *tag)
Extract the frames with the given tag from a frameset.
isaac_band isaac_get_associated_filter(const char *f)
Get the broad band filter.