ERIS Pipeline Reference Manual 1.8.10
eris_ifu_combine_static.c
1/* $Id$
2 *
3 * This file is part of the ERIS Pipeline
4 * Copyright (C) 2002,2003 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
25#include <math.h>
26#include <string.h>
27#include <cpl.h>
28#include "eris_pfits.h"
29#include "eris_ifu_error.h"
30#include "eris_ifu_functions.h"
31#include "eris_ifu_utils.h"
32#include "eris_ifu_combine_static.h"
33
75cpl_error_code eris_ifu_combine_jittered_images(
76 cpl_image **imagesData,
77 cpl_image **imagesError,
78 int nx_out,
79 int ny_out,
80 cpl_image **mergedImageData,
81 cpl_image **mergedImageError,
82 cpl_image **mergedImageDIT,
83 int n_cubes,
84 const float *offsetx,
85 const float *offsety,
86 const double *exptimes,
87 const double kappa,
88 const char *compute_mode,
89 const int pclip)
90{
91 int llx0 = 0,
92 lly0 = 0,
93 nx_in = 0,
94 ny_in = 0,
95 min_lx = INT_MAX,
96 min_ly = INT_MAX,
97 *llx = NULL,
98 *lly = NULL;
99 float *sub_offsetx = NULL,
100 *sub_offsety = NULL;
101 cpl_image **imagesDataShifted = NULL,
102 **imagesErrorShifted = NULL;
103 cpl_error_code ret_err = CPL_ERROR_NONE;
104
105 cpl_ensure_code(imagesData != NULL, CPL_ERROR_NULL_INPUT);
106 cpl_ensure_code(imagesError != NULL, CPL_ERROR_NULL_INPUT);
107 cpl_ensure_code(mergedImageData != NULL, CPL_ERROR_NULL_INPUT);
108 cpl_ensure_code(mergedImageError != NULL, CPL_ERROR_NULL_INPUT);
109 cpl_ensure_code(mergedImageDIT != NULL, CPL_ERROR_NULL_INPUT);
110 cpl_ensure_code(offsetx != NULL, CPL_ERROR_NULL_INPUT);
111 cpl_ensure_code(offsety != NULL, CPL_ERROR_NULL_INPUT);
112 cpl_ensure_code(exptimes != NULL, CPL_ERROR_NULL_INPUT);
113 cpl_ensure_code(compute_mode != NULL, CPL_ERROR_NULL_INPUT);
114
115 TRY {
116 nx_in = cpl_image_get_size_x(imagesData[0]);
117 ny_in = cpl_image_get_size_y(imagesData[0]);
118
119 /* Center the cubes within the allocated big cube.
120 * That means to define the (0,0) positions of the cubes in the image planes
121 * to sub-pixel accuracy by using cumoffsetx/y and the reference cube. */
122
123 /* Position of first reference frame, centered in big cube */
124 llx0 = (int)((double)(nx_out - nx_in) / 2.0 + 0.5);
125 lly0 = (int)((double)(ny_out - ny_in) / 2.0 + 0.5);
126
127 /* Go through the frame list and determine the lower left edge position
128 * of the shifted cubes. Additionnally, the sub-pixel offsets are
129 * determined. */
130 llx = cpl_calloc(n_cubes, sizeof(int));
131 lly = cpl_calloc(n_cubes, sizeof(int));
132 sub_offsetx = cpl_calloc(n_cubes, sizeof(float));
133 sub_offsety = cpl_calloc(n_cubes, sizeof(float));
135
136 for (int i = 0; i < n_cubes; i++) {
137 llx[i] = llx0 - eris_ifu_combine_nearest_int(offsetx[i]);
138
139 sub_offsetx[i] = (float)eris_ifu_combine_nearest_int(offsetx[i]) - offsetx[i];
140 lly[i] = lly0 - eris_ifu_combine_nearest_int(offsety[i]);
141 sub_offsety[i] = (float)eris_ifu_combine_nearest_int(offsety[i]) - offsety[i];
142
143 if (llx[i] < min_lx) {
144 min_lx = llx[i];
145 }
146 if (lly[i] < min_ly) {
147 min_ly = lly[i];
148 }
149 }
151
152 /* "Normalize" the shift - minimum should be 0 */
153 if (min_lx != 0) {
154 for (int i = 0 ; i < n_cubes ; i++ ) {
155 llx[i] = llx[i] - min_lx;
156 }
157 }
158 if (min_ly != 0) {
159 for (int i = 0 ; i < n_cubes ; i++ ) {
160 lly[i] = lly[i] - min_ly;
161 }
162 }
163
164 /* Shift the cubes according to the computed sub-pixel offsets
165 * that means shift the single image planes of each cube
166 * first determine an interpolation kernel
167 */
169 imagesDataShifted = (cpl_image**)cpl_calloc(n_cubes, sizeof(cpl_imagelist*)));
171 imagesErrorShifted = (cpl_image**)cpl_calloc(n_cubes, sizeof(cpl_imagelist*)));
172
173 for (int i = 0; i < n_cubes; i++) {
175 imagesDataShifted[i] = eris_ifu_combine_shift_image_kmos(
176 imagesData[i],
177 sub_offsetx[i], sub_offsety[i],
178 "NN", NONE_NANS));
180 imagesErrorShifted[i] = eris_ifu_combine_shift_image_kmos(
181 imagesError[i],
182 sub_offsetx[i], sub_offsety[i],
183 "NN", NONE_NANS));
184 }
185
186 /* Build the DIT cube */
188 eris_ifu_combine_build_mask_cube(imagesDataShifted,
189 mergedImageDIT,
190 llx, lly, exptimes,
191 n_cubes,
192 nx_out, ny_out));
193
194 if ((kappa != -1) && (pclip != -1)) {
195 // ks-clipping
197 eris_ifu_combine_coadd_ks_clip(
198 n_cubes,
199 kappa, llx, lly, exptimes,
200 mergedImageData, mergedImageError, *mergedImageDIT,
201 imagesDataShifted, imagesErrorShifted,
202 compute_mode, pclip, nx_out, ny_out));
203 } else {
204 /* Calculate a weighted average using the exposure time of the
205 * single frames of the overlapping regions of the cubes */
207 eris_ifu_combine_coadd(n_cubes,
208 mergedImageData, mergedImageError, *mergedImageDIT,
209 imagesDataShifted, imagesErrorShifted,
210 exptimes,
211 llx, lly, compute_mode, nx_out, ny_out));
212 }
213 } CATCH {
214 CATCH_MSGS();
215 ret_err = cpl_error_get_code();
216 eris_ifu_free_image(mergedImageData);
217 eris_ifu_free_image(mergedImageError);
218 eris_ifu_free_image(mergedImageDIT);
219 }
220
221 // free memory
222 for (int i = 0; i < n_cubes; i++) {
223 eris_ifu_free_image(&imagesDataShifted[i]);
224 eris_ifu_free_image(&imagesErrorShifted[i]);
225 }
226
227 cpl_free(imagesDataShifted); imagesDataShifted = NULL;
228 cpl_free(imagesErrorShifted); imagesErrorShifted = NULL;
229 cpl_free(llx); llx = NULL;
230 cpl_free(lly); lly = NULL;
231 cpl_free(sub_offsetx); sub_offsetx = NULL;
232 cpl_free(sub_offsety); sub_offsety = NULL;
233
234 return ret_err;
235}
236
246cpl_error_code eris_ifu_combine_divide_DIT( cpl_imagelist **cubesData,
247 const int n_cubes,
248 const double *exptimes)
249{
250 cpl_ensure_code(cubesData,CPL_ERROR_NULL_INPUT);
251 TRY {
252 for (int i = 0; i < n_cubes; i++) {
254 cpl_imagelist_divide_scalar(cubesData[i], exptimes[i]));
255 }
256 } CATCH {
257
258 }
259
260 return cpl_error_get_code();
261}
262
279cpl_error_code eris_ifu_combine_auto_size_cube(const float *offsetx,
280 const float *offsety,
281 const int nframes,
282 float *ref_offx,
283 float *ref_offy,
284 int *size_x,
285 int *size_y)
286{
287 float min_offx = 0,
288 max_offx = 0,
289 min_offy = 0,
290 max_offy = 0;
291
292 cpl_ensure_code(offsetx != NULL, CPL_ERROR_ILLEGAL_INPUT);
293 cpl_ensure_code(offsety != NULL, CPL_ERROR_ILLEGAL_INPUT);
294 cpl_ensure_code(nframes > 0, CPL_ERROR_ILLEGAL_INPUT);
295 cpl_ensure_code(*size_x >= 64, CPL_ERROR_ILLEGAL_INPUT);
296 cpl_ensure_code(*size_y >= 64, CPL_ERROR_ILLEGAL_INPUT);
297
298 cpl_msg_info (cpl_func, "Computation of output cube size") ;
299 eris_ifu_combine_get_xy_min_max(nframes,
300 offsetx, offsety,
301 &min_offx, &max_offx,
302 &min_offy, &max_offy);
303
304 cpl_msg_info(cpl_func, " max_offx = %f, max_offy = %f", max_offx, max_offy);
305 cpl_msg_info(cpl_func, " min_offx = %f, min_offy = %f", min_offx, min_offy);
306
307 *ref_offx = (min_offx+max_offx)/2;
308 *ref_offy = (min_offy+max_offy)/2;
309
310 /* The following to allow to compute the size of output cube in case the input
311 * has size different than 64x64
312 */
313 *size_x += 2*floor(max_offx-min_offx+0.5);
314 *size_y += 2*floor(max_offy-min_offy+0.5);
315
316 cpl_msg_info(cpl_func, " Output cube size: %d x %d",*size_x,*size_y);
317 cpl_msg_info(cpl_func, " Ref. offset x: %f, y: %f",*ref_offx,*ref_offy);
318 cpl_msg_info(cpl_func, " Max. offset x: %f, y: %f",max_offx,max_offy);
319 cpl_msg_info(cpl_func, " Min. offset x: %f, y: %f",min_offx,min_offy);
320
321 return cpl_error_get_code();
322}
323
356cpl_error_code eris_ifu_combine_build_mask(cpl_imagelist **cubesDataShifted,
357 cpl_image *mergedImgDIT,
358 const int n_cubes,
359 const int *llx,
360 const int *lly,
361 const double *exptimes)
362{
363 int nx_in = 0,
364 ny_in = 0;
365 cpl_size nx_out = 0,
366 ny_out = 0;
367 cpl_image *imgCubesDataShifted = NULL;
368 double *pimgMergedCubeDIT = NULL;
369
370 cpl_ensure_code(llx != NULL, CPL_ERROR_NULL_INPUT);
371 cpl_ensure_code(lly != NULL, CPL_ERROR_NULL_INPUT);
372 cpl_ensure_code(exptimes != NULL, CPL_ERROR_NULL_INPUT);
373 cpl_ensure_code(cubesDataShifted != NULL, CPL_ERROR_NULL_INPUT);
374 cpl_ensure_code(mergedImgDIT != NULL, CPL_ERROR_NULL_INPUT);
375
376 nx_out = cpl_image_get_size_x(mergedImgDIT);
377 ny_out = cpl_image_get_size_y(mergedImgDIT);
378
379 pimgMergedCubeDIT = cpl_image_get_data_double(mergedImgDIT);
380
381 for (int i = 0; i < n_cubes; i++) {
382 imgCubesDataShifted = cpl_imagelist_get(cubesDataShifted[i], 0);
383 nx_in = cpl_image_get_size_x(imgCubesDataShifted);
384 ny_in = cpl_image_get_size_y(imgCubesDataShifted);
385
386 //go through the first image plane of the big data cube
387 for (int y = 0; y < ny_out; y++) {
388 for (int x = 0; x < nx_out; x++) {
389 // find the position of the present cube and go
390 // through the single spectra
391 if ((y >= lly[i]) && (y < lly[i]+ny_in) &&
392 (x >= llx[i]) && (x < llx[i]+nx_in))
393 {
394 pimgMergedCubeDIT[x+y*nx_out] += exptimes[i];
395 }
396 } // end for(x)
397 } // end for(y)
398 } // end for(i)
399 return cpl_error_get_code();
400}
401
425cpl_error_code eris_ifu_combine_build_mask_cube(cpl_image **imagesDataShifted,
426 cpl_image **mergedImgDIT,
427 const int *llx,
428 const int *lly,
429 const double *exptimes,
430 int n_cubes,
431 cpl_size nx_out,
432 cpl_size ny_out)
433{
434 int nx_in = 0,
435 ny_in = 0,
436 x_in = 0,
437 y_in = 0;
438 double *pimgMergedCubeDIT = NULL,
439 *pimgCubesDataShifted = NULL;
440 cpl_image *imgCubesDataShifted = NULL;
441 cpl_error_code ret_err = CPL_ERROR_NONE;
442
443 cpl_ensure_code(llx != NULL, CPL_ERROR_NULL_INPUT);
444 cpl_ensure_code(lly != NULL, CPL_ERROR_NULL_INPUT);
445 cpl_ensure_code(exptimes != NULL, CPL_ERROR_NULL_INPUT);
446 cpl_ensure_code(imagesDataShifted != NULL, CPL_ERROR_NULL_INPUT);
447 cpl_ensure_code(mergedImgDIT != NULL, CPL_ERROR_NULL_INPUT);
448
449 TRY {
451 *mergedImgDIT = cpl_image_new(nx_out, ny_out, CPL_TYPE_DOUBLE));
453 pimgMergedCubeDIT = cpl_image_get_data_double(*mergedImgDIT));
454
455 for (int i = 0; i < n_cubes; i++) {
456 imgCubesDataShifted = imagesDataShifted[i];
458 pimgCubesDataShifted = cpl_image_get_data_double(imgCubesDataShifted));
459 nx_in = cpl_image_get_size_x(imgCubesDataShifted);
460 ny_in = cpl_image_get_size_y(imgCubesDataShifted);
461 x_in = 0;
462 y_in = 0;
463 for (int y = 0; y < ny_out; y++) {
464 for (int x = 0; x < nx_out; x++) {
465 // find the position of the present cube and go
466 // through the single spectra
467 if ((y >= lly[i]) && (y < lly[i]+ny_in) &&
468 (x >= llx[i]) && (x < llx[i]+nx_in))
469 {
470 if (!eris_ifu_is_nan_or_inf(pimgCubesDataShifted[x_in+nx_in*y_in]) &&
471 !cpl_image_is_rejected(imgCubesDataShifted, x_in+1, y_in+1))
472 {
473 pimgMergedCubeDIT[x+y*nx_out] += exptimes[i];
474 }
475 x_in++;
476 if (x_in >= nx_in) {
477 x_in = 0;
478 y_in++;
479 }
480 }
481 } // end for(x)
482 } // end for(y)
483 } // end for(i)
484 }
485 CATCH
486 {
487 CATCH_MSGS();
488 eris_ifu_free_image(mergedImgDIT);
489 ret_err = cpl_error_get_code();
490 }
491
492 return ret_err;
493}
520cpl_error_code eris_ifu_combine_coadd_ks_clip(const int n_frames,
521 const double kappa,
522 int *llx,
523 int *lly,
524 const double *exptimes,
525 cpl_image **imgMergedCubeData,
526 cpl_image **imgMergedCubeError,
527 cpl_image *mergedImgDIT,
528 cpl_image **imagesDataShifted,
529 cpl_image **imagesErrorShifted,
530 const char *compute_mode,
531 const int pclip,
532 const int nx_out,
533 const int ny_out)
534{
535 int n_contributes = 0,
536 nx_in = 0,
537 ny_in = 0,
538 posx = 0,
539 posy = 0,
540 ovr = 0; //overlap count
541 double *pimgCubesDataShifted = NULL,
542 *pimgCubesErrorShifted = NULL,
543 *pimgMergedCubeData = NULL,
544 *pimgMergedCubeError = NULL,
545 *pmergedImgDIT = NULL;
546 cpl_vector *msk = NULL,
547 *val = NULL; // vector to compute median of an output pixel
548 eris_ifu_vector *data_vec = NULL,
549 *err_vec = NULL;
550
551 TRY {
552 nx_in = cpl_image_get_size_x(imagesDataShifted[0]);
553 ny_in = cpl_image_get_size_y(imagesDataShifted[0]);
554
555 if (
556 (nx_out != cpl_image_get_size_x(mergedImgDIT)) ||
557 (ny_out != cpl_image_get_size_y(mergedImgDIT))
558 )
559 {
560 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
561 return cpl_error_get_code();
562 }
563
565 *imgMergedCubeData = cpl_image_new(nx_out, ny_out, CPL_TYPE_DOUBLE));
567 pimgMergedCubeData = cpl_image_get_data_double(*imgMergedCubeData));
568
570 *imgMergedCubeError = cpl_image_new(nx_out, ny_out, CPL_TYPE_DOUBLE));
572 pimgMergedCubeError = cpl_image_get_data_double(*imgMergedCubeError));
573
575 pmergedImgDIT = cpl_image_get_data_double(mergedImgDIT));
576
577 for (int y = 0; y < ny_out; y++) {
578 for (int x = 0; x < nx_out; x++) {
579 n_contributes = eris_ifu_combine_calc_contributions(imagesDataShifted,
580 n_frames,
581 llx, lly, x, y);
582 if (n_contributes > 0) {
583 msk = cpl_vector_new(n_frames);
584 for (int i = 0; i < n_frames; i++) {
585 cpl_vector_set(msk, i, 1);
586 }
587
589 eris_ifu_combine_coadd_ks_clip_internal(imagesDataShifted, n_frames,
590 n_contributes, x, y,
591 llx, lly, kappa, &msk,
592 compute_mode, pclip));
593
594 if (!strcmp(compute_mode, "MEDIAN")){
595 // median
596 val = cpl_vector_new(n_frames);
597 ovr = 0;
598 }
599
600 data_vec = eris_ifu_vector_new(n_frames);
601 err_vec = eris_ifu_vector_new(n_frames);
602
603 for (int i = 0; i < n_frames; i++) {
604 if ((y >= lly[i]) && (y < lly[i]+ny_in) &&
605 (x >= llx[i]) && (x < llx[i]+nx_in))
606 {
607 pimgCubesDataShifted = cpl_image_get_data_double(imagesDataShifted[i]);
608 pimgCubesErrorShifted = cpl_image_get_data_double(imagesErrorShifted[i]);
609
610 posx = x - llx[i];
611 posy = y - lly[i];
612
613 if (!isnan(pimgCubesDataShifted[posx+posy*nx_in]) &&
614 (fabs(pimgCubesDataShifted[posx+posy*nx_in]) > DBL_ZERO_TOLERANCE) &&
615 (fabs(pmergedImgDIT[x+y*nx_out]) > DBL_ZERO_TOLERANCE) &&
616 (cpl_vector_get(msk, i) != 0))
617 {
618 if (!strcmp(compute_mode, "MEDIAN")) {
619 // median
620 cpl_vector_set(val, ovr, pimgCubesDataShifted[posx+posy*nx_in]);
621 ovr++;
622 } else {
623 // mean
624 pimgMergedCubeData[x+y*nx_out] += pimgCubesDataShifted[posx+posy*nx_in] * exptimes[i];
625 }
626 eris_ifu_vector_set(data_vec, i, pimgCubesDataShifted[posx+posy*nx_in]);
627 eris_ifu_vector_set(err_vec, i, pimgCubesErrorShifted[posx+posy*nx_in]);
628 } else {
629 // invalid data value
630 eris_ifu_vector_reject(data_vec, i);
631 eris_ifu_vector_reject(err_vec, i);
632 }
633 } else {
634 // invalid data value
635 eris_ifu_vector_reject(data_vec, i);
636 eris_ifu_vector_reject(err_vec, i);
637 }
638 } // end for(i)
639
640 // calculate error
641 pimgMergedCubeError[x+y*nx_out] = eris_ifu_combine_calc_error(data_vec, err_vec, compute_mode);
642 eris_ifu_vector_delete(data_vec); data_vec = NULL;
643 eris_ifu_vector_delete(err_vec); err_vec = NULL;
644
645 if (!strcmp(compute_mode, "MEDIAN")) {
646 // median
647 if (ovr > 0) {
648 cpl_vector *tval = cpl_vector_extract(val, 0, ovr-1, 1);
649 pimgMergedCubeData[x+y*nx_out] = cpl_vector_get_median_const(tval);
651 }
653 } else {
654 // mean
655 pimgMergedCubeData[x+y*nx_out] /= pmergedImgDIT[x+y*nx_out];
656 }
657
659
660 } // end check if overlap nc > 0
661 } // end loop over x
662 } // end loop over y
663 } CATCH {
666 eris_ifu_free_image(imgMergedCubeData);
667 eris_ifu_free_image(imgMergedCubeError);
668 }
669
670 return cpl_error_get_code();
671}
672
691cpl_error_code eris_ifu_combine_coadd_ks_clip_internal(cpl_image** imagesDataShifted,
692 const int n_frames,
693 const int n_contributions,
694 const int x,
695 const int y,
696 int *llx,
697 int *lly,
698 const double kappa,
699 cpl_vector **msk,
700 const char *compute_mode,
701 const int pclip)
702{
703 int nclip = 0,
704 lox = 0,
705 loy = 0,
706 upx = 0,
707 upy = 0,
708 posx = 0,
709 posy = 0,
710 pos = 0,
711 ovr = 0,
712 pk = 0;
713 double sig = 0.,
714 med = 0.,
715 *pimg_in = NULL;
716 cpl_size nx = 0,
717 ny = 0;
718 cpl_vector *val = NULL;
719 cpl_error_code ret_err = CPL_ERROR_NONE;
720
721 TRY {
722 nx = cpl_image_get_size_x(imagesDataShifted[0]);
723 ny = cpl_image_get_size_y(imagesDataShifted[0]);
724
725 for (int ks = 0; ks < n_contributions; ks++) { //for large nc: may optimize for efficiency
726 sig = 0;
727 med = 0;
728 ovr = 0;
729
730 if (n_contributions-nclip > 0) {
731 val = cpl_vector_new(n_contributions-nclip);
732 } else {
733 break;
734 }
735
736 // fill val
737 for (int i = 0; i < n_frames; i++) {
738 pimg_in = cpl_image_get_data_double(imagesDataShifted[i]);
739
740 lox = llx[i];
741 loy = lly[i];
742 upx = llx[i]+nx;
743 upy = lly[i]+ny;
744
745 if ((y >= loy) && (y < upy) && (x >= lox) && (x < upx)) {
746 posx = x - lox;
747 posy = y - loy;
748 pos = posx+posy*nx;
749
750 if (!isnan(pimg_in[pos]) &&
751 (fabs(pimg_in[pos]) > DBL_ZERO_TOLERANCE) &&
752 (cpl_vector_get(*msk, i) != 0))
753 {
755 cpl_vector_set(val, ovr, pimg_in[pos]));
756 ovr++;
757 }
758 }
759 }
760
761 // get avg, med, sig
762 if (ovr > 2) {
763 if (!strcmp(compute_mode, "MEDIAN")) {
764 med=cpl_vector_get_median(val);
765 } else {
766 med = cpl_vector_get_mean(val);
767 }
768
769 //Initial percentile cut
770 if ((ks == 0) && (pclip < 100) && (pclip > 0)) {
771 med = cpl_vector_get_median(val);
772 cpl_vector_subtract_scalar(val, med);
773 cpl_vector_power(val, 2);
774 cpl_vector_sqrt(val);
775 cpl_vector_sort(val, CPL_SORT_ASCENDING);
776 pk = round(pclip/100.0*(cpl_vector_get_size(val)-1));
777 sig = cpl_vector_get(val, pk) / kappa;
778 } else {
779 if (!strcmp(compute_mode, "MEDIAN")){ //Median: sigma = 1.4826*MAD
780 cpl_vector_subtract_scalar(val, med);
781 cpl_vector_power(val, 2);
782 cpl_vector_sqrt(val);
783 sig = 1.4826 * cpl_vector_get_median(val);
784 } else {
785 sig=cpl_vector_get_stdev(val);
786 }
787 }
788
789 for (int i = 0 ; i < n_frames; i++) {
790 pimg_in = cpl_image_get_data_double(imagesDataShifted[i]);
791
792 lox = llx[i];
793 loy = lly[i];
794 upx = llx[i]+nx;
795 upy = lly[i]+ny;
796
797 // Do k-s clipping at each pixel
798 if ((y >= loy) && (y < upy) && (x >= lox) && (x < upx)) {
799 posx = x - lox;
800 posy = y - loy;
801 pos = posx+posy*nx;
802
803 if (!isnan(pimg_in[pos]) &&
804 (fabs(pimg_in[pos]) > DBL_ZERO_TOLERANCE) &&
805 (cpl_vector_get(*msk,i) != 0))
806 {
807 if(fabs((pimg_in[pos]-med)) > kappa*sig)
808 {
809 // clipping pixel here
810 pimg_in[pos] = NAN;
811 // agudo: added this in, hopefully with correct coordinates
812 cpl_image_reject(imagesDataShifted[i], posx+1, posy+1);
813 cpl_vector_set(*msk, i, 0);
814 nclip++;
815 }
816 }
817 }
818 }
819 }
821 } // end for(ks)
822 } CATCH {
824 ret_err = cpl_error_get_code();
825 }
826
827 return ret_err;
828}
829
855cpl_error_code eris_ifu_combine_coadd( const int n_cubes,
856 cpl_image **imgMergedCubeData,
857 cpl_image **imgMergedCubeError,
858 cpl_image *mergedImgDIT,
859 cpl_image **imagesDataShifted,
860 cpl_image **imagesErrorShifted,
861 const double *exptimes,
862 int *llx,
863 int *lly,
864 const char *compute_mode,
865 const int nx_out,
866 const int ny_out)
867{
868 int nx_in = 0,
869 ny_in = 0,
870 posx = 0,
871 posy = 0,
872 ovr = 0; //overlap count
873 double *pimgCubesDataShifted = NULL,
874 *pimgCubesErrorShifted = NULL,
875 *pimgMergedCubeData = NULL,
876 *pimgMergedCubeError = NULL,
877 *pmergedImgDIT = NULL;
878 cpl_vector *val = NULL; // vector to compute median of an output pixel
879 eris_ifu_vector *data_vec = NULL,
880 *err_vec = NULL;
881
882 nx_in = cpl_image_get_size_x(imagesDataShifted[0]);
883 ny_in = cpl_image_get_size_y(imagesDataShifted[0]);
884
885 if (
886 (nx_out != cpl_image_get_size_x(mergedImgDIT)) ||
887 (ny_out != cpl_image_get_size_y(mergedImgDIT))
888 )
889 {
890 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
891 return cpl_error_get_code();
892 }
893
894 *imgMergedCubeData = cpl_image_new(nx_out, ny_out, CPL_TYPE_DOUBLE);
895 pimgMergedCubeData = cpl_image_get_data_double(*imgMergedCubeData);
896
897 *imgMergedCubeError = cpl_image_new(nx_out, ny_out, CPL_TYPE_DOUBLE);
898 pimgMergedCubeError = cpl_image_get_data_double(*imgMergedCubeError);
899
900 pmergedImgDIT = cpl_image_get_data_double(mergedImgDIT);
901
902 for (int y = 0; y < ny_out; y++) {
903 for (int x = 0; x < nx_out; x++) {
904 if (!strcmp(compute_mode, "MEDIAN")) {
905 // median
906 val = cpl_vector_new(n_cubes);
907 ovr = 0;
908 }
909
910 data_vec = eris_ifu_vector_new(n_cubes);
911 err_vec = eris_ifu_vector_new(n_cubes);
912
913 for (int i = 0; i < n_cubes; i++) {
914 if ((y >= lly[i]) && (y < lly[i]+ny_in) &&
915 (x >= llx[i]) && (x < llx[i]+nx_in))
916 {
917 pimgCubesDataShifted = cpl_image_get_data_double(imagesDataShifted[i]);
918 pimgCubesErrorShifted = cpl_image_get_data_double(imagesErrorShifted[i]);
919
920 posx = x - llx[i];
921 posy = y - lly[i];
922
923 if (!isnan(pimgCubesDataShifted[posx+posy*nx_in]) &&
924 (fabs(pimgCubesDataShifted[posx+posy*nx_in]) > DBL_ZERO_TOLERANCE) &&
925 (fabs(pmergedImgDIT[x+y*nx_out]) > DBL_ZERO_TOLERANCE))
926 {
927 // valid data value
928 if (!strcmp(compute_mode, "MEDIAN")) {
929 // median
930 cpl_vector_set(val, ovr, pimgCubesDataShifted[posx+posy*nx_in]);
931 ovr++;
932 } else {
933 // mean
934 pimgMergedCubeData[x+y*nx_out] += pimgCubesDataShifted[posx+posy*nx_in] * exptimes[i];
935 }
936 eris_ifu_vector_set(data_vec, i, pimgCubesDataShifted[posx+posy*nx_in]);
937 eris_ifu_vector_set(err_vec, i, pimgCubesErrorShifted[posx+posy*nx_in]);
938 } else {
939 // invalid data value
940 eris_ifu_vector_reject(data_vec, i);
941 eris_ifu_vector_reject(err_vec, i);
942 }
943 } else {
944 // invalid data value
945 eris_ifu_vector_reject(data_vec, i);
946 eris_ifu_vector_reject(err_vec, i);
947 }
948 } // end for(i)
949
950 // calculate error
951 pimgMergedCubeError[x+y*nx_out] = eris_ifu_combine_calc_error(data_vec, err_vec, compute_mode);
952
953 eris_ifu_vector_delete(data_vec); data_vec = NULL;
954 eris_ifu_vector_delete(err_vec); err_vec = NULL;
955
956 if (!strcmp(compute_mode, "MEDIAN")){
957 // median
958 if (ovr > 0) {
959 cpl_vector *tval = cpl_vector_extract(val, 0, ovr-1, 1);
960 pimgMergedCubeData[x+y*nx_out] = cpl_vector_get_median_const(tval);
962 }
964 } else {
965 // mean
966 pimgMergedCubeData[x+y*nx_out] /= pmergedImgDIT[x+y*nx_out];
967 }
968 } // end for x
969 } // end for y
970
971 return cpl_error_get_code();
972}
973
974int eris_ifu_combine_calc_contributions(cpl_image **imagesDataShifted,
975 const int n_frames,
976 const int* llx, const int* lly,
977 const int x, const int y)
978{
979 int n_contributes = 0,
980 pos = 0,
981 posx = 0,
982 posy = 0,
983 lox = 0,
984 loy = 0,
985 upx = 0,
986 upy = 0;
987 double *pimg = NULL;
988 cpl_size nx = 0,
989 ny = 0;
990
991 nx = cpl_image_get_size_x(imagesDataShifted[0]);
992 ny = cpl_image_get_size_y(imagesDataShifted[0]);
993
994 // Count the number of shifted input cubes to be used for
995 // each overlapping point at x,y
996 for (int i = 0; i < n_frames; i++) {
997 pimg = cpl_image_get_data_double(imagesDataShifted[i]);
998
999 lox = llx[i];
1000 loy = lly[i];
1001 upx = llx[i] + nx;
1002 upy = lly[i] + ny;
1003
1004 if ((y >= loy) && (y < upy) && (x >= lox) && (x < upx)) {
1005 posx = x - lox;
1006 posy = y - loy;
1007 pos = posx+posy*nx;
1008
1009 if (!isnan(pimg[pos]) && (fabs(pimg[pos]) > DBL_ZERO_TOLERANCE)) {
1010 n_contributes++;
1011 }
1012 }
1013 }
1014
1015 return n_contributes;
1016}
1017
1024cpl_error_code eris_ifu_combine_subtract_background(cpl_image *img,
1025 bool *warn)
1026{
1027 double local_median = 0.;
1028 cpl_error_code err = CPL_ERROR_NONE;
1029
1030 cpl_ensure_code(img != NULL, CPL_ERROR_NULL_INPUT);
1031
1032 TRY {
1034 cpl_image_reject_value(img, CPL_VALUE_NOTFINITE));
1035
1036 local_median = cpl_image_get_median(img);
1037 if (cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) {
1038 local_median = NAN;
1039 RECOVER();
1040 }
1042
1043 if (!isnan(local_median)) {
1045 cpl_image_subtract_scalar(img, local_median));
1046 *warn = FALSE;
1047 } else {
1048 *warn = TRUE;
1049 }
1050 } CATCH {
1051 CATCH_MSGS();
1052 err = cpl_error_get_code();
1053 }
1054 return err;
1055}
1056
1069void eris_ifu_combine_get_xy_min_max(const int nframes,
1070 const float *offsetx, const float *offsety,
1071 float *min_offx, float *max_offx,
1072 float *min_offy, float *max_offy)
1073{
1074 float offx = 0.,
1075 offy = 0.;
1076
1077 for (int n = 0; n < nframes; n++) {
1078 offx = offsetx[n];
1079 offy = offsety[n];
1080 if (n == 0) {
1081 *min_offx = offx;
1082 *min_offy = offy;
1083 *max_offx = offx;
1084 *max_offy = offy;
1085 } else {
1086 if(offx > *max_offx)
1087 *max_offx=offx;
1088 if(offy > *max_offy)
1089 *max_offy=offy;
1090 if(offx < *min_offx)
1091 *min_offx=offx;
1092 if(offy < *min_offy)
1093 *min_offy=offy;
1094 }
1095 }
1096}
1097
1106int eris_ifu_combine_nearest_int(const double x)
1107{
1108 int k = x;
1109
1110 if (x >= 0.) {
1111 if ((x - (double)k) <= 0.5) {
1112 return k;
1113 } else {
1114 return k + 1;
1115 }
1116 } else {
1117 if ((x - (double)k) <= -0.5) {
1118 return k - 1;
1119 } else {
1120 return k;
1121 }
1122 }
1123}
1124
1154cpl_image* eris_ifu_combine_shift_image(const cpl_image *img_in,
1155 const double shift_x,
1156 const double shift_y,
1157 const double *kernel)
1158{
1159 cpl_image *img_shifted = NULL;
1160 cpl_size nx = 0,
1161 ny = 0;
1162 int samples = KERNEL_SAMPLES,
1163 mid = samples / 2,
1164 px = 0,
1165 py = 0,
1166 pos = 0,
1167 tabx = 0,
1168 taby = 0;
1169 double norm = 0.,
1170 value = 0.,
1171 fx = 0.,
1172 rx = 0.,
1173 fy = 0.,
1174 ry = 0.,
1175 *first_pass = NULL,
1176 *pimg_shifted = NULL;
1177 const double *pimg_in = NULL;
1178
1179 cpl_ensure(img_in != NULL, CPL_ERROR_NULL_INPUT, NULL);
1180 cpl_ensure(kernel != NULL, CPL_ERROR_NULL_INPUT, NULL);
1181
1182 /* Shifting by a zero offset returns a copy of the input image */
1183 if ((fabs(shift_x) < 1e-2) && (fabs(shift_y) < 1e-2))
1184 return cpl_image_duplicate(img_in);
1185
1186 nx = cpl_image_get_size_x(img_in);
1187 ny = cpl_image_get_size_y(img_in);
1188
1189 pimg_in = cpl_image_get_data_double_const(img_in);
1190 if (pimg_in != NULL) {
1191 first_pass = cpl_calloc(nx, ny*sizeof(double));
1192 img_shifted = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
1193 pimg_shifted = cpl_image_get_data_double(img_shifted);
1194 for (int y = 0; y < (int)ny; y++) {
1195 for (int x = 1; x < (int)nx-2; x++) {
1196 fx = (double)x - shift_x;
1197 px = (int)fx;
1198 rx = fx - (double)px;
1199 pos = px + y * (int)nx;
1200
1201 if ((px>1) && (px<(nx-3))) {
1202 tabx = (int)(fabs(mid * rx));
1203
1204 // Sum up over 4 closest pixel values,
1205 // weighted by interpolation kernel values
1206 value = pimg_in[pos-1] * kernel[mid+tabx] +
1207 pimg_in[pos] * kernel[tabx] +
1208 pimg_in[pos+1] * kernel[mid-tabx] +
1209 pimg_in[pos+2] * kernel[samples-tabx-1];
1210
1211 // Also sum up interpolation kernel coefficients
1212 // for further normalization
1213 norm = kernel[mid+tabx] +
1214 kernel[tabx] +
1215 kernel[mid-tabx] +
1216 kernel[samples-tabx-1];
1217
1218 if (fabs(norm) > 1e-4) {
1219 value /= norm;
1220 }
1221 } else {
1222 value = 0.;
1223 }
1224 // There may be a problem of rounding here if pixelvalue
1225 // has not enough bits to sustain the accuracy.
1226 first_pass[x+y*nx] = value;
1227 }
1228 }
1229
1230 for (int x = 0; x < (int)nx; x++) {
1231 for (int y = 1; y < (int)ny-3; y++) {
1232 fy = (double)y - shift_y;
1233 py = (int)fy ;
1234 ry = fy - (double)py ;
1235 pos = x + py * nx ;
1236
1237 if ((py > 1) && (py < ((int)ny-2))) {
1238 taby = (int)(fabs((double)mid * ry));
1239
1240 // Sum up over 4 closest pixel values,
1241 // weighted by interpolation kernel values
1242 value = first_pass[pos-nx] * kernel[mid+taby] +
1243 first_pass[pos] * kernel[taby] +
1244 first_pass[pos+nx] * kernel[mid-taby] +
1245 first_pass[pos+2*nx]*kernel[samples-taby-1];
1246
1247 // Also sum up interpolation kernel coefficients
1248 // for further normalization
1249 norm = kernel[mid+taby] +
1250 kernel[taby] +
1251 kernel[mid-taby] +
1252 kernel[samples-taby-1];
1253
1254 if (fabs(norm) > 1e-4) {
1255 value /= norm;
1256 }
1257 } else {
1258 value = 0.0;
1259 }
1260 pimg_shifted[x+y*nx] = value;
1261 }
1262 }
1263 } else {
1264 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT);
1265 cpl_msg_error(cpl_func, "Cannot get a data from an image");
1266 return NULL;
1267 }
1268
1269 // free memory
1270 cpl_free(first_pass); first_pass = NULL;
1271
1272 return img_shifted;
1273}
1274
1279void eris_ifu_combine_convert_0_to_NaN_img(cpl_image *img)
1280{
1281 cpl_size nx = 0,
1282 ny = 0;
1283 double *pimg = NULL;
1284
1285 if (img != NULL) {
1286 pimg = cpl_image_get_data_double(img);
1287
1288 nx = cpl_image_get_size_x(img);
1289 ny = cpl_image_get_size_y(img);
1290
1291 for (int i = 0 ; i < nx*ny; i++) {
1292 if (fabs(pimg[i]) < DBL_ZERO_TOLERANCE) {
1293 pimg[i] = NAN;
1294 }
1295 }
1296 }
1297}
1298
1299double eris_ifu_combine_calc_error(eris_ifu_vector *data_vec,
1300 eris_ifu_vector *err_vec,
1301 const char *compute_mode)
1302{
1303 double std_err = 0.,
1304 std_dev = 0.;
1305 int vec_size = 0;
1306 cpl_ensure_code(data_vec != NULL, CPL_ERROR_NULL_INPUT);
1307 cpl_ensure_code(err_vec != NULL, CPL_ERROR_NULL_INPUT);
1308
1309 vec_size = eris_ifu_vector_count_non_rejected(data_vec);
1310
1311 if (vec_size > 2) {
1312 // recalculate error from input data (regardless if there is
1313 // input error or not)
1314
1315 if (!strcmp(compute_mode, "MEDIAN")) {
1316 std_dev = eris_ifu_vector_get_stdev_median(data_vec);
1317 } else {
1318 std_dev = eris_ifu_vector_get_stdev(data_vec);
1319 }
1320 std_err = std_dev / sqrt(vec_size);
1321 } else {
1322 vec_size = eris_ifu_vector_count_non_rejected(err_vec);
1323 /* error propagation from input error*/
1324 if (vec_size == 1) {
1325 int i = 0;
1326 while (eris_ifu_vector_is_rejected(err_vec, i)) {
1327 i++;
1328 }
1329 std_err = eris_ifu_vector_get(err_vec, i);
1330 } else if (vec_size == 2) {
1331 double tmp_dbl = 0.;
1332 int i = 0;
1333 while (eris_ifu_vector_is_rejected(err_vec, i)) {
1334 i++;
1335 }
1336
1337 int j = i+1;
1338 while (eris_ifu_vector_is_rejected(err_vec, j)) {
1339 j++;
1340 }
1341
1342 tmp_dbl = sqrt(pow(eris_ifu_vector_get(err_vec, i), 2) +
1343 pow(eris_ifu_vector_get(err_vec, j), 2));
1344
1345 std_dev = tmp_dbl / 2;
1346 std_err = std_dev / sqrt(2);
1347 }
1348 }
1349 return std_err;
1350}
1351
1352/* --- simple shifting from KMOS pipeline --- */
1353
1354enum boundary_mode {
1355 NATURAL,
1356 EXACT,
1357 ESTIMATED1,
1358 ESTIMATED2
1359};
1360
1361double** matrix(int nrow, int ncol) {
1362 double **matrix = (double**)cpl_malloc((size_t)((nrow)*sizeof(double*)));
1363
1364 for(int i = 0; i < nrow; i++) {
1365 matrix[i] = (double *) cpl_malloc((size_t)((ncol)*sizeof(double)));
1366 }
1367
1368 return matrix;
1369}
1370
1371void free_matrix(double **matrix, int nrow) {
1372 for(int i = 0; i < nrow; i++) {
1373 cpl_free(matrix[i]); matrix[i] = NULL;
1374 }
1375 cpl_free(matrix); matrix = NULL;
1376}
1377
1390cpl_error_code eris_ifu_reject_nan(cpl_image *img)
1391{
1392 cpl_error_code err = CPL_ERROR_NONE;
1393 int nx = 0,
1394 ny = 0,
1395 is_rej = 0;
1396 float tmp = 0.0;
1397
1398 cpl_ensure_code(img != NULL, CPL_ERROR_NULL_INPUT);
1399
1400 TRY {
1401
1402 nx = cpl_image_get_size_x(img);
1403 ny = cpl_image_get_size_y(img);
1405
1406 for (int ix = 1; ix <= nx; ix++) {
1407 for (int iy = 1; iy <= ny; iy++) {
1408 tmp = cpl_image_get(img, ix, iy, &is_rej);
1410
1411 if (!is_rej && isnan(tmp)) {
1413 cpl_image_reject(img, ix, iy));
1414 }
1415 }
1416 }
1417 } CATCH {
1418 err = cpl_error_get_code();
1419 }
1420
1421 return err;
1422}
1423
1472cpl_image* eris_ifu_combine_shift_image_kmos(const cpl_image *img_in,
1473 double xshift,
1474 double yshift,
1475 const char *method,
1476 const enum extrapolationType extrapolation)
1477{
1478 const double *pimg_in = NULL;
1479 double **array_in = NULL,
1480 **array_out = NULL,
1481 *pimg_out = NULL;
1482 cpl_image *img_out = NULL;
1483 int xdim = 0,
1484 ydim = 0,
1485 xdim_new = 0,
1486 ydim_new = 0;
1487
1488 cpl_ensure(img_in != NULL, CPL_ERROR_NULL_INPUT, NULL);
1489 cpl_ensure((extrapolation == NONE_NANS) ||
1490 (extrapolation == NONE_CLIPPING)/* ||
1491 (extrapolation == BCS_NATURAL) ||
1492 (extrapolation == BCS_ESTIMATED)*/, CPL_ERROR_ILLEGAL_INPUT, NULL);
1493
1494 TRY {
1495 if ((xshift == 0.0) && (yshift == 0.0)) {
1496 // duplicate image
1498 img_out = cpl_image_duplicate(img_in));
1499 } else {
1500 xdim = cpl_image_get_size_x(img_in);
1501 ydim = cpl_image_get_size_y(img_in);
1502
1503 pimg_in = cpl_image_get_data_double_const(img_in);
1504
1505 array_in = matrix(xdim, ydim);
1506 for (int j = 0; j < ydim ; j++) {
1507 for (int i = 0; i < xdim ; i++) {
1508 if (isnan(pimg_in[i + j*xdim]))
1509 /* agudo: fix because of NaN-input */
1510 array_in[i][j] = 0;
1511 else
1512 array_in[i][j] = pimg_in[i + j*xdim];
1513 }
1514 }
1515
1516 /*if (strcmp(method, "BCS") == 0) {
1517 xdim_new = xdim;
1518 ydim_new = ydim;
1519 xstart_new = xshift;
1520 ystart_new = yshift;
1521
1522 enum boundary_mode boundaryMode = NATURAL;
1523 if (extrapolation == BCS_ESTIMATED) {
1524 boundaryMode = ESTIMATED2;
1525 }
1526
1527 array_out = bicubicspline_reg_reg(
1528 xdim, 0.0, 1.0,
1529 ydim, 0.0, 1.0,
1530 array_in,
1531 xdim_new, xstart_new, 1.0,
1532 ydim_new, ystart_new, 1.0,
1533 boundaryMode);
1534 } else */if (strcmp(method, "NN") == 0) {
1535 if (fabs(xshift) > 1.0 || fabs(yshift) > 1.0) {
1536 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
1537 "Neither xshift nor yshift are allowed to "
1538 "be greater than 1 pixel for NN");
1539 }
1540 int xoffset = 0,
1541 yoffset = 0;
1542 if (xshift > 0.5) {
1543 xoffset = 1;
1544 } else if (xshift < -0.5) {
1545 xoffset = -1;
1546 } else {
1547 xoffset = 0;
1548 }
1549 if (yshift > 0.5) {
1550 yoffset = 1;
1551 } else if (yshift < -0.5) {
1552 yoffset = -1;
1553 } else {
1554 yoffset = 0;
1555 }
1556 array_out = matrix(xdim,ydim);
1557 for (int j = 0; j < ydim; j++) {
1558 for (int i = 0; i < xdim; i++) {
1559 int xix = i+xoffset,
1560 yix = j+yoffset;
1561 if (xix < 0 || xix >= xdim || yix < 0 || yix >= ydim) {
1562 array_out[i][j] = NAN;
1563 } else {
1564 array_out[i][j] = array_in[i+xoffset][j+yoffset];
1565 }
1566 }
1567 }
1568 } else {
1569 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
1570 "Unknown value for interpolation method");
1571 }
1572 free_matrix(array_in, xdim);
1573
1574 switch (extrapolation) {
1575// case BCS_NATURAL:
1576// case BCS_ESTIMATED:
1577// BRK_IF_NULL(
1578// image_out = cpl_malloc(xdim_new * ydim_new * sizeof(double)));
1579// for (int j = 0; j < ydim_new; j++) {
1580// for (int i = 0; i < xdim_new; i++) {
1581// image_out[i+j*xdim_new] = array_out[i][j];
1582// }
1583// }
1584// break;
1585 case NONE_CLIPPING:
1586 xdim_new = xdim - lrintf(ceill(fabsl(xshift)));
1587 ydim_new = xdim - lrintf(ceill(fabsl(yshift)));
1589 pimg_out = cpl_malloc(xdim_new * ydim_new * sizeof(double)));
1590 int xmin = - floorl(xshift);
1591 if (xmin < 0)
1592 xmin = 0;
1593 int xmax = xdim - ceill(xshift);
1594 if (xmax > xdim)
1595 xmax = xdim;
1596 int ymin = - floorl(yshift);
1597 if (ymin < 0)
1598 ymin = 0;
1599 int ymax = ydim - ceill(yshift);
1600 if (ymax > ydim)
1601 ymax = ydim;
1602 for (int j = ymin; j < ymax; j++) {
1603 for (int i = xmin; i < xmax; i++) {
1604 pimg_out[(i - xmin) + (j - ymin) * xdim_new] = array_out[i][j];
1605 }
1606 }
1607 break;
1608 case NONE_NANS:
1609 xdim_new = xdim;
1610 ydim_new = ydim;
1612 pimg_out = cpl_malloc(xdim * ydim * sizeof(double)));
1613 float xxmin = 0 - xshift;
1614 float xxmax = xdim - 1 - xshift;
1615 float yymin = 0 - yshift;
1616 float yymax = ydim - 1 - yshift;
1617 for (int j = 0; j < ydim; j++) {
1618 for (int i = 0; i < xdim; i++) {
1619 if ((i < xxmin ) || (i > xxmax) ||
1620 (j < yymin ) || (j > yymax))
1621 {
1622 pimg_out[i+j*xdim] = NAN;
1623 } else {
1624 pimg_out[i+j*xdim] = array_out[i][j];
1625 }
1626 }
1627 }
1628 break;
1629 default:
1630 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
1631 "Unknown value for extrapolation type");
1632 }
1633
1634 free_matrix(array_out, xdim);
1635 img_out = cpl_image_wrap_double(xdim_new, ydim_new, pimg_out);
1636
1637 /* reject NaN values here */
1639 eris_ifu_reject_nan(img_out));
1640 }
1641 }
1642 CATCH
1643 {
1644 CATCH_MSGS();
1645 eris_ifu_free_image(&img_out);
1646 }
1647
1648 return img_out;
1649}
1650
1651cpl_error_code eris_ifu_combine_read_image_planes(const cpl_frameset *frameset,
1652 cpl_image **imagesData,
1653 cpl_image **imagesError,
1654 int z,
1655 int edge_trim,
1656 bool subtract_background)
1657{
1658 cpl_size nframes = 0,
1659 llx = 0,
1660 lly = 0,
1661 urx = 0,
1662 ury = 0;
1663 cpl_error_code err = CPL_ERROR_NONE;
1664 const cpl_frame *frame = NULL;
1665 cpl_mask *tmp_mask = NULL;
1666 cpl_image *cube_qual_tmp = NULL;
1667 cpl_propertylist *plist = NULL;
1668 const char *name = NULL;
1669 int tmp_size_x = 0,
1670 tmp_size_y = 0;
1671 bool warn = FALSE,
1672 warned = FALSE;
1673
1674 cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
1675
1676 TRY {
1677 nframes = cpl_frameset_get_size(frameset);
1678
1679 /* Read in cubes */
1680 for (cpl_size n = 0; n < nframes; n++) {
1682 frame = cpl_frameset_get_position_const(frameset, n));
1684 name = cpl_frame_get_filename(frame));
1685 if (edge_trim > 0) {
1687 plist = cpl_propertylist_load(name, 1));
1688 tmp_size_x = eris_pfits_get_naxis1(plist);
1689 tmp_size_y = eris_pfits_get_naxis2(plist);
1691
1693 llx = 1 + edge_trim;
1694 lly = 1 + edge_trim;
1695 urx = tmp_size_x - edge_trim;
1696 ury = tmp_size_y - edge_trim;
1697
1699 imagesData[n] = cpl_image_load_window(name, CPL_TYPE_DOUBLE, z, 1, llx, lly, urx, ury));
1701 imagesError[n] = cpl_image_load_window(name, CPL_TYPE_DOUBLE, z, 2, llx, lly, urx, ury));
1703 cube_qual_tmp = cpl_image_load_window(name, CPL_TYPE_DOUBLE, z, 3, llx, lly, urx, ury));
1704 }
1705 else{
1707 imagesData[n] = cpl_image_load(name, CPL_TYPE_DOUBLE, z, 1));
1709 imagesError[n] = cpl_image_load(name, CPL_TYPE_DOUBLE, z, 2));
1711 cube_qual_tmp = cpl_image_load(name, CPL_TYPE_DOUBLE, z, 3));
1712 }
1713
1714 /* Reject mask */
1716 tmp_mask = cpl_mask_threshold_image_create(cube_qual_tmp, 0, INT_MAX));
1718 cpl_image_reject_from_mask(imagesData[n], tmp_mask));
1720 cpl_image_reject_from_mask(imagesError[n], tmp_mask));
1721 eris_ifu_free_mask(&tmp_mask);
1722 eris_ifu_free_image(&cube_qual_tmp);
1723
1724 if (subtract_background) {
1726 eris_ifu_combine_subtract_background(imagesData[n], &warn));
1727 if (warn && !warned) {
1728 warned = TRUE;
1729 cpl_msg_warning(cpl_func, " local_median is NAN in %dth plane", z);
1730 }
1731 }
1733 } // end for nframes
1734 } CATCH {
1735 CATCH_MSGS();
1736 err = cpl_error_get_code();
1737 }
1738 return err;
1739}
1740
1750int eris_ifu_combine_min_cube_size(const cpl_frameset *fs) {
1751 int naxis3 = 0,
1752 naxis3_tmp = 0;
1753 double crval3 = 0.,
1754 crpix3 = 0,
1755 cd3_3 = 0.,
1756 crval3_tmp = 0.,
1757 crpix3_tmp = 0.,
1758 cd3_3_tmp = 0.;
1759 const char *name = NULL;
1760 const cpl_frame *fr = NULL;
1761 cpl_propertylist *pl = NULL;
1762
1763 cpl_ensure(fs != NULL, CPL_ERROR_NULL_INPUT, -1);
1764
1765 TRY {
1766 // initialize with 1st frame
1767 cpl_frameset_iterator *iter = NULL;
1769 iter = cpl_frameset_iterator_new(fs));
1770 fr = cpl_frameset_iterator_get(iter);
1773 name = cpl_frame_get_filename(fr));
1774
1775 // load header of data extension
1777 pl = cpl_propertylist_load(name, 1));
1778 naxis3 = cpl_propertylist_get_int( pl, NAXIS3);
1779 crpix3 = cpl_propertylist_get_double(pl, CRPIX3);
1780 crval3 = cpl_propertylist_get_double(pl, CRVAL3);
1781 cd3_3 = cpl_propertylist_get_double(pl, CD3_3);
1784
1786 cpl_frameset_iterator_advance(iter, 1));
1787 fr = cpl_frameset_iterator_get(iter);
1789
1790 while (fr != NULL) {
1792 name = cpl_frame_get_filename(fr));
1793 // load header of data extension
1795 pl = cpl_propertylist_load(name, 1));
1796
1797 naxis3_tmp = cpl_propertylist_get_int( pl, NAXIS3);
1798 crpix3_tmp = cpl_propertylist_get_double(pl, CRPIX3);
1799 crval3_tmp = cpl_propertylist_get_double(pl, CRVAL3);
1800 cd3_3_tmp = cpl_propertylist_get_double(pl, CD3_3);
1803
1804 if ((fabs(crpix3 - crpix3_tmp) > DBL_ZERO_TOLERANCE) ||
1805 (fabs(crval3 - crval3_tmp) > DBL_ZERO_TOLERANCE) ||
1806 (fabs(cd3_3 - cd3_3_tmp) > DBL_ZERO_TOLERANCE))
1807 {
1808 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
1809 "WCS not matching for all frames!");
1810 }
1811
1812 if (naxis3_tmp < naxis3) {
1813 naxis3 = naxis3_tmp;
1814 }
1815
1817 cpl_frameset_iterator_advance(iter, 1));
1818 fr = cpl_frameset_iterator_get(iter);
1820 } // end while
1821 } CATCH {
1822 CATCH_MSGS();
1823 naxis3 = -1;
1824 }
1825 return naxis3;
1826}
#define BRK_IF_ERROR(function)
If function is or returns an error != CPL_ERROR_NONE, then the try-block is exited.
#define RECOVER(void)
Recover the error state which was present during TRY (at the beginning of the try-block).
#define CHECK_ERROR_STATE(void)
Check the CPL error state, and exit the try-block if not CPL_ERROR_NONE.
#define BRK_WITH_ERROR_MSG(code,...)
Set a new CPL error, and exit the try-block.
#define TRY
Beginning of a TRY-block.
#define CATCH
End of a TRY-block, beginning of a CATCH-block.
#define BRK_IF_NULL(function)
If function is or returns a NULL pointer, then the try-block is exited.
#define CATCH_MSGS()
Displays an error message stack.
void eris_ifu_free_propertylist(cpl_propertylist **item)
free memory and set pointer to null
void eris_ifu_free_vector(cpl_vector **item)
free memory and set pointer to null
void eris_ifu_free_image(cpl_image **item)
free memory and set pointer to null
void eris_ifu_free_mask(cpl_mask **item)
free memory and set pointer to null
double eris_ifu_vector_get_stdev_median(const eris_ifu_vector *ev)
Compute the bias-corrected standard deviation of a vectors elements using median.
int eris_ifu_is_nan_or_inf(double A)
Checks if a value is nan, inf or -inf.
eris_ifu_vector * eris_ifu_vector_new(int n)
Create a new eris_ifu_vector.
double eris_ifu_vector_get_stdev(const eris_ifu_vector *ev)
Compute the bias-corrected standard deviation of a vectors elements.
int eris_ifu_vector_is_rejected(const eris_ifu_vector *ev, int n)
Test if a value is good or bad.
int eris_ifu_vector_count_non_rejected(const eris_ifu_vector *ev)
Count the number of non-rejected elements in a eris_ifu_vector.
cpl_error_code eris_ifu_vector_set(eris_ifu_vector *ev, int pos, double val)
Set an element of the eris_ifu_vector.
double eris_ifu_vector_get(const eris_ifu_vector *ev, int pos)
Get an element of the eris_ifu_vector.
void eris_ifu_vector_delete(eris_ifu_vector *ev)
Delete a eris_ifu_vector.
cpl_error_code eris_ifu_vector_reject(eris_ifu_vector *ev, int n)
Set a value as rejected in a eris_ifu_vector.
int eris_pfits_get_naxis2(const cpl_propertylist *plist)
find out the character string associated to the NAXIS2 keyword
Definition: eris_pfits.c:168
int eris_pfits_get_naxis1(const cpl_propertylist *plist)
find out the character string associated to the NAXIS1 keyword
Definition: eris_pfits.c:155