47#include "irplib_wlxcorr.h"
48#include "irplib_spectrum.h"
50#include "eris_ifu_error.h"
51#include "eris_ifu_sky_tweak.h"
52#include "eris_ifu_lambda_corr.h"
53#include "eris_ifu_functions.h"
54#include "eris_utils.h"
59#define HC_K 14387.7512979
60#define PLANCK(lambda,t) (pow((lambda),-5.0) / (exp(HC_K/((lambda) * fabs(t))) - 1.))
64double * cont_sky_sig=NULL,
66 * cont_object_sig=NULL,
67 * line_object_sig=NULL,
72double *spectrum_lambda=NULL;
73double *spectrum_value=NULL;
74double *thermal_background=NULL;
79static cpl_imagelist * eris_ifu_priv_sky_stretch(
84 int resampling_method,
86static cpl_polynomial * eris_ifu_stretch_get_poly(
87 const cpl_vector * obj,
88 const cpl_vector * sky,
91 cpl_bivector ** matching_lines) ;
92static cpl_imagelist * eris_ifu_stretch_apply_linear(
94 cpl_polynomial * stretch) ;
95static cpl_imagelist * eris_ifu_stretch_apply_spline(
97 cpl_polynomial * stretch) ;
98static int eris_ifu_stretch_check(
101 cpl_imagelist * new_sky,
103static int eris_ifu_stretch_plot_positions_differences(
104 cpl_bivector * matching_lines,
105 cpl_bivector * new_matching_lines) ;
106static cpl_bivector * eris_ifu_strech_get_matching_lines(
107 const cpl_vector * obj,
108 const cpl_vector * sky,
113static void amoeba(
double**,
double y[],
int,
double,
114 double (*funk)(
double []),
int *) ;
115static double amotry(
double **,
double y[],
double psum[],
int,
116 double (*funk)(
double []),
int,
double);
118static double fitsky(
double *) ;
119static double fitbkd(
double *) ;
121static int eris_ifu_sky_tweak_identify_lines_cont(cpl_vector *,
int *,
int *,
123static void eris_ifu_plot_arrays(
double *,
double *,
double *,
int) ;
124static cpl_bivector * eris_ifu_sky_tweak_thermal_bgd(cpl_bivector *,
double) ;
125static double eris_ifu_sky_tweak_get_mean_wo_outliers(
const cpl_vector *) ;
126static cpl_error_code eris_ifu_sky_tweak_get_spectra(
const cpl_imagelist *,
127 const cpl_imagelist *,
const cpl_vector *,
const cpl_image *,
128 const int, cpl_bivector **, cpl_bivector **,
int *) ;
129static cpl_error_code eris_ifu_sky_tweak_get_spectra_simple(
const cpl_imagelist *,
130 const cpl_imagelist *,
const cpl_image *, cpl_vector **, cpl_vector **);
131static cpl_bivector * eris_ifu_sky_tweak_correct_vibrational_trans(
132 cpl_bivector *, cpl_bivector *,
int,
int) ;
133double **matrix(
int nrow,
int ncol);
134void free_matrix(
double ** matrix,
int nrow);
156 cpl_vector * obj_spec ;
157 cpl_vector * sky_spec ;
160 if (obj == NULL)
return -1 ;
166 if (eris_ifu_sky_tweak_get_spectra_simple(obj, obj, mask, &obj_spec,
167 &sky_spec) != CPL_ERROR_NONE) {
168 cpl_msg_error(cpl_func,
"Cannot extract the spectra from cubes") ;
169 cpl_image_delete(mask) ;
173 cpl_plot_vector(
"set grid;set xlabel 'pix';",
"t 'CUBE BGD' w lines",
"",
176 cpl_vector_delete(obj_spec) ;
177 cpl_vector_delete(sky_spec) ;
204 const cpl_propertylist * header,
210 int stretch_resampling,
212 cpl_imagelist ** new_sky)
214 cpl_imagelist * new_obj ;
216 cpl_bivector * obj_spec = NULL;
217 cpl_bivector * sky_spec = NULL;
218 cpl_bivector * thermal_backg ;
219 cpl_bivector * vscales ;
220 cpl_vector * lambda ;
221 int nx, ny, nz, ix, kx, snx, sny, snz, kmax, first_nonan ;
224 cpl_ensure(obj, CPL_ERROR_NULL_INPUT, NULL);
225 cpl_ensure(sky, CPL_ERROR_NULL_INPUT, NULL);
226 cpl_ensure(header, CPL_ERROR_NULL_INPUT, NULL);
227 cpl_ensure(new_sky, CPL_ERROR_NULL_INPUT, NULL);
228 cpl_ensure(min_frac > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
229 cpl_ensure(stretch_resampling > 0 && stretch_resampling < 3, CPL_ERROR_ILLEGAL_INPUT, NULL);
231 nx = cpl_image_get_size_x(cpl_imagelist_get_const(obj, 0));
232 ny = cpl_image_get_size_y(cpl_imagelist_get_const(obj, 0));
233 nz = cpl_imagelist_get_size(obj);
234 snx = cpl_image_get_size_x(cpl_imagelist_get_const(sky, 0));
235 sny = cpl_image_get_size_y(cpl_imagelist_get_const(sky, 0));
236 snz = cpl_imagelist_get_size(sky);
237 if (nx!=snx || ny!=sny || nz!=snz) {
238 cpl_msg_error(__func__,
"Illegal inputs") ;
239 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
245 *new_sky = eris_ifu_priv_sky_stretch(obj, sky, .3, stretch_degree,
246 stretch_resampling, plot) ;
248 *new_sky = cpl_imagelist_duplicate(sky) ;
253 if (nz != cpl_vector_get_size(lambda)) {
254 cpl_msg_error(__func__,
"Illegal inputs") ;
255 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
261 if (cpl_msg_get_level() == CPL_MSG_DEBUG)
262 cpl_image_save(mask,
"mask.fits", CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
267 eris_ifu_sky_tweak_get_spectra(obj, *new_sky, lambda, mask, 0,
268 &obj_spec, &sky_spec, &first_nonan);
271 vscales = eris_ifu_sky_tweak_correct_vibrational_trans(obj_spec,
272 sky_spec, skip_last, plot);
273 if (cpl_msg_get_level() == CPL_MSG_DEBUG && plot)
274 cpl_plot_bivector(
"set title \"SCALES\";",
"w lines",
"",vscales);
277 thermal_backg = eris_ifu_sky_tweak_thermal_bgd(obj_spec, 1.0);
280 if (thermal_backg == NULL) {
282 cpl_msg_indent_more() ;
283 cpl_msg_warning(__func__,
284 "Thermal Bgd failed, re-try by clipping highest values") ;
285 thermal_backg = eris_ifu_sky_tweak_thermal_bgd(obj_spec, 0.98);
286 if (thermal_backg == NULL) {
287 cpl_msg_warning(__func__,
288 "Recovery failed - skip the thermal background correction");
291 cpl_msg_info(__func__,
"Recovery succeeded");
293 cpl_msg_indent_less() ;
296 if (cpl_msg_get_level() == CPL_MSG_DEBUG && plot)
297 cpl_plot_bivector(
"set title \"Th. bgd\";",
"w lines",
"",thermal_backg);
300 new_obj = cpl_imagelist_duplicate(obj);
301 kmax = cpl_vector_get_size(cpl_bivector_get_x_const(obj_spec));
303 for (ix=0; ix<nz; ix++) {
304 if ((kx < kmax ) && (cpl_vector_get(lambda,ix)==cpl_vector_get(
305 cpl_bivector_get_x_const(obj_spec),kx))) {
307 if (thermal_backg != NULL) {
308 cpl_image_subtract_scalar(cpl_imagelist_get(*new_sky ,ix),
309 cpl_vector_get(cpl_bivector_get_y_const(thermal_backg),
315 cpl_image_multiply_scalar(cpl_imagelist_get(*new_sky, ix),
316 cpl_vector_get(cpl_bivector_get_y_const(vscales), kx));
319 cpl_image_subtract(cpl_imagelist_get(new_obj, ix),
320 cpl_imagelist_get(*new_sky, ix));
323 if (tbsub && thermal_backg != NULL) {
324 cpl_image_subtract_scalar(cpl_imagelist_get(new_obj, ix),
325 cpl_vector_get(cpl_bivector_get_y_const(
326 thermal_backg), kx));
331 cpl_bivector_delete(obj_spec);
332 cpl_bivector_delete(sky_spec);
333 if (thermal_backg != NULL) cpl_bivector_delete(thermal_backg);
334 cpl_bivector_delete(vscales);
335 cpl_vector_delete(lambda);
337 cpl_image_delete(mask);
354static void eris_ifu_plot_arrays(
360 cpl_vector ** vectors ;
363 if (obj == NULL || sky == NULL) return ;
366 vectors = cpl_malloc(3*
sizeof(cpl_vector*)) ;
367 vectors[0] = cpl_vector_wrap(arr_size, wl) ;
368 vectors[1] = cpl_vector_wrap(arr_size, obj) ;
369 vectors[2] = cpl_vector_wrap(arr_size, sky) ;
371 CPL_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
372 cpl_plot_vectors(
"set grid;set xlabel 'Wavelength (microns)';",
373 "t 'Obj and Sky sub-band' w lines",
"",
374 (
const cpl_vector **)vectors,
378 cpl_vector_unwrap(vectors[0]) ;
379 cpl_vector_unwrap(vectors[1]) ;
380 cpl_vector_unwrap(vectors[2]) ;
393static cpl_bivector * eris_ifu_sky_tweak_thermal_bgd(
394 cpl_bivector * spectrum,
397 cpl_bivector * result ;
398 cpl_vector * spectrum_v ;
399 cpl_vector * thermal_v ;
401 cpl_vector * sorted_y ;
403 const int nsimplex = ndim + 1;
405 double p_init[ndim+1];
406 double * lspectrum = NULL,
410 int i, j, ix, loop, niter, new_size, skip, input_size ;
411 double min, max, tmp, diff, limit, clip_limit ;
414 if (spectrum == NULL) {
415 cpl_msg_error(__func__,
"NULL inputs") ;
416 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
419 if ((clip_rate < 0.5) || (clip_rate > 1.0)) {
420 cpl_msg_error(__func__,
"Invalid clip rate: %g", clip_rate) ;
421 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
431 input_size = cpl_bivector_get_size(spectrum) ;
433 lspectrum = cpl_bivector_get_x_data(spectrum);
434 vspectrum = cpl_bivector_get_y_data(spectrum);
435 spectrum_lambda=cpl_malloc(input_size*
sizeof(
double));
436 spectrum_value=cpl_malloc(input_size*
sizeof(
double));
437 thermal_background= cpl_malloc(input_size*
sizeof(
double));
440 if (clip_rate < 1.0) {
441 sorted_y = cpl_vector_duplicate(cpl_bivector_get_y(spectrum));
442 cpl_vector_sort(sorted_y, CPL_SORT_ASCENDING);
443 clip_limit = cpl_vector_get(sorted_y,
444 cpl_vector_get_size(sorted_y) * clip_rate);
445 cpl_vector_delete(sorted_y) ;
451 for (ix=0; ix < input_size ; ix++)
if (vspectrum[ix] != 0.0)
break;
455 for (i=ix+skip; i<input_size; i++) {
457 && (vspectrum[i] <= clip_limit) ) {
458 spectrum_lambda[new_size] = lspectrum[i];
459 spectrum_value[new_size] = vspectrum[i];
460 if (vspectrum[i] < min) { min = vspectrum[i]; }
465 for (ix=new_size; ix >= 0; ix--)
if (vspectrum[ix] != 0.0)
break;
467 spectrum_size = ix-skip;
469 y_amoeba=cpl_malloc((nsimplex+1)*
sizeof(
double));
470 x_amoeba=cpl_malloc((ndim+1)*
sizeof(
double));
471 p = matrix(nsimplex+1,ndim+1);
474 p_init[2] = spectrum_value[spectrum_size-1];
480 for (loop=0; loop<20; loop++) {
485 for (i=2; i<nsimplex+1; i++) {
486 for (j=1; j<ndim+1; j++) p[i][j] = p[1][j];
488 for (i=2; i<nsimplex+1; i++) p[i][i-1] = p[i][i-1] * 1.2;
489 for (i=1; i<nsimplex+1; i++) {
490 for (j=1; j<ndim+1; j++) x_amoeba[j] = p[i][j];
491 y_amoeba[i] = fitbkd(x_amoeba);
493 amoeba(p, y_amoeba, 3, 1.e-5, fitbkd, &niter);
495 cpl_msg_error(__func__,
"Function minimization failed") ;
499 cpl_free(spectrum_lambda);
500 cpl_free(spectrum_value);
501 cpl_free(thermal_background);
502 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
505 spectrum_v = cpl_vector_wrap(spectrum_size, spectrum_value);
506 thermal_v = cpl_vector_wrap(spectrum_size, thermal_background);
507 tmp_v = cpl_vector_duplicate(spectrum_v);
508 cpl_vector_subtract(tmp_v, thermal_v);
509 limit = cpl_vector_get_median(tmp_v) + 2. * cpl_vector_get_stdev(tmp_v);
510 cpl_vector_delete(tmp_v);
511 cpl_vector_unwrap(spectrum_v);
512 cpl_vector_unwrap(thermal_v);
516 for (i=0; i<spectrum_size; i++) {
517 diff = spectrum_value[i] - thermal_background[i];
519 spectrum_lambda[new_size] = spectrum_lambda[i];
520 spectrum_value[new_size] = spectrum_value[i];
521 if (spectrum_value[i] < min) min = spectrum_value[i];
525 spectrum_size = new_size;
528 for (i=0; i<spectrum_size; i++) {
529 tmp = PLANCK(spectrum_lambda[i], p[1][3]);
530 if (tmp > max) max = tmp;
532 if (fabs(max) < 1e-90) {
533 cpl_msg_error(__func__,
"Cannot determine thermal Background") ;
537 cpl_free(spectrum_lambda);
538 cpl_free(spectrum_value);
539 cpl_free(thermal_background);
540 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
544 for (i=0; i<input_size; i++) {
545 spectrum_lambda[i] = lspectrum[i];
546 spectrum_value[i] = vspectrum[i];
547 tmp = PLANCK(spectrum_lambda[i], p[1][3]);
548 thermal_background[i] = p[1][1] + tmp / max * p[1][2];
550 thermal_v = cpl_vector_wrap(input_size, thermal_background);
551 tmp_v = cpl_vector_duplicate(thermal_v);
552 cpl_vector_unwrap(thermal_v);
554 result = cpl_bivector_wrap_vectors(
555 cpl_vector_duplicate(cpl_bivector_get_x_const(spectrum)), tmp_v);
560 cpl_free(spectrum_lambda);
561 cpl_free(spectrum_value);
562 cpl_free(thermal_background);
573static double eris_ifu_sky_tweak_get_mean_wo_outliers(
const cpl_vector * vdata)
579 const double * data ;
581 double avg, median, stdev, clip;
582 int nr_data, i, nr_i;
584 nr_data = cpl_vector_get_size(vdata);
585 data = cpl_vector_get_data_const(vdata);
586 tmpv1 = cpl_vector_new(nr_data);
587 tmpv1_data = cpl_vector_get_data(tmpv1);
589 median = cpl_vector_get_median_const(vdata);
590 for (i=0; i<nr_data; i++) tmpv1_data[i] = fabs(data[i] - median);
591 cpl_vector_sort(tmpv1, CPL_SORT_ASCENDING);
592 clip = cpl_vector_get(tmpv1, (
int) .8*nr_data);
595 median = cpl_vector_get_median_const(tmpv3);
596 stdev = cpl_vector_get_stdev(tmpv3);
598 for (i=0; i<nr_data; i++) {
599 if ((data[i] < median + 3. * stdev) && (data[i] > median - 3. * stdev)){
600 tmpv1_data[nr_i] = data[i];
604 tmpv4 = cpl_vector_wrap(nr_i, tmpv1_data);
605 avg = cpl_vector_get_mean(tmpv4);
607 cpl_vector_delete(tmpv1);
608 cpl_vector_delete(tmpv2);
609 cpl_vector_delete(tmpv3);
610 cpl_vector_unwrap(tmpv4);
621static cpl_error_code eris_ifu_sky_tweak_get_spectra_simple(
622 const cpl_imagelist *
object,
623 const cpl_imagelist * sky,
624 const cpl_image * mask,
625 cpl_vector ** obj_spec,
626 cpl_vector ** sky_spec)
628 cpl_vector * intobj ;
629 cpl_vector * intsky ;
630 const cpl_image * oimg ;
631 const cpl_image * simg ;
632 double * intobj_data ;
633 double * intsky_data ;
638 double mpix, opix, spix;
639 int nx, ny, nz, snx, sny, snz, ix, iy, iz, found,
640 m_is_rejected, o_is_rejected, s_is_rejected;
643 nx = cpl_image_get_size_x(cpl_imagelist_get_const(
object, 0));
644 ny = cpl_image_get_size_y(cpl_imagelist_get_const(
object, 0));
645 nz = cpl_imagelist_get_size(
object);
646 snx = cpl_image_get_size_x(cpl_imagelist_get_const(sky, 0));
647 sny = cpl_image_get_size_y(cpl_imagelist_get_const(sky, 0));
648 snz = cpl_imagelist_get_size(sky);
651 if (nx!=snx || ny!=sny || nz!=snz) {
652 cpl_msg_error(__func__,
"Illegal inputs") ;
653 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
654 return CPL_ERROR_ILLEGAL_INPUT ;
658 intobj = cpl_vector_new(nz);
659 intsky = cpl_vector_new(snz);
660 intobj_data = cpl_vector_get_data(intobj);
661 intsky_data = cpl_vector_get_data(intsky);
662 vo = cpl_malloc(nx * ny *
sizeof(
double));
663 vs = cpl_malloc(nx * ny *
sizeof(
double));
666 for (iz = 0; iz <nz; iz++) {
667 oimg = cpl_imagelist_get_const(
object, iz);
668 simg = cpl_imagelist_get_const(sky, iz);
670 for (ix = 1; ix<=nx; ix++) {
671 for (iy = 1; iy<=ny; iy++) {
672 mpix = cpl_image_get(mask, ix, iy, &m_is_rejected);
673 opix = cpl_image_get(oimg, ix, iy, &o_is_rejected);
674 spix = cpl_image_get(simg, ix, iy, &s_is_rejected);
675 if ( mpix > .5 && m_is_rejected == 0 && o_is_rejected == 0 &&
676 s_is_rejected == 0 ) {
684 if (found >= nx*ny/4.) {
685 ovec = cpl_vector_wrap(found, vo);
686 svec = cpl_vector_wrap(found, vs);
688 if (found < nx*ny/2. ) {
689 intobj_data[iz] = cpl_vector_get_median(ovec);
690 intsky_data[iz] = cpl_vector_get_median(svec);
692 intobj_data[iz] = eris_ifu_sky_tweak_get_mean_wo_outliers(ovec);
693 intsky_data[iz] = eris_ifu_sky_tweak_get_mean_wo_outliers(svec);
695 cpl_vector_unwrap(ovec);
696 cpl_vector_unwrap(svec);
698 intobj_data[iz] = 0.;
699 intsky_data[iz] = 0.;
708 return CPL_ERROR_NONE;
718static cpl_error_code eris_ifu_sky_tweak_get_spectra(
719 const cpl_imagelist *
object,
720 const cpl_imagelist * sky,
721 const cpl_vector * lambda,
722 const cpl_image * mask,
724 cpl_bivector ** obj_spectrum_ptr,
725 cpl_bivector ** sky_spectrum_ptr,
728 cpl_bivector * obj_spectrum ;
729 cpl_bivector * sky_spectrum ;
730 cpl_vector * intobj ;
731 cpl_vector * intsky ;
732 cpl_vector * new_lambda ;
733 cpl_vector * new_intobj ;
734 cpl_vector * new_intsky ;
735 const cpl_image * oimg ;
736 const cpl_image * simg ;
737 double * intobj_data ;
738 double * intsky_data ;
741 double * new_lambda_d ;
742 double * new_intobj_d ;
743 double * new_intsky_d ;
744 const double * lambda_d ;
747 double mpix, opix, spix;
748 int nx, ny, nz, snx, sny, snz, ix, iy, iz, ni, found,
749 nr_valid_int, m_is_rejected, o_is_rejected,
754 if (first_nonan==NULL) {
755 cpl_msg_error(__func__,
"Illegal inputs") ;
756 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
757 return CPL_ERROR_ILLEGAL_INPUT ;
762 nx = cpl_image_get_size_x(cpl_imagelist_get_const(
object, 0));
763 ny = cpl_image_get_size_y(cpl_imagelist_get_const(
object, 0));
764 nz = cpl_imagelist_get_size(
object);
765 snx = cpl_image_get_size_x(cpl_imagelist_get_const(sky, 0));
766 sny = cpl_image_get_size_y(cpl_imagelist_get_const(sky, 0));
767 snz = cpl_imagelist_get_size(sky);
769 if (nx!=snx || ny!=sny || nz!=snz) {
770 cpl_msg_error(__func__,
"Illegal inputs") ;
771 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
772 return CPL_ERROR_ILLEGAL_INPUT ;
775 if (nz != cpl_vector_get_size(lambda)) {
776 cpl_msg_error(__func__,
"Illegal inputs") ;
777 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
778 return CPL_ERROR_ILLEGAL_INPUT ;
781 intobj = cpl_vector_new(cpl_vector_get_size(lambda));
782 intsky = cpl_vector_new(cpl_vector_get_size(lambda));
783 intobj_data = cpl_vector_get_data(intobj);
784 intsky_data = cpl_vector_get_data(intsky);
786 vo = cpl_malloc(nx * ny *
sizeof(
double));
787 vs = cpl_malloc(nx * ny *
sizeof(
double));
790 for (iz = 0; iz <nz; iz++) {
791 oimg = cpl_imagelist_get_const(
object, iz);
792 simg = cpl_imagelist_get_const(sky, iz);
794 for (ix = 1; ix<=nx; ix++) {
795 for (iy = 1; iy<=ny; iy++) {
796 mpix = cpl_image_get(mask, ix, iy, &m_is_rejected);
797 opix = cpl_image_get(oimg, ix, iy, &o_is_rejected);
798 spix = cpl_image_get(simg, ix, iy, &s_is_rejected);
799 if ( mpix > .5 && m_is_rejected == 0 && o_is_rejected == 0 &&
800 s_is_rejected == 0 ) {
808 if (found >= nx*ny/4.) {
809 if (*first_nonan < 0) *first_nonan = iz ;
811 ovec = cpl_vector_wrap(found, vo);
812 svec = cpl_vector_wrap(found, vs);
814 if (found < nx*ny/2. ) {
815 intobj_data[iz] = cpl_vector_get_median(ovec);
816 intsky_data[iz] = cpl_vector_get_median(svec);
818 intobj_data[iz] = eris_ifu_sky_tweak_get_mean_wo_outliers(ovec);
819 intsky_data[iz] = eris_ifu_sky_tweak_get_mean_wo_outliers(svec);
821 cpl_vector_unwrap(ovec);
822 cpl_vector_unwrap(svec);
825 intobj_data[iz] = 0./0.;
826 intsky_data[iz] = 0./0.;
829 intobj_data[iz] = 0.;
830 intsky_data[iz] = 0.;
836 new_lambda = cpl_vector_new(nr_valid_int);
837 new_intobj = cpl_vector_new(nr_valid_int);
838 new_intsky = cpl_vector_new(nr_valid_int);
839 new_lambda_d=cpl_vector_get_data(new_lambda);
840 new_intobj_d=cpl_vector_get_data(new_intobj);
841 new_intsky_d=cpl_vector_get_data(new_intsky);
842 lambda_d=cpl_vector_get_data_const(lambda);
845 for (iz=0 ; iz<nz; iz++) {
846 if ((! isnan(intobj_data[iz])) && ni < nr_valid_int) {
847 new_lambda_d[ni] = lambda_d[iz];
848 new_intobj_d[ni] = intobj_data[iz];
849 new_intsky_d[ni] = intsky_data[iz];
853 obj_spectrum = cpl_bivector_wrap_vectors(new_lambda, new_intobj) ;
854 sky_spectrum = cpl_bivector_wrap_vectors(
855 cpl_vector_duplicate(new_lambda), new_intsky);
857 cpl_vector_delete(intobj);
858 cpl_vector_delete(intsky);
860 obj_spectrum = cpl_bivector_wrap_vectors(cpl_vector_duplicate(lambda),
862 sky_spectrum = cpl_bivector_wrap_vectors(cpl_vector_duplicate(lambda),
868 *obj_spectrum_ptr = obj_spectrum;
869 *sky_spectrum_ptr = sky_spectrum;
870 return CPL_ERROR_NONE;
880static cpl_bivector * eris_ifu_sky_tweak_correct_vibrational_trans(
881 cpl_bivector * obj_spectrum,
882 cpl_bivector * sky_spectrum,
886 cpl_bivector * result ;
888 double * lambda_boundaries ;
889 const char ** labels ;
890 const double * lambda ;
891 const double * intobj ;
892 const double * intsky ;
896 double * line_interpolate_object ;
897 double * line_interpolate_sky ;
899 cpl_vector * tmp_vec ;
900 cpl_vector * sky_lines_map_vec ;
901 double median, stdev ;
902 int i, ix, il, lx, cx, nr_lambda, nr_samples, nr_boundaries,
903 cont_start, cont_end ;
904 cpl_error_code errCode;
907 if (obj_spectrum == NULL || sky_spectrum == NULL) {
908 cpl_msg_error(__func__,
"NULL inputs") ;
909 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
912 if (cpl_bivector_get_size(obj_spectrum) !=
913 cpl_bivector_get_size(sky_spectrum)) {
914 cpl_msg_error(__func__,
"Illegal inputs") ;
915 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
920 nr_lambda = cpl_bivector_get_size(obj_spectrum);
921 lambda = cpl_vector_get_data_const(cpl_bivector_get_x_const(obj_spectrum));
922 intobj = cpl_vector_get_data_const(cpl_bivector_get_y_const(obj_spectrum));
923 intsky = cpl_vector_get_data_const(cpl_bivector_get_y_const(sky_spectrum));
924 median = stdev = 0.0 ;
927 for (ix=0; ix<nr_lambda; ix++) {
928 if (fabs(lambda[ix] -
929 cpl_vector_get(cpl_bivector_get_x_const(sky_spectrum), ix))
931 cpl_msg_error(__func__,
"Illegal inputs") ;
932 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
940 lambda_boundaries = cpl_malloc(nr_boundaries *
sizeof(
double)) ;
941 labels = cpl_malloc((nr_boundaries-1) *
sizeof(
char*)) ;
944 lambda_boundaries = cpl_malloc(nr_boundaries *
sizeof(
double)) ;
945 labels = cpl_malloc((nr_boundaries-1) *
sizeof(
char*)) ;
947 lambda_boundaries[0] = 0.780 ; labels[0] =
"" ;
948 lambda_boundaries[1] = 0.824 ; labels[1] =
"" ;
949 lambda_boundaries[2] = 0.873 ; labels[2] =
"" ;
950 lambda_boundaries[3] = 0.926 ; labels[3] =
"" ;
951 lambda_boundaries[4] = 0.964 ; labels[4] =
"" ;
952 lambda_boundaries[5] = 1.014 ; labels[5] =
"4-1 transitions" ;
953 lambda_boundaries[6] = 1.067 ; labels[6] =
"5-2 transitions" ;
954 lambda_boundaries[7] = 1.125 ; labels[7] =
"6-3 transitions" ;
955 lambda_boundaries[8] = 1.196 ; labels[8] =
"7-4 transitions" ;
956 lambda_boundaries[9] = 1.252 ; labels[9] =
" 02 transitions" ;
957 lambda_boundaries[10] = 1.289 ; labels[10] =
"8-5 transitions" ;
958 lambda_boundaries[11] = 1.400 ; labels[11] =
"2-0 transitions" ;
959 lambda_boundaries[12] = 1.472 ; labels[12] =
"3-1 transitions" ;
960 lambda_boundaries[13] = 1.5543 ; labels[13] =
"4-2 transitions" ;
961 lambda_boundaries[14] = 1.6356 ; labels[14] =
"5-3 transitions" ;
962 lambda_boundaries[15] = 1.7253 ; labels[15] =
"6-4 transitions" ;
963 lambda_boundaries[16] = 1.840 ; labels[16] =
"7-5 transitions" ;
964 lambda_boundaries[17] = 1.9570 ; labels[17] =
"8-6 transitions" ;
965 lambda_boundaries[18] = 2.095 ; labels[18] =
"9-7 transitions" ;
967 lambda_boundaries[19] = 2.460 ;
969 lambda_boundaries[19] = 2.30 ; labels[19] =
"final bit" ;
970 lambda_boundaries[20] = 2.460 ;
974 scalings = cpl_malloc(nr_boundaries *
sizeof(
double)) ;
975 for (ix=0; ix<nr_boundaries; ix++) scalings[ix] = 0.;
977 array_wls = cpl_malloc(nr_lambda *
sizeof(
double)) ;
978 array_obj = cpl_malloc(nr_lambda *
sizeof(
double)) ;
979 array_sky = cpl_malloc(nr_lambda *
sizeof(
double)) ;
982 for (ix = 0; ix<nr_boundaries-1; ix++) {
983 cpl_msg_debug(__func__,
"Sub-band %2d: %s", ix+1, labels[ix]) ;
984 cpl_msg_indent_more() ;
988 for (il=0; il<nr_lambda; il++) {
989 if ((lambda[il] >= lambda_boundaries[ix] ) &&
990 (lambda[il] < lambda_boundaries[ix+1]) ) {
994 intsky[il] == 0. || intobj[il] == 0. ) {
995 cpl_msg_indent_less() ;
999 array_wls[nr_samples] = lambda[il];
1000 array_obj[nr_samples] = intobj[il];
1001 array_sky[nr_samples] = intsky[il];
1005 cpl_msg_debug(__func__,
"Found %d samples", nr_samples) ;
1008 if (nr_samples <= 20) {
1009 cpl_msg_indent_less() ;
1012 if (plot==ix+1 && cpl_msg_get_level() == CPL_MSG_DEBUG)
1013 eris_ifu_plot_arrays(array_wls, array_obj, array_sky, nr_samples);
1016 tmp_vec = cpl_vector_wrap(nr_samples, array_sky);
1017 median = cpl_vector_get_median_const(tmp_vec);
1018 stdev = cpl_vector_get_stdev(tmp_vec);
1019 cpl_vector_unwrap(tmp_vec);
1020 cpl_msg_debug(__func__,
"Sky Stats - Med: %g Stdev: %g", median, stdev);
1023 sky_lines_map_vec = cpl_vector_new(nr_samples) ;
1024 cpl_vector_fill(sky_lines_map_vec, 0.0) ;
1025 for (i=0; i<nr_samples; i++) {
1026 if (array_sky[i] > median+stdev)
1027 cpl_vector_set(sky_lines_map_vec, i, 10.0) ;
1029 if (plot==ix+1 && cpl_msg_get_level() == CPL_MSG_DEBUG)
1030 cpl_plot_vector(
"set grid;set xlabel 'Samples';set ylabel 'Map';",
1031 "t 'Sky lines map' w lines",
"", sky_lines_map_vec);
1034 tmp_vec=cpl_vector_filter_lowpass_create(sky_lines_map_vec,
1035 CPL_LOWPASS_LINEAR,2);
1036 cpl_vector_delete(sky_lines_map_vec);
1037 sky_lines_map_vec = tmp_vec ;
1039 if (plot==ix+1 && cpl_msg_get_level() == CPL_MSG_DEBUG)
1040 cpl_plot_vector(
"set grid;set xlabel 'Samples';set ylabel 'Map';",
1041 "t 'Smoothed sky lines map' w lines",
"",
1045 eris_ifu_sky_tweak_identify_lines_cont(sky_lines_map_vec,
1046 &cont_start, &cont_end, &cont_size, &lines_size) ;
1047 if (lines_size == 0) {
1048 cpl_msg_warning(__func__,
"No line region found") ;
1049 cpl_vector_delete(sky_lines_map_vec);
1050 cpl_msg_indent_less() ;
1056 cont_sky_sig = cpl_malloc(cont_size *
sizeof(
double));
1057 cont_object_sig = cpl_malloc(cont_size *
sizeof(
double));
1058 cont_lambda = cpl_malloc(cont_size *
sizeof(
double));
1059 line_sky_sig = cpl_malloc(lines_size *
sizeof(
double));
1060 line_object_sig = cpl_malloc(lines_size *
sizeof(
double));
1061 line_lambda = cpl_malloc(lines_size *
sizeof(
double));
1065 for (i = cont_start; i <= cont_end ; i++) {
1066 if (cpl_vector_get(sky_lines_map_vec, i) > 0.) {
1067 line_sky_sig[lx] = array_sky[i];
1068 line_object_sig[lx] = array_obj[i];
1069 line_lambda[lx] = array_wls[i];
1072 cont_sky_sig[cx] = array_sky[i];
1073 cont_object_sig[cx] = array_obj[i];
1074 cont_lambda[cx] = array_wls[i];
1082 const int nsimplex = ndim + 1;
1084 double *x_amoeba = NULL,
1089 y_amoeba = cpl_malloc((nsimplex+1) *
sizeof(
double));
1090 x_amoeba = cpl_malloc((ndim+1) *
sizeof(
double));
1091 p = matrix(nsimplex+1,ndim+1);
1095 for (ip=1; ip<nsimplex+1; ip++) {
1096 for (jp=1; jp<ndim+1; jp++) {
1097 x_amoeba[jp] = p[ip][jp];
1099 y_amoeba[ip] = fitsky(x_amoeba);
1101 amoeba(p, y_amoeba, ndim, 1.e-5, fitsky, &niter );
1103 cpl_msg_error(__func__,
"Function minimization failed") ;
1107 cpl_free(spectrum_lambda);
1108 cpl_free(spectrum_value);
1109 cpl_free(thermal_background);
1110 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
1114 flineres = cpl_malloc(lines_size *
sizeof(
double));
1123 line_interpolate_object = cpl_calloc(lines_size,
sizeof(
double));
1125 cont_lambda, cont_object_sig, cont_size,
1126 line_lambda, line_interpolate_object, lines_size, 2);
1127 if (errCode != CPL_ERROR_NONE) {
1128 printf(
"ERROR: The function eris_ifu_1d_interpolation called in eris_ifu_sky_tweak_correct_vibrational_trans returned the error %d\n", errCode);
1129 printf(
"%s\n", cpl_error_get_message_default(errCode));
1132 line_interpolate_sky = cpl_calloc(lines_size,
sizeof(
double));
1134 cont_lambda, cont_sky_sig, cont_size,
1135 line_lambda, line_interpolate_sky, lines_size, 2);
1136 if (errCode != CPL_ERROR_NONE) {
1137 printf(
"ERROR: The function eris_ifu_1d_interpolation called in eris_ifu_sky_tweak_correct_vibrational_trans returned the error %d\n", errCode);
1138 printf(
"%s\n", cpl_error_get_message_default(errCode));
1141 for (i=0; i<lines_size; i++) {
1142 flineres[i] = (line_object_sig[i] -
1143 line_interpolate_object[i]) -
1144 (line_sky_sig[i] - line_interpolate_sky[i]) * scale;
1147 tmp_vec = cpl_vector_wrap(lines_size, flineres);
1148 median = cpl_vector_get_median_const(tmp_vec);
1149 stdev = cpl_vector_get_stdev(tmp_vec);
1150 cpl_vector_unwrap(tmp_vec) ;
1153 for (i=0; i<lines_size; i++) {
1154 if ( fabs(flineres[i] - median) <= (3 * stdev) ) {
1158 cpl_msg_debug(__func__,
"Outliers: %d", lines_size-clip_cnt) ;
1160 if ((clip_cnt != lines_size) && (clip_cnt >= 3)) {
1162 for (i=0; i<lines_size; i++) {
1163 if ( fabs(flineres[i] - median) <= (3 * stdev) ) {
1164 line_sky_sig[lx] = line_sky_sig[i];
1165 line_object_sig[lx] =
1167 line_lambda[lx] = line_lambda[i];
1172 cpl_msg_debug(__func__,
"2. Lines size: %d", lines_size) ;
1176 for (ip=1; ip<nsimplex+1; ip++) {
1177 for (jp=1; jp<ndim+1; jp++) x_amoeba[jp] = p[ip][jp];
1178 y_amoeba[ip] = fitsky(x_amoeba);
1180 amoeba(p, y_amoeba, ndim, 1.e-5, fitsky, &niter);
1182 cpl_msg_error(__func__,
"Function minimization failed") ;
1186 cpl_free(spectrum_lambda);
1187 cpl_free(spectrum_value);
1188 cpl_free(thermal_background);
1189 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
1194 cpl_msg_debug(__func__,
"Scale: %g", scale) ;
1195 scalings[ix] = scale;
1197 cpl_vector_delete(sky_lines_map_vec);
1198 free_matrix(p, nsimplex+1);
1201 cpl_free(cont_sky_sig);
1202 cpl_free(line_sky_sig);
1203 cpl_free(cont_object_sig);
1204 cpl_free(line_object_sig);
1205 cpl_free(cont_lambda);
1206 cpl_free(line_lambda);
1208 cpl_free(line_interpolate_object);
1209 cpl_free(line_interpolate_sky);
1211 cpl_msg_indent_less() ;
1218 double valid_scales[nr_boundaries];
1219 cpl_vector *valid_scales_v = NULL;
1220 for (ix=0; ix<nr_boundaries; ix++) {
1221 if (scalings[ix] != 0.0 ) {
1222 valid_scales[nr_valid] = scalings[ix];
1226 valid_scales_v = cpl_vector_wrap(nr_valid, valid_scales);
1227 median = cpl_vector_get_median_const(valid_scales_v);
1228 stdev = cpl_vector_get_stdev(valid_scales_v);
1230 for (ix=0; ix<nr_boundaries; ix++) {
1231 if (scalings[ix] != 0.0 ) {
1232 if (fabs(valid_scales[v_ix] - median) > 2 * stdev) {
1238 if (valid_scales_v != NULL) {
1239 cpl_vector_unwrap(valid_scales_v);
1240 valid_scales_v = NULL;
1244 double *scale0_lambda = NULL,
1245 *scale0_value = NULL,
1247 cpl_vector *scale_v = NULL;
1249 scale0_lambda = cpl_malloc(nr_lambda *
sizeof(
double));
1250 scale0_value = cpl_malloc(nr_lambda *
sizeof(
double));
1253 for (il=0; il<nr_lambda; il++) {
1254 for (ix = 0; ix<nr_boundaries-1; ix++) {
1255 if (scalings[ix] != 0.) {
1256 if ((lambda[il] >= lambda_boundaries[ix] ) &&
1257 (lambda[il] < lambda_boundaries[ix+1]) ) {
1258 scale0_lambda[scale0_size] = lambda[il];
1259 scale0_value[scale0_size] = scalings[ix];
1265 cpl_free(scalings) ;
1266 cpl_free(lambda_boundaries) ;
1271 scale = cpl_calloc(nr_lambda,
sizeof(
double));
1273 double* lambda_tmp = (
double*) lambda;
1275 scale0_lambda, scale0_value, scale0_size,
1276 lambda_tmp, scale, nr_lambda, 2);
1277 if (errCode != CPL_ERROR_NONE) {
1278 printf(
"ERROR: The function eris_ifu_1d_interpolation called in eris_ifu_sky_tweak_correct_vibrational_trans returned the error %d\n", errCode);
1279 printf(
"%s\n", cpl_error_get_message_default(errCode));
1282 scale_v = cpl_vector_wrap(nr_lambda, scale);
1284 if (scale0_lambda != NULL) cpl_free(scale0_lambda);
1285 if (scale0_value != NULL) cpl_free(scale0_value);
1286 result = cpl_bivector_wrap_vectors(
1287 cpl_vector_duplicate(cpl_bivector_get_x_const(obj_spectrum)),
1290 cpl_free(array_wls) ;
1291 cpl_free(array_obj) ;
1292 cpl_free(array_sky) ;
1304static int eris_ifu_sky_tweak_identify_lines_cont(
1305 cpl_vector * sky_lines_map_vec,
1308 int * local_cont_size,
1309 int * local_lines_size)
1311 int current_line_size, nr_samples, i ;
1316 current_line_size = 0 ;
1317 nr_samples = cpl_vector_get_size(sky_lines_map_vec) ;
1322 *local_cont_size = 0;
1323 *local_lines_size = 0;
1324 for (i=0; i<nr_samples; i++) {
1325 if (cpl_vector_get(sky_lines_map_vec, i) > 0.) {
1328 if (*cont_start == -1)
continue;
1329 current_line_size++;
1332 if (*cont_start == -1) *cont_start = i;
1334 (*local_cont_size)++;
1335 *local_lines_size += current_line_size;
1336 current_line_size = 0;
1339 cpl_msg_debug(__func__,
"Cont [%d, %d] size: %d / Lines size: %d",
1340 *cont_start, *cont_end, *local_cont_size, *local_lines_size) ;
1344static double fitsky(
double *p) {
1346 double *cont_sky = NULL,
1347 *cont_object = NULL;
1350 cpl_error_code errCode;
1359 cont_sky = cpl_calloc(lines_size,
sizeof(
double));
1361 line_lambda, cont_sky, lines_size, 2);
1362 if (errCode != CPL_ERROR_NONE) {
1363 printf(
"ERROR: The function eris_ifu_1d_interpolation called in fitsky returned the error %d\n", errCode);
1364 printf(
"%s\n", cpl_error_get_message_default(errCode));
1367 cont_object = cpl_calloc(lines_size,
sizeof(
double));
1369 line_lambda, cont_object, lines_size, 2);
1370 if (errCode != CPL_ERROR_NONE) {
1371 printf(
"ERROR: The function eris_ifu_1d_interpolation called in fitsky returned the error %d\n", errCode);
1372 printf(
"%s\n", cpl_error_get_message_default(errCode));
1375 for (ix=0; ix<lines_size; ix++) {
1376 double diff = (line_object_sig[ix] - cont_object[ix]) -
1377 (line_sky_sig[ix] - cont_sky[ix]) * p[1];
1389static double fitbkd(
double *p) {
1395 tmp = cpl_malloc(spectrum_size *
sizeof(
double));
1398 for (i=0; i<spectrum_size; i++) {
1399 tmp[i] = PLANCK(spectrum_lambda[i], p[3]);
1406 for (i=0; i<spectrum_size; i++) {
1407 thermal_background[i] = p[1] + tmp[i] / max * fabs(p[2]);
1410 for (i=0; i<spectrum_size; i++) {
1411 thermal_background[i] = tmp[i];
1416 for (i=0; i<spectrum_size; i++) {
1417 result += (spectrum_value[i] - thermal_background[i]) *
1418 (spectrum_value[i] - thermal_background[i]);
1421 if (tmp != NULL) cpl_free(tmp);
1429 for (j=1;j<=ndim;j++) {\
1430 for (sum=0.0,i=1;i<=mpts;i++) sum += p[i][j];\
1432#define SWAP(a,b) {swap=(a);(a)=(b);(b)=swap;}
1438 double (*funk)(
double []),
1441 int i,ihi,ilo,inhi,j,mpts=ndim+1;
1442 double rtol, sum, swap, ysave, ytry, *psum = NULL, d;
1444 psum=cpl_calloc(ndim+1,
sizeof(
double));
1449 ihi = y[1]>y[2] ? (inhi=2,1) : (inhi=1,2);
1450 for (i=1;i<=mpts;i++) {
1451 if (y[i] <= y[ilo]) {
1454 if (y[i] > y[ihi]) {
1457 }
else if (y[i] > y[inhi] && i != ihi) inhi=i;
1459 d = fabs(y[ihi])+fabs(y[ilo]);
1463 rtol=2.0*fabs(y[ihi]-y[ilo])/d;
1467 for (i=1;i<=ndim;i++) SWAP(p[1][i],p[ilo][i])
1470 if (*nfunk >= 5000) {
1476 ytry=amotry(p,y,psum,ndim,funk,ihi,-1.0);
1478 ytry=amotry(p,y,psum,ndim,funk,ihi,2.0);
1479 else if (ytry >= y[inhi]) {
1481 ytry=amotry(p,y,psum,ndim,funk,ihi,0.5);
1482 if (ytry >= ysave) {
1483 for (i=1;i<=mpts;i++) {
1485 for (j=1;j<=ndim;j++) {
1486 p[i][j]=psum[j]=0.5*(p[i][j]+p[ilo][j]);
1503static double amotry(
1508 double (*funk)(
double []),
1513 double fac1,fac2,ytry,*ptry=NULL;
1515 ptry=cpl_calloc(ndim+1,
sizeof(
double));
1516 fac1=(1.0-fac)/ndim;
1518 for (j=1;j<=ndim;j++) ptry[j]=psum[j]*fac1-p[ihi][j]*fac2;
1520 if (ytry < y[ihi]) {
1522 for (j=1;j<=ndim;j++) {
1523 psum[j] += ptry[j]-p[ihi][j];
1554static cpl_imagelist * eris_ifu_priv_sky_stretch(
1555 cpl_imagelist * obj,
1556 cpl_imagelist * sky,
1559 int resampling_method,
1562 cpl_vector * obj_spec ;
1563 cpl_vector * sky_spec ;
1564 cpl_imagelist * new_sky ;
1566 cpl_polynomial * transf_poly ;
1567 cpl_polynomial * new_transf_poly ;
1568 cpl_bivector * matching_lines ;
1569 cpl_bivector * new_matching_lines ;
1572 if (obj == NULL || sky == NULL)
return NULL ;
1573 if (resampling_method != 1 && resampling_method != 2)
return NULL ;
1579 if (eris_ifu_sky_tweak_get_spectra_simple(obj, sky, mask, &obj_spec,
1580 &sky_spec) != CPL_ERROR_NONE) {
1581 cpl_msg_error(cpl_func,
"Cannot extract the spectra from cubes") ;
1582 cpl_image_delete(mask) ;
1587 if ((transf_poly = eris_ifu_stretch_get_poly(obj_spec, sky_spec, 5, poly_degree,
1588 &matching_lines))==NULL) {
1589 cpl_msg_error(cpl_func,
"Cannot compute the transformation polynomial");
1590 cpl_vector_delete(obj_spec) ;
1591 cpl_vector_delete(sky_spec) ;
1592 cpl_image_delete(mask) ;
1595 cpl_vector_delete(obj_spec) ;
1596 cpl_vector_delete(sky_spec) ;
1599 if (resampling_method == 1)
1600 new_sky = eris_ifu_stretch_apply_linear(sky, transf_poly) ;
1602 new_sky = eris_ifu_stretch_apply_spline(sky, transf_poly) ;
1603 if (new_sky == NULL) {
1604 cpl_msg_error(cpl_func,
"Cannot apply the transformation");
1605 cpl_polynomial_delete(transf_poly) ;
1606 cpl_image_delete(mask) ;
1611 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
1612 if (eris_ifu_sky_tweak_get_spectra_simple(obj, new_sky, mask, &obj_spec,
1613 &sky_spec) != CPL_ERROR_NONE) {
1614 cpl_msg_error(cpl_func,
"Cannot extract the spectra from cubes") ;
1615 cpl_image_delete(mask) ;
1616 cpl_bivector_delete(matching_lines) ;
1617 cpl_polynomial_delete(transf_poly) ;
1618 cpl_imagelist_delete(new_sky) ;
1621 if ((new_transf_poly = eris_ifu_stretch_get_poly(obj_spec, sky_spec, 5,
1622 poly_degree, &new_matching_lines))==NULL) {
1623 cpl_msg_error(cpl_func,
"Cannot compute the transf. polynomial");
1624 cpl_vector_delete(obj_spec) ;
1625 cpl_vector_delete(sky_spec) ;
1626 cpl_image_delete(mask) ;
1627 cpl_bivector_delete(matching_lines) ;
1628 cpl_polynomial_delete(transf_poly) ;
1629 cpl_imagelist_delete(new_sky) ;
1632 cpl_vector_delete(obj_spec) ;
1633 cpl_vector_delete(sky_spec) ;
1635 cpl_polynomial_dump(transf_poly, stdout) ;
1639 eris_ifu_stretch_plot_positions_differences(matching_lines,
1640 new_matching_lines) ;
1641 eris_ifu_stretch_check(obj, sky, new_sky, mask) ;
1643 cpl_bivector_delete(new_matching_lines) ;
1644 cpl_polynomial_delete(new_transf_poly) ;
1647 cpl_bivector_delete(matching_lines) ;
1648 cpl_polynomial_delete(transf_poly) ;
1649 cpl_image_delete(mask) ;
1654static cpl_polynomial * eris_ifu_stretch_get_poly(
1655 const cpl_vector * obj,
1656 const cpl_vector * sky,
1659 cpl_bivector ** matching_lines)
1663 cpl_matrix * matchedx ;
1664 cpl_polynomial * fitted ;
1667 if (obj == NULL || sky == NULL || matching_lines == NULL)
return NULL ;
1670 deg_loc = (cpl_size)degree ;
1673 *matching_lines=eris_ifu_strech_get_matching_lines(obj, sky, min_gap, 1,degree);
1674 nb_lines = cpl_bivector_get_size(*matching_lines) ;
1677 matchedx = cpl_matrix_wrap(1, nb_lines,
1678 cpl_vector_get_data(cpl_bivector_get_x(*matching_lines)));
1679 fitted = cpl_polynomial_new(1);
1680 if (cpl_polynomial_fit(fitted, matchedx, NULL,
1681 cpl_bivector_get_y(*matching_lines), NULL, CPL_FALSE,
1682 NULL, °_loc) != CPL_ERROR_NONE) {
1683 cpl_msg_error(cpl_func,
"Cannot fit the polynomial") ;
1684 cpl_polynomial_delete(fitted);
1685 cpl_matrix_unwrap(matchedx);
1686 cpl_bivector_delete(*matching_lines) ;
1689 cpl_matrix_unwrap(matchedx);
1702static cpl_imagelist * eris_ifu_stretch_apply_spline(
1704 cpl_polynomial * stretch)
1706 cpl_imagelist * out ;
1707 cpl_vector ** zlines ;
1708 cpl_vector ** resampled_zlines ;
1709 double * image_data ;
1712 double * resampled_array ;
1713 cpl_vector * new_pos ;
1714 int spec_size, nx, ny, i, j, k ;
1717 spec_size = cpl_imagelist_get_size(in) ;
1718 nx = cpl_image_get_size_x(cpl_imagelist_get_const(in, 0)) ;
1719 ny = cpl_image_get_size_x(cpl_imagelist_get_const(in, 0)) ;
1722 zlines = cpl_malloc(nx*ny*
sizeof(cpl_vector*)) ;
1723 for (i=0 ; i<nx ; i++)
1724 for (j=0 ; j<ny ; j++)
1725 zlines[i+j*nx] = cpl_vector_new(spec_size) ;
1728 for (k=0 ; k<spec_size ; k++) {
1729 image_data = cpl_image_get_data_double(cpl_imagelist_get(in, k)) ;
1730 for (i=0 ; i<nx ; i++)
1731 for (j=0 ; j<ny ; j++)
1732 if (!isnan(image_data[i+j*nx]))
1733 cpl_vector_set(zlines[i+j*nx], k, image_data[i+j*nx]) ;
1735 cpl_vector_set(zlines[i+j*nx], k, 0.0) ;
1739 pos = cpl_vector_new(spec_size) ;
1740 ppos = cpl_vector_get_data(pos);
1741 for (i=0 ; i<spec_size ; i++) ppos[i] = i+1 ;
1744 new_pos = cpl_vector_new(spec_size) ;
1745 cpl_vector_fill_polynomial(new_pos, stretch, 1, 1) ;
1748 if (cpl_vector_get(new_pos, 0) < 1.0) cpl_vector_set(new_pos, 0, 1.0) ;
1749 if (cpl_vector_get(new_pos, spec_size-1) > spec_size-1)
1750 cpl_vector_set(new_pos, spec_size-1, spec_size-1) ;
1752 resampled_zlines = cpl_malloc(nx*ny*
sizeof(cpl_vector*)) ;
1754 cpl_error_code retErr;
1755 for (i=0 ; i<nx ; i++) {
1756 for (j=0 ; j<ny ; j++) {
1757 resampled_array = cpl_malloc(spec_size *
sizeof(
double));
1759 ppos, cpl_vector_get_data(zlines[i+j*nx]), spec_size,
1760 cpl_vector_get_data(new_pos), resampled_array, spec_size,
1762 if (retErr != CPL_ERROR_NONE) {
1763 printf(
"ERROR: The function eris_ifu_1d_interpolation called in eris_ifu_stretch_apply_spline returned the error %d\n", retErr);
1764 printf(
"%s\n", cpl_error_get_message_default(retErr));
1772 resampled_zlines[i+j*nx] = cpl_vector_wrap(spec_size,
1776 cpl_vector_delete(new_pos) ;
1777 cpl_vector_delete(pos) ;
1781 for (i=0 ; i<nx ; i++)
1782 for (j=0 ; j<ny ; j++)
1783 cpl_vector_delete(zlines[i+j*nx]) ;
1787 out = cpl_imagelist_duplicate(in) ;
1788 for (k=0 ; k<spec_size ; k++) {
1789 image_data = cpl_image_get_data_double(cpl_imagelist_get(out, k)) ;
1790 for (i=0 ; i<nx ; i++)
1791 for (j=0 ; j<ny ; j++)
1792 image_data[i+j*nx]= cpl_vector_get(resampled_zlines[i+j*nx],k) ;
1796 for (i=0 ; i<nx ; i++)
1797 for (j=0 ; j<ny ; j++)
1798 cpl_free(cpl_vector_unwrap(resampled_zlines[i+j*nx]));
1800 cpl_free(resampled_zlines) ;
1813static cpl_imagelist * eris_ifu_stretch_apply_linear(
1815 cpl_polynomial * stretch)
1817 cpl_imagelist * out ;
1818 cpl_vector ** zlines ;
1819 cpl_vector ** resampled_zlines ;
1820 double * image_data ;
1823 cpl_vector * new_pos ;
1824 cpl_bivector * ref_spec ;
1825 cpl_bivector * resampled_spec ;
1826 int spec_size, nx, ny, i, j, k ;
1829 spec_size = cpl_imagelist_get_size(in) ;
1830 nx = cpl_image_get_size_x(cpl_imagelist_get_const(in, 0)) ;
1831 ny = cpl_image_get_size_x(cpl_imagelist_get_const(in, 0)) ;
1834 zlines = cpl_malloc(nx*ny*
sizeof(cpl_vector*)) ;
1835 for (i=0 ; i<nx ; i++)
1836 for (j=0 ; j<ny ; j++)
1837 zlines[i+j*nx] = cpl_vector_new(spec_size) ;
1840 for (k=0 ; k<spec_size ; k++) {
1841 image_data = cpl_image_get_data_double(cpl_imagelist_get(in, k)) ;
1842 for (i=0 ; i<nx ; i++)
1843 for (j=0 ; j<ny ; j++)
1844 if (!isnan(image_data[i+j*nx]))
1845 cpl_vector_set(zlines[i+j*nx], k, image_data[i+j*nx]) ;
1847 cpl_vector_set(zlines[i+j*nx], k, 0.0) ;
1851 pos = cpl_vector_new(spec_size) ;
1852 ppos = cpl_vector_get_data(pos);
1853 for (i=0 ; i<spec_size ; i++) ppos[i] = i+1 ;
1856 new_pos = cpl_vector_new(spec_size) ;
1857 cpl_vector_fill_polynomial(new_pos, stretch, 1, 1) ;
1860 if (cpl_vector_get(new_pos, 0) < 1.0) cpl_vector_set(new_pos, 0, 1.0) ;
1861 if (cpl_vector_get(new_pos, spec_size-1) > spec_size-1)
1862 cpl_vector_set(new_pos, spec_size-1, spec_size-1) ;
1864 resampled_zlines = cpl_malloc(nx*ny*
sizeof(cpl_vector*)) ;
1866 for (i=0 ; i<nx ; i++) {
1867 for (j=0 ; j<ny ; j++) {
1869 resampled_zlines[i+j*nx] = cpl_vector_new(spec_size) ;
1872 ref_spec = cpl_bivector_wrap_vectors(pos, zlines[i+j*nx]);
1873 resampled_spec = cpl_bivector_wrap_vectors(new_pos,
1874 resampled_zlines[i+j*nx]) ;
1876 cpl_bivector_interpolate_linear(resampled_spec, ref_spec) ;
1879 cpl_bivector_unwrap_vectors(ref_spec) ;
1880 cpl_bivector_unwrap_vectors(resampled_spec) ;
1883 cpl_vector_delete(new_pos) ;
1884 cpl_vector_delete(pos) ;
1887 for (i=0 ; i<nx ; i++)
1888 for (j=0 ; j<ny ; j++)
1889 cpl_vector_delete(zlines[i+j*nx]) ;
1893 out = cpl_imagelist_duplicate(in) ;
1894 for (k=0 ; k<spec_size ; k++) {
1895 image_data = cpl_image_get_data_double(cpl_imagelist_get(out, k)) ;
1896 for (i=0 ; i<nx ; i++)
1897 for (j=0 ; j<ny ; j++)
1898 image_data[i+j*nx]= cpl_vector_get(resampled_zlines[i+j*nx],k) ;
1902 for (i=0 ; i<nx ; i++)
1903 for (j=0 ; j<ny ; j++)
1904 cpl_vector_delete(resampled_zlines[i+j*nx]) ;
1905 cpl_free(resampled_zlines) ;
1909static int eris_ifu_stretch_check(
1910 cpl_imagelist * obj,
1911 cpl_imagelist * sky,
1912 cpl_imagelist * new_sky,
1915 cpl_vector * spec1 ;
1916 cpl_vector * spec2 ;
1918 eris_ifu_sky_tweak_get_spectra_simple(obj, sky, mask, &spec1, &spec2);
1919 cpl_plot_vector(
"set grid;set xlabel 'pix';",
"t 'obj' w lines",
"",
1921 cpl_plot_vector(
"set grid;set xlabel 'pix';",
1922 "t 'sky before stretching' w lines",
"", spec2);
1923 cpl_vector_subtract(spec1, spec2) ;
1925 cpl_plot_vector(
"set grid;set xlabel 'pix';",
1926 "t 'obj-sky before stretching' w lines",
"",
1928 cpl_vector_delete(spec1) ;
1929 cpl_vector_delete(spec2) ;
1931 eris_ifu_sky_tweak_get_spectra_simple(obj, new_sky, mask, &spec1, &spec2);
1932 cpl_plot_vector(
"set grid;set xlabel 'pix';",
1933 "t 'sky after stretching' w lines",
"", spec2);
1934 cpl_vector_subtract(spec1, spec2) ;
1936 cpl_plot_vector(
"set grid;set xlabel 'pix';",
1937 "t 'obj-sky after stretching' w lines",
"",
1939 cpl_vector_delete(spec1) ;
1940 cpl_vector_delete(spec2) ;
1945static int eris_ifu_stretch_plot_positions_differences(
1946 cpl_bivector * matching_lines,
1947 cpl_bivector * new_matching_lines)
1949 cpl_vector * diff_values ;
1950 cpl_bivector * diff ;
1953 diff_values = cpl_vector_duplicate(cpl_bivector_get_x(matching_lines)) ;
1954 cpl_vector_subtract(diff_values, cpl_bivector_get_y(matching_lines)) ;
1955 diff = cpl_bivector_wrap_vectors(cpl_bivector_get_x(matching_lines),
1957 cpl_plot_bivector(
"set grid;",
"t 'Pos. diff. BEFORE STRECHING'",
"", diff);
1958 cpl_bivector_unwrap_vectors(diff) ;
1959 cpl_vector_delete(diff_values) ;
1962 diff_values = cpl_vector_duplicate(cpl_bivector_get_x(new_matching_lines)) ;
1963 cpl_vector_subtract(diff_values, cpl_bivector_get_y(new_matching_lines)) ;
1964 diff = cpl_bivector_wrap_vectors(cpl_bivector_get_x(new_matching_lines),
1966 cpl_plot_bivector(
"set grid;",
"t 'Pos. diff. AFTER STRECHING'",
"", diff);
1967 cpl_bivector_unwrap_vectors(diff) ;
1968 cpl_vector_delete(diff_values) ;
1974static cpl_bivector * eris_ifu_strech_get_matching_lines(
1975 const cpl_vector * obj,
1976 const cpl_vector * sky,
1978 int remove_outliers,
1981 cpl_vector * tmp_vec ;
1982 cpl_vector * obj_lines ;
1983 cpl_vector * obj_lines_clean ;
1984 double * pobj_lines ;
1985 cpl_vector * sky_lines ;
1986 cpl_vector * sky_lines_clean ;
1987 double * psky_lines ;
1989 double * obj_lines_arr ;
1990 double * sky_lines_arr ;
1991 double obj_pos, sky_pos ;
1992 cpl_size sky_idx, nb_lines ;
1993 double fwhm, kappa, threshold ;
1997 if (obj == NULL || sky == NULL)
return NULL ;
2008 threshold = fabs(cpl_vector_get_mean(obj) + cpl_vector_get_stdev(obj)) ;
2009 tmp_vec = cpl_vector_duplicate(obj) ;
2010 for (i=0 ; i<cpl_vector_get_size(tmp_vec) ; i++) {
2011 if (cpl_vector_get(tmp_vec, i) < threshold)
2012 cpl_vector_set(tmp_vec, i, 0.0);
2014 if ((obj_lines = irplib_spectrum_detect_peaks(tmp_vec, fwhm,
2015 kappa, 0, NULL, NULL)) == NULL) {
2016 cpl_msg_error(cpl_func,
"Cannot detect peaks from obj") ;
2017 cpl_vector_delete(tmp_vec) ;
2020 cpl_vector_delete(tmp_vec) ;
2024 threshold = fabs(cpl_vector_get_mean(sky) + cpl_vector_get_stdev(sky)) ;
2025 tmp_vec = cpl_vector_duplicate(sky) ;
2026 for (i=0 ; i<cpl_vector_get_size(tmp_vec) ; i++) {
2027 if (cpl_vector_get(tmp_vec, i) < threshold)
2028 cpl_vector_set(tmp_vec, i, 0.0);
2030 if ((sky_lines = irplib_spectrum_detect_peaks(tmp_vec, fwhm,
2031 kappa, 0, NULL, NULL)) == NULL) {
2032 cpl_msg_error(cpl_func,
"Cannot detect peaks from sky") ;
2033 cpl_vector_delete(obj_lines) ;
2034 cpl_vector_delete(tmp_vec) ;
2037 cpl_vector_delete(tmp_vec) ;
2039 cpl_msg_debug(cpl_func,
"Detected %"CPL_SIZE_FORMAT
" lines from obj",
2040 cpl_vector_get_size(obj_lines));
2041 cpl_msg_debug(cpl_func,
"Detected %"CPL_SIZE_FORMAT
" lines from sky",
2042 cpl_vector_get_size(sky_lines));
2045 cpl_vector_sort(obj_lines, CPL_SORT_ASCENDING) ;
2046 nb_lines = cpl_vector_get_size(obj_lines) ;
2047 pobj_lines = cpl_vector_get_data(obj_lines) ;
2048 obj_lines_arr = cpl_malloc(nb_lines *
sizeof(
double)) ;
2050 obj_lines_arr[0] = pobj_lines[0] ;
2052 for (i=1 ; i<nb_lines ; i++) {
2054 if (fabs(pobj_lines[i]-pobj_lines[i-1]) > min_gap) {
2055 obj_lines_arr[nb_found] = pobj_lines[i] ;
2060 cpl_vector_delete(obj_lines) ;
2061 obj_lines = cpl_vector_new(nb_found) ;
2062 pobj_lines = cpl_vector_get_data(obj_lines) ;
2063 for (i=0 ; i<nb_found ; i++) pobj_lines[i] = obj_lines_arr[i] ;
2064 cpl_free(obj_lines_arr) ;
2065 nb_lines = cpl_vector_get_size(obj_lines) ;
2067 cpl_msg_debug(cpl_func,
2068 "Detected %"CPL_SIZE_FORMAT
" separated lines from obj",
2069 cpl_vector_get_size(obj_lines));
2072 obj_lines_arr = cpl_malloc(nb_lines *
sizeof(
double)) ;
2073 sky_lines_arr = cpl_malloc(nb_lines *
sizeof(
double)) ;
2075 cpl_vector_sort(sky_lines, CPL_SORT_ASCENDING) ;
2076 for (i=0 ; i<nb_lines ; i++) {
2077 obj_pos = cpl_vector_get(obj_lines, i) ;
2078 sky_idx = cpl_vector_find(sky_lines, obj_pos) ;
2079 sky_pos = cpl_vector_get(sky_lines, sky_idx) ;
2081 if (fabs(obj_pos-sky_pos) < min_gap) {
2082 obj_lines_arr[nb_found] = obj_pos ;
2083 sky_lines_arr[nb_found] = sky_pos ;
2089 cpl_vector_delete(obj_lines) ;
2090 cpl_vector_delete(sky_lines) ;
2091 obj_lines = cpl_vector_new(nb_found) ;
2092 sky_lines = cpl_vector_new(nb_found) ;
2093 nb_lines = cpl_vector_get_size(obj_lines) ;
2094 pobj_lines = cpl_vector_get_data(obj_lines) ;
2095 psky_lines = cpl_vector_get_data(sky_lines) ;
2096 for (i=0 ; i<nb_found ; i++) {
2097 pobj_lines[i] = obj_lines_arr[i] ;
2098 psky_lines[i] = sky_lines_arr[i] ;
2100 cpl_free(obj_lines_arr) ;
2101 cpl_free(sky_lines_arr) ;
2104 if (remove_outliers) {
2105 diff = cpl_vector_duplicate(obj_lines) ;
2106 cpl_vector_subtract(diff, sky_lines) ;
2107 threshold = fabs(cpl_vector_get_median_const(diff)) +
2108 2 * cpl_vector_get_stdev(diff) ;
2110 for (i=0 ; i<cpl_vector_get_size(diff) ; i++)
2111 if (fabs(cpl_vector_get(diff, i)) < threshold) nb_found++ ;
2112 obj_lines_clean = cpl_vector_new(nb_found) ;
2113 sky_lines_clean = cpl_vector_new(nb_found) ;
2115 for (i=0 ; i<cpl_vector_get_size(diff) ; i++)
2116 if (fabs(cpl_vector_get(diff, i)) < threshold) {
2117 cpl_vector_set(obj_lines_clean, nb_found,
2118 cpl_vector_get(obj_lines, i)) ;
2119 cpl_vector_set(sky_lines_clean, nb_found,
2120 cpl_vector_get(sky_lines, i)) ;
2123 cpl_vector_delete(diff) ;
2124 cpl_vector_delete(obj_lines) ;
2125 cpl_vector_delete(sky_lines) ;
2126 obj_lines = obj_lines_clean ;
2127 sky_lines = sky_lines_clean ;
2131 if (nb_found <= degree) {
2132 cpl_msg_error(cpl_func,
"Not enough match for the fit") ;
2133 cpl_vector_delete(obj_lines) ;
2134 cpl_vector_delete(sky_lines) ;
2138 cpl_msg_debug(cpl_func,
"Matched %"CPL_SIZE_FORMAT
" lines",
2139 cpl_vector_get_size(obj_lines));
2141 return cpl_bivector_wrap_vectors(obj_lines, sky_lines);
cpl_error_code eris_ifu_1d_interpolation(double *xIn, double *yIn, int nIn, double *xOut, double *yOut, int nOut, const int interType)
Perform 1D interpolation using GSL routines.
cpl_image * eris_ifu_lcorr_create_object_mask(const cpl_imagelist *cube, double min_frac, const cpl_vector *lambda, const cpl_vector *range)
Creates a mask of the cube.
cpl_vector * eris_ifu_lcorr_create_lambda_vector(const cpl_propertylist *header)
Creates a wavelength vector from an input cube.
int eris_ifu_plot_cube_background(cpl_imagelist *obj)
Extract backgroung from cube and plot.
cpl_imagelist * eris_ifu_sky_tweak(cpl_imagelist *obj, cpl_imagelist *sky, const cpl_propertylist *header, float min_frac, int tbsub, int skip_last, int stretch, int stretch_degree, int stretch_resampling, int plot, cpl_imagelist **new_sky)
Main sky tweaking function.
cpl_vector * eris_ifu_idl_values_at_indices(const cpl_vector *data, const cpl_vector *indices)
Returns a vector of given indices.
void eris_ifu_free_double_array(double **item)
free memory and set pointer to null
cpl_vector * eris_ifu_idl_where(const cpl_vector *data, double val, int op)
Implements the where-function knownm from IDL.
int eris_ifu_is_nan_or_inf(double A)
Checks if a value is nan, inf or -inf.
cpl_error_code eris_check_error_code(const char *func_id)
handle CPL errors