ERIS Pipeline Reference Manual 1.8.15
eris_ifu_jitter_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 "cpl.h"
26
27#include <stdbool.h>
28#include <string.h>
29#include <strings.h>
30#include <math.h>
31#include <gsl/gsl_math.h>
32#include <gsl/gsl_interp2d.h>
33#include <gsl/gsl_spline2d.h>
34
35#include "eris_ifu_error.h"
36#include "eris_ifu_utils.h"
37#include "eris_ifu_functions.h"
38#include "eris_ifu_dfs.h"
39#include "eris_ifu_extract_spec_static.h"
40#include "eris_ifu_jitter_static.h"
41#include "eris_ifu_wavecal_static.h"
42#include "eris_ifu_distortion_static.h"
43#include "eris_ifu_lambda_corr.h"
44#include "eris_ifu_sky_tweak.h"
45#include "eris_ifu_efficiency_response.h"
46#include "eris_ifu_lambda_corr.h"
47#include "eris_utils.h"
48#include "eris_pfits.h"
49#include "skycorr/eris_ifu_skycorr.h"
50#include "skycorr/sc_skycorr.h"
51#include "skycorr/sc_lines.h"
52
112//eris_ifu_jitter_free_exposureEntry(struct exposureEntry* exp_entry){
113
114// if(exp_entry != NULL) {
115// if(exp_entry->frame != NULL) cpl_frame_delete(exp_entry->frame);
116// if(exp_entry->hdr != NULL) cpl_propertylist_delete(exp_entry->hdr);
117// if(exp_entry->rawImage != NULL) hdrl_image_delete(exp_entry->rawImage);
118// if(exp_entry->cube != NULL) hdrl_imagelist_delete(exp_entry->cube);
119// if(exp_entry->cubeBpm != NULL) cpl_imagelist_delete(exp_entry->cubeBpm);
120// if(exp_entry->cubeHdr != NULL) cpl_propertylist_delete(exp_entry->cubeHdr);
121// if(exp_entry->badPixelMask != NULL) cpl_mask_delete(exp_entry->badPixelMask);
122// if(exp_entry->darkSubtrImage != NULL) hdrl_image_delete(exp_entry->darkSubtrImage);
123// if(exp_entry->skySubtrImage != NULL) hdrl_image_delete(exp_entry->skySubtrImage);
124// exp_entry = NULL;
125// };
126// return;
127//}
128
129/* --------------------------------------------------------------------------
130 FUNCTION DOCUMENTATION BLOCKS (Insert before each function)
131 -------------------------------------------------------------------------- */
132
133#define ERIS_IFU_SKIP_SKY_CORR_PLANES 75
134
135/*----------------------------------------------------------------------------*/
153/*----------------------------------------------------------------------------*/
154void eris_ifu_jitter_free_sofStruct(struct sofStruct* sof_struct){
155
156 /* The following commented lines of code creates seg faults */
157 if(sof_struct != NULL) {
158 if(sof_struct->exposureTable != NULL) {
159 for(cpl_size i = 0; i < sof_struct->exposureTableCnt; i++) {
160 if (sof_struct->exposureTable != NULL) {
161
162 if(sof_struct->exposureTable[i].frame != NULL) {
163 //cpl_frame_delete(sof_struct->exposureTable[i].frame);
164 }
165 if(sof_struct->exposureTable[i].hdr != NULL) {
166 cpl_propertylist_delete(sof_struct->exposureTable[i].hdr);
167 }
168 if(sof_struct->exposureTable[i].rawImage != NULL) {
169 //hdrl_image_delete(sof_struct->exposureTable[i].rawImage);
170 }
171 if(sof_struct->exposureTable[i].cube != NULL){
172 hdrl_imagelist_delete(sof_struct->exposureTable[i].cube);
173 }
174 if(sof_struct->exposureTable[i].cubeBpm != NULL){
175 cpl_imagelist_delete(sof_struct->exposureTable[i].cubeBpm);
176 }
177 if(sof_struct->exposureTable[i].cubeHdr != NULL) {
178 cpl_propertylist_delete(sof_struct->exposureTable[i].cubeHdr);
179 }
180 if(sof_struct->exposureTable[i].badPixelMask != NULL) {
181 cpl_mask_delete(sof_struct->exposureTable[i].badPixelMask);
182 }
183 if(sof_struct->exposureTable[i].darkSubtrImage != NULL){
184 hdrl_image_delete(sof_struct->exposureTable[i].darkSubtrImage);
185 }
186 if(sof_struct->exposureTable[i].skySubtrImage != NULL){
187 hdrl_image_delete(sof_struct->exposureTable[i].skySubtrImage);
188 }
189
190 }
191 }
192 //eris_ifu_jitter_free_exposureEntry(sof_struct->exposureTable);
193 }
194 if(sof_struct->masterDark != NULL) hdrl_image_delete(sof_struct->masterDark);
195 if(sof_struct->masterFlat != NULL) hdrl_image_delete(sof_struct->masterFlat);
196 if(sof_struct->waveMap != NULL) cpl_image_delete(sof_struct->waveMap);
197 if(sof_struct->badPixelMask != NULL) cpl_mask_delete(sof_struct->badPixelMask);
198 if(sof_struct->distortion != NULL) {
199 for (int sx = 0; sx < SLITLET_CNT; sx++) {
200 cpl_polynomial_delete(sof_struct->distortion[sx]);
201 }
202 cpl_free(sof_struct->distortion);
203 }
204 if(sof_struct->dqi != NULL) {
205 cpl_image_delete(sof_struct->dqi);
206 }
207 if(sof_struct->oh_ref_peaks != NULL) cpl_vector_delete(sof_struct->oh_ref_peaks);
208 if(sof_struct->oh_ref_frame != NULL) cpl_frame_delete(sof_struct->oh_ref_frame);
209 if(sof_struct->borders != NULL) cpl_table_delete(sof_struct->borders);
210 if(sof_struct->poly_u != NULL) cpl_polynomial_delete(sof_struct->poly_u);
211 if(sof_struct->poly_v != NULL) cpl_polynomial_delete(sof_struct->poly_v);
212 if(sof_struct->distances != NULL) cpl_vector_delete(sof_struct->distances);
213 if(sof_struct->positions != NULL) cpl_bivector_delete(sof_struct->positions);
214 sof_struct = NULL;
215 }
216 return;
217}
218
219 /*----------------------------------------------------------------------------*/
228 /*----------------------------------------------------------------------------*/
229void
231{
232
233 switch(type) {
234 case OBJECT_CUBE:
235 cpl_msg_info(cpl_func,"type: OBJECT_CUBE");
236 break;
237 case STD_CUBE:
238 cpl_msg_info(cpl_func,"type: STD_CUBE");
239 break;
240 case STD_FLUX_CUBE:
241 cpl_msg_info(cpl_func,"type: STD_FLUX_CUBE");
242 break;
243 case STD_CUBE_NOFLAT:
244 cpl_msg_info(cpl_func,"type: STD_CUBE_NOFLAT");
245 break;
246 case STD_FLUX_CUBE_NOFLAT:
247 cpl_msg_info(cpl_func,"type: STD_FLUX_CUBE_NOFLAT");
248 break;
249 case PSF_CUBE:
250 cpl_msg_info(cpl_func,"type: PSF_CUBE");
251 break;
252 case SKY_OBJECT_CUBE:
253 cpl_msg_info(cpl_func,"type: SKY_OBJECT_CUBE");
254 break;
255 case SKY_STD_CUBE:
256 cpl_msg_info(cpl_func,"type: SKY_STD_CUBE");
257 break;
258 case SKY_STD_FLUX_CUBE:
259 cpl_msg_info(cpl_func,"type: SKY_STD_FLUX_CUBE");
260 break;
261 case SKY_PSF_CUBE:
262 cpl_msg_info(cpl_func,"type: SKY_PSF_CUBE");
263 break;
264 case TWEAKED_CUBE:
265 cpl_msg_info(cpl_func,"type: TWEAKED_CUBE");
266 break;
267 case DAR_CUBE:
268 cpl_msg_info(cpl_func,"type: DAR_CUBE");
269 break;
270 case JITTER_CUBE:
271 cpl_msg_info(cpl_func,"type: JITTER_CUBE");
272 break;
273 case BPM_CUBE:
274 cpl_msg_info(cpl_func,"type: BPM_CUBE");
275 break;
276 case OBJECT_CUBE_COADD:
277 cpl_msg_info(cpl_func,"type: OBJECT_CUBE_COADD");
278 break;
279 case STD_CUBE_COADD:
280 cpl_msg_info(cpl_func,"type: STD_CUBE_COADD");
281 break;
282 case PSF_CUBE_COADD:
283 cpl_msg_info(cpl_func,"type: PSF_CUBE_COADD");
284 break;
285 case STD_FLUX_CUBE_COADD:
286 cpl_msg_info(cpl_func,"type: STD_FLUX_CUBE_COADD");
287 break;
288 case DAR_STD_FLUX_CUBE:
289 cpl_msg_info(cpl_func,"type: DAR_STD_FLUX_CUBE");
290 break;
291 case TWEAKED_CUBE_COADD:
292 cpl_msg_info(cpl_func,"type: TWEAKED_CUBE_COADD");
293 break;
294 case DAR_CUBE_COADD:
295 cpl_msg_info(cpl_func,"type: DAR_CUBE_COADD");
296 break;
297 case STD_FLUX_CUBE_COADD_NOFLAT:
298 cpl_msg_info(cpl_func,"type: STD_FLUX_CUBE_COADD_NOFLAT");
299 break;
300 case STD_CUBE_COADD_NOFLAT:
301 cpl_msg_info(cpl_func,"type: STD_CUBE_COADD_NOFLAT");
302 break;
303 default:
304 cpl_msg_info(cpl_func,"type: DEFAULT %d",type);
305 break;
306 }
307
308 return;
309}
310
311/*----------------------------------------------------------------------------*/
322/*----------------------------------------------------------------------------*/
323cubeType
325{
326 cubeType coadd_type;
327 switch(type) {
328 case OBJECT_CUBE:
329 coadd_type = OBJECT_CUBE_COADD;
330 break;
331 case OBJECT_CUBE_COADD:
332 coadd_type = OBJECT_CUBE_COADD;
333 break;
334 case DAR_CUBE:
335 coadd_type = DAR_CUBE_COADD;
336 break;
337 case STD_CUBE:
338 coadd_type = STD_CUBE_COADD;
339 break;
340 case STD_CUBE_COADD:
341 coadd_type = STD_CUBE_COADD;
342 break;
343 case STD_FLUX_CUBE:
344 coadd_type = STD_FLUX_CUBE_COADD;
345 break;
346 case STD_FLUX_CUBE_COADD:
347 coadd_type = STD_FLUX_CUBE_COADD;
348 break;
349 case STD_FLUX_CUBE_COADD_NOFLAT:
350 coadd_type = STD_FLUX_CUBE_COADD_NOFLAT;
351 break;
352 case STD_CUBE_NOFLAT:
353 coadd_type = STD_CUBE_COADD_NOFLAT;
354 break;
355 case STD_CUBE_COADD_NOFLAT:
356 coadd_type = STD_CUBE_COADD_NOFLAT;
357 break;
358 case PSF_CUBE:
359 coadd_type = PSF_CUBE_COADD;
360 break;
361 case DAR_CUBE_COADD:
362 coadd_type = DAR_CUBE_COADD;
363 break;
364 case DAR_STD_CUBE_COADD:
365 coadd_type = STD_CUBE_COADD;
366 break;
367 case TWEAKED_CUBE_COADD:
368 coadd_type = TWEAKED_CUBE_COADD;
369 break;
370 default:
371 cpl_msg_warning(cpl_func,"case %d not found switch to default case",type);
372 coadd_type = OBJECT_CUBE_COADD;
373 break;
374 }
375
376 return coadd_type;
377}
378
379/*----------------------------------------------------------------------------*/
394/*----------------------------------------------------------------------------*/
395cubeType
397{
398 cubeType type;
399 switch(mode) {
400 case SCIENCE:
401 type = OBJECT_CUBE;
402 break;
403 case STD:
404 type = STD_CUBE;
405 break;
406 case STD_FLUX:
407 type = STD_FLUX_CUBE;
408 break;
409 case PSF:
410 type = PSF_CUBE;
411 break;
412 default:
413 type = OBJECT_CUBE;
414 break;
415 }
416
417 return type;
418}
419
420/*----------------------------------------------------------------------------*/
435/*----------------------------------------------------------------------------*/
436cubeType
438{
439 cubeType type;
440 switch(mode) {
441 case SCIENCE:
442 type = SKY_OBJECT_CUBE;
443 break;
444 case STD:
445 type = SKY_STD_CUBE;
446 break;
447 case STD_FLUX:
448 type = SKY_STD_FLUX_CUBE;
449 break;
450 case PSF:
451 type = SKY_PSF_CUBE;
452 break;
453 default:
454 type = SKY_OBJECT_CUBE;
455 break;
456 }
457 return type;
458}
459
460/*----------------------------------------------------------------------------*/
488/*----------------------------------------------------------------------------*/
489static cpl_error_code
490eris_ifu_jitter_save_cpl_cube(
491 cpl_frameset *allframes,
492 cpl_frameset *usedframes,
493 cpl_frame *inherit,
494 const cpl_parameterlist * parlist,
495 cpl_imagelist *cube,
496 hdrl_imagelist *hdrlCube,
497 cpl_imagelist *bpmCube,
498 cpl_propertylist *hdr,
499 struct paramStruct params,
500 cubeType type,
501 int counter,
502 const char* recipe_name)
503{
504 cpl_error_code retVal = CPL_ERROR_NONE;
505 char *proCatg = NULL;
506 char *filenamePrefix = NULL;
507 char *filename = NULL;
508
509 TRY
510 {
511 ASSURE(cube != NULL || hdrlCube != NULL,
512 CPL_ERROR_ILLEGAL_INPUT, "One of cube or hdrlCube must be not NULL");
513 ASSURE(!(cube != NULL && hdrlCube != NULL),
514 CPL_ERROR_ILLEGAL_INPUT, "One of cube or hdrlCube must be NULL");
515 eris_ifu_jitter_get_procatg_and_filename(type,&proCatg,&filenamePrefix);
516
517 if (counter >= 0) {
518 filename = cpl_sprintf("%s_%s_%3.3d.fits", recipe_name, filenamePrefix, counter);
519 } else {
520 filename = cpl_sprintf("%s_%s.fits", recipe_name, filenamePrefix);
521 }
522 cpl_propertylist_erase(hdr,"RADECSYS");
523 if (cube != NULL) {
524 eris_ifu_save_imagelist(allframes,
525 inherit,
526 hdr,
527 parlist,
528 recipe_name,
529 proCatg,
530 filename,
531 CPL_TYPE_FLOAT,
532 cube);
533 if (bpmCube != NULL) {
534 cpl_imagelist_save(bpmCube, filename, CPL_TYPE_INT,
535 NULL,CPL_IO_EXTEND);
536 }
537
538 } else {
539 cpl_imagelist *datacube = cpl_imagelist_new();
540 cpl_imagelist *errorcube = cpl_imagelist_new();
541 cpl_propertylist *applist = NULL;
542
543 // BRK_IF_NULL(applist = cpl_propertylist_new());
544 applist = cpl_propertylist_duplicate(hdr);
545 cpl_propertylist_update_string(applist, CPL_DFS_PRO_CATG, proCatg);
546
547 //TODO: Why adding CPL_DFS_PRO_TYPE, CPL_DFS_PRO_TECH ???
548 cpl_propertylist_update_string(applist, CPL_DFS_PRO_TYPE, "CUBE");
549 cpl_propertylist_update_string(applist, CPL_DFS_PRO_TECH, "CUBE");
550
551 eris_ifu_split_hdrl_imagelist(hdrlCube, datacube, errorcube);
552
553 cpl_imagelist *bpmMaskZero;
555 bpmCube, params.bpmThreshold);
556
557 /*
558 cpl_imagelist *bpmMaskZero = cpl_imagelist_new();
559 for (cpl_size iz=0; iz < cpl_imagelist_get_size(datacube); iz++) {
560 cpl_imagelist_set(bpmMaskZero,
561 cpl_image_new_from_mask(
562 hdrl_image_get_mask(
563 hdrl_imagelist_get(hdrlCube, iz)
564 )), iz);
565 CHECK_ERROR_STATE();
566 }
567 */
568
569 eris_ifu_save_deq_cube(allframes,
570 NULL,
571 parlist,
572 usedframes,
573 inherit,
574 recipe_name,
575 applist,
576 "RADECSYS",
577 filename,
578 datacube,
579 errorcube,
580 rmse,
581 bpmMaskZero,
582 maskzero/*,
583 CPL_TYPE_FLOAT */);
584
585 //cpl_imagelist_unwrap(datacube);
586 //cpl_imagelist_unwrap(errorcube);
587 cpl_imagelist_delete(datacube);
588 cpl_imagelist_delete(errorcube);
589 cpl_propertylist_delete(applist);
590 cpl_imagelist_delete(bpmMaskZero);
591 }
592 }
593 CATCH
594 {
595 retVal = cpl_error_get_code();
596 }
597
598 eris_ifu_free_string(&proCatg);
599 eris_ifu_free_string(&filenamePrefix);
600 eris_ifu_free_string(&filename);
601 eris_check_error_code("eris_ifu_jitter_save_cpl_cube");
602 return retVal;
603}
604/*---------------------------------------------------------------------------*/
620/*---------------------------------------------------------------------------*/
621static cpl_frameset*
622eris_ifu_frameset_extract_obj_set(const cpl_frameset* set, struct sofStruct* sof,
623 const cpl_size ix)
624{
625 //cpl_msg_info(cpl_func,"check inputs");
626 cpl_ensure(set, CPL_ERROR_NULL_INPUT, NULL);
627 cpl_ensure(sof, CPL_ERROR_NULL_INPUT, NULL);
628 cpl_ensure(ix >= 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
629 //cpl_ensure_code(out, CPL_ERROR_NULL_INPUT);
630
631 cpl_frameset * obj_set = NULL;
632 cpl_frameset * sky_set = NULL;
633 cpl_frameset * cdb_set = NULL;
634 cpl_frameset * out_set = NULL;
635
636 //cpl_msg_info(cpl_func,"select obj");
637 obj_set = cpl_frameset_new();
638 eris_ifu_extract_obj_frames(set, obj_set);
639 //cpl_frameset_dump(obj_set, stdout);
640
641 //cpl_msg_info(cpl_func,"select sky");
642 sky_set = cpl_frameset_new();
643 eris_ifu_extract_sky_frames(set, sky_set);
644 //cpl_frameset_dump(sky_set, stdout);
645
646 //cpl_msg_info(cpl_func,"select cdb");
647 cdb_set = cpl_frameset_new();
648 eris_ifu_extract_mst_frames(set, cdb_set);
649 //cpl_frameset_dump(cdb_set, stdout);
650
651 cpl_frame* frame = sof->exposureTable[ix].frame;
652// const char* fname = cpl_frame_get_filename(frame);
653
654 //cpl_msg_info(cpl_func,"put all together");
655 out_set = cpl_frameset_new();
656 cpl_frameset_insert(out_set, cpl_frame_duplicate(frame));
657 cpl_frameset_join(out_set, sky_set);
658 cpl_frameset_join(out_set, cdb_set);
659 //cpl_msg_info(cpl_func,"dumping");
660 //cpl_frameset_dump(out_set, stdout);
661
662 cpl_frameset_delete(obj_set);
663 cpl_frameset_delete(sky_set);
664 cpl_frameset_delete(cdb_set);
665 eris_check_error_code("eris_frameset_extract_obj_set");
666
667 return out_set;
668}
669/*----------------------------------------------------------------------------*/
703/*----------------------------------------------------------------------------*/
704cpl_error_code eris_ifu_jitter_process_exposures(struct sofStruct *sof,
705 struct stdParamStruct stdParams,
706 struct paramStruct params,
707 cpl_frameset *frameset,
708 const cpl_parameterlist * parlist,
709 const char* recipe_name,
710 const char* context)
711{
712 cpl_error_code retVal = CPL_ERROR_NONE;
713 hdrl_image *objImg = NULL;
714 hdrl_image *tmpImg = NULL;
715 struct exposureEntry *objEntry;
716 cpl_polynomial *ohLambdaCorrection = NULL;
717 productDepthType productDepth = stdParams.productDepth;
718 bool doOHbasedLambdaCorrection = FALSE;
719 cubeType type = OBJECT_CUBE;
720 const char *expType = NULL;
721 double cdelt = 0.;
722 double centralLambda = 0.0;
723 double shift = 0.0;
724 bool isSky = FALSE;
725
726 TRY
727 {
728 cpl_msg_info(cpl_func,"Build OBJ and SKY data cubes, may correct wavecal by OH lines, subtract sky background");
729
730 if ((sof->oh_ref_frame != NULL) && !params.skip_oh_align && !(isSky && params.skip_sky_oh_align)) {
731 doOHbasedLambdaCorrection = TRUE;
732 } else {
733 doOHbasedLambdaCorrection = FALSE;
734 }
735 cpl_msg_debug(cpl_func,"doOHbasedLambdaCorrection: %d, isSky: %d, "
736 "params.skip_sky_oh_align: %d, params.skip_oh_align: %d",
737 doOHbasedLambdaCorrection, isSky,
738 params.skip_sky_oh_align, params.skip_oh_align);
739
740 if (getenv("USE_OCS") != NULL) {
742 }
743
744 for (int ix=0; ix < sof->exposureTableCnt; ix++) {
745 if (sof->exposureTable[ix].isObject) {
746 expType = "OBJ";
747 isSky = FALSE;
748 type = eris_ifu_jitter_get_obj_type(sof->mode);
749 } else {
750 expType = "SKY";
751 isSky = TRUE;
752 type = eris_ifu_jitter_get_sky_type(sof->mode);
753 }
754 cpl_msg_info(__func__, "Process exposure #\%3.3d %s %s", ix, expType,
755 cpl_frame_get_filename(sof->exposureTable[ix].frame));
756
757 objEntry = &sof->exposureTable[ix];
758 objImg = objEntry->rawImage;
759
760 // build OBJECT cube
762 objEntry->cube = eris_ifu_jitter_build_cube(
763 objImg, ix, sof, params, false,
764 ohLambdaCorrection, productDepth));
765
766 eris_ifu_free_polynomial(&ohLambdaCorrection);
767 // TODO: do lambda correct. with OH lines also for PS or STD OBS?
768
769 if (doOHbasedLambdaCorrection) {
770 // compute OH based lambda correction
771
772 /* to prevent memory leak delete cpl_polynomial structure */
773 eris_ifu_free_polynomial(&ohLambdaCorrection);
774
775 int pfit_order = 0;
776 char* param_name = cpl_sprintf("%s.oh_align_poly_order", context);
777 cpl_msg_info(cpl_func,"pname: %s",param_name);
778 pfit_order = cpl_parameter_get_int(cpl_parameterlist_find_const(parlist, param_name));
779 cpl_free(param_name);
780
781
782 BRK_IF_NULL( ohLambdaCorrection = eris_ifu_lcorr_get(NULL,
783 objEntry->cube, objEntry->cubeHdr, sof->oh_ref_peaks, pfit_order));
784
785 cdelt = cpl_propertylist_get_double(objEntry->cubeHdr, "CDELT3");
786 centralLambda = cpl_propertylist_get_double(
787 objEntry->cubeHdr, "CRVAL3") +
788 hdrl_imagelist_get_size(objEntry->cube) * cdelt * 0.5;
789 shift = cpl_polynomial_eval_1d(
790 ohLambdaCorrection, centralLambda, NULL);
791 cpl_msg_info(__func__,
792 "Overall shift of wavelength due OH lambda correction: %f [micron] %f [pixel]",
793 shift, shift/cdelt);
794
795 eris_ifu_free_hdrl_imagelist(&objEntry->cube);
796
798 params.skyTweak, ix, sof, productDepth);
799
800 objEntry->cube = eris_ifu_jitter_build_cube(
801 tmpImg, ix, sof, params, true,
802 ohLambdaCorrection, productDepth);
803
804 eris_ifu_free_polynomial(&ohLambdaCorrection);
805
807 objEntry->cubeHdr, "LAMBDA SHIFT UM", shift,
808 "[um] OH based lambda shift"));
810 objEntry->cubeHdr, "LAMBDA SHIFT PIXEL", shift/cdelt,
811 "[px] OH based lambda shift"));
812 } else {
813 if (params.skip_oh_align && (ix == 0)) {
814 cpl_msg_warning(cpl_func, " |------------------------------------------------------|");
815 cpl_msg_warning(cpl_func, " | WARNING: with parameter --sky_oh_align the spectral |");
816 cpl_msg_warning(cpl_func, " | calibration of the outputs is expected to |");
817 cpl_msg_warning(cpl_func, " | be off for several pixels due to flexure of |");
818 cpl_msg_warning(cpl_func, " | the instrument |");
819 cpl_msg_warning(cpl_func, " |------------------------------------------------------|");
820 }
821 }
822
823 if (productDepth >= PD_AUXILLIARY) {
824/*
825 cpl_imagelist *datacube = cpl_imagelist_new();
826 cpl_imagelist *errorcube = cpl_imagelist_new();
827 BRK_IF_ERROR(
828 eris_ifu_split_hdrl_imagelist(objEntry->cube, datacube, errorcube));
829*/
830
831/*
832 cpl_imagelist *bpmMaskZero;
833 BRK_IF_NULL(
834 bpmMaskZero = eris_ifu_interpolatedMasK_to_maskZero(
835 objEntry->cubeBpm, params.bpmThreshold));
836 for (cpl_size zx=0; zx<cpl_imagelist_get_size(datacube); zx++){
837 cpl_image *tmpImg = cpl_imagelist_get(datacube, zx);
838 cpl_mask *tmpMask = cpl_mask_threshold_image_create(
839 cpl_imagelist_get(objEntry->cubeBpm, zx), 0.5, 1.5);
840 cpl_image_reject_from_mask(tmpImg, tmpMask);
841 eris_ifu_free_mask(&tmpMask);
842 CHECK_ERROR_STATE();
843 }
844*/
845 // eris_ifu_jitter_save_cpl_cube(frameset, objEntry->frame, parlist,
846 // datacube, NULL, bpmMaskOne, objEntry->cubeHdr, params, type, ix, recipe_name);
847 cpl_frameset* obj_set =
848 eris_ifu_frameset_extract_obj_set(frameset, sof, ix);
849 eris_ifu_jitter_save_cpl_cube(frameset, obj_set, objEntry->frame, parlist,
850 NULL, objEntry->cube, objEntry->cubeBpm, objEntry->cubeHdr, params, type, ix, recipe_name);
851 eris_ifu_jitter_save_cpl_cube(frameset, obj_set, objEntry->frame, parlist,
852 objEntry->cubeBpm, NULL, NULL, objEntry->cubeHdr, params, BPM_CUBE, ix, recipe_name);
853 cpl_frameset_delete(obj_set);
854 }
855
856
857 cpl_boolean chop_nan = CPL_FALSE;
858 char* param_name = cpl_sprintf("%s.chop-nan", context);
859 //cpl_msg_info(cpl_func,"pname: %s",param_name);
860 chop_nan = cpl_parameter_get_bool(
861 cpl_parameterlist_find_const(parlist, param_name));
862 cpl_free(param_name);
863 if(chop_nan) {
864 ifsBand ifu_band = eris_ifu_get_band(objEntry->cubeHdr);
865 cpl_size zmin = 0;
866 cpl_size zmax = 0;
867 eris_ifu_get_plane_cut_min_max(ifu_band, &zmin, &zmax);
868 //cpl_msg_info(cpl_func,"check zmin: %lld zmax: %lld", zmin, zmax);
869
870 eris_ifu_cube_trim_nans(zmin, zmax, &(objEntry->cube),
871 &(objEntry->cubeBpm), objEntry->cubeHdr);
872 }
873
874
876 }
877 //AMO TODO STRANGE: added line: this fixes a leak but creates another problem
878 //eris_ifu_free_hdrl_imagelist(&objEntry->cube);
879 }
880 CATCH
881 {
882 retVal = cpl_error_get_code();
883 }
884 eris_ifu_free_polynomial(&ohLambdaCorrection);
886 eris_check_error_code("eris_ifu_jitter_process_exposures");
887 return retVal;
888}
889
890/*----------------------------------------------------------------------------*/
911/*----------------------------------------------------------------------------*/
912static cpl_error_code
913eris_ifu_jitter_skycorr_from_mask(struct exposureEntry *objEntry,
914 const cpl_mask*mask_obj, const int sky_est_method)
915{
916
917 cpl_image* ima;
918 cpl_image* err;
919 cpl_mask* bpm;
920 hdrl_image* himg;
921 cpl_size skip = ERIS_IFU_SKIP_SKY_CORR_PLANES;
922 cpl_size size_z = hdrl_imagelist_get_size(objEntry->cube);
923
924 hdrl_value sky = {0, 0};
925 for (cpl_size zx = skip; zx < size_z - skip; zx++){
926 //cpl_msg_info(cpl_func,"zx: %lld",zx);
927
928 himg = hdrl_imagelist_get(objEntry->cube, zx);
929 ima = hdrl_image_get_image(himg);
930 err = hdrl_image_get_error(himg);
931 bpm = hdrl_image_get_mask(himg);
932
933 hdrl_image_reject_from_mask(himg, mask_obj);
934 if(sky_est_method==0) {
935 sky = hdrl_image_get_median(himg);
936 } else {
937 sky = hdrl_image_get_mean(himg);
938 }
939
940 himg = hdrl_image_create(ima, err);
942 hdrl_image_sub_scalar(himg, sky);
943
945 hdrl_imagelist_set(objEntry->cube, hdrl_image_duplicate(himg), zx);
946 hdrl_image_delete(himg);
947
948 if(cpl_error_get_code() != CPL_ERROR_NONE) {
949 eris_check_error_code("eris_ifu_jitter_skycorr_from_mask");
950 cpl_msg_error(cpl_func,"Error found in eris_ifu_jitter_skycorr_from_mask. Exit!");
951 exit(0);
952 }
953 }
954 eris_check_error_code("eris_ifu_jitter_skycorr_from_mask");
955 return cpl_error_get_code();
956
957}
958
959/*----------------------------------------------------------------------------*/
981/*----------------------------------------------------------------------------*/
982static cpl_error_code
983eris_ifu_jitter_get_split_param_int(const cpl_parameterlist * parlist,
984 const char* pname, const int min_x, const int min_y,
985 const int max_x, const int max_y, int* px, int* py)
986{
987
988 const cpl_parameter* par = NULL;
989 char* param_name;
990 const char* context = "eris.eris_ifu_jitter";
991
992 const char* pname_string_value;
993 param_name = cpl_sprintf("%s.%s", context, pname);
994 par = cpl_parameterlist_find_const(parlist, param_name);
995 pname_string_value = cpl_parameter_get_string(par);
996 cpl_free(param_name);
997
998 int nFields;
999 unsigned int end;
1000
1001 nFields = sscanf(pname_string_value, "%d,%d%n", px, py, &end);
1002
1003 if (nFields != 2 || end != strlen(pname_string_value)) {
1004 cpl_msg_error(cpl_func, "The %s parameter must be "
1005 "a list of two integers separated by a comma", pname);
1006 printf("Error reading sky-box-center string\n");
1007 }
1008
1009 if (*px < min_x) {
1010 cpl_msg_warning(cpl_func,"%s_x: %d set it to 0",pname, *px);
1011 *px = 0;
1012 }
1013 if (*py < min_y) {
1014 cpl_msg_warning(cpl_func,"%s_y: %d set it to 0",pname, *py);
1015 *py = 0;
1016 }
1017 if (*px > max_x) {
1018 cpl_msg_warning(cpl_func,"%s_x: %d set it to 10",pname, *px);
1019 *px = 10;
1020 }
1021 if (*py > max_y) {
1022 cpl_msg_warning(cpl_func,"%s_y: %d set it to 10", pname, *py);
1023 *py = 10;
1024 }
1025 /*
1026 cpl_msg_debug(cpl_func,"%s_x: %d, %s_y: %d",
1027 pname, *px, pname, *py);
1028 */
1029 eris_check_error_code("eris_ifu_jitter_get_split_param_int");
1030 return cpl_error_get_code();
1031}
1032/*----------------------------------------------------------------------------*/
1062/*----------------------------------------------------------------------------*/
1063static cpl_error_code
1064eris_ifu_jitter_skycor_from_box(const cpl_parameterlist * parlist,
1065 struct exposureEntry *objEntry, const int aj_method)
1066{
1067
1068 int sky_box_center_x, sky_box_center_y,
1069 sky_box_width_x, sky_box_width_y,
1070 sky_box_edges_margin_x, sky_box_edges_margin_y;
1071
1072 eris_ifu_jitter_get_split_param_int(parlist,"sky-box-center", 0, 0, 64, 64,
1073 &sky_box_center_x, &sky_box_center_y);
1074 eris_ifu_jitter_get_split_param_int(parlist,"sky-box-width", 0, 0, 10, 10,
1075 &sky_box_width_x, &sky_box_width_y);
1076 eris_ifu_jitter_get_split_param_int(parlist,"sky-box-edges-margin", 0, 0, 10, 10,
1077 &sky_box_edges_margin_x, &sky_box_edges_margin_y);
1078
1079
1080 cpl_msg_info(cpl_func,"sky_box_center_x: %d sky_box_center_y: %d",
1081 sky_box_center_x, sky_box_center_y);
1082 cpl_msg_info(cpl_func,"sky_box_width_x: %d sky_box_width_y: %d",
1083 sky_box_width_x, sky_box_width_y);
1084 cpl_msg_info(cpl_func,"sky_box_edges_margin_x: %d sky_box_edges_margin_y: %d",
1085 sky_box_edges_margin_x, sky_box_edges_margin_y);
1086
1087
1088
1089 char* param_name;
1090 int sky_est_method = -1;
1091 const char* context = "eris.eris_ifu_jitter";
1092 const cpl_parameter* p = NULL;
1093
1094 param_name = cpl_sprintf("%s.sky-est-method", context);
1095 p = cpl_parameterlist_find_const(parlist, param_name);
1096 if(p != NULL) {
1097 sky_est_method = cpl_parameter_get_int(p);
1098 }
1099 cpl_free(param_name);
1100
1101 int niter = 5;
1102
1103 param_name = cpl_sprintf("%s.sky-est-niter", context);
1104 p = cpl_parameterlist_find_const(parlist, param_name);
1105 if(p != NULL) {
1106 niter = cpl_parameter_get_int(p);
1107 }
1108 cpl_free(param_name);
1109
1110 int kappa = 3;
1111 param_name = cpl_sprintf("%s.sky-est-kappa", context);
1112 p = cpl_parameterlist_find_const(parlist, param_name);
1113 if(p != NULL) {
1114 kappa = cpl_parameter_get_double(p);
1115 }
1116 cpl_free(param_name);
1117
1118 /* apply correction based on user defined parameters */
1119 cpl_image* img = NULL;
1120 hdrl_image* himg = NULL;
1121 hdrl_value sky = {0, 0};
1122 cpl_size llx = 0 , urx = 0, lly = 0 , ury = 0 ;
1123 cpl_msg_info(cpl_func,"llx, lly, urx, ury, [%lld,%lld,%lld,%lld]",
1124 llx,lly,urx,ury);
1125 /* TODO: Handle start/end wave ranges where object is NAN */
1126 cpl_size skip = ERIS_IFU_SKIP_SKY_CORR_PLANES;
1127 /*
1128 cpl_imagelist* before = cpl_imagelist_new();
1129 cpl_imagelist* after = cpl_imagelist_new();
1130 for (cpl_size zx = 0;zx<hdrl_imagelist_get_size(objEntry->cube);zx++){
1131 himg = hdrl_imagelist_get(objEntry->cube, zx);
1132 img = hdrl_image_get_image(himg);
1133 cpl_imagelist_set(before, img, zx);
1134 }
1135 cpl_imagelist_save(before, "cube_before.fits", CPL_TYPE_INT,
1136 NULL, CPL_IO_DEFAULT);
1137 */
1138 cpl_bivector* xy_pos = NULL;
1139 cpl_vector* sky_data = NULL;
1140 double* x_pos = NULL;
1141 double* y_pos = NULL;
1142
1143 cpl_size size_x = hdrl_imagelist_get_size_x(objEntry->cube);
1144 cpl_size size_y = hdrl_imagelist_get_size_y(objEntry->cube);
1145 if(aj_method == 5) {
1146 xy_pos = cpl_bivector_new(4);
1147 sky_data = cpl_vector_new(4);
1148 x_pos = cpl_bivector_get_x_data(xy_pos);
1149 y_pos = cpl_bivector_get_y_data(xy_pos);
1150
1151 x_pos[0] = sky_box_edges_margin_x + sky_box_width_x;
1152 y_pos[0] = sky_box_edges_margin_y + sky_box_width_y;
1153
1154 x_pos[1] = sky_box_edges_margin_x + sky_box_width_x;
1155 y_pos[1] = size_y - sky_box_edges_margin_y - sky_box_width_y;
1156
1157 x_pos[2] = size_x - sky_box_edges_margin_x - sky_box_width_x;
1158 y_pos[2] = sky_box_edges_margin_y + sky_box_width_y;
1159
1160 x_pos[3] = size_x - sky_box_edges_margin_x - sky_box_width_x;
1161 y_pos[3] = size_y - sky_box_edges_margin_y - sky_box_width_y;
1162
1163 }
1164
1165 if(aj_method == 6) {
1166 xy_pos = cpl_bivector_new(8);
1167 sky_data = cpl_vector_new(8);
1168 x_pos = cpl_bivector_get_x_data(xy_pos);
1169 y_pos = cpl_bivector_get_y_data(xy_pos);
1170
1171
1172 x_pos[0] = sky_box_edges_margin_x + sky_box_width_x;
1173 y_pos[0] = sky_box_edges_margin_y + sky_box_width_y;
1174
1175 x_pos[1] = sky_box_edges_margin_x + sky_box_width_x;
1176 y_pos[1] = size_y - sky_box_edges_margin_y - sky_box_width_y;
1177
1178 x_pos[2] = size_x - sky_box_edges_margin_x - sky_box_width_x;
1179 y_pos[2] = sky_box_edges_margin_y + sky_box_width_y;
1180
1181 x_pos[3] = size_x - sky_box_edges_margin_x - sky_box_width_x;
1182 y_pos[3] = size_y - sky_box_edges_margin_y - sky_box_width_y;
1183
1184
1185
1186 x_pos[4] = floor(0.5 * size_x);
1187 y_pos[4] = sky_box_edges_margin_y + sky_box_width_y;
1188
1189 x_pos[5] = sky_box_edges_margin_x + sky_box_width_x;
1190 y_pos[5] = floor(0.5 * size_y);
1191
1192 x_pos[6] = size_x - sky_box_edges_margin_x - sky_box_width_x;
1193 y_pos[6] = floor(0.5 * size_y);
1194
1195 x_pos[7] = floor(0.5 * size_x);
1196 y_pos[7] = size_y - sky_box_edges_margin_y - sky_box_width_y;
1197
1198 }
1199
1200 cpl_size size_z = hdrl_imagelist_get_size(objEntry->cube);
1201 double sky_tmp_val = 0;
1202 if(aj_method == 4) {
1203 llx = sky_box_center_x - sky_box_width_x;
1204 urx = sky_box_center_x + sky_box_width_x;
1205 lly = sky_box_center_y - sky_box_width_y;
1206 ury = sky_box_center_y + sky_box_width_y;
1207 for (cpl_size zx = skip; zx < size_z - skip; zx++){
1208 //cpl_msg_info(cpl_func,"zx: %lld",zx);
1209 himg = hdrl_imagelist_get(objEntry->cube, zx);
1210 img = hdrl_image_get_image(himg);
1211 /* the following may fail at start end wave ranges */
1212 if(sky_est_method==0) {
1213 sky.data = cpl_image_get_median_window(img, llx, lly, urx, ury);
1214 } else {
1215 sky.data = cpl_image_get_mean_window(img, llx, lly, urx, ury);
1216 }
1217 hdrl_image_sub_scalar(himg, sky);
1218 hdrl_imagelist_set(objEntry->cube, himg, zx);
1219 }
1220 } else if(aj_method == 5 || aj_method == 6) {
1221 cpl_size xy_pos_size = cpl_bivector_get_size(xy_pos);
1222 double* psky_data = cpl_vector_get_data(sky_data);
1223 for (cpl_size zx = skip; zx < size_z - skip; zx++){
1224
1225 himg = hdrl_imagelist_get(objEntry->cube, zx);
1226 img = hdrl_image_get_image(himg);
1227 /* the following may fail at start end wave ranges */
1228 for (cpl_size k = 0; k < xy_pos_size; k++){
1229 llx = ((cpl_size) x_pos[k] - sky_box_width_x);
1230 lly = ((cpl_size) y_pos[k] - sky_box_width_y);
1231 urx = ((cpl_size) x_pos[k] + sky_box_width_x);
1232 ury = ((cpl_size) y_pos[k] + sky_box_width_y);
1233 //cpl_msg_info(cpl_func,"llx, lly, urx, ury: [%lld,%lld,%lld,%lld]",llx, lly, urx, ury);
1234 if(sky_est_method==0) {
1235 sky_tmp_val = cpl_image_get_median_window(img, llx, lly, urx, ury);
1236 if(cpl_error_get_code() != CPL_ERROR_NONE) {
1237 cpl_error_reset();
1238 continue;
1239 } else {
1240 psky_data[k] = sky_tmp_val;
1241 }
1242
1243 } else {
1244 sky_tmp_val = cpl_image_get_mean_window(img, llx, lly, urx, ury);
1245 if(cpl_error_get_code() != CPL_ERROR_NONE) {
1246 cpl_error_reset();
1247 continue;
1248 } else {
1249 psky_data[k] = sky_tmp_val;
1250 }
1251 }
1252 if(cpl_error_get_code() != CPL_ERROR_NONE) {
1253 cpl_msg_error(cpl_func,"Some error during sky modeling: "
1254 "try to use a different region or other aj-method");
1255 eris_check_error_code("eris_ifu_jitter_skycor_from_box");
1256 exit(0);
1257 }
1258 }
1259 if(sky_est_method==0) {
1260 sky.data = cpl_vector_get_median(sky_data);
1261 } else {
1262 sky.data = cpl_vector_get_mean(sky_data);
1263 }
1264 hdrl_image_sub_scalar(himg, sky);
1265 hdrl_imagelist_set(objEntry->cube, himg, zx);
1266 }
1267 } else if(aj_method == 7) {
1268
1269 hdrl_image* cube_collapsed = NULL;
1270 cpl_image* cube_cmap = NULL;
1271 hdrl_imagelist_collapse_mean(objEntry->cube, &cube_collapsed, &cube_cmap);
1272 /*
1273 cpl_image_save(hdrl_image_get_image(cube_collapsed), "collapsed_mean.fits",
1274 CPL_TYPE_FLOAT, NULL, CPL_IO_DEFAULT);
1275 cpl_image_save(cube_cmap, "cube_cmap.fits", CPL_TYPE_FLOAT, NULL,
1276 CPL_IO_DEFAULT);
1277 */
1278 cpl_mask* mask_obj;
1279
1280 mask_obj = eris_ifu_hima_get_obj_mask(cube_collapsed, niter, kappa);
1281
1282 hdrl_image_delete(cube_collapsed);
1283 cpl_image_delete(cube_cmap);
1284
1285 eris_ifu_jitter_skycorr_from_mask(objEntry, mask_obj, sky_est_method);
1286
1287 cpl_mask_delete(mask_obj);
1288 } else if(aj_method == 8) {
1289 hdrl_image* cube_mean = NULL;
1290 cpl_image* cube_cmap = NULL;
1291 hdrl_imagelist_collapse_mean(objEntry->cube, &cube_mean, &cube_cmap);
1292 cpl_mask* mask_obj = eris_ifu_hima_get_obj_mask_percent(cube_mean, 0.25);
1293
1294 hdrl_image_delete(cube_mean);
1295 cpl_image_delete(cube_cmap);
1296 eris_ifu_jitter_skycorr_from_mask(objEntry, mask_obj, sky_est_method);
1297 cpl_mask_delete(mask_obj);
1298 }
1299
1300 /*
1301 for (cpl_size zx = 0;zx<hdrl_imagelist_get_size(objEntry->cube);zx++){
1302 himg = hdrl_imagelist_get(objEntry->cube, zx);
1303 img = hdrl_image_get_image(himg);
1304 cpl_imagelist_set(after, img, zx);
1305 }
1306
1307 cpl_imagelist_save(after, "cube_after.fits",
1308 CPL_TYPE_INT, NULL, CPL_IO_DEFAULT);
1309 */
1310
1311
1312 eris_check_error_code("eris_ifu_jitter_skycor_from_box");
1313 return cpl_error_get_code();
1314
1315}
1316/*----------------------------------------------------------------------------*/
1346/*----------------------------------------------------------------------------*/
1347cpl_error_code eris_ifu_jitter_process_cubes(struct sofStruct *sof,
1348 struct stdParamStruct stdParams,
1349 struct paramStruct params,
1350 cpl_frameset *frameset,
1351 const cpl_parameterlist * parlist,
1352 const char* recipe_name,
1353 cubeType *obj_type)
1354{
1355 cpl_error_code retVal = CPL_ERROR_NONE,
1356 err = CPL_ERROR_NONE;
1357 struct exposureEntry *objEntry = NULL,
1358 *skyEntry = NULL;
1359 cpl_mask *tmpMask = NULL;
1360 hdrl_image *tmpImg = NULL;
1361 cpl_size imgSize = 0;
1362 double *pObjErr = NULL,
1363 *pSkyErr = NULL,
1364 *pTweakedErr = NULL;
1365 cpl_binary *pObjMask = NULL,
1366 *pErrMask = NULL,
1367 *pTweakedMask = NULL;
1368
1369 TRY
1370 {
1371 cpl_msg_info(cpl_func, "Process Jitter Cubes: split Obj & Sky, correct Sky as user specified");
1372
1373 for (int ix = 0; ix < sof->exposureTableCnt; ix++) {
1374 if (!sof->exposureTable[ix].isObject) {
1375 continue; // loop only over OBJECT cubes, skip SKY
1376 }
1377 objEntry = &sof->exposureTable[ix];
1378 cpl_frameset* obj_set =
1379 eris_ifu_frameset_extract_obj_set(frameset, sof, ix);
1380 // apply skytweak if desired
1381 if (params.skyTweak != NONE) {
1382 int skyIndex = objEntry->skyIndex;
1383 if (skyIndex < 0) {
1384 BRK_WITH_ERROR_MSG(CPL_ERROR_DATA_NOT_FOUND,
1385 "no vaild sky frame found");
1386 }
1387 skyEntry = &sof->exposureTable[skyIndex];
1388
1389 if (skyEntry->cube == NULL) {
1390 cpl_msg_error(__func__,
1391 "Missing sky image for input frame %s",
1392 cpl_frame_get_filename(objEntry->frame));
1393 } else {
1394 cpl_imagelist *dataCubeObj = cpl_imagelist_new(),
1395 *errCubeObj = cpl_imagelist_new(),
1396 *dataCubeSky = cpl_imagelist_new(),
1397 *errCubeSky = cpl_imagelist_new();
1398
1400 eris_ifu_split_hdrl_imagelist(objEntry->cube,
1401 dataCubeObj, errCubeObj));
1403 eris_ifu_split_hdrl_imagelist(skyEntry->cube,
1404 dataCubeSky, errCubeSky));
1405
1406 if (params.skyTweak == DAVIES) {
1407 cpl_imagelist *skycorrObj = NULL,
1408 *skycorrSky = NULL,
1409 *skycorrErr = NULL;
1410
1411 skycorrObj = eris_ifu_sky_tweak(dataCubeObj, dataCubeSky,
1412 objEntry->cubeHdr, .3,
1413 params.tbsub,
1414 params.discard_subband,
1415 params.stretch_sky,
1416 params.stretch_degree,
1417 params.stretch_resampling,
1418 0, &skycorrSky);
1419
1420 /*
1421 * simple error calculation for sky tweaked cube
1422 * as sky tweaked cube is basically objject cube - sky cube
1423 * the error is sqrt(objectError^2 + skyError^2)
1424 */
1426 skycorrErr = cpl_imagelist_duplicate(errCubeObj));
1427
1428 imgSize = cpl_image_get_size_x(cpl_imagelist_get(skycorrErr, 0)) *
1429 cpl_image_get_size_y(cpl_imagelist_get(skycorrErr, 0));
1430
1431 for (cpl_size tx = 0; tx < cpl_imagelist_get_size(skycorrErr); tx++) {
1432 pObjErr = cpl_image_get_data_double(
1433 cpl_imagelist_get(errCubeObj,tx));
1434 pSkyErr = cpl_image_get_data_double(
1435 cpl_imagelist_get(errCubeSky,tx));
1436 pTweakedErr = cpl_image_get_data_double(
1437 cpl_imagelist_get(skycorrErr,tx));
1438 pObjMask = cpl_mask_get_data(
1439 cpl_image_get_bpm(cpl_imagelist_get(errCubeObj,tx)));
1440 pErrMask = cpl_mask_get_data(
1441 cpl_image_get_bpm(cpl_imagelist_get(errCubeSky,tx)));
1442 pTweakedMask = cpl_mask_get_data(
1443 cpl_image_get_bpm(cpl_imagelist_get(skycorrErr,tx)));
1444
1445 for (cpl_size rx = 0; rx < imgSize; rx++) {
1446 if ((pObjMask[rx] != BAD_PIX) &&
1447 (pErrMask[rx] != BAD_PIX))
1448 {
1449 pTweakedMask[rx] = GOOD_PIX;
1450 pTweakedErr[rx] = hypot(pObjErr[rx], pSkyErr[rx]);
1451 } else {
1452 pTweakedMask[rx] = BAD_PIX;
1453 }
1454 }
1455 }
1456
1457 // agudo: Possible memory leak here when objEntry->cube is overwritten?
1458 // It isn't deleted anywhere beforehand
1460 objEntry->cube = hdrl_imagelist_create(skycorrObj, skycorrErr));
1461
1462 eris_ifu_free_imagelist(&skycorrObj);
1463 eris_ifu_free_imagelist(&skycorrErr);
1464 //To delete the following two creates a seg fault
1465 eris_ifu_free_imagelist(&dataCubeSky);
1466 eris_ifu_free_imagelist(&errCubeSky);
1467 eris_ifu_free_imagelist(&dataCubeObj);
1468 eris_ifu_free_imagelist(&errCubeObj);
1469
1470 if ((stdParams.productDepth >= PD_DEBUG) && (skycorrSky != NULL)) {
1471 char *fname = cpl_sprintf(
1472 "eris_ifu_jitter_dbg_skycoorsky_%3.3d.fits", skyIndex);
1473 cpl_imagelist_save(skycorrSky, fname,
1474 CPL_TYPE_FLOAT, NULL, CPL_IO_CREATE);
1475 eris_ifu_free_string(&fname);
1476 }
1477
1478 eris_ifu_free_imagelist(&skycorrSky);
1480 }
1481 else if (params.skyTweak == AUSTRIAN) {
1482 cpl_table *objspec = NULL,
1483 *skyspec = NULL;
1484 cpl_parameterlist *parlist_skycorr = NULL;
1485 double ts = cpl_test_get_walltime();
1486
1487 // loop through all pixels of the image and apply skycorr
1488 cpl_size nx = hdrl_imagelist_get_size_x(objEntry->cube);
1489 cpl_size ny = hdrl_imagelist_get_size_y(objEntry->cube);
1490
1491 // create parameterlist for skycorr
1493 parlist_skycorr = eris_ifu_skycorr_create_parlist(skyEntry->cubeHdr));
1494
1495// agudo: couldn't successfully extract this code from sc_skycorr, so keep reading in txt files for every spectrum
1496// /* Read line groups from ASCII file and adapt it to observing conditions */
1497// cpl_table *groups = cpl_table_new(0);
1498// BRK_IF_ERROR(
1499// sc_lines(groups, parlist_skycorr));
1500
1501 // in y we increment by 2 because the iamge is already scaled by 2 here
1502 for (cpl_size y = 1; y <= ny; y += 2) {
1503 if (stdParams.productDepth == 3) {
1504 cpl_msg_debug(cpl_func, ">>>>> line %d", (int)y);
1505 }
1506 for (cpl_size x = 1; x <= nx; x++) {
1507 int success = CPL_FALSE;
1508 if (stdParams.productDepth == 3) {
1509 cpl_msg_debug(cpl_func, ">>>>> pix (%d/%d)", (int)x, (int)y);
1510 }
1512 objspec = eris_ifu_skycorr_extract_spectrum(objEntry->cube, objEntry->cubeHdr, x, y));
1514 skyspec = eris_ifu_skycorr_extract_spectrum(skyEntry->cube, skyEntry->cubeHdr, x, y));
1515
1516 if (stdParams.productDepth == 3) {
1517 char* fn = NULL;
1518
1519// cpl_table *t = NULL;
1520// t = cpl_table_duplicate(objspec);
1521// cpl_table_erase_column(t, "weight");
1522// cpl_table_erase_column(t, "mask_I");
1523// fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_objspec.fits", (int)x, (int)y);
1524// cpl_table_save(t, NULL, objEntry->cubeHdr, fn, CPL_IO_CREATE);
1525// cpl_free(fn);
1526
1527// fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_objspec_vector.fits", (int)x, (int)y);
1528// double *pt = cpl_table_get_data_double (t, "flux");
1529// cpl_vector *vt = cpl_vector_wrap(cpl_table_get_nrow(t), pt);
1530// eris_ifu_save_vector_dbg(vt, fn, CPL_IO_CREATE, objEntry->cubeHdr);
1531// cpl_free(fn);
1532
1533// cpl_table_delete(t); t = NULL;
1534// t = cpl_table_duplicate(skyspec);
1535// cpl_table_erase_column(t, "weight");
1536// cpl_table_erase_column(t, "mask_I");
1537// fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_skyspec.fits", (int)x, (int)y);
1538// cpl_table_save(t, NULL, skyEntry->cubeHdr, fn, CPL_IO_CREATE);
1539// cpl_free(fn);
1540// cpl_table_delete(t); t = NULL;
1541
1542 fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_objspec_1_orig.fits", (int)x, (int)y);
1543 cpl_table_save(objspec, NULL, objEntry->cubeHdr, fn, CPL_IO_CREATE);
1544 cpl_free(fn);
1545 fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_skyspec_1_orig.fits", (int)x, (int)y);
1546 cpl_table_save(skyspec, NULL, skyEntry->cubeHdr, fn, CPL_IO_CREATE);
1547 cpl_free(fn);
1548 }
1549
1550 /* prepare skycorr code */
1551 double mean_lambda = 0.5 * (cpl_table_get(objspec, "lambda", 0, NULL) +
1552 cpl_table_get(objspec, "lambda", cpl_table_get_nrow(objspec)-1, NULL));
1553 cpl_parameter *p = cpl_parameterlist_find(parlist_skycorr, "meanlam");
1554 cpl_parameter_set_double(p, mean_lambda);
1555
1556 double mean_obj_flux = cpl_table_get_column_mean(objspec, "flux"),
1557 mean_sky_flux = cpl_table_get_column_mean(skyspec, "flux");
1558
1559 // ignore spectra which have thoroughly a flux of zero
1560 if ((fabs(mean_obj_flux) > 0.00001) && (fabs(mean_sky_flux) > 0.00001)) {
1561 // tweak outliers that are larger than 10 times than average
1562 int outlier_factor = 10;
1564 eris_ifu_skycorr_flatten_outliers(objspec, skyspec, outlier_factor));
1565
1566 // alternatively remove outliers as good as possible (but we risk to remove as well OH lines etc.)
1567 // double min_frac = 0.5;
1568 // BRK_IF_ERROR(
1569 // eris_ifu_skycorr_flatten_outliers2(objspec, skyspec, min_frac));
1570
1571 if (stdParams.productDepth == 3) {
1572 char* fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_objspec_2_flatten1.fits", (int)x, (int)y);
1573 cpl_table_save(objspec, NULL, objEntry->cubeHdr, fn, CPL_IO_CREATE);
1574 cpl_free(fn);
1575 fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_skyspec_2_flatten1.fits", (int)x, (int)y);
1576 cpl_table_save(skyspec, NULL, skyEntry->cubeHdr, fn, CPL_IO_CREATE);
1577 cpl_free(fn);
1578 }
1579
1580 err = sc_skycorr(parlist_skycorr, objspec, skyspec, /*groups,*/ stdParams.productDepth);
1581 if (err != CPL_ERROR_NONE) {
1582 // reset error
1583 cpl_errorstate_set(CPL_ERROR_NONE);
1584 err = CPL_ERROR_NONE;
1586
1587 // tweak outliers again that are larger than 8 times than average (seems not really to help...)
1588 outlier_factor = 8;
1590 eris_ifu_skycorr_flatten_outliers(objspec, skyspec, outlier_factor));
1591
1592 if (stdParams.productDepth == 3) {
1593 char* fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_objspec_3_flatten2.fits", (int)x, (int)y);
1594 cpl_table_save(objspec, NULL, objEntry->cubeHdr, fn, CPL_IO_CREATE);
1595 cpl_free(fn);
1596 fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_skyspec_3_flatten2.fits", (int)x, (int)y);
1597 cpl_table_save(skyspec, NULL, skyEntry->cubeHdr, fn, CPL_IO_CREATE);
1598 cpl_free(fn);
1599 }
1600
1601 err = sc_skycorr(parlist_skycorr, objspec, skyspec, /*groups, */stdParams.productDepth);
1602 if (err != CPL_ERROR_NONE) {
1603 // give up sky correcting...
1604 cpl_errorstate_set(CPL_ERROR_NONE);
1605 err = CPL_ERROR_NONE;
1607 } else {
1608 success = CPL_TRUE;
1609 }
1610 } else {
1611 success = CPL_TRUE;
1612 }
1613 }
1614
1615 if (success == CPL_FALSE) {
1616 // do what? -> insert blank spectrum
1617 if (stdParams.productDepth == 3) {
1618 cpl_msg_debug(cpl_func, ">>>>> inserted blank spectrum");
1619 char* fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_objspec_4_failed.fits", (int)x, (int)y);
1620 cpl_table_save(objspec, NULL, objEntry->cubeHdr, fn, CPL_IO_CREATE);
1621 cpl_free(fn);
1622 fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_skyspec_4_failed.fits", (int)x, (int)y);
1623 cpl_table_save(skyspec, NULL, skyEntry->cubeHdr, fn, CPL_IO_CREATE);
1624 cpl_free(fn);
1625 }
1626 eris_ifu_free_table(&objspec);
1628 objspec = eris_ifu_skycorr_create_nan_spectrum(objEntry->cube));
1629 }
1631 eris_ifu_skycorr_insert_spectrum(objEntry->cube, objspec, x, y));
1632
1633 eris_ifu_free_table(&objspec);
1634 eris_ifu_free_table(&skyspec);
1636 } // end for: x <= nx
1637 } // end for: y <= ny
1638 eris_ifu_free_parameterlist(&parlist_skycorr);
1639
1640 double te = cpl_test_get_walltime();
1641 cpl_msg_debug(cpl_func,">>>>> >>>>> skycorr took %g seconds", te - ts);
1642// eris_ifu_free_table(&groups);
1643 } // end if: AUSTRIAN
1644 } // end else: (skyEntry->cube != NULL)
1645
1646 if (!cpl_propertylist_has(objEntry->cubeHdr,"PRODCATG")) {
1647 cpl_propertylist_append_string(objEntry->cubeHdr, "PRODCATG",
1648 PRODCATG_CUBE_OBJ);
1649 }
1650
1652 eris_ifu_jitter_save_cpl_cube(frameset, obj_set, objEntry->frame, parlist,
1653 NULL, objEntry->cube, objEntry->cubeBpm, objEntry->cubeHdr,
1654 params, TWEAKED_CUBE, ix, recipe_name));
1655 } /* end sky tweak handling */
1656 cpl_frameset_delete(obj_set);
1658
1659 char* param_name;
1660 int aj_method = -1;
1661 const char* context = "eris.eris_ifu_jitter";
1662 param_name = cpl_sprintf("%s.aj-method", context);
1663 const cpl_parameter* p = NULL;
1664 p = cpl_parameterlist_find_const(parlist, param_name);
1665 if (p != NULL) {
1666 aj_method = cpl_parameter_get_int(p);
1667 }
1668 cpl_free(param_name);
1669
1670 if((objEntry->skyIndex < 0) && (aj_method > 3)) {
1671 /* Handle sky subtraction in cas no sky frame is present */
1672 eris_ifu_jitter_skycor_from_box(parlist, objEntry, aj_method);
1673 }
1674
1675 if (params.darCorrection) {
1676 for (cpl_size zx = 0;zx<hdrl_imagelist_get_size(objEntry->cube);zx++){
1677 tmpImg= hdrl_imagelist_get(objEntry->cube, zx);
1678 tmpMask = cpl_mask_threshold_image_create(cpl_imagelist_get(objEntry->cubeBpm, zx), params.bpmThreshold, 1.5);;
1679 hdrl_image_reject_from_mask(tmpImg, tmpMask);
1680 eris_ifu_free_mask(&tmpMask);
1682 }
1684 eris_ifu_dar_correction(objEntry->cube,
1685 objEntry->cubeHdr, /*objEntry->cubeBpm,*/
1686 params.darShiftMethod,
1687 params.darShiftWidth, params.darShiftLength));
1688 cpl_frameset* obj_set2 =
1689 eris_ifu_frameset_extract_obj_set(frameset, sof, ix);
1690
1691 eris_ifu_jitter_save_cpl_cube(frameset, obj_set2,
1692 sof->exposureTable[ix].frame, parlist, NULL,
1693 objEntry->cube, objEntry->cubeBpm, objEntry->cubeHdr,
1694 params, DAR_CUBE, ix, recipe_name);
1695 cpl_frameset_delete(obj_set2);
1696 }
1697 } // end for: ix < sof->exposureTableCnt
1698
1699 cubeType sky_type = SKY_OBJECT_CUBE;
1700 /* TODO: In case of only one OBJ (or STD or PSF) input we need to create
1701 * a cube object. Why? */
1702 char *proCatg = NULL;
1703 char *filenamePrefix = NULL;
1704 *obj_type = eris_ifu_jitter_get_obj_type(sof->mode);
1705 eris_ifu_jitter_get_procatg_and_filename(*obj_type, &proCatg, &filenamePrefix);
1706 eris_ifu_free_string(&filenamePrefix);
1707 cpl_frameset* cube_set;
1708 if ((cube_set = eris_ifu_extract_frameset(frameset, proCatg )) == NULL){
1709 for(cpl_size i = 0; i < sof->exposureTableCnt; i++) {
1710 if (!cpl_propertylist_has(sof->exposureTable[i].cubeHdr,"PRODCATG")) {
1711 cpl_propertylist_append_string(sof->exposureTable[i].cubeHdr,
1712 "PRODCATG", "ANCILLARY.EXPMAP");
1713 }
1714
1715 if (sof->exposureTable[i].isObject) {
1716 cpl_frameset* obj_set =
1717 eris_ifu_frameset_extract_obj_set(frameset, sof, i);
1718 *obj_type = eris_ifu_jitter_get_obj_type(sof->mode);
1719 eris_ifu_jitter_save_cpl_cube(frameset, obj_set,
1720 sof->exposureTable[i].frame,
1721 parlist, NULL, sof->exposureTable[i].cube,
1722 sof->exposureTable[i].cubeBpm,
1723 sof->exposureTable[i].cubeHdr,
1724 params, *obj_type, i, recipe_name);
1725 cpl_frameset_delete(obj_set);
1726 } else {
1727 sky_type = eris_ifu_jitter_get_sky_type(sof->mode);
1728 eris_ifu_jitter_save_cpl_cube(frameset, frameset,
1729 sof->exposureTable[i].frame,
1730 parlist, NULL, sof->exposureTable[i].cube,
1731 sof->exposureTable[i].cubeBpm,
1732 sof->exposureTable[i].cubeHdr,
1733 params, sky_type, i, recipe_name);
1734 }
1735 }
1736 }
1737 cpl_free(proCatg);
1738 }
1739 CATCH
1740 {
1741 retVal = cpl_error_get_code();
1742 CATCH_MSGS();
1743 }
1744
1745 return retVal;
1746}
1747
1748/*----------------------------------------------------------------------------*/
1772/*----------------------------------------------------------------------------*/
1774 skyTweakModes sky_tweak,
1775 int objIdx,
1776 struct sofStruct *sof,
1777 productDepthType productDepth)
1778{
1779 hdrl_image *objImg = NULL;
1780 cpl_mask *inputMask = NULL;
1781 cpl_mask *outputMask = NULL;
1782 cpl_image *dqi = NULL;
1783 char *filename = NULL;
1784 char *filename2 = NULL;
1785 bool darkSkySubtracted = false;
1786
1787 cpl_ensure(sof != NULL,CPL_ERROR_NULL_INPUT, NULL);
1788
1789 TRY
1790 {
1791
1792 objImg = hdrl_image_duplicate(sof->exposureTable[objIdx].rawImage);
1793 inputMask = cpl_mask_duplicate(
1794 hdrl_image_get_mask(sof->exposureTable[objIdx].rawImage));
1795
1796 if (sky_tweak == NONE) {
1797 const int skyIdx = sof->exposureTable[objIdx].skyIndex;
1798 if (skyIdx >=0) {
1799 hdrl_image *skyImg = hdrl_image_duplicate(sof->exposureTable[skyIdx].rawImage);
1800 BRK_IF_NULL(skyImg);
1801 BRK_IF_ERROR(hdrl_image_sub_image(objImg, skyImg));
1802 darkSkySubtracted = true;
1803 hdrl_image_delete(skyImg);
1804 } else if (sof->masterDark != NULL) {
1805 hdrl_image *rawImg = hdrl_image_duplicate(sof->masterDark);
1806 BRK_IF_ERROR(hdrl_image_sub_image(objImg, sof->masterDark));
1807 darkSkySubtracted = true;
1808 hdrl_image_delete(rawImg);
1809 }
1810
1811 if (darkSkySubtracted) {
1812 outputMask = cpl_mask_duplicate(hdrl_image_get_mask(objImg));
1813 // detect new bad pixels
1814 BRK_IF_ERROR(cpl_mask_xor(outputMask, inputMask));
1815 BRK_IF_NULL(dqi = cpl_image_new_from_mask(outputMask));
1816 BRK_IF_ERROR(cpl_image_multiply_scalar(dqi, ERIS_DQI_SKY));
1817 BRK_IF_ERROR(cpl_image_add(
1818 sof->exposureTable[objIdx].dqiImage, dqi));
1819 if (productDepth >= PD_DEBUG) {
1821 filename = cpl_sprintf("%s_%3.3d",
1822 ERIS_IFU_PRO_JITTER_DBG_DARK_FN, objIdx));
1824 filename2 = cpl_sprintf("%s_%3.3d.fits",
1825 ERIS_IFU_PRO_JITTER_DBG_DARK_FN, objIdx));
1827 eris_ifu_save_hdrl_image_dbg(objImg, filename, 1, NULL));
1829 cpl_image_save(sof->exposureTable[objIdx].dqiImage,
1830 filename2, CPL_TYPE_INT, NULL, CPL_IO_EXTEND));
1831 }
1832 }
1833 }
1834 cpl_mask_delete(inputMask);
1835 }
1836 CATCH
1837 {
1838 }
1839
1840 eris_ifu_free_image(&dqi);
1841 eris_ifu_free_mask(&outputMask);
1842 eris_ifu_free_string(&filename);
1843 eris_ifu_free_string(&filename2);
1844 return objImg;
1845}
1846
1881 hdrl_image *inputImage,
1882 int sofIdx,
1883 struct sofStruct *sof,
1884 struct paramStruct params,
1885 bool doVelocityCorrection,
1886 cpl_polynomial *ohLambdaCorrection,
1887 productDepthType productDepth)
1888{
1889 hdrl_imagelist *cube = NULL;
1890 cpl_imagelist *dataCube = NULL;
1891 cpl_imagelist *errCube = NULL;
1892 hdrl_image *image1 = NULL;
1893 hdrl_image *image2 = NULL;
1894 hdrl_image *bpmImg1 = NULL;
1895 cpl_image *bpmImg2 = NULL;
1896 hdrl_image *badPixelMaskImg = NULL;
1897 cpl_image *badPixelMaskImg1 = NULL;
1898 cpl_image *badPixelMaskImg2 = NULL;
1899
1900 hdrl_image *waveImg = NULL;
1901 cpl_image *waveDataImg = NULL;
1902 cpl_image *waveErrImg = NULL;
1903 cpl_image *waveMap = NULL;
1904 struct exposureEntry *objEntry;
1905 char *filename;
1906 char *filename2;
1907 double velocityCorr;
1908 cpl_size lsize;
1909 double *pWaveMap;
1910 double minLambda = 0.;
1911 double maxLambda = 0.;
1912 bool buildCubeForOHbasedLambdaCorrection = false;
1913
1914 cpl_ensure(inputImage != NULL,CPL_ERROR_NULL_INPUT, NULL);
1915 cpl_ensure(sof != NULL,CPL_ERROR_NULL_INPUT, NULL);
1916 //cpl_ensure(ohLambdaCorrection != NULL,CPL_ERROR_NULL_INPUT, NULL);
1917
1918 TRY
1919 {
1920 if (doVelocityCorrection == false && ohLambdaCorrection == NULL) {
1921 buildCubeForOHbasedLambdaCorrection = true;
1922 }
1923
1924 objEntry = &sof->exposureTable[sofIdx];
1925 BRK_IF_NULL(image1 = hdrl_image_duplicate(inputImage));
1926
1927 //divide by flat image (if available)
1928 if (sof->masterFlat != NULL) {
1929 //BRK_IF_ERROR(
1930 hdrl_image_div_image(image1, sof->masterFlat);
1931 if (productDepth >= PD_DEBUG) {
1932 if (buildCubeForOHbasedLambdaCorrection) {
1934 filename = cpl_sprintf("%sB_%3.3d",
1935 ERIS_IFU_PRO_JITTER_DBG_FLAT_FN, sofIdx));
1936 } else {
1938 filename = cpl_sprintf("%s_%3.3d",
1939 ERIS_IFU_PRO_JITTER_DBG_FLAT_FN, sofIdx));
1940 }
1941 eris_ifu_save_hdrl_image_dbg(image1, filename, 1, NULL);
1942 eris_ifu_free_string(&filename);
1943 }
1944 }
1945
1946 //create a bad pixel mask image
1948 badPixelMaskImg = hdrl_image_new(
1949 cpl_mask_get_size_x(objEntry->badPixelMask),
1950 cpl_mask_get_size_y(objEntry->badPixelMask)));
1952 badPixelMaskImg1 = cpl_image_new_from_mask(objEntry->badPixelMask));
1954 badPixelMaskImg2 = cpl_image_cast(
1955 badPixelMaskImg1, CPL_TYPE_DOUBLE));
1957 hdrl_image_insert(badPixelMaskImg,
1958 badPixelMaskImg2, NULL, 1, 1));
1959 eris_ifu_free_image(&badPixelMaskImg1);
1960 eris_ifu_free_image(&badPixelMaskImg2);
1961
1962 cpl_msg_info(__func__, "No. bad pixels: %d", (int)cpl_image_count_rejected(hdrl_image_get_image(image1)));
1963
1964 // Correct the flatfielded image1 according to the badPixelMaskImg
1965
1966 int bpc_iter = params.bpc_iter;
1967 for (int i = 0; i < bpc_iter; i++){
1968 eris_ifu_bpm_correction(image1, badPixelMaskImg);
1969
1970 if (productDepth >= PD_DEBUG) {
1971 if (buildCubeForOHbasedLambdaCorrection) {
1973 filename = cpl_sprintf("%sB_%3.3d_%d",
1974 ERIS_IFU_PRO_JITTER_DBG_FLAT_FN"-corr", sofIdx, i));
1975 } else {
1977 filename = cpl_sprintf("%s_%3.3d_%d",
1978 ERIS_IFU_PRO_JITTER_DBG_FLAT_FN"-corr", sofIdx, i));
1979 }
1980 eris_ifu_save_hdrl_image_dbg(image1, filename, 1, NULL);
1981 eris_ifu_free_string(&filename);
1982 }
1983 }
1984
1985
1986 // apply derotator correction
1987 double derot_corr;
1988 if (params.derot_corr!=params.derot_corr)
1989 derot_corr = objEntry->derot_corr;
1990 else
1991 derot_corr = params.derot_corr;
1992 cpl_msg_info(cpl_func, "First column shifted (derot_corr): %.2f", derot_corr);
1993
1994 for (int i = 0; i < SLITLET_CNT; i++) {
1995 if (sof->distortion[i] != NULL) {
1997 cpl_polynomial_shift_1d(sof->distortion[i], 0, derot_corr));
1998 }
1999 }
2000
2001 //correct for distortion
2002 if (sof->distortion != NULL) {
2004 image2 = eris_ifu_dist_warp_image(image1,
2005 sof->distortion, sof->borders));
2007 bpmImg1 = eris_ifu_dist_warp_bpm(badPixelMaskImg,
2008 sof->distortion, sof->borders, productDepth));
2009 } else { //AGUDO3: we will never get here, since eris_ifu_jitter_processSof() will exit when distortion==NULL
2011 image2 = eris_ifu_warp_polynomial_image(image1,
2012 sof->poly_u, sof->poly_v));
2014 bpmImg1 = eris_ifu_warp_polynomial_image(badPixelMaskImg,
2015 sof->poly_u, sof->poly_v));
2016 }
2017
2018 // shift distortion back for next iteration
2019 for (int i = 0; i < SLITLET_CNT; i++) {
2020 if (sof->distortion[i] != NULL) {
2022 cpl_polynomial_shift_1d(sof->distortion[i], 0, -1*derot_corr));
2023 }
2024 }
2025
2027
2028 if (productDepth >= PD_DEBUG) {
2029 if (buildCubeForOHbasedLambdaCorrection) {
2031 filename = cpl_sprintf("%sB_%3.3d",
2032 ERIS_IFU_PRO_JITTER_DBG_WRAP_FN, sofIdx));
2033 } else {
2035 filename = cpl_sprintf("%s_%3.3d",
2036 ERIS_IFU_PRO_JITTER_DBG_WRAP_FN, sofIdx));
2037 }
2038 eris_ifu_save_hdrl_image_dbg(image2, filename, 1, NULL);
2039 if (bpmImg1 != NULL) {
2041 filename2 = cpl_sprintf("%s.fits", filename));
2043 cpl_image_save(hdrl_image_get_image(bpmImg1), filename2,
2044 CPL_TYPE_FLOAT, NULL, CPL_IO_EXTEND));
2045 eris_ifu_free_string(&filename2);
2046 }
2047 eris_ifu_free_string(&filename);
2048 }
2049
2050 waveMap = cpl_image_duplicate(sof->waveMap);
2051 lsize = cpl_image_get_size_x(waveMap) * cpl_image_get_size_y(waveMap);
2052 BRK_IF_NULL(pWaveMap = cpl_image_get_data_double(waveMap));
2053 maxLambda = cpl_image_get_max(waveMap);
2054 minLambda = cpl_image_get_min(waveMap);
2055
2056 // velocity shift
2057 if (doVelocityCorrection) {
2058 velocityCorr = 1. + params.velocityOffset * 1000. / CPL_PHYS_C;
2059 for (int ix = 0; ix < lsize; ix++) {
2060 pWaveMap[ix] *= velocityCorr;
2061 }
2062
2063 }
2064 // OH line lambda correction
2065 if (ohLambdaCorrection != NULL) {
2066 for (int ix = 0; ix < lsize; ix++) {
2067 pWaveMap[ix] -= cpl_polynomial_eval_1d(
2068 ohLambdaCorrection, pWaveMap[ix], NULL);
2069 }
2070 }
2071
2072 //wavelength resampling
2073 /* to prevent memory leaks delete header before duplication */
2074 cpl_propertylist_delete(objEntry->cubeHdr);
2075 objEntry->cubeHdr = cpl_propertylist_duplicate(objEntry->hdr);
2078 hdrl_image_get_image(image2),
2079 waveMap, sof->band, minLambda, maxLambda,
2080 objEntry->cubeHdr, 3));
2083 hdrl_image_get_error(image2),
2084 waveMap, sof->band, minLambda, maxLambda,
2085 objEntry->cubeHdr, 3));
2086
2089 hdrl_image_get_image(bpmImg1),
2090 waveMap, sof->band, minLambda, maxLambda,
2091 objEntry->cubeHdr, 3));
2092
2093 cpl_binary *pImgMask = cpl_mask_get_data(cpl_image_get_bpm(waveDataImg));
2094 float *pDqiData = cpl_image_get_data_float(bpmImg2);
2095 cpl_size size = cpl_image_get_size_x(waveDataImg)
2096 * cpl_image_get_size_y(waveDataImg);
2097 for (cpl_size px = 0; px < size; px++) {
2098 if (pDqiData[px] > params.bpmThreshold) {
2099 pImgMask[px] = BAD_PIX;
2100 }
2101 }
2102 waveImg = hdrl_image_create(waveDataImg,waveErrImg);
2104
2105 if (productDepth >= PD_DEBUG) {
2106 cpl_propertylist *pl2save = cpl_propertylist_duplicate(objEntry->hdr);
2107 // call eris_ifu_wave_resampled_arc_image again to get property list
2108 // entries for image (instead of cube)
2109 cpl_image *image2save = eris_ifu_wave_resampled_arc_image(
2110 hdrl_image_get_image(image2),
2111 waveMap, sof->band, minLambda, maxLambda, pl2save, 2);
2112 if (buildCubeForOHbasedLambdaCorrection) {
2114 filename = cpl_sprintf("%sB_%3.3d",
2115 ERIS_IFU_PRO_JITTER_DBG_WAVE_FN, sofIdx));
2116 } else {
2118 filename = cpl_sprintf("%s_%3.3d",
2119 ERIS_IFU_PRO_JITTER_DBG_WAVE_FN, sofIdx));
2120 }
2121 cpl_propertylist_erase(pl2save,"RADECSYS");
2122 eris_ifu_save_hdrl_image_dbg(waveImg, filename, 1, pl2save);
2123 eris_ifu_free_image(&image2save);
2124
2126 hdrl_image_get_image(bpmImg1),
2127 waveMap, sof->band, minLambda, maxLambda, pl2save, 2);
2129 filename2 = cpl_sprintf("%s.fits", filename));
2131 cpl_image_save(image2save, filename2,
2132 CPL_TYPE_FLOAT, pl2save, CPL_IO_EXTEND));
2133 eris_ifu_free_string(&filename);
2134 eris_ifu_free_string(&filename2);
2135 eris_ifu_free_image(&image2save);
2138 }
2139
2142 waveDataImg,
2143 params.slitletDetectionMode,
2144 params.fineTuneMode,
2145 params.firstCol,
2146 sof->distances,
2147 sof->positions));
2148 cpl_image_reject_from_mask(waveErrImg, cpl_image_get_bpm_const(waveDataImg));
2151 waveErrImg,
2152 params.slitletDetectionMode,
2153 params.fineTuneMode,
2154 params.firstCol,
2155 sof->distances,
2156 sof->positions));
2158 cube = hdrl_imagelist_create(dataCube, errCube);
2159 cpl_imagelist_delete(dataCube);
2160 cpl_imagelist_delete(errCube);
2161 cpl_propertylist_update_int(objEntry->cubeHdr,NAXIS1,64);
2162 cpl_propertylist_update_int(objEntry->cubeHdr,NAXIS2,64);
2163 cpl_propertylist_update_int(objEntry->cubeHdr,NAXIS3,
2165
2166 if(objEntry->cubeBpm != NULL) {
2167 cpl_imagelist_delete(objEntry->cubeBpm);
2168 }
2169 // AMO: commented to fix PIPE-11106 TODO: Why a multiplication by 2??? That was creating a NAN in collapsed cube
2170 cpl_image_multiply_scalar(bpmImg2, 2.0);
2171
2173 objEntry->cubeBpm = eris_ifu_jitter_reconstruct_cube(
2174 bpmImg2,
2175 params.slitletDetectionMode,
2176 params.fineTuneMode,
2177 params.firstCol,
2178 sof->distances,
2179 sof->positions));
2180
2181 }
2182 CATCH
2183 {
2184 }
2185 /* TODO: AMo does not understand why objEntry is created and cannot be
2186 * erased. In particular objEntry->cubeBpm is an object created but not
2187 * erased
2188 */
2189 //eris_free_exposureEntry(objEntry);
2190 eris_ifu_free_hdrl_image(&waveImg);
2191 eris_ifu_free_hdrl_image(&image1);
2192 eris_ifu_free_hdrl_image(&image2);
2193 eris_ifu_free_hdrl_image(&badPixelMaskImg);
2194 eris_ifu_free_image(&badPixelMaskImg1);
2195 eris_ifu_free_image(&badPixelMaskImg2);
2196 eris_ifu_free_image(&waveDataImg);
2197 eris_ifu_free_image(&waveErrImg);
2198 eris_ifu_free_image(&waveMap);
2199 eris_ifu_free_hdrl_image(&bpmImg1);
2200 eris_ifu_free_image(&bpmImg2);
2201 eris_check_error_code("eris_ifu_jitter_build_cube");
2202 return cube;
2203}
2204/*----------------------------------------------------------------------------*/
2219/*----------------------------------------------------------------------------*/
2220
2221cpl_error_code
2223 cpl_size* min, cpl_size* max)
2224{
2225 cpl_size sx = cpl_image_get_size_x(image);
2226 cpl_size sy = cpl_image_get_size_y(image);
2227 float* pdata = cpl_image_get_data(image);
2228 cpl_size rows2check = 200;
2229 cpl_size nan_counter = 0;
2230 double nan_thresh = 0.5;
2231 *min = 0;
2232 *max = sy;
2233 for(cpl_size j = 0; j < rows2check; j++) {
2234 nan_counter = 0;
2235 for(cpl_size i = 0; i < sx; i++) {
2236 if(isnan(pdata[i + j * sx])) {
2237 nan_counter++;
2238 }
2239 }
2240
2241 if(nan_counter > nan_thresh * sx) {
2242 *min = j;
2243 }
2244 }
2245
2246 for(cpl_size j = sy-1; j >= sy - rows2check; j--) {
2247 nan_counter = 0;
2248 for(cpl_size i = 0; i < sx; i++) {
2249 if(isnan(pdata[i + j * sx])) {
2250 nan_counter++;
2251 }
2252 }
2253 if(nan_counter > nan_thresh * sx) {
2254 *max = j;
2255 }
2256 }
2257 cpl_msg_info(cpl_func,"min: %lld max: %lld", *min, *max);
2258
2259 return cpl_error_get_code();
2260}
2261
2262
2297 cpl_image *resampledDetImage,
2298 slitletDetectionModes mode,
2299 int fineTuneMode,
2300 double firstCol,
2301 cpl_vector *distancesV,
2302 cpl_bivector *positionsVV)
2303{
2304
2305 cpl_ensure(resampledDetImage, CPL_ERROR_NULL_INPUT, NULL);
2306 cpl_ensure((mode >= UNSET) && (mode <= GRID), CPL_ERROR_ILLEGAL_INPUT, NULL);
2307 cpl_ensure(fineTuneMode >= -5, CPL_ERROR_ILLEGAL_INPUT, NULL);
2308 cpl_ensure(firstCol >= 0 && firstCol <= ERIS_IFU_DETECTOR_SIZE_X, CPL_ERROR_ILLEGAL_INPUT, NULL);
2309 //cpl_ensure(distancesV, CPL_ERROR_NULL_INPUT, NULL);
2310 //cpl_ensure(positionsVV, CPL_ERROR_NULL_INPUT, NULL);
2311
2312 cpl_imagelist *cube = NULL;
2313 cpl_image *slide = NULL;
2314 cpl_size inx;
2315 cpl_size onx;
2316 cpl_size ony;
2317 cpl_size onz;
2318 int beginCol[SLITLET_CNT] = {0};
2319 double start[SLITLET_CNT] = {0.};
2320 // variables needed for mode DISTANCES
2321 double di;
2322 double *distances = NULL;
2323 // variables needed for mode EDGES
2324 double center;
2325 double *left_edges = NULL;
2326 double *right_edges = NULL;
2327 float *pi = NULL;
2328 float *po = NULL;
2329 cpl_binary *mi = NULL;
2330 cpl_binary *mo = NULL;
2331 double *pt1 = NULL;
2332 double *pt2 = NULL;
2333 double *xi = NULL;
2334 double *xt = NULL;
2335 int icol;
2336 float tmp;
2337
2338 TRY
2339 {
2340 inx = cpl_image_get_size_x(resampledDetImage);
2341 onx = inx / SLITLET_CNT;
2342 ony = SLITLET_CNT * 2;
2343 onz = cpl_image_get_size_y(resampledDetImage);
2344 cube = cpl_imagelist_new();
2345 /*
2346 cpl_size iz_min = 0;
2347 cpl_size iz_max = onz;
2348 eris_image_get_valid_data_range(resampledDetImage, &iz_min, &iz_max);
2349 */
2350 if (distancesV == NULL) { // new ERIS way of simple re-sampling
2351 pi = cpl_image_get_data_float(resampledDetImage);
2352 mi = cpl_mask_get_data(cpl_image_get_bpm(resampledDetImage));
2353
2354 for (int iz=0; iz<onz; iz++) {
2356 slide = cpl_image_new(onx, ony, CPL_TYPE_FLOAT));
2357 po = cpl_image_get_data_float(slide);
2358 mo = cpl_mask_get_data(cpl_image_get_bpm(slide));
2359
2360 // flip x-axis to correct east direction (shall go to the left)
2361 for (int slitlet=0; slitlet<SLITLET_CNT; slitlet++) {
2362 for (int col=0; col < onx; col++) {
2363 tmp = (float) pi[onx-1-col + slitlet*onx + iz*inx];
2364 /* this step expands of a factor 2 along Y the
2365 * rectangular spaxel to a make it appear as square
2366 * as it is on the Sky. To conserve flux we need to
2367 * divide by 2 (or multiply by 0.5)
2368 */
2369 tmp *= 0.5;
2370 po[col + onx*(rowIndices[slitlet]*2)] = tmp;
2371 po[col + onx*(rowIndices[slitlet]*2+1)] = tmp;
2372 if (mi[onx-1-col + slitlet*onx + iz*inx] == BAD_PIX) {
2373 mo[col + onx*(rowIndices[slitlet]*2)] = BAD_PIX;
2374 mo[col + onx*(rowIndices[slitlet]*2+1)] = BAD_PIX;
2375 }
2376
2377 }
2378 }
2379
2381 cpl_imagelist_set(cube, slide, iz));
2382 }
2383 } else { // old SINFONI way
2384 if (mode == DISTANCES) {
2385 if (distancesV == NULL) {
2386 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
2387 "missing data about slitlet distances");
2388 }
2389 if (cpl_vector_get_size(distancesV) != SLITLET_CNT-1) {
2390 BRK_WITH_ERROR_MSG(CPL_ERROR_INCOMPATIBLE_INPUT,
2391 "distances vector has wrong number of elements "
2392 "(got %lld but exepected %d)",
2393 cpl_vector_get_size(distancesV), SLITLET_CNT-1);
2394 }
2395 distances = cpl_vector_get_data(distancesV);
2396 } else if (mode == EDGES) {
2397 if (positionsVV == NULL) {
2398 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
2399 "missing data about slitlet positions");
2400 }
2401 if (cpl_bivector_get_size(positionsVV) != SLITLET_CNT) {
2402 BRK_WITH_ERROR_MSG(CPL_ERROR_INCOMPATIBLE_INPUT,
2403 "slit pos bivector has wrong number of elements "
2404 "(got %lld but exepected %d)",
2405 cpl_bivector_get_size(positionsVV), SLITLET_CNT);
2406 }
2407 left_edges = cpl_vector_get_data(
2408 cpl_bivector_get_x(positionsVV));
2409 right_edges = cpl_vector_get_data(
2410 cpl_bivector_get_y(positionsVV));
2411 }
2412
2413 di = 0;
2414 for (int slitlet=0; slitlet<SLITLET_CNT; slitlet++) {
2415 if (mode == DISTANCES) {
2416 if (slitlet == 0) {
2417 start[slitlet] = firstCol;
2418 } else {
2419 di += distances[slitlet-1];
2420 start[slitlet] = firstCol + di;
2421 }
2422 } else if (mode == EDGES) {
2423 center = (left_edges[slitlet] + right_edges[slitlet]) / 2.;
2424 start[slitlet] = center - (double) (onx -1 )/2.;
2425 }else if (mode == GRID) {
2426 start[slitlet] = (double) (onx * slitlet);
2427 }
2428 beginCol[slitlet] =
2429 start[slitlet] > 0 ?
2430 (int)(start[slitlet]+.5) : (int)(start[slitlet]-.5);
2431 // double shift[SLITLET_CNT];
2432 // shift[rowIndices[slitlet]] = start[slitlet] -
2433 // (double) beginCol[slitlet];
2434 }
2435
2437 xi = cpl_calloc(onx, sizeof(double)));
2439 xt = cpl_calloc(onx, sizeof(double)));
2441 pt1 = cpl_calloc(onx, sizeof(double)));
2443 pt2 = cpl_calloc(onx, sizeof(double)));
2444 pi = cpl_image_get_data_float(resampledDetImage);
2445
2446 for (int iz=0; iz<onz; iz++) {
2448 slide = cpl_image_new(onx, ony, CPL_TYPE_FLOAT));
2449 po = cpl_image_get_data_float(slide);
2450
2451 for (int slitlet=0; slitlet<SLITLET_CNT; slitlet++) {
2452 for (int col=0; col < onx; col++) {
2453 xi[col] = (double) (beginCol[slitlet] + col);
2454 xt[col] = start[slitlet] + col;
2455 icol = beginCol[slitlet] + col;
2456 if (icol < 0) {
2457 pt1[col] = pi[0 + iz * inx];
2458 } else if (icol >= inx) {
2459 pt1[col] = pi[(inx - 1) + iz * inx];
2460 } else {
2461 pt1[col] = pi[icol + iz * inx];
2462 }
2463 }
2464 if (fineTuneMode == 0) {
2465 for (int col=0; col < onx; col++) {
2466 pt2[col] = pt1[col];
2467 }
2468 } else {
2470 eris_ifu_1d_interpolation(xi, pt1, (int) onx,
2471 xt, pt2, (int) onx, fineTuneMode));
2472 }
2473 for (int col=0; col < onx; col++) {
2474 /* this step expands of a factor 2 along Y the
2475 * rectangular spaxel to a make it appear as square
2476 * as it is on the Sky. To conserve flux we need to
2477 * divide by 2 (or multiply by 0.5)
2478 * TODO: why cast to float? It should be all in double
2479 * precision
2480 */
2481 tmp = (float) (pt2[col] * 0.5);
2482 po[col + onx*(rowIndices[slitlet]*2)] = tmp;
2483 po[col + onx*(rowIndices[slitlet]*2+1)] = tmp;
2484 }
2485 }
2487 cpl_imagelist_set(cube, slide, iz));
2488 }
2489 }
2491 }
2492 CATCH
2493 {
2495 }
2496 return cube;
2497}
2498
2513cpl_error_code
2514eris_ifu_jitter_get_procatg_and_filename(cubeType type, char **proCatg,
2515 char **filenamePrefix)
2516{
2517 cpl_ensure_code(proCatg, CPL_ERROR_NULL_INPUT);
2518 cpl_ensure_code(filenamePrefix, CPL_ERROR_NULL_INPUT);
2519
2520 switch (type) {
2521 case OBJECT_CUBE_COADD:
2522 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_OBJ_CUBE_COADD);
2523 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_OBJ_CUBE_COADD_FN);
2524 break;
2525 case TWEAKED_CUBE_COADD:
2526 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_TWK_CUBE_COADD);
2527 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_TWK_CUBE_COADD_FN);
2528 break;
2529 case DAR_CUBE_COADD:
2530 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE_COADD);
2531 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE_COADD_FN);
2532 break;
2533 case DAR_STD_CUBE_COADD:
2534 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_COADD);
2535 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_COADD_FN);
2536 break;
2537 case STD_CUBE_COADD:
2538 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_COADD);
2539 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_COADD_FN);
2540 break;
2541 case STD_FLUX_CUBE_COADD:
2542 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD);
2543 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD_FN);
2544 break;
2545 case STD_FLUX_CUBE_COADD_NOFLAT:
2546 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD_NOFLAT);
2547 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD_NOFLAT_FN);
2548 break;
2549 case STD_CUBE_COADD_NOFLAT:
2550 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_COADD_NOFLAT);
2551 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_COADD_NOFLAT_FN);
2552 break;
2553 case PSF_CUBE_COADD:
2554 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD);
2555 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD_FN);
2556 break;
2557 case OBJECT_CUBE:
2558 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_OBJ_CUBE);
2559 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_OBJ_CUBE_FN);
2560 break;
2561 case STD_CUBE:
2562 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE);
2563 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_FN);
2564 break;
2565 case STD_FLUX_CUBE:
2566 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE);
2567 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_FN);
2568 break;
2569 case STD_CUBE_NOFLAT:
2570 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_NOFLAT);
2571 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_NOFLAT_FN);
2572 break;
2573 case PSF_CUBE:
2574 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE);
2575 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE_FN);
2576 break;
2577 case SKY_OBJECT_CUBE:
2578 case SKY_STD_CUBE:
2579 case SKY_STD_FLUX_CUBE:
2580 case SKY_PSF_CUBE:
2581 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_SKY_CUBE);
2582 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_SKY_CUBE_FN);
2583 break;
2584 case TWEAKED_CUBE:
2585 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_TWK_CUBE);
2586 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_TWK_CUBE_FN);
2587 break;
2588 case TWEAKED_STD_CUBE:
2589 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE);
2590 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_FN);
2591 break;
2592 case DAR_CUBE:
2593 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE);
2594 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE_FN);
2595 break;
2596 //PIPPO
2597 case DAR_PSF_CUBE_COADD:
2598 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD);
2599 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD_FN);
2600 break;
2601 case DAR_STD_CUBE:
2602 //*proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE);
2603 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE);
2604 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_FN);
2605 break;
2606 case DAR_STD_FLUX_CUBE:
2607 //*proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE);
2608 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE);
2609 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_FN);
2610 break;
2611 case DAR_PSF_CUBE:
2612 //*proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE);
2613 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE);
2614 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE_FN);
2615 break;
2616 case BPM_CUBE:
2617 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_BPM_CUBE);
2618 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_BPM_CUBE_FN);
2619 break;
2620 case JITTER_CUBE:
2621 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_CUBE);
2622 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_CUBE_FN);
2623 break;
2624 default:
2625 cpl_msg_warning(cpl_func,"default case %d",type);
2626 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_CUBE);
2627 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_CUBE_FN);
2628 break;
2629 }
2630 cpl_msg_debug(cpl_func,"proCatg: %s",*proCatg);
2631 cpl_msg_debug(cpl_func,"filenamePrefix: %s",*filenamePrefix);
2632 return cpl_error_get_code();
2633}
2634
2635
2655 const cpl_imagelist *data_in,
2656 const cpl_imagelist *noise_in,
2657 cpl_image *mask,
2658 cpl_vector **spec_data_out,
2659 cpl_vector **spec_noise_out)
2660{
2661 cpl_error_code ret_error = CPL_ERROR_NONE;
2662
2663 const cpl_image *tmp_img = NULL;
2664 const cpl_mask *bpm = NULL;
2665 const cpl_binary *bpm_data = NULL;
2666 cpl_mask *empty_mask = NULL;
2667
2668 int nx = 0,
2669 ny = 0,
2670 nz = 0,
2671 i = 0,
2672 j = 0,
2673 g = 0;
2674
2675 const float *pmask = NULL;
2676 const double *ptmp_img = NULL;
2677
2678 double sum = 0.0,
2679 weights = 0.0,
2680 *pvec = NULL,
2681 *pvecn = NULL;
2682
2683 TRY
2684 {
2685 ASSURE((data_in != NULL) &&
2686 (spec_data_out != NULL),
2687 CPL_ERROR_NULL_INPUT,
2688 "Not all input data is provided!");
2689
2691 tmp_img = cpl_imagelist_get_const(data_in, 0));
2692
2693 nx = cpl_image_get_size_x(tmp_img);
2694 ny = cpl_image_get_size_y(tmp_img);
2695 nz = cpl_imagelist_get_size(data_in);
2696
2697 if (mask != NULL) {
2698 ASSURE((nx == cpl_image_get_size_x(mask)) &&
2699 (ny == cpl_image_get_size_y(mask)),
2700 CPL_ERROR_ILLEGAL_INPUT,
2701 "Data and mask don't have same dimensions!");
2702
2704 pmask = cpl_image_get_data_float_const(mask));
2705 }
2706
2707 if (noise_in != NULL) {
2708 ASSURE(spec_noise_out != NULL,
2709 CPL_ERROR_NULL_INPUT,
2710 "Not all input data is provided!");
2711
2713 tmp_img = cpl_imagelist_get_const(noise_in, 0));
2714
2715 ASSURE((nx == cpl_image_get_size_x(tmp_img)) &&
2716 (ny == cpl_image_get_size_y(tmp_img)) &&
2717 (nz == cpl_imagelist_get_size(noise_in)),
2718 CPL_ERROR_ILLEGAL_INPUT,
2719 "Data and noise don't have same dimensions!");
2720 }
2721
2723 *spec_data_out = cpl_vector_new(nz));
2724
2726 pvec = cpl_vector_get_data(*spec_data_out));
2727
2728 if (noise_in != NULL) {
2730 *spec_noise_out = cpl_vector_new(nz));
2731
2733 pvecn = cpl_vector_get_data(*spec_noise_out));
2734 }
2735
2737 empty_mask = cpl_mask_new(nx,ny));
2738
2739 // loop over all spatial slices
2740 for (g = 0; g < nz; g++) {
2742 tmp_img = cpl_imagelist_get_const(data_in, g));
2744 ptmp_img = cpl_image_get_data_double_const(tmp_img));
2745
2746 bpm = cpl_image_get_bpm_const(tmp_img);
2747 if (bpm == NULL) {
2748 bpm = empty_mask;
2749 }
2751 bpm_data = cpl_mask_get_data_const(bpm));
2752
2753 // extract spectrum for data
2754 sum = 0.0;
2755 weights = 0.0;
2756 for (j = 0; j < ny; j++) {
2757 for (i = 0; i < nx; i++) {
2758 // sum weighted pixels in spatial plane
2759 if ((bpm_data[i+j*nx] == GOOD_PIX) && isfinite(ptmp_img[i+j*nx])) {
2760 if (mask != NULL) {
2761 sum += ptmp_img[i+j*nx] * pmask[i+j*nx];
2762 weights += pmask[i+j*nx];
2763 } else {
2764 sum += ptmp_img[i+j*nx];
2765 weights += 1.;
2766 }
2767 }
2768 }
2769 }
2770 pvec[g] = sum/weights;
2771
2772
2773 // extract spectrum for noise
2774 if (noise_in != NULL) {
2776 tmp_img = cpl_imagelist_get_const(noise_in, g));
2778 ptmp_img = cpl_image_get_data_double_const(tmp_img));
2779
2780 sum = 0.0;
2781 weights = 0.0;
2782 for (j = 0; j < ny; j++) {
2783 for (i = 0; i < nx; i++) {
2784 // combine weighted pixels in spatial plane
2785 if ((bpm_data[i+j*nx] == GOOD_PIX) && isfinite(ptmp_img[i+j*nx])) {
2786 if (mask != NULL) {
2787 sum += pow(ptmp_img[i+j*nx], 2) * pow(pmask[i+j*nx], 2);
2788 weights += pow(pmask[i+j*nx], 2);
2789 } else {
2790 sum += pow(ptmp_img[i+j*nx], 2);
2791 weights += 1.;
2792 }
2793 }
2794 }
2795 }
2796 pvecn[g] = sqrt(sum/weights);
2797 }
2798 }
2799 }
2800 CATCH
2801 {
2802 CATCH_MSG();
2803 ret_error = cpl_error_get_code();
2804 }
2805
2806 if (empty_mask != NULL) {cpl_mask_delete(empty_mask);}
2807
2808 return ret_error;
2809}
2831static
2832cpl_error_code eris_ifu_jitter_spec_save_products(
2833 cpl_frameset* frames,
2834 const cpl_parameterlist * parlist,
2835 struct esSofStruct sof,
2836 cpl_bivector *spectrum,
2837 cpl_vector *error,
2838 cpl_vector *totalFlux,
2839 productDepthType productDepth,
2840 cpl_boolean is_sdp_format,
2841 const char* recipe_name)
2842{
2843 cpl_table *pro_tab = NULL;
2844 cpl_propertylist *pl;
2845 cpl_vector *lambda = NULL;
2846 cpl_vector *data = NULL;
2847 cpl_array *waveArray = NULL;
2848 cpl_array *fluxArray = NULL;
2849 cpl_array *errArray = NULL;
2850 cpl_array *totalFluxArray = NULL;
2851 double firstLambda;
2852 double deltaLambda;
2853 cpl_size spectrumSize;
2854
2855 TRY
2856 {
2857 spectrumSize = cpl_bivector_get_size(spectrum);
2858 BRK_IF_NULL(lambda = cpl_bivector_get_x(spectrum));
2859 BRK_IF_NULL(data = cpl_bivector_get_y(spectrum));
2860 firstLambda = cpl_vector_get(lambda,0);
2861 deltaLambda = cpl_vector_get(lambda,1) - firstLambda;
2862
2863 if (productDepth >= PD_AUXILLIARY) {
2864 pl = cpl_propertylist_duplicate(sof.header);
2865 cpl_propertylist_update_string(pl, CPL_DFS_PRO_CATG, "SPECTRUM");
2866 cpl_propertylist_update_string(pl, "CTYPE1", "WAVE");
2867 cpl_propertylist_update_double(pl, "CRPIX1", 1.);
2868 cpl_propertylist_update_double(pl, "CRVAL1", firstLambda);
2869 cpl_propertylist_update_double(pl, "CDELT1", deltaLambda);
2870 cpl_propertylist_erase(pl, "CTYPE2");
2871 cpl_propertylist_erase(pl, "CRPIX2");
2872 cpl_propertylist_erase(pl, "CRVAL2");
2873 cpl_propertylist_erase(pl, "CDELT2");
2874 cpl_propertylist_erase(pl, "CTYPE3");
2875 cpl_propertylist_erase(pl, "CRPIX3");
2876 cpl_propertylist_erase(pl, "CRVAL3");
2877 cpl_propertylist_erase(pl, "CDELT3");
2878 cpl_propertylist_update_double(pl, "CD1_1", 0.);
2879 cpl_propertylist_update_double(pl, "CD1_2", deltaLambda);
2880 cpl_propertylist_erase(pl, "CD1_3");
2881 cpl_propertylist_erase(pl, "CD2_1");
2882 cpl_propertylist_erase(pl, "CD2_2");
2883 cpl_propertylist_erase(pl, "CD2_3");
2884 cpl_propertylist_erase(pl, "CD3_1");
2885 cpl_propertylist_erase(pl, "CD3_2");
2886 cpl_propertylist_erase(pl, "CD3_3");
2887
2890 cpl_vector_save(data, "spectrum_vector.fits",
2891 CPL_TYPE_DOUBLE, pl, CPL_IO_CREATE));
2892 cpl_propertylist_delete(pl);
2893 }
2894 pl = cpl_propertylist_duplicate(sof.header);
2895
2896 if(strstr(recipe_name,"no_flat") != NULL) {
2897 cpl_msg_info(cpl_func,"recipe_name: %s",recipe_name);
2898 cpl_propertylist_update_string(pl, CPL_DFS_PRO_CATG,
2899 ERIS_IFU_PRO_JITTER_SPECTRUM_NOFLAT);
2900 } else {
2901 cpl_msg_info(cpl_func,"recipe_name: %s",recipe_name);
2902 cpl_propertylist_update_string(pl, CPL_DFS_PRO_CATG,
2903 ERIS_IFU_PRO_JITTER_SPECTRUM);
2904 }
2905
2906
2907
2908 cpl_propertylist_update_string(pl, "ESO PRO REC1 ID","eris_ifu_jitter");
2909 if(is_sdp_format) {
2910 waveArray = cpl_array_wrap_double(cpl_vector_get_data(lambda),
2911 spectrumSize);
2912 fluxArray = cpl_array_wrap_double(cpl_vector_get_data(data),
2913 spectrumSize);
2914 errArray = cpl_array_wrap_double(cpl_vector_get_data(error),
2915 spectrumSize);
2916 if (totalFlux != NULL) {
2917 totalFluxArray = cpl_array_wrap_double(cpl_vector_get_data(totalFlux),
2918 spectrumSize);
2919 }
2920
2921
2922 pro_tab = cpl_table_new(1);
2923 cpl_table_new_column_array(pro_tab, "WAVE",
2924 CPL_TYPE_DOUBLE, spectrumSize);
2925 cpl_table_new_column_array(pro_tab, "FLUX",
2926 CPL_TYPE_DOUBLE, spectrumSize);
2927 cpl_table_new_column_array(pro_tab, "ERR",
2928 CPL_TYPE_DOUBLE, spectrumSize);
2929 cpl_table_new_column_array(pro_tab, "TOT_FLUX",
2930 CPL_TYPE_DOUBLE, spectrumSize);
2931 cpl_table_set_array(pro_tab, "WAVE", 0, waveArray);
2932 cpl_table_set_array(pro_tab, "FLUX", 0, fluxArray);
2933 cpl_table_set_array(pro_tab, "ERR", 0, errArray);
2934 if (totalFlux != NULL) {
2935 cpl_table_set_array(pro_tab, "TOT_FLUX", 0, totalFluxArray);
2936 }
2937 //cpl_table_save(pro_tab, pl, NULL, "spectrum.fits", CPL_IO_CREATE);
2938 } else {
2939 pro_tab = cpl_table_new(spectrumSize);
2940 cpl_table_wrap_double(pro_tab, cpl_vector_get_data(lambda), "WAVE");
2941 if (totalFlux != NULL) {
2942 cpl_table_wrap_double(pro_tab, cpl_vector_get_data(data), "FLUX");
2943 } else {
2944 cpl_table_wrap_double(pro_tab, cpl_vector_get_data(data), "TOT_FLUX");
2945 }
2946 cpl_table_wrap_double(pro_tab, cpl_vector_get_data(error), "ERR");
2947 if (totalFlux != NULL) {
2948 cpl_table_wrap_double(pro_tab, cpl_vector_get_data(totalFlux), "TOT_FLUX");
2949 }
2950 }
2951 char *filename = cpl_sprintf("%s_spectrum.fits", recipe_name);
2952 cpl_propertylist_append_string(pl, "PRODCATG", "SCIENCE.SPECTRUM");
2953 cpl_dfs_save_table(frames, NULL, parlist, frames, NULL,
2954 pro_tab, NULL, recipe_name, pl,
2955 NULL, PACKAGE "/" PACKAGE_VERSION, filename);
2956
2957 cpl_free(filename);
2958 cpl_propertylist_delete(pl);
2959 if(is_sdp_format) {
2960 cpl_array_unwrap(waveArray);
2961 cpl_array_unwrap(fluxArray);
2962 cpl_array_unwrap(errArray);
2963 if (totalFlux != NULL) {
2964 cpl_array_unwrap(totalFluxArray);
2965 }
2966 } else {
2967 cpl_table_unwrap(pro_tab,"WAVE");
2968 if (totalFlux != NULL) {
2969 cpl_table_unwrap(pro_tab,"FLUX");
2970 } else {
2971 cpl_table_unwrap(pro_tab,"TOT_FLUX");
2972 }
2973 cpl_table_unwrap(pro_tab,"ERR");
2974 if (totalFlux != NULL) {
2975 cpl_table_unwrap(pro_tab,"TOT_FLUX");
2976 }
2977 }
2978 cpl_table_delete(pro_tab);
2980
2981 } CATCH{
2982 }
2983 eris_check_error_code("eris_ifu_jitter_spec_save_products");
2984 return cpl_error_get_code();
2985}
2986
3004 const cpl_parameterlist * parlist,
3005 struct esParamStruct *params,
3006 const char* context)
3007{
3008 TRY
3009 {
3010 const char* methodString;
3011 char* param_name = NULL;
3012
3013 param_name = cpl_sprintf("%s.mask_method", context);
3014
3015 methodString = cpl_parameter_get_string(
3016 cpl_parameterlist_find_const(parlist, param_name));
3017 cpl_free(param_name);
3018
3019
3020 if (strncasecmp(methodString, "mask", strlen("mask")) == 0) {
3021 params->mask_method = MASK;
3022 } else if (strncasecmp(methodString, "position", strlen("position")) == 0) {
3023 params->mask_method = POSITION;
3024 } else if (strncasecmp(methodString, "max", strlen("max")) == 0) {
3025 params->mask_method = MAX;
3026 } else if (strncasecmp(methodString, "fit", strlen("fit")) == 0) {
3027 params->mask_method = FIT;
3028 } else if (strncasecmp(methodString, "optimal", strlen("optimal")) == 0) {
3029 params->mask_method = OPTIMAL;
3030 } else {
3031 cpl_msg_error(cpl_func, "The maks_method parameter must be one "
3032 "of the list: mask, position, max, fit");
3033 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
3034 "Error reading recipe parameter, unknown mask method %s",
3035 methodString);
3036
3037 }
3038
3039 const char* center;
3040 param_name = cpl_sprintf("%s.center", context);
3041 center = cpl_parameter_get_string(
3042 cpl_parameterlist_find_const(parlist, param_name));
3043 cpl_free(param_name);
3044
3045 int nFields;
3046 int end;
3047 nFields = sscanf(center, "%d,%d%n",
3048 &params->center_x, &params->center_y, &end);
3049 if (nFields != 2 || end != (int)strlen(center)) {
3050 cpl_msg_error(cpl_func, "The center parameter must be "
3051 "a list of two integers separated by a comma");
3052 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
3053 "Error reading recipe parameter, cannot properly read center spec %s",
3054 center);
3055 printf("Error reading center string\n");
3056 }
3057
3058 param_name = cpl_sprintf("%s.radius", context);
3059 params->radius = cpl_parameter_get_double(
3060 cpl_parameterlist_find_const(parlist, param_name));
3061 cpl_free(param_name);
3062
3063 param_name = cpl_sprintf("%s.product_depth", context);
3064 params->productDepth = cpl_parameter_get_int(
3065 cpl_parameterlist_find_const(parlist, param_name));
3066 cpl_free(param_name);
3067
3069 } CATCH
3070 {
3071 }
3072
3073 return cpl_error_get_code();
3074}
3075
3100cpl_error_code
3101eris_ifu_jitter_extract(cpl_frameset * frameset,
3102 const cpl_parameterlist *parlist,
3103 cubeType obj_type,
3104 const char* pcatg,
3105 struct stdParamStruct stdParams,
3106 const char* pipefile_prefix,
3107 const char* context)
3108{
3109 double startLambda = 0.,
3110 deltaLambda = 0.,
3111 refPixel = 0.;
3112 cpl_frame *frame_cube_coadd = NULL;
3113 cpl_image *mask = NULL;
3114 hdrl_image *collapsedCube = NULL;
3115 cpl_bivector *spectrum = NULL;
3116 cpl_vector *error = NULL;
3117 cpl_vector *totalFlux = NULL;
3118 cpl_vector *qual = NULL;
3119 cpl_propertylist *plist = NULL;
3120 char *fnamePrefix = NULL,
3121 *proCatg = NULL;
3122 const char *fname = NULL;
3123 struct esParamStruct esParams;
3124 struct esSofStruct esSof;
3125
3126 TRY {
3127 cpl_msg_info(cpl_func,"Extracting data source from %s", pcatg);
3128
3129 frame_cube_coadd = cpl_frameset_find(frameset, pcatg);
3130 fname = cpl_frame_get_filename(frame_cube_coadd);
3131
3132 /* WCS are in header of data extention, first one */
3133 plist = cpl_propertylist_load(fname, 1);
3134 refPixel = cpl_propertylist_get_double(plist, "CRPIX3");
3135 startLambda = cpl_propertylist_get_double(plist, "CRVAL3");
3136 if(cpl_propertylist_has(plist, "CDELT3")) {
3137 deltaLambda = cpl_propertylist_get_double(plist, "CDELT3");
3138 } else {
3139 deltaLambda = cpl_propertylist_get_double(plist, "CD3_3");
3140 }
3141
3142 startLambda = startLambda - (refPixel - 1.) * deltaLambda;
3143
3145 eris_ifu_extract_spec_fetch_params(parlist, &esParams, context));
3146
3147 //eris_ifu_jitter_get_cube_type_string(obj_type);
3148 cubeType coadd_obj_type = eris_ifu_jitter_get_coadd_obj_type(obj_type);
3151 eris_ifu_jitter_extract_spec_processSof(obj_type, frameset,
3152 esParams, &esSof));
3153
3154 eris_ifu_jitter_get_procatg_and_filename(obj_type, &proCatg, &fnamePrefix);
3155
3156 cpl_image *contribMap = NULL;
3157 collapsedCube = eris_ifu_extract_spec_collapse(esSof.cube, &contribMap);
3158 eris_ifu_free_image(&contribMap);
3159
3160 char* pro_catg = cpl_sprintf("%s_MEDIAN",proCatg);
3161 cpl_free(proCatg);
3162 cpl_free(fnamePrefix);
3163 cpl_propertylist_update_string(plist, CPL_DFS_PRO_CATG, pro_catg);
3164 char *filename = cpl_sprintf("%s_cube_median.fits", pipefile_prefix);
3165 /* compute QC */
3166 if( strstr(pro_catg, "STD") != NULL ||
3167 strstr(pro_catg, "PSF") != NULL ){
3168 cpl_propertylist* qcheader =
3169 eris_compute_psf_qc(collapsedCube, parlist, context);
3170
3171 cpl_propertylist_append(plist, qcheader);
3172 cpl_propertylist_delete(qcheader);
3173 }
3174
3175 cpl_image* mask_ima = cpl_image_new_from_mask(hdrl_image_get_mask(collapsedCube));
3176
3177 eris_ifu_save_deq_image(frameset, NULL, parlist,frameset, NULL,
3178 pipefile_prefix, plist, "RADECSYS", filename,
3179 hdrl_image_get_image(collapsedCube),
3180 hdrl_image_get_error(collapsedCube),
3181 rmse, mask_ima, flag16bit, UNIT_ADU);
3182 cpl_image_delete(mask_ima);
3183
3184 cpl_free(filename);
3185 cpl_free(pro_catg);
3186
3187// const cpl_parameter *par = cpl_parameterlist_find_const(parlist, "edge-trim");
3188// if (par != NULL) {
3189// edge_trim = cpl_parameter_get_int(par);
3190// }
3191// agudo: eventually take edge_trim in respect when creating mask?
3193 mask = eris_ifu_extract_spec_create_mask(esParams, esSof,
3194 collapsedCube,
3195 esParams.productDepth));
3196
3197 cpl_propertylist_update_string(plist, CPL_DFS_PRO_CATG,
3198 ERIS_IFU_PRO_JITTER_EXTRACTION_MASK);
3199 filename = cpl_sprintf("%s_extraction_mask.fits", pipefile_prefix);
3200 cpl_dfs_save_image(frameset, plist, parlist, frameset, NULL,
3201 mask, CPL_TYPE_FLOAT, pipefile_prefix,
3202 plist, "RADECSYS",
3203 PACKAGE "/" PACKAGE_VERSION,
3204 filename);
3205
3206 cpl_free(filename);
3207
3208 if (esParams.mask_method == OPTIMAL) {
3210 spectrum = eris_ifu_optimal_extraction(esSof.cube,
3211 esSof.qualImagelist,
3212 mask,
3213 startLambda, deltaLambda,
3214 esParams.productDepth,
3215 &error));
3216 } else {
3218 spectrum = eris_ifu_extract_spectrum(esSof.cube, mask,
3219 startLambda, deltaLambda,
3220 &error, &totalFlux, &qual));
3221 }
3222
3223 eris_ifu_jitter_spec_save_products(frameset, parlist, esSof, spectrum,
3224 error, totalFlux, stdParams.productDepth, CPL_TRUE,
3225 pipefile_prefix);
3226 } CATCH
3227 {
3228 CATCH_MSG();
3229 }
3230
3231 //The following free make crush
3232 if (esSof.mask != mask) {
3233 eris_ifu_free_image(&mask);
3234 }
3236 eris_ifu_extract_free_esSofStruct(&esSof);
3237 eris_ifu_free_hdrl_image(&collapsedCube);
3238 eris_ifu_free_bivector(&spectrum);
3239 eris_ifu_free_vector(&error);
3240 eris_ifu_free_vector(&totalFlux);
3241 eris_check_error_code("eris_ifu_jitter_extract");
3242 return cpl_error_get_code();
3243}
3262cpl_error_code
3264 cubeType obj_type,
3265 cpl_frameset* frames,
3266 struct esParamStruct params,
3267 struct esSofStruct *sof)
3268{
3269 cpl_frame *frame = NULL;
3270
3271 TRY
3272 {
3273
3274 if (frames == NULL) {
3275 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
3276 "missing frameset");
3277 }
3278
3279 if (cpl_frameset_is_empty(frames)) {
3280 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
3281 "SOF file is empty or missing");
3282 }
3284
3285
3286
3287 // get data cube
3288 char *proCatg = NULL;
3289 char *fnamePrefix = NULL;
3290 eris_ifu_jitter_get_procatg_and_filename(obj_type, &proCatg, &fnamePrefix);
3291 frame = cpl_frameset_find(frames, proCatg);
3292 cpl_free(fnamePrefix);
3293
3295 if (frame != NULL) {
3298 cpl_frame_get_filename(frame),
3299 &sof->header, &sof->qualImagelist, &sof->qualityType));
3300 sof->nx = hdrl_imagelist_get_size_x(sof->cube);
3301 sof->ny = hdrl_imagelist_get_size_y(sof->cube);
3302 sof->nz = hdrl_imagelist_get_size(sof->cube);
3303 } else {
3304 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
3305 "missing \"%s\" tag in the SOF, input data cube",
3306 proCatg);
3307
3308 }
3309 cpl_free(proCatg);
3310
3311 sof->mask = NULL;
3312 if (params.mask_method == MASK) {
3313 frame = cpl_frameset_find(frames, ERIS_IFU_UTIL_MASK);
3315 if (frame != NULL) {
3317 sof->mask = cpl_image_load(
3318 cpl_frame_get_filename(frame),
3319 CPL_TYPE_DOUBLE, 0, 0));
3320 } else {
3321 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
3322 "missing \"%s\" tag in the SOF, extraction mask",
3323 ERIS_IFU_UTIL_MASK);
3324 }
3325 }
3326 } CATCH
3327 {
3328 // CATCH_MSGS();
3329 }
3330 eris_check_error_code("eris_ifu_jitter_extract_spec_processSof");
3331 return cpl_error_get_code();
3332
3333}
3356 hdrl_imagelist *cube,
3357 cpl_propertylist *hdr,
3358// cpl_imagelist *cubeBpm,
3359 int method,
3360 double radius,
3361 int length)
3362{
3363 cpl_ensure_code(cube,CPL_ERROR_NULL_INPUT);
3364 cpl_ensure_code(hdr,CPL_ERROR_NULL_INPUT);
3365 //cpl_ensure_code(radius > 0,CPL_ERROR_ILLEGAL_INPUT);
3366 //cpl_ensure_code(length > 0,CPL_ERROR_ILLEGAL_INPUT);
3367
3368 TRY {
3369 double airmass = (
3370 cpl_propertylist_get_double(hdr, "ESO TEL AIRM START") +
3371 cpl_propertylist_get_double(hdr, "ESO TEL AIRM END")) / 2.;
3372 double parang = (
3373 cpl_propertylist_get_double(hdr, "ESO TEL PARANG START") +
3374 cpl_propertylist_get_double(hdr, "ESO TEL PARANG END")) / 2.;
3375 double posang =
3376 cpl_propertylist_get_double(hdr, "ESO ADA POSANG");
3377 double temp =
3378 cpl_propertylist_get_double(hdr, "ESO TEL AMBI TEMP");
3379 double rhum =
3380 cpl_propertylist_get_double(hdr, "ESO TEL AMBI RHUM");
3381 double pres = (
3382 cpl_propertylist_get_double(hdr, "ESO TEL AMBI PRES START") +
3383 cpl_propertylist_get_double(hdr, "ESO TEL AMBI PRES END")) / 2.;
3384
3385 cpl_wcs *wcs = cpl_wcs_new_from_propertylist(hdr);
3387
3388 hdrl_parameter *darParams = NULL;
3389 darParams = hdrl_dar_parameter_create(
3390 (hdrl_value) {airmass, 0.},
3391 (hdrl_value) {parang, 0.},
3392 (hdrl_value) {posang, 0.},
3393 (hdrl_value) {temp, 0.},
3394 (hdrl_value) {rhum, 0.},
3395 (hdrl_value) {pres, 0.},
3396 wcs);
3397 //BRK_IF_ERROR(hdrl_dar_parameter_verify(darParams));
3398
3399 cpl_vector *lambdaIn = NULL;
3400 double lambdaRef;
3402 cpl_vector_multiply_scalar(lambdaIn, 10000.); // convert microns to A
3403 lambdaRef = cpl_vector_get(lambdaIn, cpl_vector_get_size(lambdaIn)/2);
3404 int naxis3 = cpl_propertylist_get_int(hdr, NAXIS3);
3405 cpl_vector *xShift = cpl_vector_new(naxis3);
3406 cpl_vector *yShift = cpl_vector_new(naxis3);
3407 cpl_vector *xShiftErr = cpl_vector_new(naxis3);
3408 cpl_vector *yShiftErr = cpl_vector_new(naxis3);
3410
3411 BRK_IF_ERROR(hdrl_dar_compute( darParams,
3412 (hdrl_value) {lambdaRef, 0.}, lambdaIn,
3413 xShift, yShift, xShiftErr, yShiftErr ));
3414 cpl_msg_info(cpl_func, "DAR correction shift in X min/max: %.1f/%.1f, "
3415 "in Y min/max: %.1f/%.1f",
3416 cpl_vector_get_min(xShift), cpl_vector_get_max(xShift),
3417 cpl_vector_get_min(yShift), cpl_vector_get_max(yShift));
3418
3419 if (radius <= 0) {
3420 radius = CPL_KERNEL_DEF_WIDTH;
3421 }
3422 if (length == 0) {
3423 length = CPL_KERNEL_DEF_SAMPLES;
3424 }
3425
3426 const char *kernelName[] = {
3427 "TANH",
3428 "SINC",
3429 "SINC2",
3430 "LANCZOS",
3431 "HAMMING",
3432 "HANN",
3433 "NEAREST",
3434 "bilinear",
3435 "bicubic"};
3436 cpl_msg_info(cpl_func,"DAR correction: shift method %s, radius %.1f, length %d",
3437 kernelName[method], radius, length);
3438
3439 for (cpl_size sx=0; sx<naxis3; sx++) {
3440 hdrl_image *hdrlImg = hdrl_imagelist_get(cube, sx);
3441 cpl_image *inImg = hdrl_image_get_image(hdrlImg);
3442 cpl_image *errImg = hdrl_image_get_error(hdrlImg);
3443 cpl_image *err2Img = cpl_image_duplicate(errImg);
3444
3445 cpl_size nx = cpl_image_get_size_x(inImg);
3446 cpl_size ny = cpl_image_get_size_y(inImg);
3447 cpl_image *outImg = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
3448 cpl_image *out2Img = NULL;
3449
3450 double shiftX = cpl_vector_get(xShift, sx);
3451 double shiftY = cpl_vector_get(yShift, sx);
3452 if (method <= 6) {
3453 out2Img = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
3454 BRK_IF_ERROR(eris_ifu_dar_cpl_shift(inImg, outImg, out2Img, shiftX, shiftY,
3455 method, radius, length));
3456 } else if (method == 7) {
3457 eris_ifu_dar_gsl_shift(inImg, outImg, shiftX, shiftY, gsl_interp2d_bilinear);
3458 } else if (method == 8) {
3459 eris_ifu_dar_gsl_shift(inImg, outImg, shiftX, shiftY, gsl_interp2d_bicubic);
3460 }
3461 cpl_image_reject_from_mask(err2Img, cpl_image_get_bpm(outImg));
3462 hdrl_image *hdrl2Img = hdrl_image_create(outImg, err2Img);
3463
3464 hdrl_imagelist_set(cube, hdrl2Img, sx);
3465 // the previous hdrl_image is deallocated by hdrl_imagelist_set
3466 //hdrl_image_delete(hdrlImg);
3467 //eris_ifu_free_image(&inImg);
3468 //eris_ifu_free_image(&errImg);
3469 eris_ifu_free_image(&out2Img);
3470 cpl_image_delete(outImg);
3471 cpl_image_delete(err2Img);
3472 }
3473
3474 hdrl_parameter_delete(darParams);
3475 eris_ifu_free_vector(&lambdaIn);
3476 eris_ifu_free_vector(&xShift);
3477 eris_ifu_free_vector(&xShiftErr);
3478 eris_ifu_free_vector(&yShift);
3479 eris_ifu_free_vector(&yShiftErr);
3480 cpl_wcs_delete(wcs);
3481 } CATCH
3482 {
3483 // CATCH_MSGS();
3484 }
3485 return cpl_error_get_code();
3486}
3487
3488/*----------------------------------------------------------------------------*/
3505 cpl_image *inImg,
3506 cpl_image *out1Img,
3507 cpl_image *out2Img,
3508 double xShift,
3509 double yShift,
3510 cpl_kernel kernelType,
3511 double width,
3512 cpl_size kernelSize)
3513{
3514
3515 cpl_ensure_code(inImg, CPL_ERROR_NULL_INPUT);
3516 cpl_ensure_code(out1Img, CPL_ERROR_NULL_INPUT);
3517 cpl_ensure_code(out2Img, CPL_ERROR_NULL_INPUT);
3518
3519
3520 TRY {
3521 cpl_size nx, ny;
3522 cpl_vector *xprofile = NULL;
3523 double xradius;
3524 cpl_vector *yprofile = NULL;
3525 double yradius;
3526 cpl_image *correction_map = NULL;
3527
3528 nx = cpl_image_get_size_x(inImg);
3529 ny = cpl_image_get_size_x(inImg);
3530 cpl_image *deltax = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
3531 cpl_image *deltay = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
3532 cpl_image_add_scalar(deltax, xShift);
3533 cpl_image_add_scalar(deltay, yShift);
3534
3535 xprofile = cpl_vector_new(kernelSize);
3536 cpl_vector_fill_kernel_profile(xprofile, kernelType, width);
3537 xradius = width;
3538 yprofile = cpl_vector_new(kernelSize);
3539 cpl_vector_fill_kernel_profile(yprofile, kernelType, width);
3540 yradius = width;
3542
3543 cpl_image_warp(out1Img, inImg, deltax, deltay, xprofile, xradius, yprofile, yradius);
3545
3546 correction_map = cpl_image_new(cpl_image_get_size_x(out1Img),
3547 cpl_image_get_size_y(out1Img),
3548 cpl_image_get_type(out1Img));
3549 cpl_image_fill_jacobian(correction_map, deltax, deltay);
3550 cpl_image_copy(out2Img, out1Img, 1, 1);
3551 cpl_image_multiply(out2Img, correction_map);
3553
3554 eris_ifu_free_image(&deltax);
3555 eris_ifu_free_image(&deltay);
3556 eris_ifu_free_image(&correction_map);
3557 eris_ifu_free_vector(&xprofile);
3558 eris_ifu_free_vector(&yprofile);
3559
3560 } CATCH
3561 {
3562 // CATCH_MSGS();
3563 }
3564
3565 return cpl_error_get_code();
3566}
3567/*----------------------------------------------------------------------------*/
3584/*----------------------------------------------------------------------------*/
3585
3587 cpl_image *inImg,
3588 cpl_image *outImg,
3589 double xShift,
3590 double yShift,
3591 const gsl_interp2d_type *T)
3592{
3593 cpl_size nx, ny;
3594
3595 //cpl_ensure_code(inImg, CPL_ERROR_NULL_INPUT);
3596 //cpl_ensure_code(outImg, CPL_ERROR_NULL_INPUT);
3597 //cpl_ensure_code(T, CPL_ERROR_NULL_INPUT);
3598
3599 gsl_set_error_handler_off();
3600 const double xa[] = {
3601 0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.,13.,14.,15.,
3602 16.,17.,18.,19.,20.,21.,22.,23.,24.,25.,26.,27.,28.,29.,30.,
3603 31.,32.,33.,34.,35.,36.,37.,38.,39.,40.,41.,42.,43.,44.,45.,
3604 46.,47.,48.,49.,50.,51.,52.,53.,54.,55.,56.,57.,58.,59.,60.,
3605 61.,62.,63.
3606 };
3607 const double ya[]= {
3608 0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.,13.,14.,15.,
3609 16.,17.,18.,19.,20.,21.,22.,23.,24.,25.,26.,27.,28.,29.,30.,
3610 31.,32.,33.,34.,35.,36.,37.,38.,39.,40.,41.,42.,43.,44.,45.,
3611 46.,47.,48.,49.,50.,51.,52.,53.,54.,55.,56.,57.,58.,59.,60.,
3612 61.,62.,63.
3613 };
3614 double *za = cpl_image_get_data_double(inImg);
3615
3616 /* initialize interpolation */
3617 nx = cpl_image_get_size_x(outImg);
3618 ny = cpl_image_get_size_y(outImg);
3619 gsl_spline2d *spline = gsl_spline2d_alloc(T, nx, ny);
3620 gsl_interp_accel *xacc = gsl_interp_accel_alloc();
3621 gsl_interp_accel *yacc = gsl_interp_accel_alloc();
3622 gsl_spline2d_init(spline, xa, ya, za, nx, ny);
3623 double z;
3624 //TODO: why error is computed but not used?
3625// int err;
3626 for (int i = 0; i < nx; ++i)
3627 {
3628 double xi = i - xShift;
3629
3630 for (int j = 0; j < nx; ++j)
3631 {
3632 double yj = j - yShift;
3633 if (xi > nx-1 || xi < 0 || yj > ny-1 || yj < 0) {
3634 z = 0.001;
3635 }/* else {
3636 err = gsl_spline2d_eval_e(spline, xi, yj, xacc, yacc, &z);
3637 }*/
3638 cpl_image_set(outImg, i+1, j+1, z);
3639// printf("%d: %d %d %f --> %f %f %f\n", err, i, j, za[j+nx*j], xi, yj, z);
3640 }
3641// printf("\n");
3642 }
3643
3644 gsl_spline2d_free(spline);
3645 gsl_interp_accel_free(xacc);
3646 gsl_interp_accel_free(yacc);
3647 return cpl_error_get_code();
3648}
3649
3660int
3661eris_frameset_count_tag(cpl_frameset * sof, const char* tag)
3662{
3663
3664 cpl_ensure(sof, CPL_ERROR_NULL_INPUT, -1);
3665 cpl_ensure(tag, CPL_ERROR_NULL_INPUT, -1);
3666
3667 int count = 0;
3668 cpl_frameset* loc_sof = cpl_frameset_duplicate(sof);
3669 cpl_frame* frame = cpl_frameset_find(loc_sof, tag);
3670 if(frame != NULL) {
3671 while(frame) {
3672 cpl_frameset_erase_frame(loc_sof, frame);
3673 frame = cpl_frameset_find(loc_sof, tag);
3674 count++;
3675 }
3676 }
3677 cpl_frameset_delete(loc_sof);
3678 return count;
3679
3680}
3699cpl_error_code
3700eris_frameset_duplicate_cube_tag(cpl_frameset* frameset, const char* pcatg,
3701 cpl_boolean apply_flat)
3702{
3703 cpl_ensure(frameset, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
3704 cpl_ensure(pcatg, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
3705 //cpl_msg_warning(cpl_func,"pcatg: %s", pcatg);
3706 //cpl_frameset_dump(frameset,stdout);
3707 cpl_frame* frm_tmp = cpl_frameset_find(frameset, pcatg);
3708 cpl_frame* frm_dup = cpl_frame_duplicate(frm_tmp);
3709 const char* fname = cpl_frame_get_filename(frm_tmp);
3710 const char* fname_new = NULL;
3711 cpl_propertylist* plist = cpl_propertylist_load(fname, 0);
3712 //cpl_msg_info(cpl_func,"pcatg: %s",pcatg);
3713 if(strcmp(pcatg,ERIS_IFU_PRO_JITTER_OBJ_CUBE) == 0) {
3714 //cpl_msg_info(cpl_func,"case OBJ");
3715 fname_new = "eris_ifu_jitter_obj_cube_coadd.fits";
3716 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_OBJ_CUBE_COADD);
3717 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_OBJ_CUBE_COADD);
3718 } else if(strcmp(pcatg,ERIS_IFU_PRO_JITTER_DAR_CUBE) == 0) {
3719 fname_new = "eris_ifu_jitter_dar_cube_coadd.fits";
3720 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_OBJ_DAR_CUBE_COADD);
3721 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_OBJ_DAR_CUBE_COADD);
3722 } else if(strcmp(pcatg,ERIS_IFU_PRO_JITTER_TWK_CUBE) == 0) {
3723 fname_new = "eris_ifu_jitter_twk_cube_coadd.fits";
3724 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_TWK_CUBE_COADD);
3725 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_TWK_CUBE_COADD);
3726 } else if(strcmp(pcatg,ERIS_IFU_PRO_JITTER_PSF_CUBE) == 0) {
3727 //cpl_msg_info(cpl_func,"case PSF");
3728 fname_new = "eris_ifu_stdstar_psf_cube_coadd.fits";
3729 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD);
3730 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD);
3731 } else if(strcmp(pcatg,ERIS_IFU_PRO_JITTER_STD_CUBE) == 0){
3732 //cpl_msg_info(cpl_func,"case STD");
3733 if(apply_flat) {
3734 fname_new = "eris_ifu_stdstar_std_cube_coadd.fits";
3735 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_STD_CUBE_COADD);
3736 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_STD_CUBE_COADD);
3737 } else {
3738 fname_new = "eris_ifu_stdstar_no_flat_std_cube_coadd.fits";
3739 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_STD_CUBE_COADD_NOFLAT);
3740 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_STD_CUBE_COADD_NOFLAT);
3741 }
3742 } else if(strcmp(pcatg,ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE) == 0){
3743 //cpl_msg_info(cpl_func,"case STD_FLUX");
3744 if(apply_flat) {
3745 fname_new = "eris_ifu_stdstar_std_flux_cube_coadd.fits";
3746 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD);
3747 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD);
3748 } else {
3749 fname_new = "eris_ifu_stdstar_no_flat_std_flux_cube_coadd.fits";
3750 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD_NOFLAT);
3751 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD_NOFLAT);
3752 }
3753 }
3754
3755 char* cmd = cpl_sprintf("cp %s %s",fname, fname_new);
3756 cpl_msg_debug(cpl_func, "Copying %s", cmd);
3757 int status = system(cmd);
3758 if(status == -1) {
3759 cpl_msg_warning(cpl_func,"call to system() failed");
3760 }
3761 cpl_frame_set_filename(frm_dup, fname_new);
3762 cpl_frame_set_group(frm_dup, CPL_FRAME_GROUP_PRODUCT);
3763 cpl_frame_set_level(frm_dup, CPL_FRAME_LEVEL_FINAL);
3764
3765 cpl_propertylist_save(plist, fname_new, CPL_IO_CREATE);
3766 cpl_propertylist_delete(plist);
3767
3768 plist = cpl_propertylist_load(fname, 1);
3769 cpl_imagelist* data = cpl_imagelist_load(fname,CPL_TYPE_FLOAT, 1);
3770 cpl_imagelist_save(data, fname_new, CPL_TYPE_FLOAT, plist, CPL_IO_EXTEND);
3771 cpl_imagelist_delete(data);
3772 cpl_propertylist_delete(plist);
3773
3774 plist = cpl_propertylist_load(fname, 2);
3775 data = cpl_imagelist_load(fname, CPL_TYPE_FLOAT, 2);
3776 cpl_imagelist_save(data, fname_new, CPL_TYPE_FLOAT, plist, CPL_IO_EXTEND);
3777 cpl_imagelist_delete(data);
3778 cpl_propertylist_delete(plist);
3779
3780 plist = cpl_propertylist_load(fname, 3);
3781 data = cpl_imagelist_load(fname, CPL_TYPE_INT, 3);
3782 cpl_imagelist_save(data, fname_new, CPL_TYPE_INT, plist, CPL_IO_EXTEND);
3783 cpl_imagelist_delete(data);
3784 cpl_propertylist_delete(plist);
3785
3786
3787 //cpl_msg_warning(cpl_func, "insert frame %s with tag %s",
3788 // cpl_frame_get_filename(frm_tmp), cpl_frame_get_tag(frm_tmp));
3789 cpl_frameset_insert(frameset, frm_dup);
3790 cpl_free(cmd);
3791
3792
3793 return cpl_error_get_code();
3794}
3795/*----------------------------------------------------------------------------*/
3813/*----------------------------------------------------------------------------*/
3814
3816 struct sofStruct *sof)
3817{
3818 cpl_error_code retval = CPL_ERROR_NONE;
3819 cpl_propertylist *header = NULL;
3820 //const char *filename;
3821 double crval1,
3822 crval2,
3823 crval1New,
3824 crval2New,
3825 crval1Ref,
3826 crval2Ref,
3827 cumOffset1,
3828 cumOffset2;
3829 int sx,
3830 rx;
3831
3832
3833 if (sof->exposureTableCnt < 2) { // nothing to do!
3834 return CPL_ERROR_NONE;
3835 }
3836
3837 TRY{
3838 /*
3839 * find reference exposure
3840 * either the first one with CUMOFFS1 and CUMOFFS1 set to 0.0
3841 * or the the first exposure
3842 */
3843 rx = -1;
3844 for (sx = 0; sx < sof->exposureTableCnt; sx++) {
3845 header = sof->exposureTable[sx].hdr;
3846 cumOffset1 = cpl_propertylist_get_double(header, FHDR_E_CUMOFFS1);
3847 cumOffset2 = cpl_propertylist_get_double(header, FHDR_E_CUMOFFS2);
3849 if (cumOffset1 == 0.0 && cumOffset2 == 0.0) {
3850 rx = sx;
3851 }
3852 cpl_msg_info("update_WCS_with_OCS_keywords",
3853 "%d %s : %f/%f %.1f/%.1f %g %g %g %g",
3854 sx, cpl_frame_get_filename(sof->exposureTable[sx].frame),
3855 cpl_propertylist_get_double(header, FHDR_E_CRVAL1),
3856 cpl_propertylist_get_double(header, FHDR_E_CRVAL2),
3857 cpl_propertylist_get_double(header, "CRPIX1"),
3858 cpl_propertylist_get_double(header, "CRPIX2"),
3859 cpl_propertylist_get_double(header, "CD1_1"),
3860 cpl_propertylist_get_double(header, "CD1_2"),
3861 cpl_propertylist_get_double(header, "CD2_1"),
3862 cpl_propertylist_get_double(header, "CD2_2")
3863 );
3865 }
3866 if (rx == -1) {
3867 rx = 0;
3868 }
3869
3870 header = sof->exposureTable[rx].hdr;
3871 crval1 = cpl_propertylist_get_double(header, FHDR_E_CRVAL1);
3872 crval2 = cpl_propertylist_get_double(header, FHDR_E_CRVAL2);
3873 cumOffset1 = cpl_propertylist_get_double(header, FHDR_E_CUMOFFS1);
3874 cumOffset2 = cpl_propertylist_get_double(header, FHDR_E_CUMOFFS2);
3876
3877 crval1Ref = crval1 - cumOffset1 / 3600.;
3878 crval2Ref = crval2 - cumOffset2 / 3600.;
3879
3880 cpl_msg_info("update_WCS_with_OCS_keywords","ref: %d %f %f",
3881 rx, crval1Ref, crval2Ref);
3882
3883 for (sx = 0; sx < sof->exposureTableCnt; sx++) {
3884 header = sof->exposureTable[sx].hdr;
3885 crval1 = cpl_propertylist_get_double(header, FHDR_E_CRVAL1);
3886 crval2 = cpl_propertylist_get_double(header, FHDR_E_CRVAL2);
3887 cumOffset1 = cpl_propertylist_get_double(header, FHDR_E_CUMOFFS1);
3888 cumOffset2 = cpl_propertylist_get_double(header, FHDR_E_CUMOFFS2);
3889
3890 crval1New = crval1Ref + cumOffset1 / 3600.;
3891 crval2New = crval2Ref + cumOffset2 / 3600.;
3892 cpl_propertylist_set_double(header, FHDR_E_CRVAL1, crval1New);
3893 cpl_propertylist_set_double(header, FHDR_E_CRVAL2, crval2New);
3895
3896 cpl_msg_info("update_WCS_with_OCS_keywords",
3897 "%d %f -> %f (%f) %f -> %f (%f) %f / %f %f / %f %f // %f",
3898 sx,
3899 crval1, crval1New, (crval1-crval1New)*3600.,
3900 crval2, crval2New, (crval2-crval2New)*3600.,
3901 cumOffset1, cumOffset2,
3902 (crval1New-crval1Ref)*3600., (crval2New-crval2Ref)*3600.,
3903 (crval1-crval1Ref)*3600., (crval2-crval2Ref)*3600. );
3904 }
3905 } CATCH {
3906 }
3907 return retval;
3908} /* End of eris_ifu_jitter_static group */
3910
cpl_image * eris_ifu_wave_resampled_arc_image(const cpl_image *arcImg, const cpl_image *waveCalImg, ifsBand band, double minLambda, double maxLambda, cpl_propertylist *plist, int axisNumber)
Resample arc image to uniform wavelength grid.
cpl_error_code eris_ifu_append_qc_float(cpl_propertylist *pl, const char *name, float val, const char *comment)
Append a QC parameter of type FLOAT to a property list.
cpl_error_code eris_ifu_extract_obj_frames(const cpl_frameset *sof, cpl_frameset *obj)
extract object raw frames from frame set and put them in a new one
cpl_frameset * eris_ifu_extract_frameset(const cpl_frameset *in, const char *tag)
Extract frames with a specific tag from a frameset.
Definition: eris_ifu_dfs.c:201
hdrl_imagelist * eris_ifu_load_deq_hdrl_imagelist(const char *filename, cpl_propertylist **primaryHeader, cpl_imagelist **qualImagelist, deqQualityType *qualityType)
Load a DEQ-format cube into an HDRL imagelist structure.
cpl_error_code eris_ifu_save_deq_image(cpl_frameset *allframes, cpl_propertylist *header, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_frame *inherit, const char *recipe, const cpl_propertylist *applist, const char *remregexp, const char *filename, const cpl_image *image, const cpl_image *error, deqErrorType errorType, const cpl_image *dataQualityMask, deqQualityType dataQualityType, const char *unit)
Save a DFS-compliant image product with data, error, and quality extensions.
Definition: eris_ifu_dfs.c:367
cpl_error_code eris_ifu_save_deq_cube(cpl_frameset *allframes, cpl_propertylist *header, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_frame *inherit, const char *recipe, cpl_propertylist *applist, const char *remregexp, const char *filename, cpl_imagelist *data, cpl_imagelist *error, deqErrorType errorType, const cpl_imagelist *dataQualityMask, deqQualityType qualityType)
Save a DFS-compliant cube product with data, error, and quality extensions.
Definition: eris_ifu_dfs.c:516
ifsBand eris_ifu_get_band(const cpl_propertylist *header)
Determine preoptic band.
cpl_error_code eris_ifu_extract_sky_frames(const cpl_frameset *sof, cpl_frameset *sky)
extract sky raw frames from frame set and put them in a new one
cpl_error_code eris_ifu_extract_mst_frames(const cpl_frameset *sof, cpl_frameset *cdb)
extract master and ref frames from input set and put them in a new one
hdrl_image * eris_ifu_dist_warp_bpm(const hdrl_image *bpmIn, cpl_polynomial **poly_u, const cpl_table *borders, productDepthType productDepth)
Warp bad pixel mask using distortion polynomials.
hdrl_image * eris_ifu_dist_warp_image(const hdrl_image *imgIn, cpl_polynomial **poly_u, const cpl_table *borders)
Warp full detector image by warping each slitlet.
#define ASSURE(condition, error,...)
error handling macro (from fors-pipeline)
#define BRK_IF_ERROR(function)
If function is or returns an error != CPL_ERROR_NONE, then the try-block is exited.
#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 CATCH_MSG()
Displays an error message.
#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.
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_error_code eris_ifu_bpm_correction(hdrl_image *himg, hdrl_image *badPixelMaskImg)
eris_ifu_bpm_correction
hdrl_image * eris_ifu_warp_polynomial_image(const hdrl_image *hdrlInImg, const cpl_polynomial *poly_u, const cpl_polynomial *poly_v)
Warp an HDRL image using 2D polynomial transformations.
cpl_error_code eris_ifu_jitter_process_cubes(struct sofStruct *sof, struct stdParamStruct stdParams, struct paramStruct params, cpl_frameset *frameset, const cpl_parameterlist *parlist, const char *recipe_name, cubeType *obj_type)
Process and combine data cubes with sky tweaking and DAR correction.
cpl_error_code eris_ifu_dar_gsl_shift(cpl_image *inImg, cpl_image *outImg, double xShift, double yShift, const gsl_interp2d_type *T)
Apply DAR correction using GSL 2D interpolation.
cpl_error_code eris_ifu_jitter_extract_spec_processSof(cubeType obj_type, cpl_frameset *frames, struct esParamStruct params, struct esSofStruct *sof)
Process SOF for spectral extraction.
void eris_ifu_jitter_free_sofStruct(struct sofStruct *sof_struct)
Free and clean up SOF structure and all contained data.
cubeType eris_ifu_jitter_get_sky_type(sofModes mode)
Get sky cube type from SOF observation mode.
cpl_error_code eris_ifu_jitter_extract(cpl_frameset *frameset, const cpl_parameterlist *parlist, cubeType obj_type, const char *pcatg, struct stdParamStruct stdParams, const char *pipefile_prefix, const char *context)
Main spectral extraction function.
cpl_error_code eris_frameset_duplicate_cube_tag(cpl_frameset *frameset, const char *pcatg, cpl_boolean apply_flat)
Duplicate a cube file with different PRODCATG for coadded version.
void eris_ifu_jitter_get_cube_type_string(cubeType type)
Print cube type as string to log.
cpl_error_code eris_ifu_update_wcs_with_OCS_keywords(struct sofStruct *sof)
Update WCS coordinates from OCS cumulative offset keywords.
cpl_error_code eris_image_get_valid_data_range(cpl_image *image, cpl_size *min, cpl_size *max)
Determine valid data range in spectral direction (find NaN-dominated rows)
#define ERIS_IFU_SKIP_SKY_CORR_PLANES
*static *‍/void
cpl_error_code eris_ifu_extract_spec(const cpl_imagelist *data_in, const cpl_imagelist *noise_in, cpl_image *mask, cpl_vector **spec_data_out, cpl_vector **spec_noise_out)
Extract a spectrum from 3D data cube.
cpl_error_code eris_ifu_jitter_get_procatg_and_filename(cubeType type, char **proCatg, char **filenamePrefix)
Get the value of the PRO.CATG and the filename as function of the type of cube.
hdrl_image * eris_ifu_jitter_subtract_background(skyTweakModes sky_tweak, int objIdx, struct sofStruct *sof, productDepthType productDepth)
Subtract sky or dark background from raw exposure image.
cubeType eris_ifu_jitter_get_obj_type(sofModes mode)
Get object cube type from SOF observation mode.
cpl_imagelist * eris_ifu_jitter_reconstruct_cube(cpl_image *resampledDetImage, slitletDetectionModes mode, int fineTuneMode, double firstCol, cpl_vector *distancesV, cpl_bivector *positionsVV)
Function to create a 3D-data cube from a re-sampled image.
cpl_error_code eris_ifu_jitter_process_exposures(struct sofStruct *sof, struct stdParamStruct stdParams, struct paramStruct params, cpl_frameset *frameset, const cpl_parameterlist *parlist, const char *recipe_name, const char *context)
Process all raw exposures into calibrated 3D data cubes.
cpl_error_code eris_ifu_dar_cpl_shift(cpl_image *inImg, cpl_image *out1Img, cpl_image *out2Img, double xShift, double yShift, cpl_kernel kernelType, double width, cpl_size kernelSize)
Apply DAR correction using CPL image shifting.
hdrl_imagelist * eris_ifu_jitter_build_cube(hdrl_image *inputImage, int sofIdx, struct sofStruct *sof, struct paramStruct params, bool doVelocityCorrection, cpl_polynomial *ohLambdaCorrection, productDepthType productDepth)
Build 3D data cube from 2D detector image.
int eris_frameset_count_tag(cpl_frameset *sof, const char *tag)
Count frames with specified tag in frameset.
cpl_error_code eris_ifu_dar_correction(hdrl_imagelist *cube, cpl_propertylist *hdr, int method, double radius, int length)
Apply Differential Atmospheric Refraction (DAR) correction.
cpl_error_code eris_ifu_extract_spec_fetch_params(const cpl_parameterlist *parlist, struct esParamStruct *params, const char *context)
Fetch spectral extraction parameters from parameter list.
cubeType eris_ifu_jitter_get_coadd_obj_type(cubeType type)
Convert cube type to corresponding coadded cube type.
cpl_polynomial * eris_ifu_lcorr_get(cpl_imagelist *cube, hdrl_imagelist *hdrlCube, const cpl_propertylist *header, cpl_vector *peaks, const int pfit_order)
Create wavelength correction polynomial from IFU cube using OH lines.
cpl_vector * eris_ifu_lcorr_create_lambda_vector(const cpl_propertylist *header)
Create wavelength vector from FITS header WCS keywords.
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_error_code eris_ifu_save_imagelist(cpl_frameset *fs, cpl_frame *inherit, const cpl_propertylist *plist, const cpl_parameterlist *parlist, const char *recipe, const char *procatg, const char *filename, cpl_type type, const cpl_imagelist *imglist)
Save imagelist with DFS compliance.
void eris_ifu_free_propertylist(cpl_propertylist **item)
Free memory and set pointer to null.
void eris_ifu_free_string(char **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_table(cpl_table **item)
Free memory and set pointer to null.
cpl_error_code eris_ifu_split_hdrl_imagelist(hdrl_imagelist *cube, cpl_imagelist *dataCube, cpl_imagelist *errorCube)
extract from hdrl_imagelist the data and error information
cpl_error_code eris_ifu_get_plane_cut_min_max(ifsBand band, cpl_size *zmin, cpl_size *zmax)
Get band-specific plane indices for NaN trimming.
void eris_ifu_free_polynomial(cpl_polynomial **item)
Free memory and set pointer to null.
cpl_propertylist * eris_compute_psf_qc(hdrl_image *hima, const cpl_parameterlist *parlist, const char *context)
compute QC parameters on a PSF STD image
cpl_mask * eris_ifu_hima_get_obj_mask_percent(hdrl_image *hima, const double percent)
find mask flagging pixels above percent(%) pixels with lower intensity
void eris_ifu_free_imagelist(cpl_imagelist **item)
Free memory and set pointer to null.
cpl_error_code eris_ifu_mask_nans_in_cube(cpl_imagelist *cube)
Mask NaNs and Infs in CPL imagelist (cube)
void eris_ifu_free_hdrl_imagelist(hdrl_imagelist **item)
Free memory and set pointer to null.
cpl_error_code eris_ifu_save_hdrl_image_dbg(const hdrl_image *hdrl_img, const char *filename, int singlefile, const cpl_propertylist *pl)
Save HDRL image for debugging (data + error + mask)
void eris_ifu_free_hdrl_image(hdrl_image **item)
Free memory and set pointer to null.
cpl_error_code eris_ifu_cube_trim_nans(const cpl_size zmin, const cpl_size zmax, hdrl_imagelist **iml, cpl_imagelist **bpm, cpl_propertylist *header)
Trim NaN-dominated planes from cube edges.
cpl_imagelist * eris_ifu_interpolatedMask_to_maskZero(cpl_imagelist *bpmCube, double threshold)
return cube flagging (as 1) pixels above a given threshold
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.
void eris_ifu_free_parameterlist(cpl_parameterlist **item)
Free memory and set pointer to null.
void eris_ifu_free_bivector(cpl_bivector **item)
Free memory and set pointer to null.
cpl_mask * eris_ifu_hima_get_obj_mask(hdrl_image *hima, const cpl_size niter, const double kappa)
find mask flagging pixels above a threshold set by ks-clip algorithm
cpl_error_code eris_check_error_code(const char *func_id)
handle CPL errors
Definition: eris_utils.c:56
cpl_error_code hdrl_dar_compute(const hdrl_parameter *params, const hdrl_value lambdaRef, const cpl_vector *lambdaIn, cpl_vector *xShift, cpl_vector *yShift, cpl_vector *xShiftErr, cpl_vector *yShiftErr)
Correct the pixel coordinates of all pixels of a given pixel table for differential atmospheric refra...
Definition: hdrl_dar.c:218
hdrl_parameter * hdrl_dar_parameter_create(hdrl_value airmass, hdrl_value parang, hdrl_value posang, hdrl_value temp, hdrl_value rhum, hdrl_value pres, cpl_wcs *wcs)
Creates DAR parameters object with the values in the header.
Definition: hdrl_dar.c:159
cpl_error_code hdrl_image_sub_image(hdrl_image *self, const hdrl_image *other)
Subtract two images, store the result in the first image.
cpl_error_code hdrl_image_reject_from_mask(hdrl_image *self, const cpl_mask *map)
set bpm of hdrl_image
Definition: hdrl_image.c:407
hdrl_value hdrl_image_get_median(const hdrl_image *self)
computes the median and associated error of an image.
cpl_error_code hdrl_image_div_image(hdrl_image *self, const hdrl_image *other)
Divide two images, store the result in the first image.
hdrl_image * hdrl_image_duplicate(const hdrl_image *himg)
copy hdrl_image
Definition: hdrl_image.c:391
cpl_mask * hdrl_image_get_mask(hdrl_image *himg)
get cpl bad pixel mask from image
Definition: hdrl_image.c:157
cpl_image * hdrl_image_get_error(hdrl_image *himg)
get error as cpl image
Definition: hdrl_image.c:131
hdrl_value hdrl_image_get_mean(const hdrl_image *self)
computes mean pixel value and associated error of an image.
cpl_error_code hdrl_image_insert(hdrl_image *self, const cpl_image *image, const cpl_image *error, cpl_size xpos, cpl_size ypos)
Copy cpl images into an hdrl image.
Definition: hdrl_image.c:715
hdrl_image * hdrl_image_create(const cpl_image *image, const cpl_image *error)
create a new hdrl_image from to existing images by copying them
Definition: hdrl_image.c:295
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:105
hdrl_image * hdrl_image_new(cpl_size nx, cpl_size ny)
create new zero filled hdrl image
Definition: hdrl_image.c:311
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
Definition: hdrl_image.c:379
cpl_error_code hdrl_image_sub_scalar(hdrl_image *self, hdrl_value value)
Elementwise subtraction of a scalar from an image.
cpl_error_code hdrl_image_accept_all(hdrl_image *self)
Accept all pixels in an image.
Definition: hdrl_image.c:508
cpl_error_code hdrl_imagelist_collapse_mean(const hdrl_imagelist *himlist, hdrl_image **out, cpl_image **contrib)
Mean collapsing of image list.
cpl_error_code hdrl_imagelist_set(hdrl_imagelist *himlist, hdrl_image *himg, cpl_size pos)
Insert an image into an imagelist.
cpl_size hdrl_imagelist_get_size_y(const hdrl_imagelist *himlist)
Get number of rows of images in the imagelist.
hdrl_imagelist * hdrl_imagelist_create(cpl_imagelist *imlist, cpl_imagelist *errlist)
Create an hdrl_imagelist out of 2 cpl_imagelist.
void hdrl_imagelist_delete(hdrl_imagelist *himlist)
Free all memory used by a hdrl_imagelist object including the images.
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
cpl_size hdrl_imagelist_get_size_x(const hdrl_imagelist *himlist)
Get number of colums of images in the imagelist.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
void hdrl_parameter_delete(hdrl_parameter *obj)
shallow delete of a parameter
cpl_error_code sc_skycorr(cpl_parameterlist *parlist, cpl_table *scispec, cpl_table *skyspec, int product_depth)
Definition: sc_skycorr.c:48