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) ;
290 cpl_vector_delete(lambda);
291 cpl_imagelist_delete(*new_sky);
297 if (cpl_msg_get_level() == CPL_MSG_DEBUG)
298 cpl_image_save(mask,
"mask.fits", CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
303 eris_ifu_sky_tweak_get_spectra(obj, *new_sky, lambda, mask, 0,
304 &obj_spec, &sky_spec, &first_nonan);
307 vscales = eris_ifu_sky_tweak_correct_vibrational_trans(obj_spec,
308 sky_spec, skip_last, plot);
309 if (cpl_msg_get_level() == CPL_MSG_DEBUG && plot)
310 cpl_plot_bivector(
"set title \"SCALES\";",
"w lines",
"",vscales);
313 thermal_backg = eris_ifu_sky_tweak_thermal_bgd(obj_spec, 1.0);
316 if (thermal_backg == NULL) {
318 cpl_msg_indent_more() ;
319 cpl_msg_warning(__func__,
320 "Thermal Bgd failed, re-try by clipping highest values") ;
321 thermal_backg = eris_ifu_sky_tweak_thermal_bgd(obj_spec, 0.98);
322 if (thermal_backg == NULL) {
323 cpl_msg_warning(__func__,
324 "Recovery failed - skip the thermal background correction");
327 cpl_msg_info(__func__,
"Recovery succeeded");
329 cpl_msg_indent_less() ;
332 if (cpl_msg_get_level() == CPL_MSG_DEBUG && plot)
333 cpl_plot_bivector(
"set title \"Th. bgd\";",
"w lines",
"",thermal_backg);
336 new_obj = cpl_imagelist_duplicate(obj);
337 kmax = cpl_vector_get_size(cpl_bivector_get_x_const(obj_spec));
339 for (ix=0; ix<nz; ix++) {
340 if ((kx < kmax ) && (cpl_vector_get(lambda,ix)==cpl_vector_get(
341 cpl_bivector_get_x_const(obj_spec),kx))) {
343 if (thermal_backg != NULL) {
344 cpl_image_subtract_scalar(cpl_imagelist_get(*new_sky ,ix),
345 cpl_vector_get(cpl_bivector_get_y_const(thermal_backg),
351 cpl_image_multiply_scalar(cpl_imagelist_get(*new_sky, ix),
352 cpl_vector_get(cpl_bivector_get_y_const(vscales), kx));
355 cpl_image_subtract(cpl_imagelist_get(new_obj, ix),
356 cpl_imagelist_get(*new_sky, ix));
359 if (tbsub && thermal_backg != NULL) {
360 cpl_image_subtract_scalar(cpl_imagelist_get(new_obj, ix),
361 cpl_vector_get(cpl_bivector_get_y_const(
362 thermal_backg), kx));
367 cpl_bivector_delete(obj_spec);
368 cpl_bivector_delete(sky_spec);
369 if (thermal_backg != NULL) cpl_bivector_delete(thermal_backg);
370 cpl_bivector_delete(vscales);
371 cpl_vector_delete(lambda);
373 cpl_image_delete(mask);
393static void eris_ifu_plot_arrays(
399 cpl_vector ** vectors ;
402 if (obj == NULL || sky == NULL) return ;
405 vectors = cpl_malloc(3*
sizeof(cpl_vector*)) ;
406 vectors[0] = cpl_vector_wrap(arr_size, wl) ;
407 vectors[1] = cpl_vector_wrap(arr_size, obj) ;
408 vectors[2] = cpl_vector_wrap(arr_size, sky) ;
410 CPL_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
411 cpl_plot_vectors(
"set grid;set xlabel 'Wavelength (microns)';",
412 "t 'Obj and Sky sub-band' w lines",
"",
413 (
const cpl_vector **)vectors,
417 cpl_vector_unwrap(vectors[0]) ;
418 cpl_vector_unwrap(vectors[1]) ;
419 cpl_vector_unwrap(vectors[2]) ;
453static cpl_bivector * eris_ifu_sky_tweak_thermal_bgd(
454 cpl_bivector * spectrum,
457 cpl_bivector * result ;
458 cpl_vector * spectrum_v ;
459 cpl_vector * thermal_v ;
461 cpl_vector * sorted_y ;
463 const int nsimplex = ndim + 1;
465 double p_init[ndim+1];
466 double * lspectrum = NULL,
470 int i, j, ix, loop, niter, new_size, skip, input_size ;
471 double min, max, tmp, diff, limit, clip_limit ;
474 if (spectrum == NULL) {
475 cpl_msg_error(__func__,
"NULL inputs") ;
476 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
479 if ((clip_rate < 0.5) || (clip_rate > 1.0)) {
480 cpl_msg_error(__func__,
"Invalid clip rate: %g", clip_rate) ;
481 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
491 input_size = cpl_bivector_get_size(spectrum) ;
493 lspectrum = cpl_bivector_get_x_data(spectrum);
494 vspectrum = cpl_bivector_get_y_data(spectrum);
495 spectrum_lambda=cpl_malloc(input_size*
sizeof(
double));
496 spectrum_value=cpl_malloc(input_size*
sizeof(
double));
497 thermal_background= cpl_malloc(input_size*
sizeof(
double));
500 if (clip_rate < 1.0) {
501 sorted_y = cpl_vector_duplicate(cpl_bivector_get_y(spectrum));
502 cpl_vector_sort(sorted_y, CPL_SORT_ASCENDING);
503 clip_limit = cpl_vector_get(sorted_y,
504 cpl_vector_get_size(sorted_y) * clip_rate);
505 cpl_vector_delete(sorted_y) ;
511 for (ix=0; ix < input_size ; ix++)
if (vspectrum[ix] != 0.0)
break;
515 for (i=ix+skip; i<input_size; i++) {
517 && (vspectrum[i] <= clip_limit) ) {
518 spectrum_lambda[new_size] = lspectrum[i];
519 spectrum_value[new_size] = vspectrum[i];
520 if (vspectrum[i] < min) { min = vspectrum[i]; }
525 for (ix=new_size; ix >= 0; ix--)
if (vspectrum[ix] != 0.0)
break;
527 spectrum_size = ix-skip;
529 y_amoeba=cpl_malloc((nsimplex+1)*
sizeof(
double));
530 x_amoeba=cpl_malloc((ndim+1)*
sizeof(
double));
531 p = matrix(nsimplex+1,ndim+1);
534 p_init[2] = spectrum_value[spectrum_size-1];
540 for (loop=0; loop<20; loop++) {
545 for (i=2; i<nsimplex+1; i++) {
546 for (j=1; j<ndim+1; j++) p[i][j] = p[1][j];
548 for (i=2; i<nsimplex+1; i++) p[i][i-1] = p[i][i-1] * 1.2;
549 for (i=1; i<nsimplex+1; i++) {
550 for (j=1; j<ndim+1; j++) x_amoeba[j] = p[i][j];
551 y_amoeba[i] = fitbkd(x_amoeba);
553 amoeba(p, y_amoeba, 3, 1.e-5, fitbkd, &niter);
555 cpl_msg_error(__func__,
"Function minimization failed") ;
559 cpl_free(spectrum_lambda);
560 cpl_free(spectrum_value);
561 cpl_free(thermal_background);
562 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
565 spectrum_v = cpl_vector_wrap(spectrum_size, spectrum_value);
566 thermal_v = cpl_vector_wrap(spectrum_size, thermal_background);
567 tmp_v = cpl_vector_duplicate(spectrum_v);
568 cpl_vector_subtract(tmp_v, thermal_v);
569 limit = cpl_vector_get_median(tmp_v) + 2. * cpl_vector_get_stdev(tmp_v);
570 cpl_vector_delete(tmp_v);
571 cpl_vector_unwrap(spectrum_v);
572 cpl_vector_unwrap(thermal_v);
576 for (i=0; i<spectrum_size; i++) {
577 diff = spectrum_value[i] - thermal_background[i];
579 spectrum_lambda[new_size] = spectrum_lambda[i];
580 spectrum_value[new_size] = spectrum_value[i];
581 if (spectrum_value[i] < min) min = spectrum_value[i];
585 spectrum_size = new_size;
588 for (i=0; i<spectrum_size; i++) {
589 tmp = PLANCK(spectrum_lambda[i], p[1][3]);
590 if (tmp > max) max = tmp;
592 if (fabs(max) < 1e-90) {
593 cpl_msg_error(__func__,
"Cannot determine thermal Background") ;
597 cpl_free(spectrum_lambda);
598 cpl_free(spectrum_value);
599 cpl_free(thermal_background);
600 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
604 for (i=0; i<input_size; i++) {
605 spectrum_lambda[i] = lspectrum[i];
606 spectrum_value[i] = vspectrum[i];
607 tmp = PLANCK(spectrum_lambda[i], p[1][3]);
608 thermal_background[i] = p[1][1] + tmp / max * p[1][2];
610 thermal_v = cpl_vector_wrap(input_size, thermal_background);
611 tmp_v = cpl_vector_duplicate(thermal_v);
612 cpl_vector_unwrap(thermal_v);
614 result = cpl_bivector_wrap_vectors(
615 cpl_vector_duplicate(cpl_bivector_get_x_const(spectrum)), tmp_v);
620 cpl_free(spectrum_lambda);
621 cpl_free(spectrum_value);
622 cpl_free(thermal_background);
642static double eris_ifu_sky_tweak_get_mean_wo_outliers(
const cpl_vector * vdata)
648 const double * data ;
650 double avg, median, stdev, clip;
651 int nr_data, i, nr_i;
653 nr_data = cpl_vector_get_size(vdata);
654 data = cpl_vector_get_data_const(vdata);
655 tmpv1 = cpl_vector_new(nr_data);
656 tmpv1_data = cpl_vector_get_data(tmpv1);
658 median = cpl_vector_get_median_const(vdata);
659 for (i=0; i<nr_data; i++) tmpv1_data[i] = fabs(data[i] - median);
660 cpl_vector_sort(tmpv1, CPL_SORT_ASCENDING);
661 clip = cpl_vector_get(tmpv1, (
int) .8*nr_data);
664 median = cpl_vector_get_median_const(tmpv3);
665 stdev = cpl_vector_get_stdev(tmpv3);
667 for (i=0; i<nr_data; i++) {
668 if ((data[i] < median + 3. * stdev) && (data[i] > median - 3. * stdev)){
669 tmpv1_data[nr_i] = data[i];
673 tmpv4 = cpl_vector_wrap(nr_i, tmpv1_data);
674 avg = cpl_vector_get_mean(tmpv4);
676 cpl_vector_delete(tmpv1);
677 cpl_vector_delete(tmpv2);
678 cpl_vector_delete(tmpv3);
679 cpl_vector_unwrap(tmpv4);
708static cpl_error_code eris_ifu_sky_tweak_get_spectra_simple(
709 const cpl_imagelist *
object,
710 const cpl_imagelist * sky,
711 const cpl_image * mask,
712 cpl_vector ** obj_spec,
713 cpl_vector ** sky_spec)
715 cpl_vector * intobj ;
716 cpl_vector * intsky ;
717 const cpl_image * oimg ;
718 const cpl_image * simg ;
719 double * intobj_data ;
720 double * intsky_data ;
725 double mpix, opix, spix;
726 int nx, ny, nz, snx, sny, snz, ix, iy, iz, found,
727 m_is_rejected, o_is_rejected, s_is_rejected;
730 nx = cpl_image_get_size_x(cpl_imagelist_get_const(
object, 0));
731 ny = cpl_image_get_size_y(cpl_imagelist_get_const(
object, 0));
732 nz = cpl_imagelist_get_size(
object);
733 snx = cpl_image_get_size_x(cpl_imagelist_get_const(sky, 0));
734 sny = cpl_image_get_size_y(cpl_imagelist_get_const(sky, 0));
735 snz = cpl_imagelist_get_size(sky);
738 if (nx!=snx || ny!=sny || nz!=snz) {
739 cpl_msg_error(__func__,
"Illegal inputs") ;
740 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
741 return CPL_ERROR_ILLEGAL_INPUT ;
745 intobj = cpl_vector_new(nz);
746 intsky = cpl_vector_new(snz);
747 intobj_data = cpl_vector_get_data(intobj);
748 intsky_data = cpl_vector_get_data(intsky);
749 vo = cpl_malloc(nx * ny *
sizeof(
double));
750 vs = cpl_malloc(nx * ny *
sizeof(
double));
753 for (iz = 0; iz <nz; iz++) {
754 oimg = cpl_imagelist_get_const(
object, iz);
755 simg = cpl_imagelist_get_const(sky, iz);
757 for (ix = 1; ix<=nx; ix++) {
758 for (iy = 1; iy<=ny; iy++) {
759 mpix = cpl_image_get(mask, ix, iy, &m_is_rejected);
760 opix = cpl_image_get(oimg, ix, iy, &o_is_rejected);
761 spix = cpl_image_get(simg, ix, iy, &s_is_rejected);
762 if ( mpix > .5 && m_is_rejected == 0 && o_is_rejected == 0 &&
763 s_is_rejected == 0 ) {
771 if (found >= nx*ny/4.) {
772 ovec = cpl_vector_wrap(found, vo);
773 svec = cpl_vector_wrap(found, vs);
775 if (found < nx*ny/2. ) {
776 intobj_data[iz] = cpl_vector_get_median(ovec);
777 intsky_data[iz] = cpl_vector_get_median(svec);
779 intobj_data[iz] = eris_ifu_sky_tweak_get_mean_wo_outliers(ovec);
780 intsky_data[iz] = eris_ifu_sky_tweak_get_mean_wo_outliers(svec);
782 cpl_vector_unwrap(ovec);
783 cpl_vector_unwrap(svec);
785 intobj_data[iz] = 0.;
786 intsky_data[iz] = 0.;
795 return CPL_ERROR_NONE;
826static cpl_error_code eris_ifu_sky_tweak_get_spectra(
827 const cpl_imagelist *
object,
828 const cpl_imagelist * sky,
829 const cpl_vector * lambda,
830 const cpl_image * mask,
832 cpl_bivector ** obj_spectrum_ptr,
833 cpl_bivector ** sky_spectrum_ptr,
836 cpl_bivector * obj_spectrum ;
837 cpl_bivector * sky_spectrum ;
838 cpl_vector * intobj ;
839 cpl_vector * intsky ;
840 cpl_vector * new_lambda ;
841 cpl_vector * new_intobj ;
842 cpl_vector * new_intsky ;
843 const cpl_image * oimg ;
844 const cpl_image * simg ;
845 double * intobj_data ;
846 double * intsky_data ;
849 double * new_lambda_d ;
850 double * new_intobj_d ;
851 double * new_intsky_d ;
852 const double * lambda_d ;
855 double mpix, opix, spix;
856 int nx, ny, nz, snx, sny, snz, ix, iy, iz, ni, found,
857 nr_valid_int, m_is_rejected, o_is_rejected,
862 if (first_nonan==NULL) {
863 cpl_msg_error(__func__,
"Illegal inputs") ;
864 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
865 return CPL_ERROR_ILLEGAL_INPUT ;
870 nx = cpl_image_get_size_x(cpl_imagelist_get_const(
object, 0));
871 ny = cpl_image_get_size_y(cpl_imagelist_get_const(
object, 0));
872 nz = cpl_imagelist_get_size(
object);
873 snx = cpl_image_get_size_x(cpl_imagelist_get_const(sky, 0));
874 sny = cpl_image_get_size_y(cpl_imagelist_get_const(sky, 0));
875 snz = cpl_imagelist_get_size(sky);
877 if (nx!=snx || ny!=sny || nz!=snz) {
878 cpl_msg_error(__func__,
"Illegal inputs") ;
879 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
880 return CPL_ERROR_ILLEGAL_INPUT ;
883 if (nz != cpl_vector_get_size(lambda)) {
884 cpl_msg_error(__func__,
"Illegal inputs") ;
885 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
886 return CPL_ERROR_ILLEGAL_INPUT ;
889 intobj = cpl_vector_new(cpl_vector_get_size(lambda));
890 intsky = cpl_vector_new(cpl_vector_get_size(lambda));
891 intobj_data = cpl_vector_get_data(intobj);
892 intsky_data = cpl_vector_get_data(intsky);
894 vo = cpl_malloc(nx * ny *
sizeof(
double));
895 vs = cpl_malloc(nx * ny *
sizeof(
double));
898 for (iz = 0; iz <nz; iz++) {
899 oimg = cpl_imagelist_get_const(
object, iz);
900 simg = cpl_imagelist_get_const(sky, iz);
902 for (ix = 1; ix<=nx; ix++) {
903 for (iy = 1; iy<=ny; iy++) {
904 mpix = cpl_image_get(mask, ix, iy, &m_is_rejected);
905 opix = cpl_image_get(oimg, ix, iy, &o_is_rejected);
906 spix = cpl_image_get(simg, ix, iy, &s_is_rejected);
907 if ( mpix > .5 && m_is_rejected == 0 && o_is_rejected == 0 &&
908 s_is_rejected == 0 ) {
916 if (found >= nx*ny/4.) {
917 if (*first_nonan < 0) *first_nonan = iz ;
919 ovec = cpl_vector_wrap(found, vo);
920 svec = cpl_vector_wrap(found, vs);
922 if (found < nx*ny/2. ) {
923 intobj_data[iz] = cpl_vector_get_median(ovec);
924 intsky_data[iz] = cpl_vector_get_median(svec);
926 intobj_data[iz] = eris_ifu_sky_tweak_get_mean_wo_outliers(ovec);
927 intsky_data[iz] = eris_ifu_sky_tweak_get_mean_wo_outliers(svec);
929 cpl_vector_unwrap(ovec);
930 cpl_vector_unwrap(svec);
933 intobj_data[iz] = 0./0.;
934 intsky_data[iz] = 0./0.;
937 intobj_data[iz] = 0.;
938 intsky_data[iz] = 0.;
944 new_lambda = cpl_vector_new(nr_valid_int);
945 new_intobj = cpl_vector_new(nr_valid_int);
946 new_intsky = cpl_vector_new(nr_valid_int);
947 new_lambda_d=cpl_vector_get_data(new_lambda);
948 new_intobj_d=cpl_vector_get_data(new_intobj);
949 new_intsky_d=cpl_vector_get_data(new_intsky);
950 lambda_d=cpl_vector_get_data_const(lambda);
953 for (iz=0 ; iz<nz; iz++) {
954 if ((! isnan(intobj_data[iz])) && ni < nr_valid_int) {
955 new_lambda_d[ni] = lambda_d[iz];
956 new_intobj_d[ni] = intobj_data[iz];
957 new_intsky_d[ni] = intsky_data[iz];
961 obj_spectrum = cpl_bivector_wrap_vectors(new_lambda, new_intobj) ;
962 sky_spectrum = cpl_bivector_wrap_vectors(
963 cpl_vector_duplicate(new_lambda), new_intsky);
965 cpl_vector_delete(intobj);
966 cpl_vector_delete(intsky);
968 obj_spectrum = cpl_bivector_wrap_vectors(cpl_vector_duplicate(lambda),
970 sky_spectrum = cpl_bivector_wrap_vectors(cpl_vector_duplicate(lambda),
976 *obj_spectrum_ptr = obj_spectrum;
977 *sky_spectrum_ptr = sky_spectrum;
978 return CPL_ERROR_NONE;
1017static cpl_bivector * eris_ifu_sky_tweak_correct_vibrational_trans(
1018 cpl_bivector * obj_spectrum,
1019 cpl_bivector * sky_spectrum,
1023 cpl_bivector * result ;
1025 double * lambda_boundaries ;
1026 const char ** labels ;
1027 const double * lambda ;
1028 const double * intobj ;
1029 const double * intsky ;
1030 double * array_wls ;
1031 double * array_obj ;
1032 double * array_sky ;
1033 double * line_interpolate_object ;
1034 double * line_interpolate_sky ;
1036 cpl_vector * tmp_vec ;
1037 cpl_vector * sky_lines_map_vec ;
1038 double median, stdev ;
1039 int i, ix, il, lx, cx, nr_lambda, nr_samples, nr_boundaries,
1040 cont_start, cont_end ;
1041 cpl_error_code errCode;
1044 if (obj_spectrum == NULL || sky_spectrum == NULL) {
1045 cpl_msg_error(__func__,
"NULL inputs") ;
1046 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
1049 if (cpl_bivector_get_size(obj_spectrum) !=
1050 cpl_bivector_get_size(sky_spectrum)) {
1051 cpl_msg_error(__func__,
"Illegal inputs") ;
1052 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
1057 nr_lambda = cpl_bivector_get_size(obj_spectrum);
1058 lambda = cpl_vector_get_data_const(cpl_bivector_get_x_const(obj_spectrum));
1059 intobj = cpl_vector_get_data_const(cpl_bivector_get_y_const(obj_spectrum));
1060 intsky = cpl_vector_get_data_const(cpl_bivector_get_y_const(sky_spectrum));
1061 median = stdev = 0.0 ;
1064 for (ix=0; ix<nr_lambda; ix++) {
1065 if (fabs(lambda[ix] -
1066 cpl_vector_get(cpl_bivector_get_x_const(sky_spectrum), ix))
1068 cpl_msg_error(__func__,
"Illegal inputs") ;
1069 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
1076 nr_boundaries = 20 ;
1077 lambda_boundaries = cpl_malloc(nr_boundaries *
sizeof(
double)) ;
1078 labels = cpl_malloc((nr_boundaries-1) *
sizeof(
char*)) ;
1080 nr_boundaries = 21 ;
1081 lambda_boundaries = cpl_malloc(nr_boundaries *
sizeof(
double)) ;
1082 labels = cpl_malloc((nr_boundaries-1) *
sizeof(
char*)) ;
1084 lambda_boundaries[0] = 0.780 ; labels[0] =
"" ;
1085 lambda_boundaries[1] = 0.824 ; labels[1] =
"" ;
1086 lambda_boundaries[2] = 0.873 ; labels[2] =
"" ;
1087 lambda_boundaries[3] = 0.926 ; labels[3] =
"" ;
1088 lambda_boundaries[4] = 0.964 ; labels[4] =
"" ;
1089 lambda_boundaries[5] = 1.014 ; labels[5] =
"4-1 transitions" ;
1090 lambda_boundaries[6] = 1.067 ; labels[6] =
"5-2 transitions" ;
1091 lambda_boundaries[7] = 1.125 ; labels[7] =
"6-3 transitions" ;
1092 lambda_boundaries[8] = 1.196 ; labels[8] =
"7-4 transitions" ;
1093 lambda_boundaries[9] = 1.252 ; labels[9] =
" 02 transitions" ;
1094 lambda_boundaries[10] = 1.289 ; labels[10] =
"8-5 transitions" ;
1095 lambda_boundaries[11] = 1.400 ; labels[11] =
"2-0 transitions" ;
1096 lambda_boundaries[12] = 1.472 ; labels[12] =
"3-1 transitions" ;
1097 lambda_boundaries[13] = 1.5543 ; labels[13] =
"4-2 transitions" ;
1098 lambda_boundaries[14] = 1.6356 ; labels[14] =
"5-3 transitions" ;
1099 lambda_boundaries[15] = 1.7253 ; labels[15] =
"6-4 transitions" ;
1100 lambda_boundaries[16] = 1.840 ; labels[16] =
"7-5 transitions" ;
1101 lambda_boundaries[17] = 1.9570 ; labels[17] =
"8-6 transitions" ;
1102 lambda_boundaries[18] = 2.095 ; labels[18] =
"9-7 transitions" ;
1104 lambda_boundaries[19] = 2.460 ;
1106 lambda_boundaries[19] = 2.30 ; labels[19] =
"final bit" ;
1107 lambda_boundaries[20] = 2.460 ;
1111 scalings = cpl_malloc(nr_boundaries *
sizeof(
double)) ;
1112 for (ix=0; ix<nr_boundaries; ix++) scalings[ix] = 0.;
1114 array_wls = cpl_malloc(nr_lambda *
sizeof(
double)) ;
1115 array_obj = cpl_malloc(nr_lambda *
sizeof(
double)) ;
1116 array_sky = cpl_malloc(nr_lambda *
sizeof(
double)) ;
1119 for (ix = 0; ix<nr_boundaries-1; ix++) {
1120 cpl_msg_debug(__func__,
"Sub-band %2d: %s", ix+1, labels[ix]) ;
1121 cpl_msg_indent_more() ;
1125 for (il=0; il<nr_lambda; il++) {
1126 if ((lambda[il] >= lambda_boundaries[ix] ) &&
1127 (lambda[il] < lambda_boundaries[ix+1]) ) {
1131 intsky[il] == 0. || intobj[il] == 0. ) {
1132 cpl_msg_indent_less() ;
1136 array_wls[nr_samples] = lambda[il];
1137 array_obj[nr_samples] = intobj[il];
1138 array_sky[nr_samples] = intsky[il];
1142 cpl_msg_debug(__func__,
"Found %d samples", nr_samples) ;
1145 if (nr_samples <= 20) {
1146 cpl_msg_indent_less() ;
1149 if (plot==ix+1 && cpl_msg_get_level() == CPL_MSG_DEBUG)
1150 eris_ifu_plot_arrays(array_wls, array_obj, array_sky, nr_samples);
1153 tmp_vec = cpl_vector_wrap(nr_samples, array_sky);
1154 median = cpl_vector_get_median_const(tmp_vec);
1155 stdev = cpl_vector_get_stdev(tmp_vec);
1156 cpl_vector_unwrap(tmp_vec);
1157 cpl_msg_debug(__func__,
"Sky Stats - Med: %g Stdev: %g", median, stdev);
1160 sky_lines_map_vec = cpl_vector_new(nr_samples) ;
1161 cpl_vector_fill(sky_lines_map_vec, 0.0) ;
1162 for (i=0; i<nr_samples; i++) {
1163 if (array_sky[i] > median+stdev)
1164 cpl_vector_set(sky_lines_map_vec, i, 10.0) ;
1166 if (plot==ix+1 && cpl_msg_get_level() == CPL_MSG_DEBUG)
1167 cpl_plot_vector(
"set grid;set xlabel 'Samples';set ylabel 'Map';",
1168 "t 'Sky lines map' w lines",
"", sky_lines_map_vec);
1171 tmp_vec=cpl_vector_filter_lowpass_create(sky_lines_map_vec,
1172 CPL_LOWPASS_LINEAR,2);
1173 cpl_vector_delete(sky_lines_map_vec);
1174 sky_lines_map_vec = tmp_vec ;
1176 if (plot==ix+1 && cpl_msg_get_level() == CPL_MSG_DEBUG)
1177 cpl_plot_vector(
"set grid;set xlabel 'Samples';set ylabel 'Map';",
1178 "t 'Smoothed sky lines map' w lines",
"",
1182 eris_ifu_sky_tweak_identify_lines_cont(sky_lines_map_vec,
1183 &cont_start, &cont_end, &cont_size, &lines_size) ;
1184 if (lines_size == 0) {
1185 cpl_msg_warning(__func__,
"No line region found") ;
1186 cpl_vector_delete(sky_lines_map_vec);
1187 cpl_msg_indent_less() ;
1193 cont_sky_sig = cpl_malloc(cont_size *
sizeof(
double));
1194 cont_object_sig = cpl_malloc(cont_size *
sizeof(
double));
1195 cont_lambda = cpl_malloc(cont_size *
sizeof(
double));
1196 line_sky_sig = cpl_malloc(lines_size *
sizeof(
double));
1197 line_object_sig = cpl_malloc(lines_size *
sizeof(
double));
1198 line_lambda = cpl_malloc(lines_size *
sizeof(
double));
1202 for (i = cont_start; i <= cont_end ; i++) {
1203 if (cpl_vector_get(sky_lines_map_vec, i) > 0.) {
1204 line_sky_sig[lx] = array_sky[i];
1205 line_object_sig[lx] = array_obj[i];
1206 line_lambda[lx] = array_wls[i];
1209 cont_sky_sig[cx] = array_sky[i];
1210 cont_object_sig[cx] = array_obj[i];
1211 cont_lambda[cx] = array_wls[i];
1219 const int nsimplex = ndim + 1;
1221 double *x_amoeba = NULL,
1226 y_amoeba = cpl_malloc((nsimplex+1) *
sizeof(
double));
1227 x_amoeba = cpl_malloc((ndim+1) *
sizeof(
double));
1228 p = matrix(nsimplex+1,ndim+1);
1232 for (ip=1; ip<nsimplex+1; ip++) {
1233 for (jp=1; jp<ndim+1; jp++) {
1234 x_amoeba[jp] = p[ip][jp];
1236 y_amoeba[ip] = fitsky(x_amoeba);
1238 amoeba(p, y_amoeba, ndim, 1.e-5, fitsky, &niter );
1240 cpl_msg_error(__func__,
"Function minimization failed") ;
1244 cpl_free(spectrum_lambda);
1245 cpl_free(spectrum_value);
1246 cpl_free(thermal_background);
1247 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
1251 flineres = cpl_malloc(lines_size *
sizeof(
double));
1260 line_interpolate_object = cpl_calloc(lines_size,
sizeof(
double));
1262 cont_lambda, cont_object_sig, cont_size,
1263 line_lambda, line_interpolate_object, lines_size, 2);
1264 if (errCode != CPL_ERROR_NONE) {
1265 printf(
"ERROR: The function eris_ifu_1d_interpolation called in eris_ifu_sky_tweak_correct_vibrational_trans returned the error %d\n", errCode);
1266 printf(
"%s\n", cpl_error_get_message_default(errCode));
1269 line_interpolate_sky = cpl_calloc(lines_size,
sizeof(
double));
1271 cont_lambda, cont_sky_sig, cont_size,
1272 line_lambda, line_interpolate_sky, lines_size, 2);
1273 if (errCode != CPL_ERROR_NONE) {
1274 printf(
"ERROR: The function eris_ifu_1d_interpolation called in eris_ifu_sky_tweak_correct_vibrational_trans returned the error %d\n", errCode);
1275 printf(
"%s\n", cpl_error_get_message_default(errCode));
1278 for (i=0; i<lines_size; i++) {
1279 flineres[i] = (line_object_sig[i] -
1280 line_interpolate_object[i]) -
1281 (line_sky_sig[i] - line_interpolate_sky[i]) * scale;
1284 tmp_vec = cpl_vector_wrap(lines_size, flineres);
1285 median = cpl_vector_get_median_const(tmp_vec);
1286 stdev = cpl_vector_get_stdev(tmp_vec);
1287 cpl_vector_unwrap(tmp_vec) ;
1290 for (i=0; i<lines_size; i++) {
1291 if ( fabs(flineres[i] - median) <= (3 * stdev) ) {
1295 cpl_msg_debug(__func__,
"Outliers: %d", lines_size-clip_cnt) ;
1297 if ((clip_cnt != lines_size) && (clip_cnt >= 3)) {
1299 for (i=0; i<lines_size; i++) {
1300 if ( fabs(flineres[i] - median) <= (3 * stdev) ) {
1301 line_sky_sig[lx] = line_sky_sig[i];
1302 line_object_sig[lx] =
1304 line_lambda[lx] = line_lambda[i];
1309 cpl_msg_debug(__func__,
"2. Lines size: %d", lines_size) ;
1313 for (ip=1; ip<nsimplex+1; ip++) {
1314 for (jp=1; jp<ndim+1; jp++) x_amoeba[jp] = p[ip][jp];
1315 y_amoeba[ip] = fitsky(x_amoeba);
1317 amoeba(p, y_amoeba, ndim, 1.e-5, fitsky, &niter);
1319 cpl_msg_error(__func__,
"Function minimization failed") ;
1323 cpl_free(spectrum_lambda);
1324 cpl_free(spectrum_value);
1325 cpl_free(thermal_background);
1326 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
1331 cpl_msg_debug(__func__,
"Scale: %g", scale) ;
1332 scalings[ix] = scale;
1334 cpl_vector_delete(sky_lines_map_vec);
1335 free_matrix(p, nsimplex+1);
1338 cpl_free(cont_sky_sig);
1339 cpl_free(line_sky_sig);
1340 cpl_free(cont_object_sig);
1341 cpl_free(line_object_sig);
1342 cpl_free(cont_lambda);
1343 cpl_free(line_lambda);
1345 cpl_free(line_interpolate_object);
1346 cpl_free(line_interpolate_sky);
1348 cpl_msg_indent_less() ;
1355 double valid_scales[nr_boundaries];
1356 cpl_vector *valid_scales_v = NULL;
1357 for (ix=0; ix<nr_boundaries; ix++) {
1358 if (scalings[ix] != 0.0 ) {
1359 valid_scales[nr_valid] = scalings[ix];
1363 valid_scales_v = cpl_vector_wrap(nr_valid, valid_scales);
1364 median = cpl_vector_get_median_const(valid_scales_v);
1365 stdev = cpl_vector_get_stdev(valid_scales_v);
1367 for (ix=0; ix<nr_boundaries; ix++) {
1368 if (scalings[ix] != 0.0 ) {
1369 if (fabs(valid_scales[v_ix] - median) > 2 * stdev) {
1375 if (valid_scales_v != NULL) {
1376 cpl_vector_unwrap(valid_scales_v);
1377 valid_scales_v = NULL;
1381 double *scale0_lambda = NULL,
1382 *scale0_value = NULL,
1384 cpl_vector *scale_v = NULL;
1386 scale0_lambda = cpl_malloc(nr_lambda *
sizeof(
double));
1387 scale0_value = cpl_malloc(nr_lambda *
sizeof(
double));
1390 for (il=0; il<nr_lambda; il++) {
1391 for (ix = 0; ix<nr_boundaries-1; ix++) {
1392 if (scalings[ix] != 0.) {
1393 if ((lambda[il] >= lambda_boundaries[ix] ) &&
1394 (lambda[il] < lambda_boundaries[ix+1]) ) {
1395 scale0_lambda[scale0_size] = lambda[il];
1396 scale0_value[scale0_size] = scalings[ix];
1402 cpl_free(scalings) ;
1403 cpl_free(lambda_boundaries) ;
1408 scale = cpl_calloc(nr_lambda,
sizeof(
double));
1410 double* lambda_tmp = (
double*) lambda;
1412 scale0_lambda, scale0_value, scale0_size,
1413 lambda_tmp, scale, nr_lambda, 2);
1414 if (errCode != CPL_ERROR_NONE) {
1415 printf(
"ERROR: The function eris_ifu_1d_interpolation called in eris_ifu_sky_tweak_correct_vibrational_trans returned the error %d\n", errCode);
1416 printf(
"%s\n", cpl_error_get_message_default(errCode));
1419 scale_v = cpl_vector_wrap(nr_lambda, scale);
1421 if (scale0_lambda != NULL) cpl_free(scale0_lambda);
1422 if (scale0_value != NULL) cpl_free(scale0_value);
1423 result = cpl_bivector_wrap_vectors(
1424 cpl_vector_duplicate(cpl_bivector_get_x_const(obj_spectrum)),
1427 cpl_free(array_wls) ;
1428 cpl_free(array_obj) ;
1429 cpl_free(array_sky) ;
1452static int eris_ifu_sky_tweak_identify_lines_cont(
1453 cpl_vector * sky_lines_map_vec,
1456 int * local_cont_size,
1457 int * local_lines_size)
1459 int current_line_size, nr_samples, i ;
1464 current_line_size = 0 ;
1465 nr_samples = cpl_vector_get_size(sky_lines_map_vec) ;
1470 *local_cont_size = 0;
1471 *local_lines_size = 0;
1472 for (i=0; i<nr_samples; i++) {
1473 if (cpl_vector_get(sky_lines_map_vec, i) > 0.) {
1476 if (*cont_start == -1)
continue;
1477 current_line_size++;
1480 if (*cont_start == -1) *cont_start = i;
1482 (*local_cont_size)++;
1483 *local_lines_size += current_line_size;
1484 current_line_size = 0;
1487 cpl_msg_debug(__func__,
"Cont [%d, %d] size: %d / Lines size: %d",
1488 *cont_start, *cont_end, *local_cont_size, *local_lines_size) ;
1510static double fitsky(
double *p) {
1512 double *cont_sky = NULL,
1513 *cont_object = NULL;
1516 cpl_error_code errCode;
1525 cont_sky = cpl_calloc(lines_size,
sizeof(
double));
1527 line_lambda, cont_sky, lines_size, 2);
1528 if (errCode != CPL_ERROR_NONE) {
1529 printf(
"ERROR: The function eris_ifu_1d_interpolation called in fitsky returned the error %d\n", errCode);
1530 printf(
"%s\n", cpl_error_get_message_default(errCode));
1533 cont_object = cpl_calloc(lines_size,
sizeof(
double));
1535 line_lambda, cont_object, lines_size, 2);
1536 if (errCode != CPL_ERROR_NONE) {
1537 printf(
"ERROR: The function eris_ifu_1d_interpolation called in fitsky returned the error %d\n", errCode);
1538 printf(
"%s\n", cpl_error_get_message_default(errCode));
1541 for (ix=0; ix<lines_size; ix++) {
1542 double diff = (line_object_sig[ix] - cont_object[ix]) -
1543 (line_sky_sig[ix] - cont_sky[ix]) * p[1];
1578static double fitbkd(
double *p) {
1584 tmp = cpl_malloc(spectrum_size *
sizeof(
double));
1587 for (i=0; i<spectrum_size; i++) {
1588 tmp[i] = PLANCK(spectrum_lambda[i], p[3]);
1595 for (i=0; i<spectrum_size; i++) {
1596 thermal_background[i] = p[1] + tmp[i] / max * fabs(p[2]);
1599 for (i=0; i<spectrum_size; i++) {
1600 thermal_background[i] = tmp[i];
1605 for (i=0; i<spectrum_size; i++) {
1606 result += (spectrum_value[i] - thermal_background[i]) *
1607 (spectrum_value[i] - thermal_background[i]);
1610 if (tmp != NULL) cpl_free(tmp);
1642 for (j=1;j<=ndim;j++) {\
1643 for (sum=0.0,i=1;i<=mpts;i++) sum += p[i][j];\
1645#define SWAP(a,b) {swap=(a);(a)=(b);(b)=swap;}
1651 double (*funk)(
double []),
1654 int i,ihi,ilo,inhi,j,mpts=ndim+1;
1655 double rtol, sum, swap, ysave, ytry, *psum = NULL, d;
1657 psum=cpl_calloc(ndim+1,
sizeof(
double));
1662 ihi = y[1]>y[2] ? (inhi=2,1) : (inhi=1,2);
1663 for (i=1;i<=mpts;i++) {
1664 if (y[i] <= y[ilo]) {
1667 if (y[i] > y[ihi]) {
1670 }
else if (y[i] > y[inhi] && i != ihi) inhi=i;
1672 d = fabs(y[ihi])+fabs(y[ilo]);
1676 rtol=2.0*fabs(y[ihi]-y[ilo])/d;
1680 for (i=1;i<=ndim;i++) SWAP(p[1][i],p[ilo][i])
1683 if (*nfunk >= 5000) {
1689 ytry=amotry(p,y,psum,ndim,funk,ihi,-1.0);
1691 ytry=amotry(p,y,psum,ndim,funk,ihi,2.0);
1692 else if (ytry >= y[inhi]) {
1694 ytry=amotry(p,y,psum,ndim,funk,ihi,0.5);
1695 if (ytry >= ysave) {
1696 for (i=1;i<=mpts;i++) {
1698 for (j=1;j<=ndim;j++) {
1699 p[i][j]=psum[j]=0.5*(p[i][j]+p[ilo][j]);
1735static double amotry(
1740 double (*funk)(
double []),
1745 double fac1,fac2,ytry,*ptry=NULL;
1747 ptry=cpl_calloc(ndim+1,
sizeof(
double));
1748 fac1=(1.0-fac)/ndim;
1750 for (j=1;j<=ndim;j++) ptry[j]=psum[j]*fac1-p[ihi][j]*fac2;
1752 if (ytry < y[ihi]) {
1754 for (j=1;j<=ndim;j++) {
1755 psum[j] += ptry[j]-p[ihi][j];
1799static cpl_imagelist * eris_ifu_priv_sky_stretch(
1800 cpl_imagelist * obj,
1801 cpl_imagelist * sky,
1804 int resampling_method,
1807 cpl_vector * obj_spec ;
1808 cpl_vector * sky_spec ;
1809 cpl_imagelist * new_sky ;
1811 cpl_polynomial * transf_poly ;
1812 cpl_polynomial * new_transf_poly ;
1813 cpl_bivector * matching_lines ;
1814 cpl_bivector * new_matching_lines ;
1817 if (obj == NULL || sky == NULL)
return NULL ;
1818 if (resampling_method != 1 && resampling_method != 2)
return NULL ;
1824 if (eris_ifu_sky_tweak_get_spectra_simple(obj, sky, mask, &obj_spec,
1825 &sky_spec) != CPL_ERROR_NONE) {
1826 cpl_msg_error(cpl_func,
"Cannot extract the spectra from cubes") ;
1827 cpl_image_delete(mask) ;
1832 if ((transf_poly = eris_ifu_stretch_get_poly(obj_spec, sky_spec, 5, poly_degree,
1833 &matching_lines))==NULL) {
1834 cpl_msg_error(cpl_func,
"Cannot compute the transformation polynomial");
1835 cpl_vector_delete(obj_spec) ;
1836 cpl_vector_delete(sky_spec) ;
1837 cpl_image_delete(mask) ;
1840 cpl_vector_delete(obj_spec) ;
1841 cpl_vector_delete(sky_spec) ;
1844 if (resampling_method == 1)
1845 new_sky = eris_ifu_stretch_apply_linear(sky, transf_poly) ;
1847 new_sky = eris_ifu_stretch_apply_spline(sky, transf_poly) ;
1848 if (new_sky == NULL) {
1849 cpl_msg_error(cpl_func,
"Cannot apply the transformation");
1850 cpl_polynomial_delete(transf_poly) ;
1851 cpl_image_delete(mask) ;
1856 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
1857 if (eris_ifu_sky_tweak_get_spectra_simple(obj, new_sky, mask, &obj_spec,
1858 &sky_spec) != CPL_ERROR_NONE) {
1859 cpl_msg_error(cpl_func,
"Cannot extract the spectra from cubes") ;
1860 cpl_image_delete(mask) ;
1861 cpl_bivector_delete(matching_lines) ;
1862 cpl_polynomial_delete(transf_poly) ;
1863 cpl_imagelist_delete(new_sky) ;
1866 if ((new_transf_poly = eris_ifu_stretch_get_poly(obj_spec, sky_spec, 5,
1867 poly_degree, &new_matching_lines))==NULL) {
1868 cpl_msg_error(cpl_func,
"Cannot compute the transf. polynomial");
1869 cpl_vector_delete(obj_spec) ;
1870 cpl_vector_delete(sky_spec) ;
1871 cpl_image_delete(mask) ;
1872 cpl_bivector_delete(matching_lines) ;
1873 cpl_polynomial_delete(transf_poly) ;
1874 cpl_imagelist_delete(new_sky) ;
1877 cpl_vector_delete(obj_spec) ;
1878 cpl_vector_delete(sky_spec) ;
1880 cpl_polynomial_dump(transf_poly, stdout) ;
1884 eris_ifu_stretch_plot_positions_differences(matching_lines,
1885 new_matching_lines) ;
1886 eris_ifu_stretch_check(obj, sky, new_sky, mask) ;
1888 cpl_bivector_delete(new_matching_lines) ;
1889 cpl_polynomial_delete(new_transf_poly) ;
1892 cpl_bivector_delete(matching_lines) ;
1893 cpl_polynomial_delete(transf_poly) ;
1894 cpl_image_delete(mask) ;
1899static cpl_polynomial * eris_ifu_stretch_get_poly(
1900 const cpl_vector * obj,
1901 const cpl_vector * sky,
1904 cpl_bivector ** matching_lines)
1908 cpl_matrix * matchedx ;
1909 cpl_polynomial * fitted ;
1912 if (obj == NULL || sky == NULL || matching_lines == NULL)
return NULL ;
1915 deg_loc = (cpl_size)degree ;
1918 *matching_lines=eris_ifu_strech_get_matching_lines(obj, sky, min_gap, 1,degree);
1919 nb_lines = cpl_bivector_get_size(*matching_lines) ;
1922 matchedx = cpl_matrix_wrap(1, nb_lines,
1923 cpl_vector_get_data(cpl_bivector_get_x(*matching_lines)));
1924 fitted = cpl_polynomial_new(1);
1925 if (cpl_polynomial_fit(fitted, matchedx, NULL,
1926 cpl_bivector_get_y(*matching_lines), NULL, CPL_FALSE,
1927 NULL, °_loc) != CPL_ERROR_NONE) {
1928 cpl_msg_error(cpl_func,
"Cannot fit the polynomial") ;
1929 cpl_polynomial_delete(fitted);
1930 cpl_matrix_unwrap(matchedx);
1931 cpl_bivector_delete(*matching_lines) ;
1934 cpl_matrix_unwrap(matchedx);
1947static cpl_imagelist * eris_ifu_stretch_apply_spline(
1949 cpl_polynomial * stretch)
1951 cpl_imagelist * out ;
1952 cpl_vector ** zlines ;
1953 cpl_vector ** resampled_zlines ;
1954 double * image_data ;
1957 double * resampled_array ;
1958 cpl_vector * new_pos ;
1959 int spec_size, nx, ny, i, j, k ;
1962 spec_size = cpl_imagelist_get_size(in) ;
1963 nx = cpl_image_get_size_x(cpl_imagelist_get_const(in, 0)) ;
1964 ny = cpl_image_get_size_x(cpl_imagelist_get_const(in, 0)) ;
1967 zlines = cpl_malloc(nx*ny*
sizeof(cpl_vector*)) ;
1968 for (i=0 ; i<nx ; i++)
1969 for (j=0 ; j<ny ; j++)
1970 zlines[i+j*nx] = cpl_vector_new(spec_size) ;
1973 for (k=0 ; k<spec_size ; k++) {
1974 image_data = cpl_image_get_data_double(cpl_imagelist_get(in, k)) ;
1975 for (i=0 ; i<nx ; i++)
1976 for (j=0 ; j<ny ; j++)
1977 if (!isnan(image_data[i+j*nx]))
1978 cpl_vector_set(zlines[i+j*nx], k, image_data[i+j*nx]) ;
1980 cpl_vector_set(zlines[i+j*nx], k, 0.0) ;
1984 pos = cpl_vector_new(spec_size) ;
1985 ppos = cpl_vector_get_data(pos);
1986 for (i=0 ; i<spec_size ; i++) ppos[i] = i+1 ;
1989 new_pos = cpl_vector_new(spec_size) ;
1990 cpl_vector_fill_polynomial(new_pos, stretch, 1, 1) ;
1993 if (cpl_vector_get(new_pos, 0) < 1.0) cpl_vector_set(new_pos, 0, 1.0) ;
1994 if (cpl_vector_get(new_pos, spec_size-1) > spec_size-1)
1995 cpl_vector_set(new_pos, spec_size-1, spec_size-1) ;
1997 resampled_zlines = cpl_malloc(nx*ny*
sizeof(cpl_vector*)) ;
1999 cpl_error_code retErr;
2000 for (i=0 ; i<nx ; i++) {
2001 for (j=0 ; j<ny ; j++) {
2002 resampled_array = cpl_malloc(spec_size *
sizeof(
double));
2004 ppos, cpl_vector_get_data(zlines[i+j*nx]), spec_size,
2005 cpl_vector_get_data(new_pos), resampled_array, spec_size,
2007 if (retErr != CPL_ERROR_NONE) {
2008 printf(
"ERROR: The function eris_ifu_1d_interpolation called in eris_ifu_stretch_apply_spline returned the error %d\n", retErr);
2009 printf(
"%s\n", cpl_error_get_message_default(retErr));
2017 resampled_zlines[i+j*nx] = cpl_vector_wrap(spec_size,
2021 cpl_vector_delete(new_pos) ;
2022 cpl_vector_delete(pos) ;
2026 for (i=0 ; i<nx ; i++)
2027 for (j=0 ; j<ny ; j++)
2028 cpl_vector_delete(zlines[i+j*nx]) ;
2032 out = cpl_imagelist_duplicate(in) ;
2033 for (k=0 ; k<spec_size ; k++) {
2034 image_data = cpl_image_get_data_double(cpl_imagelist_get(out, k)) ;
2035 for (i=0 ; i<nx ; i++)
2036 for (j=0 ; j<ny ; j++)
2037 image_data[i+j*nx]= cpl_vector_get(resampled_zlines[i+j*nx],k) ;
2041 for (i=0 ; i<nx ; i++)
2042 for (j=0 ; j<ny ; j++)
2043 cpl_free(cpl_vector_unwrap(resampled_zlines[i+j*nx]));
2045 cpl_free(resampled_zlines) ;
2058static cpl_imagelist * eris_ifu_stretch_apply_linear(
2060 cpl_polynomial * stretch)
2062 cpl_imagelist * out ;
2063 cpl_vector ** zlines ;
2064 cpl_vector ** resampled_zlines ;
2065 double * image_data ;
2068 cpl_vector * new_pos ;
2069 cpl_bivector * ref_spec ;
2070 cpl_bivector * resampled_spec ;
2071 int spec_size, nx, ny, i, j, k ;
2074 spec_size = cpl_imagelist_get_size(in) ;
2075 nx = cpl_image_get_size_x(cpl_imagelist_get_const(in, 0)) ;
2076 ny = cpl_image_get_size_x(cpl_imagelist_get_const(in, 0)) ;
2079 zlines = cpl_malloc(nx*ny*
sizeof(cpl_vector*)) ;
2080 for (i=0 ; i<nx ; i++)
2081 for (j=0 ; j<ny ; j++)
2082 zlines[i+j*nx] = cpl_vector_new(spec_size) ;
2085 for (k=0 ; k<spec_size ; k++) {
2086 image_data = cpl_image_get_data_double(cpl_imagelist_get(in, k)) ;
2087 for (i=0 ; i<nx ; i++)
2088 for (j=0 ; j<ny ; j++)
2089 if (!isnan(image_data[i+j*nx]))
2090 cpl_vector_set(zlines[i+j*nx], k, image_data[i+j*nx]) ;
2092 cpl_vector_set(zlines[i+j*nx], k, 0.0) ;
2096 pos = cpl_vector_new(spec_size) ;
2097 ppos = cpl_vector_get_data(pos);
2098 for (i=0 ; i<spec_size ; i++) ppos[i] = i+1 ;
2101 new_pos = cpl_vector_new(spec_size) ;
2102 cpl_vector_fill_polynomial(new_pos, stretch, 1, 1) ;
2105 if (cpl_vector_get(new_pos, 0) < 1.0) cpl_vector_set(new_pos, 0, 1.0) ;
2106 if (cpl_vector_get(new_pos, spec_size-1) > spec_size-1)
2107 cpl_vector_set(new_pos, spec_size-1, spec_size-1) ;
2109 resampled_zlines = cpl_malloc(nx*ny*
sizeof(cpl_vector*)) ;
2111 for (i=0 ; i<nx ; i++) {
2112 for (j=0 ; j<ny ; j++) {
2114 resampled_zlines[i+j*nx] = cpl_vector_new(spec_size) ;
2117 ref_spec = cpl_bivector_wrap_vectors(pos, zlines[i+j*nx]);
2118 resampled_spec = cpl_bivector_wrap_vectors(new_pos,
2119 resampled_zlines[i+j*nx]) ;
2121 cpl_bivector_interpolate_linear(resampled_spec, ref_spec) ;
2124 cpl_bivector_unwrap_vectors(ref_spec) ;
2125 cpl_bivector_unwrap_vectors(resampled_spec) ;
2128 cpl_vector_delete(new_pos) ;
2129 cpl_vector_delete(pos) ;
2132 for (i=0 ; i<nx ; i++)
2133 for (j=0 ; j<ny ; j++)
2134 cpl_vector_delete(zlines[i+j*nx]) ;
2138 out = cpl_imagelist_duplicate(in) ;
2139 for (k=0 ; k<spec_size ; k++) {
2140 image_data = cpl_image_get_data_double(cpl_imagelist_get(out, k)) ;
2141 for (i=0 ; i<nx ; i++)
2142 for (j=0 ; j<ny ; j++)
2143 image_data[i+j*nx]= cpl_vector_get(resampled_zlines[i+j*nx],k) ;
2147 for (i=0 ; i<nx ; i++)
2148 for (j=0 ; j<ny ; j++)
2149 cpl_vector_delete(resampled_zlines[i+j*nx]) ;
2150 cpl_free(resampled_zlines) ;
2154static int eris_ifu_stretch_check(
2155 cpl_imagelist * obj,
2156 cpl_imagelist * sky,
2157 cpl_imagelist * new_sky,
2160 cpl_vector * spec1 ;
2161 cpl_vector * spec2 ;
2163 eris_ifu_sky_tweak_get_spectra_simple(obj, sky, mask, &spec1, &spec2);
2164 cpl_plot_vector(
"set grid;set xlabel 'pix';",
"t 'obj' w lines",
"",
2166 cpl_plot_vector(
"set grid;set xlabel 'pix';",
2167 "t 'sky before stretching' w lines",
"", spec2);
2168 cpl_vector_subtract(spec1, spec2) ;
2170 cpl_plot_vector(
"set grid;set xlabel 'pix';",
2171 "t 'obj-sky before stretching' w lines",
"",
2173 cpl_vector_delete(spec1) ;
2174 cpl_vector_delete(spec2) ;
2176 eris_ifu_sky_tweak_get_spectra_simple(obj, new_sky, mask, &spec1, &spec2);
2177 cpl_plot_vector(
"set grid;set xlabel 'pix';",
2178 "t 'sky after stretching' w lines",
"", spec2);
2179 cpl_vector_subtract(spec1, spec2) ;
2181 cpl_plot_vector(
"set grid;set xlabel 'pix';",
2182 "t 'obj-sky after stretching' w lines",
"",
2184 cpl_vector_delete(spec1) ;
2185 cpl_vector_delete(spec2) ;
2190static int eris_ifu_stretch_plot_positions_differences(
2191 cpl_bivector * matching_lines,
2192 cpl_bivector * new_matching_lines)
2194 cpl_vector * diff_values ;
2195 cpl_bivector * diff ;
2198 diff_values = cpl_vector_duplicate(cpl_bivector_get_x(matching_lines)) ;
2199 cpl_vector_subtract(diff_values, cpl_bivector_get_y(matching_lines)) ;
2200 diff = cpl_bivector_wrap_vectors(cpl_bivector_get_x(matching_lines),
2202 cpl_plot_bivector(
"set grid;",
"t 'Pos. diff. BEFORE STRECHING'",
"", diff);
2203 cpl_bivector_unwrap_vectors(diff) ;
2204 cpl_vector_delete(diff_values) ;
2207 diff_values = cpl_vector_duplicate(cpl_bivector_get_x(new_matching_lines)) ;
2208 cpl_vector_subtract(diff_values, cpl_bivector_get_y(new_matching_lines)) ;
2209 diff = cpl_bivector_wrap_vectors(cpl_bivector_get_x(new_matching_lines),
2211 cpl_plot_bivector(
"set grid;",
"t 'Pos. diff. AFTER STRECHING'",
"", diff);
2212 cpl_bivector_unwrap_vectors(diff) ;
2213 cpl_vector_delete(diff_values) ;
2219static cpl_bivector * eris_ifu_strech_get_matching_lines(
2220 const cpl_vector * obj,
2221 const cpl_vector * sky,
2223 int remove_outliers,
2226 cpl_vector * tmp_vec ;
2227 cpl_vector * obj_lines ;
2228 cpl_vector * obj_lines_clean ;
2229 double * pobj_lines ;
2230 cpl_vector * sky_lines ;
2231 cpl_vector * sky_lines_clean ;
2232 double * psky_lines ;
2234 double * obj_lines_arr ;
2235 double * sky_lines_arr ;
2236 double obj_pos, sky_pos ;
2237 cpl_size sky_idx, nb_lines ;
2238 double fwhm, kappa, threshold ;
2242 if (obj == NULL || sky == NULL)
return NULL ;
2253 threshold = fabs(cpl_vector_get_mean(obj) + cpl_vector_get_stdev(obj)) ;
2254 tmp_vec = cpl_vector_duplicate(obj) ;
2255 for (i=0 ; i<cpl_vector_get_size(tmp_vec) ; i++) {
2256 if (cpl_vector_get(tmp_vec, i) < threshold)
2257 cpl_vector_set(tmp_vec, i, 0.0);
2259 if ((obj_lines = irplib_spectrum_detect_peaks(tmp_vec, fwhm,
2260 kappa, 0, NULL, NULL)) == NULL) {
2261 cpl_msg_error(cpl_func,
"Cannot detect peaks from obj") ;
2262 cpl_vector_delete(tmp_vec) ;
2265 cpl_vector_delete(tmp_vec) ;
2269 threshold = fabs(cpl_vector_get_mean(sky) + cpl_vector_get_stdev(sky)) ;
2270 tmp_vec = cpl_vector_duplicate(sky) ;
2271 for (i=0 ; i<cpl_vector_get_size(tmp_vec) ; i++) {
2272 if (cpl_vector_get(tmp_vec, i) < threshold)
2273 cpl_vector_set(tmp_vec, i, 0.0);
2275 if ((sky_lines = irplib_spectrum_detect_peaks(tmp_vec, fwhm,
2276 kappa, 0, NULL, NULL)) == NULL) {
2277 cpl_msg_error(cpl_func,
"Cannot detect peaks from sky") ;
2278 cpl_vector_delete(obj_lines) ;
2279 cpl_vector_delete(tmp_vec) ;
2282 cpl_vector_delete(tmp_vec) ;
2284 cpl_msg_debug(cpl_func,
"Detected %"CPL_SIZE_FORMAT
" lines from obj",
2285 cpl_vector_get_size(obj_lines));
2286 cpl_msg_debug(cpl_func,
"Detected %"CPL_SIZE_FORMAT
" lines from sky",
2287 cpl_vector_get_size(sky_lines));
2290 cpl_vector_sort(obj_lines, CPL_SORT_ASCENDING) ;
2291 nb_lines = cpl_vector_get_size(obj_lines) ;
2292 pobj_lines = cpl_vector_get_data(obj_lines) ;
2293 obj_lines_arr = cpl_malloc(nb_lines *
sizeof(
double)) ;
2295 obj_lines_arr[0] = pobj_lines[0] ;
2297 for (i=1 ; i<nb_lines ; i++) {
2299 if (fabs(pobj_lines[i]-pobj_lines[i-1]) > min_gap) {
2300 obj_lines_arr[nb_found] = pobj_lines[i] ;
2305 cpl_vector_delete(obj_lines) ;
2306 obj_lines = cpl_vector_new(nb_found) ;
2307 pobj_lines = cpl_vector_get_data(obj_lines) ;
2308 for (i=0 ; i<nb_found ; i++) pobj_lines[i] = obj_lines_arr[i] ;
2309 cpl_free(obj_lines_arr) ;
2310 nb_lines = cpl_vector_get_size(obj_lines) ;
2312 cpl_msg_debug(cpl_func,
2313 "Detected %"CPL_SIZE_FORMAT
" separated lines from obj",
2314 cpl_vector_get_size(obj_lines));
2317 obj_lines_arr = cpl_malloc(nb_lines *
sizeof(
double)) ;
2318 sky_lines_arr = cpl_malloc(nb_lines *
sizeof(
double)) ;
2320 cpl_vector_sort(sky_lines, CPL_SORT_ASCENDING) ;
2321 for (i=0 ; i<nb_lines ; i++) {
2322 obj_pos = cpl_vector_get(obj_lines, i) ;
2323 sky_idx = cpl_vector_find(sky_lines, obj_pos) ;
2324 sky_pos = cpl_vector_get(sky_lines, sky_idx) ;
2326 if (fabs(obj_pos-sky_pos) < min_gap) {
2327 obj_lines_arr[nb_found] = obj_pos ;
2328 sky_lines_arr[nb_found] = sky_pos ;
2334 cpl_vector_delete(obj_lines) ;
2335 cpl_vector_delete(sky_lines) ;
2336 obj_lines = cpl_vector_new(nb_found) ;
2337 sky_lines = cpl_vector_new(nb_found) ;
2338 nb_lines = cpl_vector_get_size(obj_lines) ;
2339 pobj_lines = cpl_vector_get_data(obj_lines) ;
2340 psky_lines = cpl_vector_get_data(sky_lines) ;
2341 for (i=0 ; i<nb_found ; i++) {
2342 pobj_lines[i] = obj_lines_arr[i] ;
2343 psky_lines[i] = sky_lines_arr[i] ;
2345 cpl_free(obj_lines_arr) ;
2346 cpl_free(sky_lines_arr) ;
2349 if (remove_outliers) {
2350 diff = cpl_vector_duplicate(obj_lines) ;
2351 cpl_vector_subtract(diff, sky_lines) ;
2352 threshold = fabs(cpl_vector_get_median_const(diff)) +
2353 2 * cpl_vector_get_stdev(diff) ;
2355 for (i=0 ; i<cpl_vector_get_size(diff) ; i++)
2356 if (fabs(cpl_vector_get(diff, i)) < threshold) nb_found++ ;
2357 obj_lines_clean = cpl_vector_new(nb_found) ;
2358 sky_lines_clean = cpl_vector_new(nb_found) ;
2360 for (i=0 ; i<cpl_vector_get_size(diff) ; i++)
2361 if (fabs(cpl_vector_get(diff, i)) < threshold) {
2362 cpl_vector_set(obj_lines_clean, nb_found,
2363 cpl_vector_get(obj_lines, i)) ;
2364 cpl_vector_set(sky_lines_clean, nb_found,
2365 cpl_vector_get(sky_lines, i)) ;
2368 cpl_vector_delete(diff) ;
2369 cpl_vector_delete(obj_lines) ;
2370 cpl_vector_delete(sky_lines) ;
2371 obj_lines = obj_lines_clean ;
2372 sky_lines = sky_lines_clean ;
2376 if (nb_found <= degree) {
2377 cpl_msg_error(cpl_func,
"Not enough match for the fit") ;
2378 cpl_vector_delete(obj_lines) ;
2379 cpl_vector_delete(sky_lines) ;
2383 cpl_msg_debug(cpl_func,
"Matched %"CPL_SIZE_FORMAT
" lines",
2384 cpl_vector_get_size(obj_lines));
2386 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