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);
176 cpl_vector * obj_spec ;
177 cpl_vector * sky_spec ;
180 if (obj == NULL)
return -1 ;
186 if (eris_ifu_sky_tweak_get_spectra_simple(obj, obj, mask, &obj_spec,
187 &sky_spec) != CPL_ERROR_NONE) {
188 cpl_msg_error(cpl_func,
"Cannot extract the spectra from cubes") ;
189 cpl_image_delete(mask) ;
193 cpl_plot_vector(
"set grid;set xlabel 'pix';",
"t 'CUBE BGD' w lines",
"",
196 cpl_vector_delete(obj_spec) ;
197 cpl_vector_delete(sky_spec) ;
238 const cpl_propertylist * header,
244 int stretch_resampling,
246 cpl_imagelist ** new_sky)
248 cpl_imagelist * new_obj ;
250 cpl_bivector * obj_spec = NULL;
251 cpl_bivector * sky_spec = NULL;
252 cpl_bivector * thermal_backg ;
253 cpl_bivector * vscales ;
254 cpl_vector * lambda ;
255 int nx, ny, nz, ix, kx, snx, sny, snz, kmax, first_nonan ;
258 cpl_ensure(obj, CPL_ERROR_NULL_INPUT, NULL);
259 cpl_ensure(sky, CPL_ERROR_NULL_INPUT, NULL);
260 cpl_ensure(header, CPL_ERROR_NULL_INPUT, NULL);
261 cpl_ensure(new_sky, CPL_ERROR_NULL_INPUT, NULL);
262 cpl_ensure(min_frac > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
263 cpl_ensure(stretch_resampling > 0 && stretch_resampling < 3, CPL_ERROR_ILLEGAL_INPUT, NULL);
265 nx = cpl_image_get_size_x(cpl_imagelist_get_const(obj, 0));
266 ny = cpl_image_get_size_y(cpl_imagelist_get_const(obj, 0));
267 nz = cpl_imagelist_get_size(obj);
268 snx = cpl_image_get_size_x(cpl_imagelist_get_const(sky, 0));
269 sny = cpl_image_get_size_y(cpl_imagelist_get_const(sky, 0));
270 snz = cpl_imagelist_get_size(sky);
271 if (nx!=snx || ny!=sny || nz!=snz) {
272 cpl_msg_error(__func__,
"Illegal inputs") ;
273 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
279 *new_sky = eris_ifu_priv_sky_stretch(obj, sky, .3, stretch_degree,
280 stretch_resampling, plot) ;
282 *new_sky = cpl_imagelist_duplicate(sky) ;
287 if (nz != cpl_vector_get_size(lambda)) {
288 cpl_msg_error(__func__,
"Illegal inputs") ;
289 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
295 if (cpl_msg_get_level() == CPL_MSG_DEBUG)
296 cpl_image_save(mask,
"mask.fits", CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
301 eris_ifu_sky_tweak_get_spectra(obj, *new_sky, lambda, mask, 0,
302 &obj_spec, &sky_spec, &first_nonan);
305 vscales = eris_ifu_sky_tweak_correct_vibrational_trans(obj_spec,
306 sky_spec, skip_last, plot);
307 if (cpl_msg_get_level() == CPL_MSG_DEBUG && plot)
308 cpl_plot_bivector(
"set title \"SCALES\";",
"w lines",
"",vscales);
311 thermal_backg = eris_ifu_sky_tweak_thermal_bgd(obj_spec, 1.0);
314 if (thermal_backg == NULL) {
316 cpl_msg_indent_more() ;
317 cpl_msg_warning(__func__,
318 "Thermal Bgd failed, re-try by clipping highest values") ;
319 thermal_backg = eris_ifu_sky_tweak_thermal_bgd(obj_spec, 0.98);
320 if (thermal_backg == NULL) {
321 cpl_msg_warning(__func__,
322 "Recovery failed - skip the thermal background correction");
325 cpl_msg_info(__func__,
"Recovery succeeded");
327 cpl_msg_indent_less() ;
330 if (cpl_msg_get_level() == CPL_MSG_DEBUG && plot)
331 cpl_plot_bivector(
"set title \"Th. bgd\";",
"w lines",
"",thermal_backg);
334 new_obj = cpl_imagelist_duplicate(obj);
335 kmax = cpl_vector_get_size(cpl_bivector_get_x_const(obj_spec));
337 for (ix=0; ix<nz; ix++) {
338 if ((kx < kmax ) && (cpl_vector_get(lambda,ix)==cpl_vector_get(
339 cpl_bivector_get_x_const(obj_spec),kx))) {
341 if (thermal_backg != NULL) {
342 cpl_image_subtract_scalar(cpl_imagelist_get(*new_sky ,ix),
343 cpl_vector_get(cpl_bivector_get_y_const(thermal_backg),
349 cpl_image_multiply_scalar(cpl_imagelist_get(*new_sky, ix),
350 cpl_vector_get(cpl_bivector_get_y_const(vscales), kx));
353 cpl_image_subtract(cpl_imagelist_get(new_obj, ix),
354 cpl_imagelist_get(*new_sky, ix));
357 if (tbsub && thermal_backg != NULL) {
358 cpl_image_subtract_scalar(cpl_imagelist_get(new_obj, ix),
359 cpl_vector_get(cpl_bivector_get_y_const(
360 thermal_backg), kx));
365 cpl_bivector_delete(obj_spec);
366 cpl_bivector_delete(sky_spec);
367 if (thermal_backg != NULL) cpl_bivector_delete(thermal_backg);
368 cpl_bivector_delete(vscales);
369 cpl_vector_delete(lambda);
371 cpl_image_delete(mask);
391static void eris_ifu_plot_arrays(
397 cpl_vector ** vectors ;
400 if (obj == NULL || sky == NULL) return ;
403 vectors = cpl_malloc(3*
sizeof(cpl_vector*)) ;
404 vectors[0] = cpl_vector_wrap(arr_size, wl) ;
405 vectors[1] = cpl_vector_wrap(arr_size, obj) ;
406 vectors[2] = cpl_vector_wrap(arr_size, sky) ;
408 CPL_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
409 cpl_plot_vectors(
"set grid;set xlabel 'Wavelength (microns)';",
410 "t 'Obj and Sky sub-band' w lines",
"",
411 (
const cpl_vector **)vectors,
415 cpl_vector_unwrap(vectors[0]) ;
416 cpl_vector_unwrap(vectors[1]) ;
417 cpl_vector_unwrap(vectors[2]) ;
451static cpl_bivector * eris_ifu_sky_tweak_thermal_bgd(
452 cpl_bivector * spectrum,
455 cpl_bivector * result ;
456 cpl_vector * spectrum_v ;
457 cpl_vector * thermal_v ;
459 cpl_vector * sorted_y ;
461 const int nsimplex = ndim + 1;
463 double p_init[ndim+1];
464 double * lspectrum = NULL,
468 int i, j, ix, loop, niter, new_size, skip, input_size ;
469 double min, max, tmp, diff, limit, clip_limit ;
472 if (spectrum == NULL) {
473 cpl_msg_error(__func__,
"NULL inputs") ;
474 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
477 if ((clip_rate < 0.5) || (clip_rate > 1.0)) {
478 cpl_msg_error(__func__,
"Invalid clip rate: %g", clip_rate) ;
479 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
489 input_size = cpl_bivector_get_size(spectrum) ;
491 lspectrum = cpl_bivector_get_x_data(spectrum);
492 vspectrum = cpl_bivector_get_y_data(spectrum);
493 spectrum_lambda=cpl_malloc(input_size*
sizeof(
double));
494 spectrum_value=cpl_malloc(input_size*
sizeof(
double));
495 thermal_background= cpl_malloc(input_size*
sizeof(
double));
498 if (clip_rate < 1.0) {
499 sorted_y = cpl_vector_duplicate(cpl_bivector_get_y(spectrum));
500 cpl_vector_sort(sorted_y, CPL_SORT_ASCENDING);
501 clip_limit = cpl_vector_get(sorted_y,
502 cpl_vector_get_size(sorted_y) * clip_rate);
503 cpl_vector_delete(sorted_y) ;
509 for (ix=0; ix < input_size ; ix++)
if (vspectrum[ix] != 0.0)
break;
513 for (i=ix+skip; i<input_size; i++) {
515 && (vspectrum[i] <= clip_limit) ) {
516 spectrum_lambda[new_size] = lspectrum[i];
517 spectrum_value[new_size] = vspectrum[i];
518 if (vspectrum[i] < min) { min = vspectrum[i]; }
523 for (ix=new_size; ix >= 0; ix--)
if (vspectrum[ix] != 0.0)
break;
525 spectrum_size = ix-skip;
527 y_amoeba=cpl_malloc((nsimplex+1)*
sizeof(
double));
528 x_amoeba=cpl_malloc((ndim+1)*
sizeof(
double));
529 p = matrix(nsimplex+1,ndim+1);
532 p_init[2] = spectrum_value[spectrum_size-1];
538 for (loop=0; loop<20; loop++) {
543 for (i=2; i<nsimplex+1; i++) {
544 for (j=1; j<ndim+1; j++) p[i][j] = p[1][j];
546 for (i=2; i<nsimplex+1; i++) p[i][i-1] = p[i][i-1] * 1.2;
547 for (i=1; i<nsimplex+1; i++) {
548 for (j=1; j<ndim+1; j++) x_amoeba[j] = p[i][j];
549 y_amoeba[i] = fitbkd(x_amoeba);
551 amoeba(p, y_amoeba, 3, 1.e-5, fitbkd, &niter);
553 cpl_msg_error(__func__,
"Function minimization failed") ;
557 cpl_free(spectrum_lambda);
558 cpl_free(spectrum_value);
559 cpl_free(thermal_background);
560 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
563 spectrum_v = cpl_vector_wrap(spectrum_size, spectrum_value);
564 thermal_v = cpl_vector_wrap(spectrum_size, thermal_background);
565 tmp_v = cpl_vector_duplicate(spectrum_v);
566 cpl_vector_subtract(tmp_v, thermal_v);
567 limit = cpl_vector_get_median(tmp_v) + 2. * cpl_vector_get_stdev(tmp_v);
568 cpl_vector_delete(tmp_v);
569 cpl_vector_unwrap(spectrum_v);
570 cpl_vector_unwrap(thermal_v);
574 for (i=0; i<spectrum_size; i++) {
575 diff = spectrum_value[i] - thermal_background[i];
577 spectrum_lambda[new_size] = spectrum_lambda[i];
578 spectrum_value[new_size] = spectrum_value[i];
579 if (spectrum_value[i] < min) min = spectrum_value[i];
583 spectrum_size = new_size;
586 for (i=0; i<spectrum_size; i++) {
587 tmp = PLANCK(spectrum_lambda[i], p[1][3]);
588 if (tmp > max) max = tmp;
590 if (fabs(max) < 1e-90) {
591 cpl_msg_error(__func__,
"Cannot determine thermal Background") ;
595 cpl_free(spectrum_lambda);
596 cpl_free(spectrum_value);
597 cpl_free(thermal_background);
598 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
602 for (i=0; i<input_size; i++) {
603 spectrum_lambda[i] = lspectrum[i];
604 spectrum_value[i] = vspectrum[i];
605 tmp = PLANCK(spectrum_lambda[i], p[1][3]);
606 thermal_background[i] = p[1][1] + tmp / max * p[1][2];
608 thermal_v = cpl_vector_wrap(input_size, thermal_background);
609 tmp_v = cpl_vector_duplicate(thermal_v);
610 cpl_vector_unwrap(thermal_v);
612 result = cpl_bivector_wrap_vectors(
613 cpl_vector_duplicate(cpl_bivector_get_x_const(spectrum)), tmp_v);
618 cpl_free(spectrum_lambda);
619 cpl_free(spectrum_value);
620 cpl_free(thermal_background);
640static double eris_ifu_sky_tweak_get_mean_wo_outliers(
const cpl_vector * vdata)
646 const double * data ;
648 double avg, median, stdev, clip;
649 int nr_data, i, nr_i;
651 nr_data = cpl_vector_get_size(vdata);
652 data = cpl_vector_get_data_const(vdata);
653 tmpv1 = cpl_vector_new(nr_data);
654 tmpv1_data = cpl_vector_get_data(tmpv1);
656 median = cpl_vector_get_median_const(vdata);
657 for (i=0; i<nr_data; i++) tmpv1_data[i] = fabs(data[i] - median);
658 cpl_vector_sort(tmpv1, CPL_SORT_ASCENDING);
659 clip = cpl_vector_get(tmpv1, (
int) .8*nr_data);
662 median = cpl_vector_get_median_const(tmpv3);
663 stdev = cpl_vector_get_stdev(tmpv3);
665 for (i=0; i<nr_data; i++) {
666 if ((data[i] < median + 3. * stdev) && (data[i] > median - 3. * stdev)){
667 tmpv1_data[nr_i] = data[i];
671 tmpv4 = cpl_vector_wrap(nr_i, tmpv1_data);
672 avg = cpl_vector_get_mean(tmpv4);
674 cpl_vector_delete(tmpv1);
675 cpl_vector_delete(tmpv2);
676 cpl_vector_delete(tmpv3);
677 cpl_vector_unwrap(tmpv4);
706static cpl_error_code eris_ifu_sky_tweak_get_spectra_simple(
707 const cpl_imagelist *
object,
708 const cpl_imagelist * sky,
709 const cpl_image * mask,
710 cpl_vector ** obj_spec,
711 cpl_vector ** sky_spec)
713 cpl_vector * intobj ;
714 cpl_vector * intsky ;
715 const cpl_image * oimg ;
716 const cpl_image * simg ;
717 double * intobj_data ;
718 double * intsky_data ;
723 double mpix, opix, spix;
724 int nx, ny, nz, snx, sny, snz, ix, iy, iz, found,
725 m_is_rejected, o_is_rejected, s_is_rejected;
728 nx = cpl_image_get_size_x(cpl_imagelist_get_const(
object, 0));
729 ny = cpl_image_get_size_y(cpl_imagelist_get_const(
object, 0));
730 nz = cpl_imagelist_get_size(
object);
731 snx = cpl_image_get_size_x(cpl_imagelist_get_const(sky, 0));
732 sny = cpl_image_get_size_y(cpl_imagelist_get_const(sky, 0));
733 snz = cpl_imagelist_get_size(sky);
736 if (nx!=snx || ny!=sny || nz!=snz) {
737 cpl_msg_error(__func__,
"Illegal inputs") ;
738 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
739 return CPL_ERROR_ILLEGAL_INPUT ;
743 intobj = cpl_vector_new(nz);
744 intsky = cpl_vector_new(snz);
745 intobj_data = cpl_vector_get_data(intobj);
746 intsky_data = cpl_vector_get_data(intsky);
747 vo = cpl_malloc(nx * ny *
sizeof(
double));
748 vs = cpl_malloc(nx * ny *
sizeof(
double));
751 for (iz = 0; iz <nz; iz++) {
752 oimg = cpl_imagelist_get_const(
object, iz);
753 simg = cpl_imagelist_get_const(sky, iz);
755 for (ix = 1; ix<=nx; ix++) {
756 for (iy = 1; iy<=ny; iy++) {
757 mpix = cpl_image_get(mask, ix, iy, &m_is_rejected);
758 opix = cpl_image_get(oimg, ix, iy, &o_is_rejected);
759 spix = cpl_image_get(simg, ix, iy, &s_is_rejected);
760 if ( mpix > .5 && m_is_rejected == 0 && o_is_rejected == 0 &&
761 s_is_rejected == 0 ) {
769 if (found >= nx*ny/4.) {
770 ovec = cpl_vector_wrap(found, vo);
771 svec = cpl_vector_wrap(found, vs);
773 if (found < nx*ny/2. ) {
774 intobj_data[iz] = cpl_vector_get_median(ovec);
775 intsky_data[iz] = cpl_vector_get_median(svec);
777 intobj_data[iz] = eris_ifu_sky_tweak_get_mean_wo_outliers(ovec);
778 intsky_data[iz] = eris_ifu_sky_tweak_get_mean_wo_outliers(svec);
780 cpl_vector_unwrap(ovec);
781 cpl_vector_unwrap(svec);
783 intobj_data[iz] = 0.;
784 intsky_data[iz] = 0.;
793 return CPL_ERROR_NONE;
824static cpl_error_code eris_ifu_sky_tweak_get_spectra(
825 const cpl_imagelist *
object,
826 const cpl_imagelist * sky,
827 const cpl_vector * lambda,
828 const cpl_image * mask,
830 cpl_bivector ** obj_spectrum_ptr,
831 cpl_bivector ** sky_spectrum_ptr,
834 cpl_bivector * obj_spectrum ;
835 cpl_bivector * sky_spectrum ;
836 cpl_vector * intobj ;
837 cpl_vector * intsky ;
838 cpl_vector * new_lambda ;
839 cpl_vector * new_intobj ;
840 cpl_vector * new_intsky ;
841 const cpl_image * oimg ;
842 const cpl_image * simg ;
843 double * intobj_data ;
844 double * intsky_data ;
847 double * new_lambda_d ;
848 double * new_intobj_d ;
849 double * new_intsky_d ;
850 const double * lambda_d ;
853 double mpix, opix, spix;
854 int nx, ny, nz, snx, sny, snz, ix, iy, iz, ni, found,
855 nr_valid_int, m_is_rejected, o_is_rejected,
860 if (first_nonan==NULL) {
861 cpl_msg_error(__func__,
"Illegal inputs") ;
862 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
863 return CPL_ERROR_ILLEGAL_INPUT ;
868 nx = cpl_image_get_size_x(cpl_imagelist_get_const(
object, 0));
869 ny = cpl_image_get_size_y(cpl_imagelist_get_const(
object, 0));
870 nz = cpl_imagelist_get_size(
object);
871 snx = cpl_image_get_size_x(cpl_imagelist_get_const(sky, 0));
872 sny = cpl_image_get_size_y(cpl_imagelist_get_const(sky, 0));
873 snz = cpl_imagelist_get_size(sky);
875 if (nx!=snx || ny!=sny || nz!=snz) {
876 cpl_msg_error(__func__,
"Illegal inputs") ;
877 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
878 return CPL_ERROR_ILLEGAL_INPUT ;
881 if (nz != cpl_vector_get_size(lambda)) {
882 cpl_msg_error(__func__,
"Illegal inputs") ;
883 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
884 return CPL_ERROR_ILLEGAL_INPUT ;
887 intobj = cpl_vector_new(cpl_vector_get_size(lambda));
888 intsky = cpl_vector_new(cpl_vector_get_size(lambda));
889 intobj_data = cpl_vector_get_data(intobj);
890 intsky_data = cpl_vector_get_data(intsky);
892 vo = cpl_malloc(nx * ny *
sizeof(
double));
893 vs = cpl_malloc(nx * ny *
sizeof(
double));
896 for (iz = 0; iz <nz; iz++) {
897 oimg = cpl_imagelist_get_const(
object, iz);
898 simg = cpl_imagelist_get_const(sky, iz);
900 for (ix = 1; ix<=nx; ix++) {
901 for (iy = 1; iy<=ny; iy++) {
902 mpix = cpl_image_get(mask, ix, iy, &m_is_rejected);
903 opix = cpl_image_get(oimg, ix, iy, &o_is_rejected);
904 spix = cpl_image_get(simg, ix, iy, &s_is_rejected);
905 if ( mpix > .5 && m_is_rejected == 0 && o_is_rejected == 0 &&
906 s_is_rejected == 0 ) {
914 if (found >= nx*ny/4.) {
915 if (*first_nonan < 0) *first_nonan = iz ;
917 ovec = cpl_vector_wrap(found, vo);
918 svec = cpl_vector_wrap(found, vs);
920 if (found < nx*ny/2. ) {
921 intobj_data[iz] = cpl_vector_get_median(ovec);
922 intsky_data[iz] = cpl_vector_get_median(svec);
924 intobj_data[iz] = eris_ifu_sky_tweak_get_mean_wo_outliers(ovec);
925 intsky_data[iz] = eris_ifu_sky_tweak_get_mean_wo_outliers(svec);
927 cpl_vector_unwrap(ovec);
928 cpl_vector_unwrap(svec);
931 intobj_data[iz] = 0./0.;
932 intsky_data[iz] = 0./0.;
935 intobj_data[iz] = 0.;
936 intsky_data[iz] = 0.;
942 new_lambda = cpl_vector_new(nr_valid_int);
943 new_intobj = cpl_vector_new(nr_valid_int);
944 new_intsky = cpl_vector_new(nr_valid_int);
945 new_lambda_d=cpl_vector_get_data(new_lambda);
946 new_intobj_d=cpl_vector_get_data(new_intobj);
947 new_intsky_d=cpl_vector_get_data(new_intsky);
948 lambda_d=cpl_vector_get_data_const(lambda);
951 for (iz=0 ; iz<nz; iz++) {
952 if ((! isnan(intobj_data[iz])) && ni < nr_valid_int) {
953 new_lambda_d[ni] = lambda_d[iz];
954 new_intobj_d[ni] = intobj_data[iz];
955 new_intsky_d[ni] = intsky_data[iz];
959 obj_spectrum = cpl_bivector_wrap_vectors(new_lambda, new_intobj) ;
960 sky_spectrum = cpl_bivector_wrap_vectors(
961 cpl_vector_duplicate(new_lambda), new_intsky);
963 cpl_vector_delete(intobj);
964 cpl_vector_delete(intsky);
966 obj_spectrum = cpl_bivector_wrap_vectors(cpl_vector_duplicate(lambda),
968 sky_spectrum = cpl_bivector_wrap_vectors(cpl_vector_duplicate(lambda),
974 *obj_spectrum_ptr = obj_spectrum;
975 *sky_spectrum_ptr = sky_spectrum;
976 return CPL_ERROR_NONE;
1015static cpl_bivector * eris_ifu_sky_tweak_correct_vibrational_trans(
1016 cpl_bivector * obj_spectrum,
1017 cpl_bivector * sky_spectrum,
1021 cpl_bivector * result ;
1023 double * lambda_boundaries ;
1024 const char ** labels ;
1025 const double * lambda ;
1026 const double * intobj ;
1027 const double * intsky ;
1028 double * array_wls ;
1029 double * array_obj ;
1030 double * array_sky ;
1031 double * line_interpolate_object ;
1032 double * line_interpolate_sky ;
1034 cpl_vector * tmp_vec ;
1035 cpl_vector * sky_lines_map_vec ;
1036 double median, stdev ;
1037 int i, ix, il, lx, cx, nr_lambda, nr_samples, nr_boundaries,
1038 cont_start, cont_end ;
1039 cpl_error_code errCode;
1042 if (obj_spectrum == NULL || sky_spectrum == NULL) {
1043 cpl_msg_error(__func__,
"NULL inputs") ;
1044 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
1047 if (cpl_bivector_get_size(obj_spectrum) !=
1048 cpl_bivector_get_size(sky_spectrum)) {
1049 cpl_msg_error(__func__,
"Illegal inputs") ;
1050 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
1055 nr_lambda = cpl_bivector_get_size(obj_spectrum);
1056 lambda = cpl_vector_get_data_const(cpl_bivector_get_x_const(obj_spectrum));
1057 intobj = cpl_vector_get_data_const(cpl_bivector_get_y_const(obj_spectrum));
1058 intsky = cpl_vector_get_data_const(cpl_bivector_get_y_const(sky_spectrum));
1059 median = stdev = 0.0 ;
1062 for (ix=0; ix<nr_lambda; ix++) {
1063 if (fabs(lambda[ix] -
1064 cpl_vector_get(cpl_bivector_get_x_const(sky_spectrum), ix))
1066 cpl_msg_error(__func__,
"Illegal inputs") ;
1067 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
1074 nr_boundaries = 20 ;
1075 lambda_boundaries = cpl_malloc(nr_boundaries *
sizeof(
double)) ;
1076 labels = cpl_malloc((nr_boundaries-1) *
sizeof(
char*)) ;
1078 nr_boundaries = 21 ;
1079 lambda_boundaries = cpl_malloc(nr_boundaries *
sizeof(
double)) ;
1080 labels = cpl_malloc((nr_boundaries-1) *
sizeof(
char*)) ;
1082 lambda_boundaries[0] = 0.780 ; labels[0] =
"" ;
1083 lambda_boundaries[1] = 0.824 ; labels[1] =
"" ;
1084 lambda_boundaries[2] = 0.873 ; labels[2] =
"" ;
1085 lambda_boundaries[3] = 0.926 ; labels[3] =
"" ;
1086 lambda_boundaries[4] = 0.964 ; labels[4] =
"" ;
1087 lambda_boundaries[5] = 1.014 ; labels[5] =
"4-1 transitions" ;
1088 lambda_boundaries[6] = 1.067 ; labels[6] =
"5-2 transitions" ;
1089 lambda_boundaries[7] = 1.125 ; labels[7] =
"6-3 transitions" ;
1090 lambda_boundaries[8] = 1.196 ; labels[8] =
"7-4 transitions" ;
1091 lambda_boundaries[9] = 1.252 ; labels[9] =
" 02 transitions" ;
1092 lambda_boundaries[10] = 1.289 ; labels[10] =
"8-5 transitions" ;
1093 lambda_boundaries[11] = 1.400 ; labels[11] =
"2-0 transitions" ;
1094 lambda_boundaries[12] = 1.472 ; labels[12] =
"3-1 transitions" ;
1095 lambda_boundaries[13] = 1.5543 ; labels[13] =
"4-2 transitions" ;
1096 lambda_boundaries[14] = 1.6356 ; labels[14] =
"5-3 transitions" ;
1097 lambda_boundaries[15] = 1.7253 ; labels[15] =
"6-4 transitions" ;
1098 lambda_boundaries[16] = 1.840 ; labels[16] =
"7-5 transitions" ;
1099 lambda_boundaries[17] = 1.9570 ; labels[17] =
"8-6 transitions" ;
1100 lambda_boundaries[18] = 2.095 ; labels[18] =
"9-7 transitions" ;
1102 lambda_boundaries[19] = 2.460 ;
1104 lambda_boundaries[19] = 2.30 ; labels[19] =
"final bit" ;
1105 lambda_boundaries[20] = 2.460 ;
1109 scalings = cpl_malloc(nr_boundaries *
sizeof(
double)) ;
1110 for (ix=0; ix<nr_boundaries; ix++) scalings[ix] = 0.;
1112 array_wls = cpl_malloc(nr_lambda *
sizeof(
double)) ;
1113 array_obj = cpl_malloc(nr_lambda *
sizeof(
double)) ;
1114 array_sky = cpl_malloc(nr_lambda *
sizeof(
double)) ;
1117 for (ix = 0; ix<nr_boundaries-1; ix++) {
1118 cpl_msg_debug(__func__,
"Sub-band %2d: %s", ix+1, labels[ix]) ;
1119 cpl_msg_indent_more() ;
1123 for (il=0; il<nr_lambda; il++) {
1124 if ((lambda[il] >= lambda_boundaries[ix] ) &&
1125 (lambda[il] < lambda_boundaries[ix+1]) ) {
1129 intsky[il] == 0. || intobj[il] == 0. ) {
1130 cpl_msg_indent_less() ;
1134 array_wls[nr_samples] = lambda[il];
1135 array_obj[nr_samples] = intobj[il];
1136 array_sky[nr_samples] = intsky[il];
1140 cpl_msg_debug(__func__,
"Found %d samples", nr_samples) ;
1143 if (nr_samples <= 20) {
1144 cpl_msg_indent_less() ;
1147 if (plot==ix+1 && cpl_msg_get_level() == CPL_MSG_DEBUG)
1148 eris_ifu_plot_arrays(array_wls, array_obj, array_sky, nr_samples);
1151 tmp_vec = cpl_vector_wrap(nr_samples, array_sky);
1152 median = cpl_vector_get_median_const(tmp_vec);
1153 stdev = cpl_vector_get_stdev(tmp_vec);
1154 cpl_vector_unwrap(tmp_vec);
1155 cpl_msg_debug(__func__,
"Sky Stats - Med: %g Stdev: %g", median, stdev);
1158 sky_lines_map_vec = cpl_vector_new(nr_samples) ;
1159 cpl_vector_fill(sky_lines_map_vec, 0.0) ;
1160 for (i=0; i<nr_samples; i++) {
1161 if (array_sky[i] > median+stdev)
1162 cpl_vector_set(sky_lines_map_vec, i, 10.0) ;
1164 if (plot==ix+1 && cpl_msg_get_level() == CPL_MSG_DEBUG)
1165 cpl_plot_vector(
"set grid;set xlabel 'Samples';set ylabel 'Map';",
1166 "t 'Sky lines map' w lines",
"", sky_lines_map_vec);
1169 tmp_vec=cpl_vector_filter_lowpass_create(sky_lines_map_vec,
1170 CPL_LOWPASS_LINEAR,2);
1171 cpl_vector_delete(sky_lines_map_vec);
1172 sky_lines_map_vec = tmp_vec ;
1174 if (plot==ix+1 && cpl_msg_get_level() == CPL_MSG_DEBUG)
1175 cpl_plot_vector(
"set grid;set xlabel 'Samples';set ylabel 'Map';",
1176 "t 'Smoothed sky lines map' w lines",
"",
1180 eris_ifu_sky_tweak_identify_lines_cont(sky_lines_map_vec,
1181 &cont_start, &cont_end, &cont_size, &lines_size) ;
1182 if (lines_size == 0) {
1183 cpl_msg_warning(__func__,
"No line region found") ;
1184 cpl_vector_delete(sky_lines_map_vec);
1185 cpl_msg_indent_less() ;
1191 cont_sky_sig = cpl_malloc(cont_size *
sizeof(
double));
1192 cont_object_sig = cpl_malloc(cont_size *
sizeof(
double));
1193 cont_lambda = cpl_malloc(cont_size *
sizeof(
double));
1194 line_sky_sig = cpl_malloc(lines_size *
sizeof(
double));
1195 line_object_sig = cpl_malloc(lines_size *
sizeof(
double));
1196 line_lambda = cpl_malloc(lines_size *
sizeof(
double));
1200 for (i = cont_start; i <= cont_end ; i++) {
1201 if (cpl_vector_get(sky_lines_map_vec, i) > 0.) {
1202 line_sky_sig[lx] = array_sky[i];
1203 line_object_sig[lx] = array_obj[i];
1204 line_lambda[lx] = array_wls[i];
1207 cont_sky_sig[cx] = array_sky[i];
1208 cont_object_sig[cx] = array_obj[i];
1209 cont_lambda[cx] = array_wls[i];
1217 const int nsimplex = ndim + 1;
1219 double *x_amoeba = NULL,
1224 y_amoeba = cpl_malloc((nsimplex+1) *
sizeof(
double));
1225 x_amoeba = cpl_malloc((ndim+1) *
sizeof(
double));
1226 p = matrix(nsimplex+1,ndim+1);
1230 for (ip=1; ip<nsimplex+1; ip++) {
1231 for (jp=1; jp<ndim+1; jp++) {
1232 x_amoeba[jp] = p[ip][jp];
1234 y_amoeba[ip] = fitsky(x_amoeba);
1236 amoeba(p, y_amoeba, ndim, 1.e-5, fitsky, &niter );
1238 cpl_msg_error(__func__,
"Function minimization failed") ;
1242 cpl_free(spectrum_lambda);
1243 cpl_free(spectrum_value);
1244 cpl_free(thermal_background);
1245 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
1249 flineres = cpl_malloc(lines_size *
sizeof(
double));
1258 line_interpolate_object = cpl_calloc(lines_size,
sizeof(
double));
1260 cont_lambda, cont_object_sig, cont_size,
1261 line_lambda, line_interpolate_object, lines_size, 2);
1262 if (errCode != CPL_ERROR_NONE) {
1263 printf(
"ERROR: The function eris_ifu_1d_interpolation called in eris_ifu_sky_tweak_correct_vibrational_trans returned the error %d\n", errCode);
1264 printf(
"%s\n", cpl_error_get_message_default(errCode));
1267 line_interpolate_sky = cpl_calloc(lines_size,
sizeof(
double));
1269 cont_lambda, cont_sky_sig, cont_size,
1270 line_lambda, line_interpolate_sky, lines_size, 2);
1271 if (errCode != CPL_ERROR_NONE) {
1272 printf(
"ERROR: The function eris_ifu_1d_interpolation called in eris_ifu_sky_tweak_correct_vibrational_trans returned the error %d\n", errCode);
1273 printf(
"%s\n", cpl_error_get_message_default(errCode));
1276 for (i=0; i<lines_size; i++) {
1277 flineres[i] = (line_object_sig[i] -
1278 line_interpolate_object[i]) -
1279 (line_sky_sig[i] - line_interpolate_sky[i]) * scale;
1282 tmp_vec = cpl_vector_wrap(lines_size, flineres);
1283 median = cpl_vector_get_median_const(tmp_vec);
1284 stdev = cpl_vector_get_stdev(tmp_vec);
1285 cpl_vector_unwrap(tmp_vec) ;
1288 for (i=0; i<lines_size; i++) {
1289 if ( fabs(flineres[i] - median) <= (3 * stdev) ) {
1293 cpl_msg_debug(__func__,
"Outliers: %d", lines_size-clip_cnt) ;
1295 if ((clip_cnt != lines_size) && (clip_cnt >= 3)) {
1297 for (i=0; i<lines_size; i++) {
1298 if ( fabs(flineres[i] - median) <= (3 * stdev) ) {
1299 line_sky_sig[lx] = line_sky_sig[i];
1300 line_object_sig[lx] =
1302 line_lambda[lx] = line_lambda[i];
1307 cpl_msg_debug(__func__,
"2. Lines size: %d", lines_size) ;
1311 for (ip=1; ip<nsimplex+1; ip++) {
1312 for (jp=1; jp<ndim+1; jp++) x_amoeba[jp] = p[ip][jp];
1313 y_amoeba[ip] = fitsky(x_amoeba);
1315 amoeba(p, y_amoeba, ndim, 1.e-5, fitsky, &niter);
1317 cpl_msg_error(__func__,
"Function minimization failed") ;
1321 cpl_free(spectrum_lambda);
1322 cpl_free(spectrum_value);
1323 cpl_free(thermal_background);
1324 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
1329 cpl_msg_debug(__func__,
"Scale: %g", scale) ;
1330 scalings[ix] = scale;
1332 cpl_vector_delete(sky_lines_map_vec);
1333 free_matrix(p, nsimplex+1);
1336 cpl_free(cont_sky_sig);
1337 cpl_free(line_sky_sig);
1338 cpl_free(cont_object_sig);
1339 cpl_free(line_object_sig);
1340 cpl_free(cont_lambda);
1341 cpl_free(line_lambda);
1343 cpl_free(line_interpolate_object);
1344 cpl_free(line_interpolate_sky);
1346 cpl_msg_indent_less() ;
1353 double valid_scales[nr_boundaries];
1354 cpl_vector *valid_scales_v = NULL;
1355 for (ix=0; ix<nr_boundaries; ix++) {
1356 if (scalings[ix] != 0.0 ) {
1357 valid_scales[nr_valid] = scalings[ix];
1361 valid_scales_v = cpl_vector_wrap(nr_valid, valid_scales);
1362 median = cpl_vector_get_median_const(valid_scales_v);
1363 stdev = cpl_vector_get_stdev(valid_scales_v);
1365 for (ix=0; ix<nr_boundaries; ix++) {
1366 if (scalings[ix] != 0.0 ) {
1367 if (fabs(valid_scales[v_ix] - median) > 2 * stdev) {
1373 if (valid_scales_v != NULL) {
1374 cpl_vector_unwrap(valid_scales_v);
1375 valid_scales_v = NULL;
1379 double *scale0_lambda = NULL,
1380 *scale0_value = NULL,
1382 cpl_vector *scale_v = NULL;
1384 scale0_lambda = cpl_malloc(nr_lambda *
sizeof(
double));
1385 scale0_value = cpl_malloc(nr_lambda *
sizeof(
double));
1388 for (il=0; il<nr_lambda; il++) {
1389 for (ix = 0; ix<nr_boundaries-1; ix++) {
1390 if (scalings[ix] != 0.) {
1391 if ((lambda[il] >= lambda_boundaries[ix] ) &&
1392 (lambda[il] < lambda_boundaries[ix+1]) ) {
1393 scale0_lambda[scale0_size] = lambda[il];
1394 scale0_value[scale0_size] = scalings[ix];
1400 cpl_free(scalings) ;
1401 cpl_free(lambda_boundaries) ;
1406 scale = cpl_calloc(nr_lambda,
sizeof(
double));
1408 double* lambda_tmp = (
double*) lambda;
1410 scale0_lambda, scale0_value, scale0_size,
1411 lambda_tmp, scale, nr_lambda, 2);
1412 if (errCode != CPL_ERROR_NONE) {
1413 printf(
"ERROR: The function eris_ifu_1d_interpolation called in eris_ifu_sky_tweak_correct_vibrational_trans returned the error %d\n", errCode);
1414 printf(
"%s\n", cpl_error_get_message_default(errCode));
1417 scale_v = cpl_vector_wrap(nr_lambda, scale);
1419 if (scale0_lambda != NULL) cpl_free(scale0_lambda);
1420 if (scale0_value != NULL) cpl_free(scale0_value);
1421 result = cpl_bivector_wrap_vectors(
1422 cpl_vector_duplicate(cpl_bivector_get_x_const(obj_spectrum)),
1425 cpl_free(array_wls) ;
1426 cpl_free(array_obj) ;
1427 cpl_free(array_sky) ;
1450static int eris_ifu_sky_tweak_identify_lines_cont(
1451 cpl_vector * sky_lines_map_vec,
1454 int * local_cont_size,
1455 int * local_lines_size)
1457 int current_line_size, nr_samples, i ;
1462 current_line_size = 0 ;
1463 nr_samples = cpl_vector_get_size(sky_lines_map_vec) ;
1468 *local_cont_size = 0;
1469 *local_lines_size = 0;
1470 for (i=0; i<nr_samples; i++) {
1471 if (cpl_vector_get(sky_lines_map_vec, i) > 0.) {
1474 if (*cont_start == -1)
continue;
1475 current_line_size++;
1478 if (*cont_start == -1) *cont_start = i;
1480 (*local_cont_size)++;
1481 *local_lines_size += current_line_size;
1482 current_line_size = 0;
1485 cpl_msg_debug(__func__,
"Cont [%d, %d] size: %d / Lines size: %d",
1486 *cont_start, *cont_end, *local_cont_size, *local_lines_size) ;
1508static double fitsky(
double *p) {
1510 double *cont_sky = NULL,
1511 *cont_object = NULL;
1514 cpl_error_code errCode;
1523 cont_sky = cpl_calloc(lines_size,
sizeof(
double));
1525 line_lambda, cont_sky, lines_size, 2);
1526 if (errCode != CPL_ERROR_NONE) {
1527 printf(
"ERROR: The function eris_ifu_1d_interpolation called in fitsky returned the error %d\n", errCode);
1528 printf(
"%s\n", cpl_error_get_message_default(errCode));
1531 cont_object = cpl_calloc(lines_size,
sizeof(
double));
1533 line_lambda, cont_object, lines_size, 2);
1534 if (errCode != CPL_ERROR_NONE) {
1535 printf(
"ERROR: The function eris_ifu_1d_interpolation called in fitsky returned the error %d\n", errCode);
1536 printf(
"%s\n", cpl_error_get_message_default(errCode));
1539 for (ix=0; ix<lines_size; ix++) {
1540 double diff = (line_object_sig[ix] - cont_object[ix]) -
1541 (line_sky_sig[ix] - cont_sky[ix]) * p[1];
1576static double fitbkd(
double *p) {
1582 tmp = cpl_malloc(spectrum_size *
sizeof(
double));
1585 for (i=0; i<spectrum_size; i++) {
1586 tmp[i] = PLANCK(spectrum_lambda[i], p[3]);
1593 for (i=0; i<spectrum_size; i++) {
1594 thermal_background[i] = p[1] + tmp[i] / max * fabs(p[2]);
1597 for (i=0; i<spectrum_size; i++) {
1598 thermal_background[i] = tmp[i];
1603 for (i=0; i<spectrum_size; i++) {
1604 result += (spectrum_value[i] - thermal_background[i]) *
1605 (spectrum_value[i] - thermal_background[i]);
1608 if (tmp != NULL) cpl_free(tmp);
1640 for (j=1;j<=ndim;j++) {\
1641 for (sum=0.0,i=1;i<=mpts;i++) sum += p[i][j];\
1643#define SWAP(a,b) {swap=(a);(a)=(b);(b)=swap;}
1649 double (*funk)(
double []),
1652 int i,ihi,ilo,inhi,j,mpts=ndim+1;
1653 double rtol, sum, swap, ysave, ytry, *psum = NULL, d;
1655 psum=cpl_calloc(ndim+1,
sizeof(
double));
1660 ihi = y[1]>y[2] ? (inhi=2,1) : (inhi=1,2);
1661 for (i=1;i<=mpts;i++) {
1662 if (y[i] <= y[ilo]) {
1665 if (y[i] > y[ihi]) {
1668 }
else if (y[i] > y[inhi] && i != ihi) inhi=i;
1670 d = fabs(y[ihi])+fabs(y[ilo]);
1674 rtol=2.0*fabs(y[ihi]-y[ilo])/d;
1678 for (i=1;i<=ndim;i++) SWAP(p[1][i],p[ilo][i])
1681 if (*nfunk >= 5000) {
1687 ytry=amotry(p,y,psum,ndim,funk,ihi,-1.0);
1689 ytry=amotry(p,y,psum,ndim,funk,ihi,2.0);
1690 else if (ytry >= y[inhi]) {
1692 ytry=amotry(p,y,psum,ndim,funk,ihi,0.5);
1693 if (ytry >= ysave) {
1694 for (i=1;i<=mpts;i++) {
1696 for (j=1;j<=ndim;j++) {
1697 p[i][j]=psum[j]=0.5*(p[i][j]+p[ilo][j]);
1733static double amotry(
1738 double (*funk)(
double []),
1743 double fac1,fac2,ytry,*ptry=NULL;
1745 ptry=cpl_calloc(ndim+1,
sizeof(
double));
1746 fac1=(1.0-fac)/ndim;
1748 for (j=1;j<=ndim;j++) ptry[j]=psum[j]*fac1-p[ihi][j]*fac2;
1750 if (ytry < y[ihi]) {
1752 for (j=1;j<=ndim;j++) {
1753 psum[j] += ptry[j]-p[ihi][j];
1797static cpl_imagelist * eris_ifu_priv_sky_stretch(
1798 cpl_imagelist * obj,
1799 cpl_imagelist * sky,
1802 int resampling_method,
1805 cpl_vector * obj_spec ;
1806 cpl_vector * sky_spec ;
1807 cpl_imagelist * new_sky ;
1809 cpl_polynomial * transf_poly ;
1810 cpl_polynomial * new_transf_poly ;
1811 cpl_bivector * matching_lines ;
1812 cpl_bivector * new_matching_lines ;
1815 if (obj == NULL || sky == NULL)
return NULL ;
1816 if (resampling_method != 1 && resampling_method != 2)
return NULL ;
1822 if (eris_ifu_sky_tweak_get_spectra_simple(obj, sky, mask, &obj_spec,
1823 &sky_spec) != CPL_ERROR_NONE) {
1824 cpl_msg_error(cpl_func,
"Cannot extract the spectra from cubes") ;
1825 cpl_image_delete(mask) ;
1830 if ((transf_poly = eris_ifu_stretch_get_poly(obj_spec, sky_spec, 5, poly_degree,
1831 &matching_lines))==NULL) {
1832 cpl_msg_error(cpl_func,
"Cannot compute the transformation polynomial");
1833 cpl_vector_delete(obj_spec) ;
1834 cpl_vector_delete(sky_spec) ;
1835 cpl_image_delete(mask) ;
1838 cpl_vector_delete(obj_spec) ;
1839 cpl_vector_delete(sky_spec) ;
1842 if (resampling_method == 1)
1843 new_sky = eris_ifu_stretch_apply_linear(sky, transf_poly) ;
1845 new_sky = eris_ifu_stretch_apply_spline(sky, transf_poly) ;
1846 if (new_sky == NULL) {
1847 cpl_msg_error(cpl_func,
"Cannot apply the transformation");
1848 cpl_polynomial_delete(transf_poly) ;
1849 cpl_image_delete(mask) ;
1854 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
1855 if (eris_ifu_sky_tweak_get_spectra_simple(obj, new_sky, mask, &obj_spec,
1856 &sky_spec) != CPL_ERROR_NONE) {
1857 cpl_msg_error(cpl_func,
"Cannot extract the spectra from cubes") ;
1858 cpl_image_delete(mask) ;
1859 cpl_bivector_delete(matching_lines) ;
1860 cpl_polynomial_delete(transf_poly) ;
1861 cpl_imagelist_delete(new_sky) ;
1864 if ((new_transf_poly = eris_ifu_stretch_get_poly(obj_spec, sky_spec, 5,
1865 poly_degree, &new_matching_lines))==NULL) {
1866 cpl_msg_error(cpl_func,
"Cannot compute the transf. polynomial");
1867 cpl_vector_delete(obj_spec) ;
1868 cpl_vector_delete(sky_spec) ;
1869 cpl_image_delete(mask) ;
1870 cpl_bivector_delete(matching_lines) ;
1871 cpl_polynomial_delete(transf_poly) ;
1872 cpl_imagelist_delete(new_sky) ;
1875 cpl_vector_delete(obj_spec) ;
1876 cpl_vector_delete(sky_spec) ;
1878 cpl_polynomial_dump(transf_poly, stdout) ;
1882 eris_ifu_stretch_plot_positions_differences(matching_lines,
1883 new_matching_lines) ;
1884 eris_ifu_stretch_check(obj, sky, new_sky, mask) ;
1886 cpl_bivector_delete(new_matching_lines) ;
1887 cpl_polynomial_delete(new_transf_poly) ;
1890 cpl_bivector_delete(matching_lines) ;
1891 cpl_polynomial_delete(transf_poly) ;
1892 cpl_image_delete(mask) ;
1897static cpl_polynomial * eris_ifu_stretch_get_poly(
1898 const cpl_vector * obj,
1899 const cpl_vector * sky,
1902 cpl_bivector ** matching_lines)
1906 cpl_matrix * matchedx ;
1907 cpl_polynomial * fitted ;
1910 if (obj == NULL || sky == NULL || matching_lines == NULL)
return NULL ;
1913 deg_loc = (cpl_size)degree ;
1916 *matching_lines=eris_ifu_strech_get_matching_lines(obj, sky, min_gap, 1,degree);
1917 nb_lines = cpl_bivector_get_size(*matching_lines) ;
1920 matchedx = cpl_matrix_wrap(1, nb_lines,
1921 cpl_vector_get_data(cpl_bivector_get_x(*matching_lines)));
1922 fitted = cpl_polynomial_new(1);
1923 if (cpl_polynomial_fit(fitted, matchedx, NULL,
1924 cpl_bivector_get_y(*matching_lines), NULL, CPL_FALSE,
1925 NULL, °_loc) != CPL_ERROR_NONE) {
1926 cpl_msg_error(cpl_func,
"Cannot fit the polynomial") ;
1927 cpl_polynomial_delete(fitted);
1928 cpl_matrix_unwrap(matchedx);
1929 cpl_bivector_delete(*matching_lines) ;
1932 cpl_matrix_unwrap(matchedx);
1945static cpl_imagelist * eris_ifu_stretch_apply_spline(
1947 cpl_polynomial * stretch)
1949 cpl_imagelist * out ;
1950 cpl_vector ** zlines ;
1951 cpl_vector ** resampled_zlines ;
1952 double * image_data ;
1955 double * resampled_array ;
1956 cpl_vector * new_pos ;
1957 int spec_size, nx, ny, i, j, k ;
1960 spec_size = cpl_imagelist_get_size(in) ;
1961 nx = cpl_image_get_size_x(cpl_imagelist_get_const(in, 0)) ;
1962 ny = cpl_image_get_size_x(cpl_imagelist_get_const(in, 0)) ;
1965 zlines = cpl_malloc(nx*ny*
sizeof(cpl_vector*)) ;
1966 for (i=0 ; i<nx ; i++)
1967 for (j=0 ; j<ny ; j++)
1968 zlines[i+j*nx] = cpl_vector_new(spec_size) ;
1971 for (k=0 ; k<spec_size ; k++) {
1972 image_data = cpl_image_get_data_double(cpl_imagelist_get(in, k)) ;
1973 for (i=0 ; i<nx ; i++)
1974 for (j=0 ; j<ny ; j++)
1975 if (!isnan(image_data[i+j*nx]))
1976 cpl_vector_set(zlines[i+j*nx], k, image_data[i+j*nx]) ;
1978 cpl_vector_set(zlines[i+j*nx], k, 0.0) ;
1982 pos = cpl_vector_new(spec_size) ;
1983 ppos = cpl_vector_get_data(pos);
1984 for (i=0 ; i<spec_size ; i++) ppos[i] = i+1 ;
1987 new_pos = cpl_vector_new(spec_size) ;
1988 cpl_vector_fill_polynomial(new_pos, stretch, 1, 1) ;
1991 if (cpl_vector_get(new_pos, 0) < 1.0) cpl_vector_set(new_pos, 0, 1.0) ;
1992 if (cpl_vector_get(new_pos, spec_size-1) > spec_size-1)
1993 cpl_vector_set(new_pos, spec_size-1, spec_size-1) ;
1995 resampled_zlines = cpl_malloc(nx*ny*
sizeof(cpl_vector*)) ;
1997 cpl_error_code retErr;
1998 for (i=0 ; i<nx ; i++) {
1999 for (j=0 ; j<ny ; j++) {
2000 resampled_array = cpl_malloc(spec_size *
sizeof(
double));
2002 ppos, cpl_vector_get_data(zlines[i+j*nx]), spec_size,
2003 cpl_vector_get_data(new_pos), resampled_array, spec_size,
2005 if (retErr != CPL_ERROR_NONE) {
2006 printf(
"ERROR: The function eris_ifu_1d_interpolation called in eris_ifu_stretch_apply_spline returned the error %d\n", retErr);
2007 printf(
"%s\n", cpl_error_get_message_default(retErr));
2015 resampled_zlines[i+j*nx] = cpl_vector_wrap(spec_size,
2019 cpl_vector_delete(new_pos) ;
2020 cpl_vector_delete(pos) ;
2024 for (i=0 ; i<nx ; i++)
2025 for (j=0 ; j<ny ; j++)
2026 cpl_vector_delete(zlines[i+j*nx]) ;
2030 out = cpl_imagelist_duplicate(in) ;
2031 for (k=0 ; k<spec_size ; k++) {
2032 image_data = cpl_image_get_data_double(cpl_imagelist_get(out, k)) ;
2033 for (i=0 ; i<nx ; i++)
2034 for (j=0 ; j<ny ; j++)
2035 image_data[i+j*nx]= cpl_vector_get(resampled_zlines[i+j*nx],k) ;
2039 for (i=0 ; i<nx ; i++)
2040 for (j=0 ; j<ny ; j++)
2041 cpl_free(cpl_vector_unwrap(resampled_zlines[i+j*nx]));
2043 cpl_free(resampled_zlines) ;
2056static cpl_imagelist * eris_ifu_stretch_apply_linear(
2058 cpl_polynomial * stretch)
2060 cpl_imagelist * out ;
2061 cpl_vector ** zlines ;
2062 cpl_vector ** resampled_zlines ;
2063 double * image_data ;
2066 cpl_vector * new_pos ;
2067 cpl_bivector * ref_spec ;
2068 cpl_bivector * resampled_spec ;
2069 int spec_size, nx, ny, i, j, k ;
2072 spec_size = cpl_imagelist_get_size(in) ;
2073 nx = cpl_image_get_size_x(cpl_imagelist_get_const(in, 0)) ;
2074 ny = cpl_image_get_size_x(cpl_imagelist_get_const(in, 0)) ;
2077 zlines = cpl_malloc(nx*ny*
sizeof(cpl_vector*)) ;
2078 for (i=0 ; i<nx ; i++)
2079 for (j=0 ; j<ny ; j++)
2080 zlines[i+j*nx] = cpl_vector_new(spec_size) ;
2083 for (k=0 ; k<spec_size ; k++) {
2084 image_data = cpl_image_get_data_double(cpl_imagelist_get(in, k)) ;
2085 for (i=0 ; i<nx ; i++)
2086 for (j=0 ; j<ny ; j++)
2087 if (!isnan(image_data[i+j*nx]))
2088 cpl_vector_set(zlines[i+j*nx], k, image_data[i+j*nx]) ;
2090 cpl_vector_set(zlines[i+j*nx], k, 0.0) ;
2094 pos = cpl_vector_new(spec_size) ;
2095 ppos = cpl_vector_get_data(pos);
2096 for (i=0 ; i<spec_size ; i++) ppos[i] = i+1 ;
2099 new_pos = cpl_vector_new(spec_size) ;
2100 cpl_vector_fill_polynomial(new_pos, stretch, 1, 1) ;
2103 if (cpl_vector_get(new_pos, 0) < 1.0) cpl_vector_set(new_pos, 0, 1.0) ;
2104 if (cpl_vector_get(new_pos, spec_size-1) > spec_size-1)
2105 cpl_vector_set(new_pos, spec_size-1, spec_size-1) ;
2107 resampled_zlines = cpl_malloc(nx*ny*
sizeof(cpl_vector*)) ;
2109 for (i=0 ; i<nx ; i++) {
2110 for (j=0 ; j<ny ; j++) {
2112 resampled_zlines[i+j*nx] = cpl_vector_new(spec_size) ;
2115 ref_spec = cpl_bivector_wrap_vectors(pos, zlines[i+j*nx]);
2116 resampled_spec = cpl_bivector_wrap_vectors(new_pos,
2117 resampled_zlines[i+j*nx]) ;
2119 cpl_bivector_interpolate_linear(resampled_spec, ref_spec) ;
2122 cpl_bivector_unwrap_vectors(ref_spec) ;
2123 cpl_bivector_unwrap_vectors(resampled_spec) ;
2126 cpl_vector_delete(new_pos) ;
2127 cpl_vector_delete(pos) ;
2130 for (i=0 ; i<nx ; i++)
2131 for (j=0 ; j<ny ; j++)
2132 cpl_vector_delete(zlines[i+j*nx]) ;
2136 out = cpl_imagelist_duplicate(in) ;
2137 for (k=0 ; k<spec_size ; k++) {
2138 image_data = cpl_image_get_data_double(cpl_imagelist_get(out, k)) ;
2139 for (i=0 ; i<nx ; i++)
2140 for (j=0 ; j<ny ; j++)
2141 image_data[i+j*nx]= cpl_vector_get(resampled_zlines[i+j*nx],k) ;
2145 for (i=0 ; i<nx ; i++)
2146 for (j=0 ; j<ny ; j++)
2147 cpl_vector_delete(resampled_zlines[i+j*nx]) ;
2148 cpl_free(resampled_zlines) ;
2152static int eris_ifu_stretch_check(
2153 cpl_imagelist * obj,
2154 cpl_imagelist * sky,
2155 cpl_imagelist * new_sky,
2158 cpl_vector * spec1 ;
2159 cpl_vector * spec2 ;
2161 eris_ifu_sky_tweak_get_spectra_simple(obj, sky, mask, &spec1, &spec2);
2162 cpl_plot_vector(
"set grid;set xlabel 'pix';",
"t 'obj' w lines",
"",
2164 cpl_plot_vector(
"set grid;set xlabel 'pix';",
2165 "t 'sky before stretching' w lines",
"", spec2);
2166 cpl_vector_subtract(spec1, spec2) ;
2168 cpl_plot_vector(
"set grid;set xlabel 'pix';",
2169 "t 'obj-sky before stretching' w lines",
"",
2171 cpl_vector_delete(spec1) ;
2172 cpl_vector_delete(spec2) ;
2174 eris_ifu_sky_tweak_get_spectra_simple(obj, new_sky, mask, &spec1, &spec2);
2175 cpl_plot_vector(
"set grid;set xlabel 'pix';",
2176 "t 'sky after stretching' w lines",
"", spec2);
2177 cpl_vector_subtract(spec1, spec2) ;
2179 cpl_plot_vector(
"set grid;set xlabel 'pix';",
2180 "t 'obj-sky after stretching' w lines",
"",
2182 cpl_vector_delete(spec1) ;
2183 cpl_vector_delete(spec2) ;
2188static int eris_ifu_stretch_plot_positions_differences(
2189 cpl_bivector * matching_lines,
2190 cpl_bivector * new_matching_lines)
2192 cpl_vector * diff_values ;
2193 cpl_bivector * diff ;
2196 diff_values = cpl_vector_duplicate(cpl_bivector_get_x(matching_lines)) ;
2197 cpl_vector_subtract(diff_values, cpl_bivector_get_y(matching_lines)) ;
2198 diff = cpl_bivector_wrap_vectors(cpl_bivector_get_x(matching_lines),
2200 cpl_plot_bivector(
"set grid;",
"t 'Pos. diff. BEFORE STRECHING'",
"", diff);
2201 cpl_bivector_unwrap_vectors(diff) ;
2202 cpl_vector_delete(diff_values) ;
2205 diff_values = cpl_vector_duplicate(cpl_bivector_get_x(new_matching_lines)) ;
2206 cpl_vector_subtract(diff_values, cpl_bivector_get_y(new_matching_lines)) ;
2207 diff = cpl_bivector_wrap_vectors(cpl_bivector_get_x(new_matching_lines),
2209 cpl_plot_bivector(
"set grid;",
"t 'Pos. diff. AFTER STRECHING'",
"", diff);
2210 cpl_bivector_unwrap_vectors(diff) ;
2211 cpl_vector_delete(diff_values) ;
2217static cpl_bivector * eris_ifu_strech_get_matching_lines(
2218 const cpl_vector * obj,
2219 const cpl_vector * sky,
2221 int remove_outliers,
2224 cpl_vector * tmp_vec ;
2225 cpl_vector * obj_lines ;
2226 cpl_vector * obj_lines_clean ;
2227 double * pobj_lines ;
2228 cpl_vector * sky_lines ;
2229 cpl_vector * sky_lines_clean ;
2230 double * psky_lines ;
2232 double * obj_lines_arr ;
2233 double * sky_lines_arr ;
2234 double obj_pos, sky_pos ;
2235 cpl_size sky_idx, nb_lines ;
2236 double fwhm, kappa, threshold ;
2240 if (obj == NULL || sky == NULL)
return NULL ;
2251 threshold = fabs(cpl_vector_get_mean(obj) + cpl_vector_get_stdev(obj)) ;
2252 tmp_vec = cpl_vector_duplicate(obj) ;
2253 for (i=0 ; i<cpl_vector_get_size(tmp_vec) ; i++) {
2254 if (cpl_vector_get(tmp_vec, i) < threshold)
2255 cpl_vector_set(tmp_vec, i, 0.0);
2257 if ((obj_lines = irplib_spectrum_detect_peaks(tmp_vec, fwhm,
2258 kappa, 0, NULL, NULL)) == NULL) {
2259 cpl_msg_error(cpl_func,
"Cannot detect peaks from obj") ;
2260 cpl_vector_delete(tmp_vec) ;
2263 cpl_vector_delete(tmp_vec) ;
2267 threshold = fabs(cpl_vector_get_mean(sky) + cpl_vector_get_stdev(sky)) ;
2268 tmp_vec = cpl_vector_duplicate(sky) ;
2269 for (i=0 ; i<cpl_vector_get_size(tmp_vec) ; i++) {
2270 if (cpl_vector_get(tmp_vec, i) < threshold)
2271 cpl_vector_set(tmp_vec, i, 0.0);
2273 if ((sky_lines = irplib_spectrum_detect_peaks(tmp_vec, fwhm,
2274 kappa, 0, NULL, NULL)) == NULL) {
2275 cpl_msg_error(cpl_func,
"Cannot detect peaks from sky") ;
2276 cpl_vector_delete(obj_lines) ;
2277 cpl_vector_delete(tmp_vec) ;
2280 cpl_vector_delete(tmp_vec) ;
2282 cpl_msg_debug(cpl_func,
"Detected %"CPL_SIZE_FORMAT
" lines from obj",
2283 cpl_vector_get_size(obj_lines));
2284 cpl_msg_debug(cpl_func,
"Detected %"CPL_SIZE_FORMAT
" lines from sky",
2285 cpl_vector_get_size(sky_lines));
2288 cpl_vector_sort(obj_lines, CPL_SORT_ASCENDING) ;
2289 nb_lines = cpl_vector_get_size(obj_lines) ;
2290 pobj_lines = cpl_vector_get_data(obj_lines) ;
2291 obj_lines_arr = cpl_malloc(nb_lines *
sizeof(
double)) ;
2293 obj_lines_arr[0] = pobj_lines[0] ;
2295 for (i=1 ; i<nb_lines ; i++) {
2297 if (fabs(pobj_lines[i]-pobj_lines[i-1]) > min_gap) {
2298 obj_lines_arr[nb_found] = pobj_lines[i] ;
2303 cpl_vector_delete(obj_lines) ;
2304 obj_lines = cpl_vector_new(nb_found) ;
2305 pobj_lines = cpl_vector_get_data(obj_lines) ;
2306 for (i=0 ; i<nb_found ; i++) pobj_lines[i] = obj_lines_arr[i] ;
2307 cpl_free(obj_lines_arr) ;
2308 nb_lines = cpl_vector_get_size(obj_lines) ;
2310 cpl_msg_debug(cpl_func,
2311 "Detected %"CPL_SIZE_FORMAT
" separated lines from obj",
2312 cpl_vector_get_size(obj_lines));
2315 obj_lines_arr = cpl_malloc(nb_lines *
sizeof(
double)) ;
2316 sky_lines_arr = cpl_malloc(nb_lines *
sizeof(
double)) ;
2318 cpl_vector_sort(sky_lines, CPL_SORT_ASCENDING) ;
2319 for (i=0 ; i<nb_lines ; i++) {
2320 obj_pos = cpl_vector_get(obj_lines, i) ;
2321 sky_idx = cpl_vector_find(sky_lines, obj_pos) ;
2322 sky_pos = cpl_vector_get(sky_lines, sky_idx) ;
2324 if (fabs(obj_pos-sky_pos) < min_gap) {
2325 obj_lines_arr[nb_found] = obj_pos ;
2326 sky_lines_arr[nb_found] = sky_pos ;
2332 cpl_vector_delete(obj_lines) ;
2333 cpl_vector_delete(sky_lines) ;
2334 obj_lines = cpl_vector_new(nb_found) ;
2335 sky_lines = cpl_vector_new(nb_found) ;
2336 nb_lines = cpl_vector_get_size(obj_lines) ;
2337 pobj_lines = cpl_vector_get_data(obj_lines) ;
2338 psky_lines = cpl_vector_get_data(sky_lines) ;
2339 for (i=0 ; i<nb_found ; i++) {
2340 pobj_lines[i] = obj_lines_arr[i] ;
2341 psky_lines[i] = sky_lines_arr[i] ;
2343 cpl_free(obj_lines_arr) ;
2344 cpl_free(sky_lines_arr) ;
2347 if (remove_outliers) {
2348 diff = cpl_vector_duplicate(obj_lines) ;
2349 cpl_vector_subtract(diff, sky_lines) ;
2350 threshold = fabs(cpl_vector_get_median_const(diff)) +
2351 2 * cpl_vector_get_stdev(diff) ;
2353 for (i=0 ; i<cpl_vector_get_size(diff) ; i++)
2354 if (fabs(cpl_vector_get(diff, i)) < threshold) nb_found++ ;
2355 obj_lines_clean = cpl_vector_new(nb_found) ;
2356 sky_lines_clean = cpl_vector_new(nb_found) ;
2358 for (i=0 ; i<cpl_vector_get_size(diff) ; i++)
2359 if (fabs(cpl_vector_get(diff, i)) < threshold) {
2360 cpl_vector_set(obj_lines_clean, nb_found,
2361 cpl_vector_get(obj_lines, i)) ;
2362 cpl_vector_set(sky_lines_clean, nb_found,
2363 cpl_vector_get(sky_lines, i)) ;
2366 cpl_vector_delete(diff) ;
2367 cpl_vector_delete(obj_lines) ;
2368 cpl_vector_delete(sky_lines) ;
2369 obj_lines = obj_lines_clean ;
2370 sky_lines = sky_lines_clean ;
2374 if (nb_found <= degree) {
2375 cpl_msg_error(cpl_func,
"Not enough match for the fit") ;
2376 cpl_vector_delete(obj_lines) ;
2377 cpl_vector_delete(sky_lines) ;
2381 cpl_msg_debug(cpl_func,
"Matched %"CPL_SIZE_FORMAT
" lines",
2382 cpl_vector_get_size(obj_lines));
2384 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)
Create spaxel selection mask for spectrum extraction.
cpl_vector * eris_ifu_lcorr_create_lambda_vector(const cpl_propertylist *header)
Create wavelength vector from FITS header WCS keywords.
int eris_ifu_plot_cube_background(cpl_imagelist *obj)
Extract background spectrum from cube and plot it.
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 and subtraction 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 known 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