ERIS Pipeline Reference Manual 1.8.14
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
54//eris_ifu_jitter_free_exposureEntry(struct exposureEntry* exp_entry){
55
56// if(exp_entry != NULL) {
57// if(exp_entry->frame != NULL) cpl_frame_delete(exp_entry->frame);
58// if(exp_entry->hdr != NULL) cpl_propertylist_delete(exp_entry->hdr);
59// if(exp_entry->rawImage != NULL) hdrl_image_delete(exp_entry->rawImage);
60// if(exp_entry->cube != NULL) hdrl_imagelist_delete(exp_entry->cube);
61// if(exp_entry->cubeBpm != NULL) cpl_imagelist_delete(exp_entry->cubeBpm);
62// if(exp_entry->cubeHdr != NULL) cpl_propertylist_delete(exp_entry->cubeHdr);
63// if(exp_entry->badPixelMask != NULL) cpl_mask_delete(exp_entry->badPixelMask);
64// if(exp_entry->darkSubtrImage != NULL) hdrl_image_delete(exp_entry->darkSubtrImage);
65// if(exp_entry->skySubtrImage != NULL) hdrl_image_delete(exp_entry->skySubtrImage);
66// exp_entry = NULL;
67// };
68// return;
69//}
70
71#define ERIS_IFU_SKIP_SKY_CORR_PLANES 75
72void eris_ifu_jitter_free_sofStruct(struct sofStruct* sof_struct){
73
74 /* The following commented lines of code creates seg faults */
75 if(sof_struct != NULL) {
76 if(sof_struct->exposureTable != NULL) {
77 for(cpl_size i = 0; i < sof_struct->exposureTableCnt; i++) {
78 if (sof_struct->exposureTable != NULL) {
79
80 if(sof_struct->exposureTable[i].frame != NULL) {
81 //cpl_frame_delete(sof_struct->exposureTable[i].frame);
82 }
83 if(sof_struct->exposureTable[i].hdr != NULL) {
84 cpl_propertylist_delete(sof_struct->exposureTable[i].hdr);
85 }
86 if(sof_struct->exposureTable[i].rawImage != NULL) {
87 //hdrl_image_delete(sof_struct->exposureTable[i].rawImage);
88 }
89 if(sof_struct->exposureTable[i].cube != NULL){
90 hdrl_imagelist_delete(sof_struct->exposureTable[i].cube);
91 }
92 if(sof_struct->exposureTable[i].cubeBpm != NULL){
93 cpl_imagelist_delete(sof_struct->exposureTable[i].cubeBpm);
94 }
95 if(sof_struct->exposureTable[i].cubeHdr != NULL) {
96 cpl_propertylist_delete(sof_struct->exposureTable[i].cubeHdr);
97 }
98 if(sof_struct->exposureTable[i].badPixelMask != NULL) {
99 cpl_mask_delete(sof_struct->exposureTable[i].badPixelMask);
100 }
101 if(sof_struct->exposureTable[i].darkSubtrImage != NULL){
102 hdrl_image_delete(sof_struct->exposureTable[i].darkSubtrImage);
103 }
104 if(sof_struct->exposureTable[i].skySubtrImage != NULL){
105 hdrl_image_delete(sof_struct->exposureTable[i].skySubtrImage);
106 }
107
108 }
109 }
110 //eris_ifu_jitter_free_exposureEntry(sof_struct->exposureTable);
111 }
112 if(sof_struct->masterDark != NULL) hdrl_image_delete(sof_struct->masterDark);
113 if(sof_struct->masterFlat != NULL) hdrl_image_delete(sof_struct->masterFlat);
114 if(sof_struct->waveMap != NULL) cpl_image_delete(sof_struct->waveMap);
115 if(sof_struct->badPixelMask != NULL) cpl_mask_delete(sof_struct->badPixelMask);
116 if(sof_struct->distortion != NULL) {
117 for (int sx = 0; sx < SLITLET_CNT; sx++) {
118 cpl_polynomial_delete(sof_struct->distortion[sx]);
119 }
120 cpl_free(sof_struct->distortion);
121 }
122 if(sof_struct->dqi != NULL) {
123 cpl_image_delete(sof_struct->dqi);
124 }
125 if(sof_struct->oh_ref_peaks != NULL) cpl_vector_delete(sof_struct->oh_ref_peaks);
126 if(sof_struct->oh_ref_frame != NULL) cpl_frame_delete(sof_struct->oh_ref_frame);
127 if(sof_struct->borders != NULL) cpl_table_delete(sof_struct->borders);
128 if(sof_struct->poly_u != NULL) cpl_polynomial_delete(sof_struct->poly_u);
129 if(sof_struct->poly_v != NULL) cpl_polynomial_delete(sof_struct->poly_v);
130 if(sof_struct->distances != NULL) cpl_vector_delete(sof_struct->distances);
131 if(sof_struct->positions != NULL) cpl_bivector_delete(sof_struct->positions);
132 sof_struct = NULL;
133 }
134 return;
135}
136
137
138void
139eris_ifu_jitter_get_cube_type_string(cubeType type)
140{
141
142 switch(type) {
143 case OBJECT_CUBE:
144 cpl_msg_info(cpl_func,"type: OBJECT_CUBE");
145 break;
146 case STD_CUBE:
147 cpl_msg_info(cpl_func,"type: STD_CUBE");
148 break;
149 case STD_FLUX_CUBE:
150 cpl_msg_info(cpl_func,"type: STD_FLUX_CUBE");
151 break;
152 case STD_CUBE_NOFLAT:
153 cpl_msg_info(cpl_func,"type: STD_CUBE_NOFLAT");
154 break;
155 case STD_FLUX_CUBE_NOFLAT:
156 cpl_msg_info(cpl_func,"type: STD_FLUX_CUBE_NOFLAT");
157 break;
158 case PSF_CUBE:
159 cpl_msg_info(cpl_func,"type: PSF_CUBE");
160 break;
161 case SKY_OBJECT_CUBE:
162 cpl_msg_info(cpl_func,"type: SKY_OBJECT_CUBE");
163 break;
164 case SKY_STD_CUBE:
165 cpl_msg_info(cpl_func,"type: SKY_STD_CUBE");
166 break;
167 case SKY_STD_FLUX_CUBE:
168 cpl_msg_info(cpl_func,"type: SKY_STD_FLUX_CUBE");
169 break;
170 case SKY_PSF_CUBE:
171 cpl_msg_info(cpl_func,"type: SKY_PSF_CUBE");
172 break;
173 case TWEAKED_CUBE:
174 cpl_msg_info(cpl_func,"type: TWEAKED_CUBE");
175 break;
176 case DAR_CUBE:
177 cpl_msg_info(cpl_func,"type: DAR_CUBE");
178 break;
179 case JITTER_CUBE:
180 cpl_msg_info(cpl_func,"type: JITTER_CUBE");
181 break;
182 case BPM_CUBE:
183 cpl_msg_info(cpl_func,"type: BPM_CUBE");
184 break;
185 case OBJECT_CUBE_COADD:
186 cpl_msg_info(cpl_func,"type: OBJECT_CUBE_COADD");
187 break;
188 case STD_CUBE_COADD:
189 cpl_msg_info(cpl_func,"type: STD_CUBE_COADD");
190 break;
191 case PSF_CUBE_COADD:
192 cpl_msg_info(cpl_func,"type: PSF_CUBE_COADD");
193 break;
194 case STD_FLUX_CUBE_COADD:
195 cpl_msg_info(cpl_func,"type: STD_FLUX_CUBE_COADD");
196 break;
197 case DAR_STD_FLUX_CUBE:
198 cpl_msg_info(cpl_func,"type: DAR_STD_FLUX_CUBE");
199 break;
200 case TWEAKED_CUBE_COADD:
201 cpl_msg_info(cpl_func,"type: TWEAKED_CUBE_COADD");
202 break;
203 case DAR_CUBE_COADD:
204 cpl_msg_info(cpl_func,"type: DAR_CUBE_COADD");
205 break;
206 case STD_FLUX_CUBE_COADD_NOFLAT:
207 cpl_msg_info(cpl_func,"type: STD_FLUX_CUBE_COADD_NOFLAT");
208 break;
209 case STD_CUBE_COADD_NOFLAT:
210 cpl_msg_info(cpl_func,"type: STD_CUBE_COADD_NOFLAT");
211 break;
212 default:
213 cpl_msg_info(cpl_func,"type: DEFAULT %d",type);
214 break;
215 }
216
217 return;
218}
219cubeType
220eris_ifu_jitter_get_coadd_obj_type(cubeType type)
221{
222 cubeType coadd_type;
223 switch(type) {
224 case OBJECT_CUBE:
225 coadd_type = OBJECT_CUBE_COADD;
226 break;
227 case OBJECT_CUBE_COADD:
228 coadd_type = OBJECT_CUBE_COADD;
229 break;
230 case DAR_CUBE:
231 coadd_type = DAR_CUBE_COADD;
232 break;
233 case STD_CUBE:
234 coadd_type = STD_CUBE_COADD;
235 break;
236 case STD_CUBE_COADD:
237 coadd_type = STD_CUBE_COADD;
238 break;
239 case STD_FLUX_CUBE:
240 coadd_type = STD_FLUX_CUBE_COADD;
241 break;
242 case STD_FLUX_CUBE_COADD:
243 coadd_type = STD_FLUX_CUBE_COADD;
244 break;
245 case STD_FLUX_CUBE_COADD_NOFLAT:
246 coadd_type = STD_FLUX_CUBE_COADD_NOFLAT;
247 break;
248 case STD_CUBE_NOFLAT:
249 coadd_type = STD_CUBE_COADD_NOFLAT;
250 break;
251 case STD_CUBE_COADD_NOFLAT:
252 coadd_type = STD_CUBE_COADD_NOFLAT;
253 break;
254 case PSF_CUBE:
255 coadd_type = PSF_CUBE_COADD;
256 break;
257 case DAR_CUBE_COADD:
258 coadd_type = DAR_CUBE_COADD;
259 break;
260 case DAR_STD_CUBE_COADD:
261 coadd_type = STD_CUBE_COADD;
262 break;
263 case TWEAKED_CUBE_COADD:
264 coadd_type = TWEAKED_CUBE_COADD;
265 break;
266 default:
267 cpl_msg_warning(cpl_func,"case %d not found switch to default case",type);
268 coadd_type = OBJECT_CUBE_COADD;
269 break;
270 }
271
272 return coadd_type;
273}
274cubeType
275eris_ifu_jitter_get_obj_type(sofModes mode)
276{
277 cubeType type;
278 switch(mode) {
279 case SCIENCE:
280 type = OBJECT_CUBE;
281 break;
282 case STD:
283 type = STD_CUBE;
284 break;
285 case STD_FLUX:
286 type = STD_FLUX_CUBE;
287 break;
288 case PSF:
289 type = PSF_CUBE;
290 break;
291 default:
292 type = OBJECT_CUBE;
293 break;
294 }
295
296 return type;
297}
298cubeType
299eris_ifu_jitter_get_sky_type(sofModes mode)
300{
301 cubeType type;
302 switch(mode) {
303 case SCIENCE:
304 type = SKY_OBJECT_CUBE;
305 break;
306 case STD:
307 type = SKY_STD_CUBE;
308 break;
309 case STD_FLUX:
310 type = SKY_STD_FLUX_CUBE;
311 break;
312 case PSF:
313 type = SKY_PSF_CUBE;
314 break;
315 default:
316 type = SKY_OBJECT_CUBE;
317 break;
318 }
319 return type;
320}
321
322
323
324static cpl_error_code
325eris_ifu_jitter_save_cpl_cube(
326 cpl_frameset *allframes,
327 cpl_frameset *usedframes,
328 cpl_frame *inherit,
329 const cpl_parameterlist * parlist,
330 cpl_imagelist *cube,
331 hdrl_imagelist *hdrlCube,
332 cpl_imagelist *bpmCube,
333 cpl_propertylist *hdr,
334 struct paramStruct params,
335 cubeType type,
336 int counter,
337 const char* recipe_name)
338{
339 cpl_error_code retVal = CPL_ERROR_NONE;
340 char *proCatg = NULL;
341 char *filenamePrefix = NULL;
342 char *filename = NULL;
343
344 TRY
345 {
346 ASSURE(cube != NULL || hdrlCube != NULL,
347 CPL_ERROR_ILLEGAL_INPUT, "One of cube or hdrlCube must be not NULL");
348 ASSURE(!(cube != NULL && hdrlCube != NULL),
349 CPL_ERROR_ILLEGAL_INPUT, "One of cube or hdrlCube must be NULL");
350 eris_ifu_jitter_get_procatg_and_filename(type,&proCatg,&filenamePrefix);
351
352 if (counter >= 0) {
353 filename = cpl_sprintf("%s_%s_%3.3d.fits", recipe_name, filenamePrefix, counter);
354 } else {
355 filename = cpl_sprintf("%s_%s.fits", recipe_name, filenamePrefix);
356 }
357 cpl_propertylist_erase(hdr,"RADECSYS");
358 if (cube != NULL) {
359 eris_ifu_save_imagelist(allframes,
360 inherit,
361 hdr,
362 parlist,
363 recipe_name,
364 proCatg,
365 filename,
366 CPL_TYPE_FLOAT,
367 cube);
368 if (bpmCube != NULL) {
369 cpl_imagelist_save(bpmCube, filename, CPL_TYPE_INT,
370 NULL,CPL_IO_EXTEND);
371 }
372
373 } else {
374 cpl_imagelist *datacube = cpl_imagelist_new();
375 cpl_imagelist *errorcube = cpl_imagelist_new();
376 cpl_propertylist *applist = NULL;
377
378 // BRK_IF_NULL(applist = cpl_propertylist_new());
379 applist = cpl_propertylist_duplicate(hdr);
380 cpl_propertylist_update_string(applist, CPL_DFS_PRO_CATG, proCatg);
381
382 //TODO: Why adding CPL_DFS_PRO_TYPE, CPL_DFS_PRO_TECH ???
383 cpl_propertylist_update_string(applist, CPL_DFS_PRO_TYPE, "CUBE");
384 cpl_propertylist_update_string(applist, CPL_DFS_PRO_TECH, "CUBE");
385
386 eris_ifu_split_hdrl_imagelist(hdrlCube, datacube, errorcube);
387
388 cpl_imagelist *bpmMaskZero;
390 bpmCube, params.bpmThreshold);
391
392 /*
393 cpl_imagelist *bpmMaskZero = cpl_imagelist_new();
394 for (cpl_size iz=0; iz < cpl_imagelist_get_size(datacube); iz++) {
395 cpl_imagelist_set(bpmMaskZero,
396 cpl_image_new_from_mask(
397 hdrl_image_get_mask(
398 hdrl_imagelist_get(hdrlCube, iz)
399 )), iz);
400 CHECK_ERROR_STATE();
401 }
402 */
403
404 eris_ifu_save_deq_cube(allframes,
405 NULL,
406 parlist,
407 usedframes,
408 inherit,
409 recipe_name,
410 applist,
411 "RADECSYS",
412 filename,
413 datacube,
414 errorcube,
415 rmse,
416 bpmMaskZero,
417 maskzero/*,
418 CPL_TYPE_FLOAT */);
419
420 //cpl_imagelist_unwrap(datacube);
421 //cpl_imagelist_unwrap(errorcube);
422 cpl_imagelist_delete(datacube);
423 cpl_imagelist_delete(errorcube);
424 cpl_propertylist_delete(applist);
425 cpl_imagelist_delete(bpmMaskZero);
426 }
427 }
428 CATCH
429 {
430 retVal = cpl_error_get_code();
431 }
432
433 eris_ifu_free_string(&proCatg);
434 eris_ifu_free_string(&filenamePrefix);
435 eris_ifu_free_string(&filename);
436 eris_check_error_code("eris_ifu_jitter_save_cpl_cube");
437 return retVal;
438}
439
440/*---------------------------------------------------------------------------*/
451/*---------------------------------------------------------------------------*/
452static cpl_frameset*
453eris_ifu_frameset_extract_obj_set(const cpl_frameset* set, struct sofStruct* sof,
454 const cpl_size ix)
455{
456 //cpl_msg_info(cpl_func,"check inputs");
457 cpl_ensure(set, CPL_ERROR_NULL_INPUT, NULL);
458 cpl_ensure(sof, CPL_ERROR_NULL_INPUT, NULL);
459 cpl_ensure(ix >= 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
460 //cpl_ensure_code(out, CPL_ERROR_NULL_INPUT);
461
462 cpl_frameset * obj_set = NULL;
463 cpl_frameset * sky_set = NULL;
464 cpl_frameset * cdb_set = NULL;
465 cpl_frameset * out_set = NULL;
466
467 //cpl_msg_info(cpl_func,"select obj");
468 obj_set = cpl_frameset_new();
469 eris_ifu_extract_obj_frames(set, obj_set);
470 //cpl_frameset_dump(obj_set, stdout);
471
472 //cpl_msg_info(cpl_func,"select sky");
473 sky_set = cpl_frameset_new();
474 eris_ifu_extract_sky_frames(set, sky_set);
475 //cpl_frameset_dump(sky_set, stdout);
476
477 //cpl_msg_info(cpl_func,"select cdb");
478 cdb_set = cpl_frameset_new();
479 eris_ifu_extract_mst_frames(set, cdb_set);
480 //cpl_frameset_dump(cdb_set, stdout);
481
482 cpl_frame* frame = sof->exposureTable[ix].frame;
483// const char* fname = cpl_frame_get_filename(frame);
484
485 //cpl_msg_info(cpl_func,"put all together");
486 out_set = cpl_frameset_new();
487 cpl_frameset_insert(out_set, cpl_frame_duplicate(frame));
488 cpl_frameset_join(out_set, sky_set);
489 cpl_frameset_join(out_set, cdb_set);
490 //cpl_msg_info(cpl_func,"dumping");
491 //cpl_frameset_dump(out_set, stdout);
492
493 cpl_frameset_delete(obj_set);
494 cpl_frameset_delete(sky_set);
495 cpl_frameset_delete(cdb_set);
496 eris_check_error_code("eris_frameset_extract_obj_set");
497
498 return out_set;
499}
500
501cpl_error_code eris_ifu_jitter_process_exposures(struct sofStruct *sof,
502 struct stdParamStruct stdParams,
503 struct paramStruct params,
504 cpl_frameset *frameset,
505 const cpl_parameterlist * parlist,
506 const char* recipe_name,
507 const char* context)
508{
509 cpl_error_code retVal = CPL_ERROR_NONE;
510 hdrl_image *objImg = NULL;
511 hdrl_image *tmpImg = NULL;
512 struct exposureEntry *objEntry;
513 cpl_polynomial *ohLambdaCorrection = NULL;
514 productDepthType productDepth = stdParams.productDepth;
515 bool doOHbasedLambdaCorrection = FALSE;
516 cubeType type = OBJECT_CUBE;
517 const char *expType = NULL;
518 double cdelt = 0.;
519 double centralLambda = 0.0;
520 double shift = 0.0;
521 bool isSky = FALSE;
522
523 TRY
524 {
525 cpl_msg_info(cpl_func,"Build OBJ and SKY data cubes, may correct wavecal by OH lines, subtract sky background");
526
527 if ((sof->oh_ref_frame != NULL) && !params.skip_oh_align && !(isSky && params.skip_sky_oh_align)) {
528 doOHbasedLambdaCorrection = TRUE;
529 } else {
530 doOHbasedLambdaCorrection = FALSE;
531 }
532 cpl_msg_debug(cpl_func,"doOHbasedLambdaCorrection: %d, isSky: %d, "
533 "params.skip_sky_oh_align: %d, params.skip_oh_align: %d",
534 doOHbasedLambdaCorrection, isSky,
535 params.skip_sky_oh_align, params.skip_oh_align);
536
537 if (getenv("USE_OCS") != NULL) {
538 eris_ifu_update_wcs_with_OCS_keywords(sof);
539 }
540
541 for (int ix=0; ix < sof->exposureTableCnt; ix++) {
542 if (sof->exposureTable[ix].isObject) {
543 expType = "OBJ";
544 isSky = FALSE;
545 type = eris_ifu_jitter_get_obj_type(sof->mode);
546 } else {
547 expType = "SKY";
548 isSky = TRUE;
549 type = eris_ifu_jitter_get_sky_type(sof->mode);
550 }
551 cpl_msg_info(__func__, "Process exposure #\%3.3d %s %s", ix, expType,
552 cpl_frame_get_filename(sof->exposureTable[ix].frame));
553
554 objEntry = &sof->exposureTable[ix];
555 objImg = objEntry->rawImage;
556
557 // build OBJECT cube
559 objEntry->cube = eris_ifu_jitter_build_cube(
560 objImg, ix, sof, params, false,
561 ohLambdaCorrection, productDepth));
562
563 eris_ifu_free_polynomial(&ohLambdaCorrection);
564 // TODO: do lambda correct. with OH lines also for PS or STD OBS?
565
566 if (doOHbasedLambdaCorrection) {
567 // compute OH based lambda correction
568
569 /* to prevent memory leak delete cpl_polynomial structure */
570 eris_ifu_free_polynomial(&ohLambdaCorrection);
571
572 int pfit_order = 0;
573 char* param_name = cpl_sprintf("%s.oh_align_poly_order", context);
574 cpl_msg_info(cpl_func,"pname: %s",param_name);
575 pfit_order = cpl_parameter_get_int(cpl_parameterlist_find_const(parlist, param_name));
576 cpl_free(param_name);
577
578
579 BRK_IF_NULL( ohLambdaCorrection = eris_ifu_lcorr_get(NULL,
580 objEntry->cube, objEntry->cubeHdr, sof->oh_ref_peaks, pfit_order));
581
582 cdelt = cpl_propertylist_get_double(objEntry->cubeHdr, "CDELT3");
583 centralLambda = cpl_propertylist_get_double(
584 objEntry->cubeHdr, "CRVAL3") +
585 hdrl_imagelist_get_size(objEntry->cube) * cdelt * 0.5;
586 shift = cpl_polynomial_eval_1d(
587 ohLambdaCorrection, centralLambda, NULL);
588 cpl_msg_info(__func__,
589 "Overall shift of wavelength due OH lambda correction: %f [micron] %f [pixel]",
590 shift, shift/cdelt);
591
592 eris_ifu_free_hdrl_imagelist(&objEntry->cube);
593
594 tmpImg = eris_ifu_jitter_subtract_background(
595 params.skyTweak, ix, sof, productDepth);
596
597 objEntry->cube = eris_ifu_jitter_build_cube(
598 tmpImg, ix, sof, params, true,
599 ohLambdaCorrection, productDepth);
600
601 eris_ifu_free_polynomial(&ohLambdaCorrection);
602
604 objEntry->cubeHdr, "LAMBDA SHIFT UM", shift,
605 "[um] OH based lambda shift"));
607 objEntry->cubeHdr, "LAMBDA SHIFT PIXEL", shift/cdelt,
608 "[px] OH based lambda shift"));
609 } else {
610 if (params.skip_oh_align && (ix == 0)) {
611 cpl_msg_warning(cpl_func, " |------------------------------------------------------|");
612 cpl_msg_warning(cpl_func, " | WARNING: with parameter --sky_oh_align the spectral |");
613 cpl_msg_warning(cpl_func, " | calibration of the outputs is expected to |");
614 cpl_msg_warning(cpl_func, " | be off for several pixels due to flexure of |");
615 cpl_msg_warning(cpl_func, " | the instrument |");
616 cpl_msg_warning(cpl_func, " |------------------------------------------------------|");
617 }
618 }
619
620 if (productDepth >= PD_AUXILLIARY) {
621/*
622 cpl_imagelist *datacube = cpl_imagelist_new();
623 cpl_imagelist *errorcube = cpl_imagelist_new();
624 BRK_IF_ERROR(
625 eris_ifu_split_hdrl_imagelist(objEntry->cube, datacube, errorcube));
626*/
627
628/*
629 cpl_imagelist *bpmMaskZero;
630 BRK_IF_NULL(
631 bpmMaskZero = eris_ifu_interpolatedMasK_to_maskZero(
632 objEntry->cubeBpm, params.bpmThreshold));
633 for (cpl_size zx=0; zx<cpl_imagelist_get_size(datacube); zx++){
634 cpl_image *tmpImg = cpl_imagelist_get(datacube, zx);
635 cpl_mask *tmpMask = cpl_mask_threshold_image_create(
636 cpl_imagelist_get(objEntry->cubeBpm, zx), 0.5, 1.5);
637 cpl_image_reject_from_mask(tmpImg, tmpMask);
638 eris_ifu_free_mask(&tmpMask);
639 CHECK_ERROR_STATE();
640 }
641*/
642 // eris_ifu_jitter_save_cpl_cube(frameset, objEntry->frame, parlist,
643 // datacube, NULL, bpmMaskOne, objEntry->cubeHdr, params, type, ix, recipe_name);
644 cpl_frameset* obj_set =
645 eris_ifu_frameset_extract_obj_set(frameset, sof, ix);
646 eris_ifu_jitter_save_cpl_cube(frameset, obj_set, objEntry->frame, parlist,
647 NULL, objEntry->cube, objEntry->cubeBpm, objEntry->cubeHdr, params, type, ix, recipe_name);
648 eris_ifu_jitter_save_cpl_cube(frameset, obj_set, objEntry->frame, parlist,
649 objEntry->cubeBpm, NULL, NULL, objEntry->cubeHdr, params, BPM_CUBE, ix, recipe_name);
650 cpl_frameset_delete(obj_set);
651 }
652
653
654 cpl_boolean chop_nan = CPL_FALSE;
655 char* param_name = cpl_sprintf("%s.chop-nan", context);
656 //cpl_msg_info(cpl_func,"pname: %s",param_name);
657 chop_nan = cpl_parameter_get_bool(
658 cpl_parameterlist_find_const(parlist, param_name));
659 cpl_free(param_name);
660 if(chop_nan) {
661 ifsBand ifu_band = eris_ifu_get_band(objEntry->cubeHdr);
662 cpl_size zmin = 0;
663 cpl_size zmax = 0;
664 eris_ifu_get_plane_cut_min_max(ifu_band, &zmin, &zmax);
665 //cpl_msg_info(cpl_func,"check zmin: %lld zmax: %lld", zmin, zmax);
666
667 eris_ifu_cube_trim_nans(zmin, zmax, &(objEntry->cube),
668 &(objEntry->cubeBpm), objEntry->cubeHdr);
669 }
670
671
673 }
674 //AMO TODO STRANGE: added line: this fixes a leak but creates another problem
675 //eris_ifu_free_hdrl_imagelist(&objEntry->cube);
676 }
677 CATCH
678 {
679 retVal = cpl_error_get_code();
680 }
681 eris_ifu_free_polynomial(&ohLambdaCorrection);
683 eris_check_error_code("eris_ifu_jitter_process_exposures");
684 return retVal;
685}
686static cpl_error_code
687eris_ifu_jitter_skycorr_from_mask(struct exposureEntry *objEntry,
688 const cpl_mask*mask_obj, const int sky_est_method)
689{
690
691 cpl_image* ima;
692 cpl_image* err;
693 cpl_mask* bpm;
694 hdrl_image* himg;
695 cpl_size skip = ERIS_IFU_SKIP_SKY_CORR_PLANES;
696 cpl_size size_z = hdrl_imagelist_get_size(objEntry->cube);
697
698 hdrl_value sky = {0, 0};
699 for (cpl_size zx = skip; zx < size_z - skip; zx++){
700 //cpl_msg_info(cpl_func,"zx: %lld",zx);
701
702 himg = hdrl_imagelist_get(objEntry->cube, zx);
703 ima = hdrl_image_get_image(himg);
704 err = hdrl_image_get_error(himg);
705 bpm = hdrl_image_get_mask(himg);
706
707 hdrl_image_reject_from_mask(himg, mask_obj);
708 if(sky_est_method==0) {
709 sky = hdrl_image_get_median(himg);
710 } else {
711 sky = hdrl_image_get_mean(himg);
712 }
713
714 himg = hdrl_image_create(ima, err);
716 hdrl_image_sub_scalar(himg, sky);
717
719 hdrl_imagelist_set(objEntry->cube, hdrl_image_duplicate(himg), zx);
720 hdrl_image_delete(himg);
721
722 if(cpl_error_get_code() != CPL_ERROR_NONE) {
723 eris_check_error_code("eris_ifu_jitter_skycorr_from_mask");
724 cpl_msg_error(cpl_func,"Error found in eris_ifu_jitter_skycorr_from_mask. Exit!");
725 exit(0);
726 }
727 }
728 eris_check_error_code("eris_ifu_jitter_skycorr_from_mask");
729 return cpl_error_get_code();
730
731}
732static cpl_error_code
733eris_ifu_jitter_get_split_param_int(const cpl_parameterlist * parlist,
734 const char* pname, const int min_x, const int min_y,
735 const int max_x, const int max_y, int* px, int* py)
736{
737
738 const cpl_parameter* par = NULL;
739 char* param_name;
740 const char* context = "eris.eris_ifu_jitter";
741
742 const char* pname_string_value;
743 param_name = cpl_sprintf("%s.%s", context, pname);
744 par = cpl_parameterlist_find_const(parlist, param_name);
745 pname_string_value = cpl_parameter_get_string(par);
746 cpl_free(param_name);
747
748 int nFields;
749 unsigned int end;
750
751 nFields = sscanf(pname_string_value, "%d,%d%n", px, py, &end);
752
753 if (nFields != 2 || end != strlen(pname_string_value)) {
754 cpl_msg_error(cpl_func, "The %s parameter must be "
755 "a list of two integers separated by a comma", pname);
756 printf("Error reading sky-box-center string\n");
757 }
758
759 if (*px < min_x) {
760 cpl_msg_warning(cpl_func,"%s_x: %d set it to 0",pname, *px);
761 *px = 0;
762 }
763 if (*py < min_y) {
764 cpl_msg_warning(cpl_func,"%s_y: %d set it to 0",pname, *py);
765 *py = 0;
766 }
767 if (*px > max_x) {
768 cpl_msg_warning(cpl_func,"%s_x: %d set it to 10",pname, *px);
769 *px = 10;
770 }
771 if (*py > max_y) {
772 cpl_msg_warning(cpl_func,"%s_y: %d set it to 10", pname, *py);
773 *py = 10;
774 }
775 /*
776 cpl_msg_debug(cpl_func,"%s_x: %d, %s_y: %d",
777 pname, *px, pname, *py);
778 */
779 eris_check_error_code("eris_ifu_jitter_get_split_param_int");
780 return cpl_error_get_code();
781}
782
783static cpl_error_code
784eris_ifu_jitter_skycor_from_box(const cpl_parameterlist * parlist,
785 struct exposureEntry *objEntry, const int aj_method)
786{
787
788 int sky_box_center_x, sky_box_center_y,
789 sky_box_width_x, sky_box_width_y,
790 sky_box_edges_margin_x, sky_box_edges_margin_y;
791
792 eris_ifu_jitter_get_split_param_int(parlist,"sky-box-center", 0, 0, 64, 64,
793 &sky_box_center_x, &sky_box_center_y);
794 eris_ifu_jitter_get_split_param_int(parlist,"sky-box-width", 0, 0, 10, 10,
795 &sky_box_width_x, &sky_box_width_y);
796 eris_ifu_jitter_get_split_param_int(parlist,"sky-box-edges-margin", 0, 0, 10, 10,
797 &sky_box_edges_margin_x, &sky_box_edges_margin_y);
798
799
800 cpl_msg_info(cpl_func,"sky_box_center_x: %d sky_box_center_y: %d",
801 sky_box_center_x, sky_box_center_y);
802 cpl_msg_info(cpl_func,"sky_box_width_x: %d sky_box_width_y: %d",
803 sky_box_width_x, sky_box_width_y);
804 cpl_msg_info(cpl_func,"sky_box_edges_margin_x: %d sky_box_edges_margin_y: %d",
805 sky_box_edges_margin_x, sky_box_edges_margin_y);
806
807
808
809 char* param_name;
810 int sky_est_method = -1;
811 const char* context = "eris.eris_ifu_jitter";
812 const cpl_parameter* p = NULL;
813
814 param_name = cpl_sprintf("%s.sky-est-method", context);
815 p = cpl_parameterlist_find_const(parlist, param_name);
816 if(p != NULL) {
817 sky_est_method = cpl_parameter_get_int(p);
818 }
819 cpl_free(param_name);
820
821 int niter = 5;
822
823 param_name = cpl_sprintf("%s.sky-est-niter", context);
824 p = cpl_parameterlist_find_const(parlist, param_name);
825 if(p != NULL) {
826 niter = cpl_parameter_get_int(p);
827 }
828 cpl_free(param_name);
829
830 int kappa = 3;
831 param_name = cpl_sprintf("%s.sky-est-kappa", context);
832 p = cpl_parameterlist_find_const(parlist, param_name);
833 if(p != NULL) {
834 kappa = cpl_parameter_get_double(p);
835 }
836 cpl_free(param_name);
837
838 /* apply correction based on user defined parameters */
839 cpl_image* img = NULL;
840 hdrl_image* himg = NULL;
841 hdrl_value sky = {0, 0};
842 cpl_size llx = 0 , urx = 0, lly = 0 , ury = 0 ;
843 cpl_msg_info(cpl_func,"llx, lly, urx, ury, [%lld,%lld,%lld,%lld]",
844 llx,lly,urx,ury);
845 /* TODO: Handle start/end wave ranges where object is NAN */
846 cpl_size skip = ERIS_IFU_SKIP_SKY_CORR_PLANES;
847 /*
848 cpl_imagelist* before = cpl_imagelist_new();
849 cpl_imagelist* after = cpl_imagelist_new();
850 for (cpl_size zx = 0;zx<hdrl_imagelist_get_size(objEntry->cube);zx++){
851 himg = hdrl_imagelist_get(objEntry->cube, zx);
852 img = hdrl_image_get_image(himg);
853 cpl_imagelist_set(before, img, zx);
854 }
855 cpl_imagelist_save(before, "cube_before.fits", CPL_TYPE_INT,
856 NULL, CPL_IO_DEFAULT);
857 */
858 cpl_bivector* xy_pos = NULL;
859 cpl_vector* sky_data = NULL;
860 double* x_pos = NULL;
861 double* y_pos = NULL;
862
863 cpl_size size_x = hdrl_imagelist_get_size_x(objEntry->cube);
864 cpl_size size_y = hdrl_imagelist_get_size_y(objEntry->cube);
865 if(aj_method == 5) {
866 xy_pos = cpl_bivector_new(4);
867 sky_data = cpl_vector_new(4);
868 x_pos = cpl_bivector_get_x_data(xy_pos);
869 y_pos = cpl_bivector_get_y_data(xy_pos);
870
871 x_pos[0] = sky_box_edges_margin_x + sky_box_width_x;
872 y_pos[0] = sky_box_edges_margin_y + sky_box_width_y;
873
874 x_pos[1] = sky_box_edges_margin_x + sky_box_width_x;
875 y_pos[1] = size_y - sky_box_edges_margin_y - sky_box_width_y;
876
877 x_pos[2] = size_x - sky_box_edges_margin_x - sky_box_width_x;
878 y_pos[2] = sky_box_edges_margin_y + sky_box_width_y;
879
880 x_pos[3] = size_x - sky_box_edges_margin_x - sky_box_width_x;
881 y_pos[3] = size_y - sky_box_edges_margin_y - sky_box_width_y;
882
883 }
884
885 if(aj_method == 6) {
886 xy_pos = cpl_bivector_new(8);
887 sky_data = cpl_vector_new(8);
888 x_pos = cpl_bivector_get_x_data(xy_pos);
889 y_pos = cpl_bivector_get_y_data(xy_pos);
890
891
892 x_pos[0] = sky_box_edges_margin_x + sky_box_width_x;
893 y_pos[0] = sky_box_edges_margin_y + sky_box_width_y;
894
895 x_pos[1] = sky_box_edges_margin_x + sky_box_width_x;
896 y_pos[1] = size_y - sky_box_edges_margin_y - sky_box_width_y;
897
898 x_pos[2] = size_x - sky_box_edges_margin_x - sky_box_width_x;
899 y_pos[2] = sky_box_edges_margin_y + sky_box_width_y;
900
901 x_pos[3] = size_x - sky_box_edges_margin_x - sky_box_width_x;
902 y_pos[3] = size_y - sky_box_edges_margin_y - sky_box_width_y;
903
904
905
906 x_pos[4] = floor(0.5 * size_x);
907 y_pos[4] = sky_box_edges_margin_y + sky_box_width_y;
908
909 x_pos[5] = sky_box_edges_margin_x + sky_box_width_x;
910 y_pos[5] = floor(0.5 * size_y);
911
912 x_pos[6] = size_x - sky_box_edges_margin_x - sky_box_width_x;
913 y_pos[6] = floor(0.5 * size_y);
914
915 x_pos[7] = floor(0.5 * size_x);
916 y_pos[7] = size_y - sky_box_edges_margin_y - sky_box_width_y;
917
918 }
919
920 cpl_size size_z = hdrl_imagelist_get_size(objEntry->cube);
921 double sky_tmp_val = 0;
922 if(aj_method == 4) {
923 llx = sky_box_center_x - sky_box_width_x;
924 urx = sky_box_center_x + sky_box_width_x;
925 lly = sky_box_center_y - sky_box_width_y;
926 ury = sky_box_center_y + sky_box_width_y;
927 for (cpl_size zx = skip; zx < size_z - skip; zx++){
928 //cpl_msg_info(cpl_func,"zx: %lld",zx);
929 himg = hdrl_imagelist_get(objEntry->cube, zx);
930 img = hdrl_image_get_image(himg);
931 /* the following may fail at start end wave ranges */
932 if(sky_est_method==0) {
933 sky.data = cpl_image_get_median_window(img, llx, lly, urx, ury);
934 } else {
935 sky.data = cpl_image_get_mean_window(img, llx, lly, urx, ury);
936 }
937 hdrl_image_sub_scalar(himg, sky);
938 hdrl_imagelist_set(objEntry->cube, himg, zx);
939 }
940 } else if(aj_method == 5 || aj_method == 6) {
941 cpl_size xy_pos_size = cpl_bivector_get_size(xy_pos);
942 double* psky_data = cpl_vector_get_data(sky_data);
943 for (cpl_size zx = skip; zx < size_z - skip; zx++){
944
945 himg = hdrl_imagelist_get(objEntry->cube, zx);
946 img = hdrl_image_get_image(himg);
947 /* the following may fail at start end wave ranges */
948 for (cpl_size k = 0; k < xy_pos_size; k++){
949 llx = ((cpl_size) x_pos[k] - sky_box_width_x);
950 lly = ((cpl_size) y_pos[k] - sky_box_width_y);
951 urx = ((cpl_size) x_pos[k] + sky_box_width_x);
952 ury = ((cpl_size) y_pos[k] + sky_box_width_y);
953 //cpl_msg_info(cpl_func,"llx, lly, urx, ury: [%lld,%lld,%lld,%lld]",llx, lly, urx, ury);
954 if(sky_est_method==0) {
955 sky_tmp_val = cpl_image_get_median_window(img, llx, lly, urx, ury);
956 if(cpl_error_get_code() != CPL_ERROR_NONE) {
957 cpl_error_reset();
958 continue;
959 } else {
960 psky_data[k] = sky_tmp_val;
961 }
962
963 } else {
964 sky_tmp_val = cpl_image_get_mean_window(img, llx, lly, urx, ury);
965 if(cpl_error_get_code() != CPL_ERROR_NONE) {
966 cpl_error_reset();
967 continue;
968 } else {
969 psky_data[k] = sky_tmp_val;
970 }
971 }
972 if(cpl_error_get_code() != CPL_ERROR_NONE) {
973 cpl_msg_error(cpl_func,"Some error during sky modeling: "
974 "try to use a different region or other aj-method");
975 eris_check_error_code("eris_ifu_jitter_skycor_from_box");
976 exit(0);
977 }
978 }
979 if(sky_est_method==0) {
980 sky.data = cpl_vector_get_median(sky_data);
981 } else {
982 sky.data = cpl_vector_get_mean(sky_data);
983 }
984 hdrl_image_sub_scalar(himg, sky);
985 hdrl_imagelist_set(objEntry->cube, himg, zx);
986 }
987 } else if(aj_method == 7) {
988
989 hdrl_image* cube_collapsed = NULL;
990 cpl_image* cube_cmap = NULL;
991 hdrl_imagelist_collapse_mean(objEntry->cube, &cube_collapsed, &cube_cmap);
992 /*
993 cpl_image_save(hdrl_image_get_image(cube_collapsed), "collapsed_mean.fits",
994 CPL_TYPE_FLOAT, NULL, CPL_IO_DEFAULT);
995 cpl_image_save(cube_cmap, "cube_cmap.fits", CPL_TYPE_FLOAT, NULL,
996 CPL_IO_DEFAULT);
997 */
998 cpl_mask* mask_obj;
999
1000 mask_obj = eris_ifu_hima_get_obj_mask(cube_collapsed, niter, kappa);
1001
1002 hdrl_image_delete(cube_collapsed);
1003 cpl_image_delete(cube_cmap);
1004
1005 eris_ifu_jitter_skycorr_from_mask(objEntry, mask_obj, sky_est_method);
1006
1007 cpl_mask_delete(mask_obj);
1008 } else if(aj_method == 8) {
1009 hdrl_image* cube_mean = NULL;
1010 cpl_image* cube_cmap = NULL;
1011 hdrl_imagelist_collapse_mean(objEntry->cube, &cube_mean, &cube_cmap);
1012 cpl_mask* mask_obj = eris_ifu_hima_get_obj_mask_percent(cube_mean, 0.25);
1013
1014 hdrl_image_delete(cube_mean);
1015 cpl_image_delete(cube_cmap);
1016 eris_ifu_jitter_skycorr_from_mask(objEntry, mask_obj, sky_est_method);
1017 cpl_mask_delete(mask_obj);
1018 }
1019
1020 /*
1021 for (cpl_size zx = 0;zx<hdrl_imagelist_get_size(objEntry->cube);zx++){
1022 himg = hdrl_imagelist_get(objEntry->cube, zx);
1023 img = hdrl_image_get_image(himg);
1024 cpl_imagelist_set(after, img, zx);
1025 }
1026
1027 cpl_imagelist_save(after, "cube_after.fits",
1028 CPL_TYPE_INT, NULL, CPL_IO_DEFAULT);
1029 */
1030
1031
1032 eris_check_error_code("eris_ifu_jitter_skycor_from_box");
1033 return cpl_error_get_code();
1034
1035}
1036
1037cpl_error_code eris_ifu_jitter_process_cubes(struct sofStruct *sof,
1038 struct stdParamStruct stdParams,
1039 struct paramStruct params,
1040 cpl_frameset *frameset,
1041 const cpl_parameterlist * parlist,
1042 const char* recipe_name,
1043 cubeType *obj_type)
1044{
1045 cpl_error_code retVal = CPL_ERROR_NONE,
1046 err = CPL_ERROR_NONE;
1047 struct exposureEntry *objEntry = NULL,
1048 *skyEntry = NULL;
1049 cpl_mask *tmpMask = NULL;
1050 hdrl_image *tmpImg = NULL;
1051 cpl_size imgSize = 0;
1052 double *pObjErr = NULL,
1053 *pSkyErr = NULL,
1054 *pTweakedErr = NULL;
1055 cpl_binary *pObjMask = NULL,
1056 *pErrMask = NULL,
1057 *pTweakedMask = NULL;
1058
1059 TRY
1060 {
1061 cpl_msg_info(cpl_func, "Process Jitter Cubes: split Obj & Sky, correct Sky as user specified");
1062
1063 for (int ix = 0; ix < sof->exposureTableCnt; ix++) {
1064 if (!sof->exposureTable[ix].isObject) {
1065 continue; // loop only over OBJECT cubes, skip SKY
1066 }
1067 objEntry = &sof->exposureTable[ix];
1068 cpl_frameset* obj_set =
1069 eris_ifu_frameset_extract_obj_set(frameset, sof, ix);
1070 // apply skytweak if desired
1071 if (params.skyTweak != NONE) {
1072 int skyIndex = objEntry->skyIndex;
1073 if (skyIndex < 0) {
1074 BRK_WITH_ERROR_MSG(CPL_ERROR_DATA_NOT_FOUND,
1075 "no vaild sky frame found");
1076 }
1077 skyEntry = &sof->exposureTable[skyIndex];
1078
1079 if (skyEntry->cube == NULL) {
1080 cpl_msg_error(__func__,
1081 "Missing sky image for input frame %s",
1082 cpl_frame_get_filename(objEntry->frame));
1083 } else {
1084 cpl_imagelist *dataCubeObj = cpl_imagelist_new(),
1085 *errCubeObj = cpl_imagelist_new(),
1086 *dataCubeSky = cpl_imagelist_new(),
1087 *errCubeSky = cpl_imagelist_new();
1088
1090 eris_ifu_split_hdrl_imagelist(objEntry->cube,
1091 dataCubeObj, errCubeObj));
1093 eris_ifu_split_hdrl_imagelist(skyEntry->cube,
1094 dataCubeSky, errCubeSky));
1095
1096 if (params.skyTweak == DAVIES) {
1097 cpl_imagelist *skycorrObj = NULL,
1098 *skycorrSky = NULL,
1099 *skycorrErr = NULL;
1100
1101 skycorrObj = eris_ifu_sky_tweak(dataCubeObj, dataCubeSky,
1102 objEntry->cubeHdr, .3,
1103 params.tbsub,
1104 params.discard_subband,
1105 params.stretch_sky,
1106 params.stretch_degree,
1107 params.stretch_resampling,
1108 0, &skycorrSky);
1109
1110 /*
1111 * simple error calculation for sky tweaked cube
1112 * as sky tweaked cube is basically objject cube - sky cube
1113 * the error is sqrt(objectError^2 + skyError^2)
1114 */
1116 skycorrErr = cpl_imagelist_duplicate(errCubeObj));
1117
1118 imgSize = cpl_image_get_size_x(cpl_imagelist_get(skycorrErr, 0)) *
1119 cpl_image_get_size_y(cpl_imagelist_get(skycorrErr, 0));
1120
1121 for (cpl_size tx = 0; tx < cpl_imagelist_get_size(skycorrErr); tx++) {
1122 pObjErr = cpl_image_get_data_double(
1123 cpl_imagelist_get(errCubeObj,tx));
1124 pSkyErr = cpl_image_get_data_double(
1125 cpl_imagelist_get(errCubeSky,tx));
1126 pTweakedErr = cpl_image_get_data_double(
1127 cpl_imagelist_get(skycorrErr,tx));
1128 pObjMask = cpl_mask_get_data(
1129 cpl_image_get_bpm(cpl_imagelist_get(errCubeObj,tx)));
1130 pErrMask = cpl_mask_get_data(
1131 cpl_image_get_bpm(cpl_imagelist_get(errCubeSky,tx)));
1132 pTweakedMask = cpl_mask_get_data(
1133 cpl_image_get_bpm(cpl_imagelist_get(skycorrErr,tx)));
1134
1135 for (cpl_size rx = 0; rx < imgSize; rx++) {
1136 if ((pObjMask[rx] != BAD_PIX) &&
1137 (pErrMask[rx] != BAD_PIX))
1138 {
1139 pTweakedMask[rx] = GOOD_PIX;
1140 pTweakedErr[rx] = hypot(pObjErr[rx], pSkyErr[rx]);
1141 } else {
1142 pTweakedMask[rx] = BAD_PIX;
1143 }
1144 }
1145 }
1146
1147 // agudo: Possible memory leak here when objEntry->cube is overwritten?
1148 // It isn't deleted anywhere beforehand
1150 objEntry->cube = hdrl_imagelist_create(skycorrObj, skycorrErr));
1151
1152 eris_ifu_free_imagelist(&skycorrObj);
1153 eris_ifu_free_imagelist(&skycorrErr);
1154 //To delete the following two creates a seg fault
1155 eris_ifu_free_imagelist(&dataCubeSky);
1156 eris_ifu_free_imagelist(&errCubeSky);
1157 eris_ifu_free_imagelist(&dataCubeObj);
1158 eris_ifu_free_imagelist(&errCubeObj);
1159
1160 if ((stdParams.productDepth >= PD_DEBUG) && (skycorrSky != NULL)) {
1161 char *fname = cpl_sprintf(
1162 "eris_ifu_jitter_dbg_skycoorsky_%3.3d.fits", skyIndex);
1163 cpl_imagelist_save(skycorrSky, fname,
1164 CPL_TYPE_FLOAT, NULL, CPL_IO_CREATE);
1165 eris_ifu_free_string(&fname);
1166 }
1167
1168 eris_ifu_free_imagelist(&skycorrSky);
1170 }
1171 else if (params.skyTweak == AUSTRIAN) {
1172 cpl_table *objspec = NULL,
1173 *skyspec = NULL;
1174 cpl_parameterlist *parlist_skycorr = NULL;
1175 double ts = cpl_test_get_walltime();
1176
1177 // loop through all pixels of the image and apply skycorr
1178 cpl_size nx = hdrl_imagelist_get_size_x(objEntry->cube);
1179 cpl_size ny = hdrl_imagelist_get_size_y(objEntry->cube);
1180
1181 // create parameterlist for skycorr
1183 parlist_skycorr = eris_ifu_skycorr_create_parlist(skyEntry->cubeHdr));
1184
1185// agudo: couldn't successfully extract this code from sc_skycorr, so keep reading in txt files for every spectrum
1186// /* Read line groups from ASCII file and adapt it to observing conditions */
1187// cpl_table *groups = cpl_table_new(0);
1188// BRK_IF_ERROR(
1189// sc_lines(groups, parlist_skycorr));
1190
1191 // in y we increment by 2 because the iamge is already scaled by 2 here
1192 for (cpl_size y = 1; y <= ny; y += 2) {
1193 if (stdParams.productDepth == 3) {
1194 cpl_msg_debug(cpl_func, ">>>>> line %d", (int)y);
1195 }
1196 for (cpl_size x = 1; x <= nx; x++) {
1197 int success = CPL_FALSE;
1198 if (stdParams.productDepth == 3) {
1199 cpl_msg_debug(cpl_func, ">>>>> pix (%d/%d)", (int)x, (int)y);
1200 }
1202 objspec = eris_ifu_skycorr_extract_spectrum(objEntry->cube, objEntry->cubeHdr, x, y));
1204 skyspec = eris_ifu_skycorr_extract_spectrum(skyEntry->cube, skyEntry->cubeHdr, x, y));
1205
1206 if (stdParams.productDepth == 3) {
1207 char* fn = NULL;
1208
1209// cpl_table *t = NULL;
1210// t = cpl_table_duplicate(objspec);
1211// cpl_table_erase_column(t, "weight");
1212// cpl_table_erase_column(t, "mask_I");
1213// fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_objspec.fits", (int)x, (int)y);
1214// cpl_table_save(t, NULL, objEntry->cubeHdr, fn, CPL_IO_CREATE);
1215// cpl_free(fn);
1216
1217// fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_objspec_vector.fits", (int)x, (int)y);
1218// double *pt = cpl_table_get_data_double (t, "flux");
1219// cpl_vector *vt = cpl_vector_wrap(cpl_table_get_nrow(t), pt);
1220// eris_ifu_save_vector_dbg(vt, fn, CPL_IO_CREATE, objEntry->cubeHdr);
1221// cpl_free(fn);
1222
1223// cpl_table_delete(t); t = NULL;
1224// t = cpl_table_duplicate(skyspec);
1225// cpl_table_erase_column(t, "weight");
1226// cpl_table_erase_column(t, "mask_I");
1227// fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_skyspec.fits", (int)x, (int)y);
1228// cpl_table_save(t, NULL, skyEntry->cubeHdr, fn, CPL_IO_CREATE);
1229// cpl_free(fn);
1230// cpl_table_delete(t); t = NULL;
1231
1232 fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_objspec_1_orig.fits", (int)x, (int)y);
1233 cpl_table_save(objspec, NULL, objEntry->cubeHdr, fn, CPL_IO_CREATE);
1234 cpl_free(fn);
1235 fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_skyspec_1_orig.fits", (int)x, (int)y);
1236 cpl_table_save(skyspec, NULL, skyEntry->cubeHdr, fn, CPL_IO_CREATE);
1237 cpl_free(fn);
1238 }
1239
1240 /* prepare skycorr code */
1241 double mean_lambda = 0.5 * (cpl_table_get(objspec, "lambda", 0, NULL) +
1242 cpl_table_get(objspec, "lambda", cpl_table_get_nrow(objspec)-1, NULL));
1243 cpl_parameter *p = cpl_parameterlist_find(parlist_skycorr, "meanlam");
1244 cpl_parameter_set_double(p, mean_lambda);
1245
1246 double mean_obj_flux = cpl_table_get_column_mean(objspec, "flux"),
1247 mean_sky_flux = cpl_table_get_column_mean(skyspec, "flux");
1248
1249 // ignore spectra which have thoroughly a flux of zero
1250 if ((fabs(mean_obj_flux) > 0.00001) && (fabs(mean_sky_flux) > 0.00001)) {
1251 // tweak outliers that are larger than 10 times than average
1252 int outlier_factor = 10;
1254 eris_ifu_skycorr_flatten_outliers(objspec, skyspec, outlier_factor));
1255
1256 // alternatively remove outliers as good as possible (but we risk to remove as well OH lines etc.)
1257 // double min_frac = 0.5;
1258 // BRK_IF_ERROR(
1259 // eris_ifu_skycorr_flatten_outliers2(objspec, skyspec, min_frac));
1260
1261 if (stdParams.productDepth == 3) {
1262 char* fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_objspec_2_flatten1.fits", (int)x, (int)y);
1263 cpl_table_save(objspec, NULL, objEntry->cubeHdr, fn, CPL_IO_CREATE);
1264 cpl_free(fn);
1265 fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_skyspec_2_flatten1.fits", (int)x, (int)y);
1266 cpl_table_save(skyspec, NULL, skyEntry->cubeHdr, fn, CPL_IO_CREATE);
1267 cpl_free(fn);
1268 }
1269
1270 err = sc_skycorr(parlist_skycorr, objspec, skyspec, /*groups,*/ stdParams.productDepth);
1271 if (err != CPL_ERROR_NONE) {
1272 // reset error
1273 cpl_errorstate_set(CPL_ERROR_NONE);
1274 err = CPL_ERROR_NONE;
1276
1277 // tweak outliers again that are larger than 8 times than average (seems not really to help...)
1278 outlier_factor = 8;
1280 eris_ifu_skycorr_flatten_outliers(objspec, skyspec, outlier_factor));
1281
1282 if (stdParams.productDepth == 3) {
1283 char* fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_objspec_3_flatten2.fits", (int)x, (int)y);
1284 cpl_table_save(objspec, NULL, objEntry->cubeHdr, fn, CPL_IO_CREATE);
1285 cpl_free(fn);
1286 fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_skyspec_3_flatten2.fits", (int)x, (int)y);
1287 cpl_table_save(skyspec, NULL, skyEntry->cubeHdr, fn, CPL_IO_CREATE);
1288 cpl_free(fn);
1289 }
1290
1291 err = sc_skycorr(parlist_skycorr, objspec, skyspec, /*groups, */stdParams.productDepth);
1292 if (err != CPL_ERROR_NONE) {
1293 // give up sky correcting...
1294 cpl_errorstate_set(CPL_ERROR_NONE);
1295 err = CPL_ERROR_NONE;
1297 } else {
1298 success = CPL_TRUE;
1299 }
1300 } else {
1301 success = CPL_TRUE;
1302 }
1303 }
1304
1305 if (success == CPL_FALSE) {
1306 // do what? -> insert blank spectrum
1307 if (stdParams.productDepth == 3) {
1308 cpl_msg_debug(cpl_func, ">>>>> inserted blank spectrum");
1309 char* fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_objspec_4_failed.fits", (int)x, (int)y);
1310 cpl_table_save(objspec, NULL, objEntry->cubeHdr, fn, CPL_IO_CREATE);
1311 cpl_free(fn);
1312 fn = cpl_sprintf("%d_%d_eris_ifu_jitter_dbg_skyspec_4_failed.fits", (int)x, (int)y);
1313 cpl_table_save(skyspec, NULL, skyEntry->cubeHdr, fn, CPL_IO_CREATE);
1314 cpl_free(fn);
1315 }
1316 eris_ifu_free_table(&objspec);
1318 objspec = eris_ifu_skycorr_create_nan_spectrum(objEntry->cube));
1319 }
1321 eris_ifu_skycorr_insert_spectrum(objEntry->cube, objspec, x, y));
1322
1323 eris_ifu_free_table(&objspec);
1324 eris_ifu_free_table(&skyspec);
1326 } // end for: x <= nx
1327 } // end for: y <= ny
1328 eris_ifu_free_parameterlist(&parlist_skycorr);
1329
1330 double te = cpl_test_get_walltime();
1331 cpl_msg_debug(cpl_func,">>>>> >>>>> skycorr took %g seconds", te - ts);
1332// eris_ifu_free_table(&groups);
1333 } // end if: AUSTRIAN
1334 } // end else: (skyEntry->cube != NULL)
1335
1336 if (!cpl_propertylist_has(objEntry->cubeHdr,"PRODCATG")) {
1337 cpl_propertylist_append_string(objEntry->cubeHdr, "PRODCATG",
1338 PRODCATG_CUBE_OBJ);
1339 }
1340
1342 eris_ifu_jitter_save_cpl_cube(frameset, obj_set, objEntry->frame, parlist,
1343 NULL, objEntry->cube, objEntry->cubeBpm, objEntry->cubeHdr,
1344 params, TWEAKED_CUBE, ix, recipe_name));
1345 } /* end sky tweak handling */
1346 cpl_frameset_delete(obj_set);
1348
1349 char* param_name;
1350 int aj_method = -1;
1351 const char* context = "eris.eris_ifu_jitter";
1352 param_name = cpl_sprintf("%s.aj-method", context);
1353 const cpl_parameter* p = NULL;
1354 p = cpl_parameterlist_find_const(parlist, param_name);
1355 if (p != NULL) {
1356 aj_method = cpl_parameter_get_int(p);
1357 }
1358 cpl_free(param_name);
1359
1360 if((objEntry->skyIndex < 0) && (aj_method > 3)) {
1361 /* Handle sky subtraction in cas no sky frame is present */
1362 eris_ifu_jitter_skycor_from_box(parlist, objEntry, aj_method);
1363 }
1364
1365 if (params.darCorrection) {
1366 for (cpl_size zx = 0;zx<hdrl_imagelist_get_size(objEntry->cube);zx++){
1367 tmpImg= hdrl_imagelist_get(objEntry->cube, zx);
1368 tmpMask = cpl_mask_threshold_image_create(cpl_imagelist_get(objEntry->cubeBpm, zx), params.bpmThreshold, 1.5);;
1369 hdrl_image_reject_from_mask(tmpImg, tmpMask);
1370 eris_ifu_free_mask(&tmpMask);
1372 }
1374 eris_ifu_dar_correction(objEntry->cube,
1375 objEntry->cubeHdr, /*objEntry->cubeBpm,*/
1376 params.darShiftMethod,
1377 params.darShiftWidth, params.darShiftLength));
1378 cpl_frameset* obj_set2 =
1379 eris_ifu_frameset_extract_obj_set(frameset, sof, ix);
1380
1381 eris_ifu_jitter_save_cpl_cube(frameset, obj_set2,
1382 sof->exposureTable[ix].frame, parlist, NULL,
1383 objEntry->cube, objEntry->cubeBpm, objEntry->cubeHdr,
1384 params, DAR_CUBE, ix, recipe_name);
1385 cpl_frameset_delete(obj_set2);
1386 }
1387 } // end for: ix < sof->exposureTableCnt
1388
1389 cubeType sky_type = SKY_OBJECT_CUBE;
1390 /* TODO: In case of only one OBJ (or STD or PSF) input we need to create
1391 * a cube object. Why? */
1392 char *proCatg = NULL;
1393 char *filenamePrefix = NULL;
1394 *obj_type = eris_ifu_jitter_get_obj_type(sof->mode);
1395 eris_ifu_jitter_get_procatg_and_filename(*obj_type, &proCatg, &filenamePrefix);
1396 eris_ifu_free_string(&filenamePrefix);
1397 cpl_frameset* cube_set;
1398 if ((cube_set = eris_ifu_extract_frameset(frameset, proCatg )) == NULL){
1399 for(cpl_size i = 0; i < sof->exposureTableCnt; i++) {
1400 if (!cpl_propertylist_has(sof->exposureTable[i].cubeHdr,"PRODCATG")) {
1401 cpl_propertylist_append_string(sof->exposureTable[i].cubeHdr,
1402 "PRODCATG", "ANCILLARY.EXPMAP");
1403 }
1404
1405 if (sof->exposureTable[i].isObject) {
1406 cpl_frameset* obj_set =
1407 eris_ifu_frameset_extract_obj_set(frameset, sof, i);
1408 *obj_type = eris_ifu_jitter_get_obj_type(sof->mode);
1409 eris_ifu_jitter_save_cpl_cube(frameset, obj_set,
1410 sof->exposureTable[i].frame,
1411 parlist, NULL, sof->exposureTable[i].cube,
1412 sof->exposureTable[i].cubeBpm,
1413 sof->exposureTable[i].cubeHdr,
1414 params, *obj_type, i, recipe_name);
1415 cpl_frameset_delete(obj_set);
1416 } else {
1417 sky_type = eris_ifu_jitter_get_sky_type(sof->mode);
1418 eris_ifu_jitter_save_cpl_cube(frameset, frameset,
1419 sof->exposureTable[i].frame,
1420 parlist, NULL, sof->exposureTable[i].cube,
1421 sof->exposureTable[i].cubeBpm,
1422 sof->exposureTable[i].cubeHdr,
1423 params, sky_type, i, recipe_name);
1424 }
1425 }
1426 }
1427 cpl_free(proCatg);
1428 }
1429 CATCH
1430 {
1431 retVal = cpl_error_get_code();
1432 CATCH_MSGS();
1433 }
1434
1435 return retVal;
1436}
1437
1438
1439hdrl_image *eris_ifu_jitter_subtract_background(
1440 skyTweakModes sky_tweak,
1441 int objIdx,
1442 struct sofStruct *sof,
1443 productDepthType productDepth)
1444{
1445 hdrl_image *objImg = NULL;
1446 cpl_mask *inputMask = NULL;
1447 cpl_mask *outputMask = NULL;
1448 cpl_image *dqi = NULL;
1449 char *filename = NULL;
1450 char *filename2 = NULL;
1451 bool darkSkySubtracted = false;
1452
1453 cpl_ensure(sof != NULL,CPL_ERROR_NULL_INPUT, NULL);
1454
1455 TRY
1456 {
1457
1458 objImg = hdrl_image_duplicate(sof->exposureTable[objIdx].rawImage);
1459 inputMask = cpl_mask_duplicate(
1460 hdrl_image_get_mask(sof->exposureTable[objIdx].rawImage));
1461
1462 if (sky_tweak == NONE) {
1463 const int skyIdx = sof->exposureTable[objIdx].skyIndex;
1464 if (skyIdx >=0) {
1465 hdrl_image *skyImg = hdrl_image_duplicate(sof->exposureTable[skyIdx].rawImage);
1466 BRK_IF_NULL(skyImg);
1467 BRK_IF_ERROR(hdrl_image_sub_image(objImg, skyImg));
1468 darkSkySubtracted = true;
1469 hdrl_image_delete(skyImg);
1470 } else if (sof->masterDark != NULL) {
1471 hdrl_image *rawImg = hdrl_image_duplicate(sof->masterDark);
1472 BRK_IF_ERROR(hdrl_image_sub_image(objImg, sof->masterDark));
1473 darkSkySubtracted = true;
1474 hdrl_image_delete(rawImg);
1475 }
1476
1477 if (darkSkySubtracted) {
1478 outputMask = cpl_mask_duplicate(hdrl_image_get_mask(objImg));
1479 // detect new bad pixels
1480 BRK_IF_ERROR(cpl_mask_xor(outputMask, inputMask));
1481 BRK_IF_NULL(dqi = cpl_image_new_from_mask(outputMask));
1482 BRK_IF_ERROR(cpl_image_multiply_scalar(dqi, ERIS_DQI_SKY));
1483 BRK_IF_ERROR(cpl_image_add(
1484 sof->exposureTable[objIdx].dqiImage, dqi));
1485 if (productDepth >= PD_DEBUG) {
1487 filename = cpl_sprintf("%s_%3.3d",
1488 ERIS_IFU_PRO_JITTER_DBG_DARK_FN, objIdx));
1490 filename2 = cpl_sprintf("%s_%3.3d.fits",
1491 ERIS_IFU_PRO_JITTER_DBG_DARK_FN, objIdx));
1493 eris_ifu_save_hdrl_image_dbg(objImg, filename, 1, NULL));
1495 cpl_image_save(sof->exposureTable[objIdx].dqiImage,
1496 filename2, CPL_TYPE_INT, NULL, CPL_IO_EXTEND));
1497 }
1498 }
1499 }
1500 cpl_mask_delete(inputMask);
1501 }
1502 CATCH
1503 {
1504 }
1505
1506 eris_ifu_free_image(&dqi);
1507 eris_ifu_free_mask(&outputMask);
1508 eris_ifu_free_string(&filename);
1509 eris_ifu_free_string(&filename2);
1510 return objImg;
1511}
1512
1524hdrl_imagelist *eris_ifu_jitter_build_cube(
1525 hdrl_image *inputImage,
1526 int sofIdx,
1527 struct sofStruct *sof,
1528 struct paramStruct params,
1529 bool doVelocityCorrection,
1530 cpl_polynomial *ohLambdaCorrection,
1531 productDepthType productDepth)
1532{
1533 hdrl_imagelist *cube = NULL;
1534 cpl_imagelist *dataCube = NULL;
1535 cpl_imagelist *errCube = NULL;
1536 hdrl_image *image1 = NULL;
1537 hdrl_image *image2 = NULL;
1538 hdrl_image *bpmImg1 = NULL;
1539 cpl_image *bpmImg2 = NULL;
1540 hdrl_image *badPixelMaskImg = NULL;
1541 cpl_image *badPixelMaskImg1 = NULL;
1542 cpl_image *badPixelMaskImg2 = NULL;
1543
1544 hdrl_image *waveImg = NULL;
1545 cpl_image *waveDataImg = NULL;
1546 cpl_image *waveErrImg = NULL;
1547 cpl_image *waveMap = NULL;
1548 struct exposureEntry *objEntry;
1549 char *filename;
1550 char *filename2;
1551 double velocityCorr;
1552 cpl_size lsize;
1553 double *pWaveMap;
1554 double minLambda = 0.;
1555 double maxLambda = 0.;
1556 bool buildCubeForOHbasedLambdaCorrection = false;
1557
1558 cpl_ensure(inputImage != NULL,CPL_ERROR_NULL_INPUT, NULL);
1559 cpl_ensure(sof != NULL,CPL_ERROR_NULL_INPUT, NULL);
1560 //cpl_ensure(ohLambdaCorrection != NULL,CPL_ERROR_NULL_INPUT, NULL);
1561
1562 TRY
1563 {
1564 if (doVelocityCorrection == false && ohLambdaCorrection == NULL) {
1565 buildCubeForOHbasedLambdaCorrection = true;
1566 }
1567
1568 objEntry = &sof->exposureTable[sofIdx];
1569 BRK_IF_NULL(image1 = hdrl_image_duplicate(inputImage));
1570
1571 //divide by flat image (if available)
1572 if (sof->masterFlat != NULL) {
1573 //BRK_IF_ERROR(
1574 hdrl_image_div_image(image1, sof->masterFlat);
1575 if (productDepth >= PD_DEBUG) {
1576 if (buildCubeForOHbasedLambdaCorrection) {
1578 filename = cpl_sprintf("%sB_%3.3d",
1579 ERIS_IFU_PRO_JITTER_DBG_FLAT_FN, sofIdx));
1580 } else {
1582 filename = cpl_sprintf("%s_%3.3d",
1583 ERIS_IFU_PRO_JITTER_DBG_FLAT_FN, sofIdx));
1584 }
1585 eris_ifu_save_hdrl_image_dbg(image1, filename, 1, NULL);
1586 eris_ifu_free_string(&filename);
1587 }
1588 }
1589
1590 //create a bad pixel mask image
1592 badPixelMaskImg = hdrl_image_new(
1593 cpl_mask_get_size_x(objEntry->badPixelMask),
1594 cpl_mask_get_size_y(objEntry->badPixelMask)));
1596 badPixelMaskImg1 = cpl_image_new_from_mask(objEntry->badPixelMask));
1598 badPixelMaskImg2 = cpl_image_cast(
1599 badPixelMaskImg1, CPL_TYPE_DOUBLE));
1601 hdrl_image_insert(badPixelMaskImg,
1602 badPixelMaskImg2, NULL, 1, 1));
1603 eris_ifu_free_image(&badPixelMaskImg1);
1604 eris_ifu_free_image(&badPixelMaskImg2);
1605
1606 cpl_msg_info(__func__, "No. bad pixels: %d", (int)cpl_image_count_rejected(hdrl_image_get_image(image1)));
1607
1608 // Correct the flatfielded image1 according to the badPixelMaskImg
1609
1610 int bpc_iter = params.bpc_iter;
1611 for (int i = 0; i < bpc_iter; i++){
1612 eris_ifu_bpm_correction(image1, badPixelMaskImg);
1613
1614 if (productDepth >= PD_DEBUG) {
1615 if (buildCubeForOHbasedLambdaCorrection) {
1617 filename = cpl_sprintf("%sB_%3.3d_%d",
1618 ERIS_IFU_PRO_JITTER_DBG_FLAT_FN"-corr", sofIdx, i));
1619 } else {
1621 filename = cpl_sprintf("%s_%3.3d_%d",
1622 ERIS_IFU_PRO_JITTER_DBG_FLAT_FN"-corr", sofIdx, i));
1623 }
1624 eris_ifu_save_hdrl_image_dbg(image1, filename, 1, NULL);
1625 eris_ifu_free_string(&filename);
1626 }
1627 }
1628
1629
1630 // apply derotator correction
1631 double derot_corr;
1632 if (params.derot_corr!=params.derot_corr)
1633 derot_corr = objEntry->derot_corr;
1634 else
1635 derot_corr = params.derot_corr;
1636 cpl_msg_info(cpl_func, "First column shifted (derot_corr): %.2f", derot_corr);
1637
1638 for (int i = 0; i < SLITLET_CNT; i++) {
1639 if (sof->distortion[i] != NULL) {
1641 cpl_polynomial_shift_1d(sof->distortion[i], 0, derot_corr));
1642 }
1643 }
1644
1645 //correct for distortion
1646 if (sof->distortion != NULL) {
1648 image2 = eris_ifu_dist_warp_image(image1,
1649 sof->distortion, sof->borders));
1651 bpmImg1 = eris_ifu_dist_warp_bpm(badPixelMaskImg,
1652 sof->distortion, sof->borders, productDepth));
1653 } else { //AGUDO3: we will never get here, since eris_ifu_jitter_processSof() will exit when distortion==NULL
1655 image2 = eris_ifu_warp_polynomial_image(image1,
1656 sof->poly_u, sof->poly_v));
1658 bpmImg1 = eris_ifu_warp_polynomial_image(badPixelMaskImg,
1659 sof->poly_u, sof->poly_v));
1660 }
1661
1662 // shift distortion back for next iteration
1663 for (int i = 0; i < SLITLET_CNT; i++) {
1664 if (sof->distortion[i] != NULL) {
1666 cpl_polynomial_shift_1d(sof->distortion[i], 0, -1*derot_corr));
1667 }
1668 }
1669
1671
1672 if (productDepth >= PD_DEBUG) {
1673 if (buildCubeForOHbasedLambdaCorrection) {
1675 filename = cpl_sprintf("%sB_%3.3d",
1676 ERIS_IFU_PRO_JITTER_DBG_WRAP_FN, sofIdx));
1677 } else {
1679 filename = cpl_sprintf("%s_%3.3d",
1680 ERIS_IFU_PRO_JITTER_DBG_WRAP_FN, sofIdx));
1681 }
1682 eris_ifu_save_hdrl_image_dbg(image2, filename, 1, NULL);
1683 if (bpmImg1 != NULL) {
1685 filename2 = cpl_sprintf("%s.fits", filename));
1687 cpl_image_save(hdrl_image_get_image(bpmImg1), filename2,
1688 CPL_TYPE_FLOAT, NULL, CPL_IO_EXTEND));
1689 eris_ifu_free_string(&filename2);
1690 }
1691 eris_ifu_free_string(&filename);
1692 }
1693
1694 waveMap = cpl_image_duplicate(sof->waveMap);
1695 lsize = cpl_image_get_size_x(waveMap) * cpl_image_get_size_y(waveMap);
1696 BRK_IF_NULL(pWaveMap = cpl_image_get_data_double(waveMap));
1697 maxLambda = cpl_image_get_max(waveMap);
1698 minLambda = cpl_image_get_min(waveMap);
1699
1700 // velocity shift
1701 if (doVelocityCorrection) {
1702 velocityCorr = 1. + params.velocityOffset * 1000. / CPL_PHYS_C;
1703 for (int ix = 0; ix < lsize; ix++) {
1704 pWaveMap[ix] *= velocityCorr;
1705 }
1706
1707 }
1708 // OH line lambda correction
1709 if (ohLambdaCorrection != NULL) {
1710 for (int ix = 0; ix < lsize; ix++) {
1711 pWaveMap[ix] -= cpl_polynomial_eval_1d(
1712 ohLambdaCorrection, pWaveMap[ix], NULL);
1713 }
1714 }
1715
1716 //wavelength resampling
1717 /* to prevent memory leaks delete header before duplication */
1718 cpl_propertylist_delete(objEntry->cubeHdr);
1719 objEntry->cubeHdr = cpl_propertylist_duplicate(objEntry->hdr);
1721 waveDataImg = eris_ifu_wave_resampled_arc_image(
1722 hdrl_image_get_image(image2),
1723 waveMap, sof->band, minLambda, maxLambda,
1724 objEntry->cubeHdr, 3));
1726 waveErrImg = eris_ifu_wave_resampled_arc_image(
1727 hdrl_image_get_error(image2),
1728 waveMap, sof->band, minLambda, maxLambda,
1729 objEntry->cubeHdr, 3));
1730
1732 bpmImg2 = eris_ifu_wave_resampled_arc_image(
1733 hdrl_image_get_image(bpmImg1),
1734 waveMap, sof->band, minLambda, maxLambda,
1735 objEntry->cubeHdr, 3));
1736
1737 cpl_binary *pImgMask = cpl_mask_get_data(cpl_image_get_bpm(waveDataImg));
1738 float *pDqiData = cpl_image_get_data_float(bpmImg2);
1739 cpl_size size = cpl_image_get_size_x(waveDataImg)
1740 * cpl_image_get_size_y(waveDataImg);
1741 for (cpl_size px = 0; px < size; px++) {
1742 if (pDqiData[px] > params.bpmThreshold) {
1743 pImgMask[px] = BAD_PIX;
1744 }
1745 }
1746 waveImg = hdrl_image_create(waveDataImg,waveErrImg);
1748
1749 if (productDepth >= PD_DEBUG) {
1750 cpl_propertylist *pl2save = cpl_propertylist_duplicate(objEntry->hdr);
1751 // call eris_ifu_wave_resampled_arc_image again to get property list
1752 // entries for image (instead of cube)
1753 cpl_image *image2save = eris_ifu_wave_resampled_arc_image(
1754 hdrl_image_get_image(image2),
1755 waveMap, sof->band, minLambda, maxLambda, pl2save, 2);
1756 if (buildCubeForOHbasedLambdaCorrection) {
1758 filename = cpl_sprintf("%sB_%3.3d",
1759 ERIS_IFU_PRO_JITTER_DBG_WAVE_FN, sofIdx));
1760 } else {
1762 filename = cpl_sprintf("%s_%3.3d",
1763 ERIS_IFU_PRO_JITTER_DBG_WAVE_FN, sofIdx));
1764 }
1765 cpl_propertylist_erase(pl2save,"RADECSYS");
1766 eris_ifu_save_hdrl_image_dbg(waveImg, filename, 1, pl2save);
1767 eris_ifu_free_image(&image2save);
1768
1769 image2save = eris_ifu_wave_resampled_arc_image(
1770 hdrl_image_get_image(bpmImg1),
1771 waveMap, sof->band, minLambda, maxLambda, pl2save, 2);
1773 filename2 = cpl_sprintf("%s.fits", filename));
1775 cpl_image_save(image2save, filename2,
1776 CPL_TYPE_FLOAT, pl2save, CPL_IO_EXTEND));
1777 eris_ifu_free_string(&filename);
1778 eris_ifu_free_string(&filename2);
1779 eris_ifu_free_image(&image2save);
1782 }
1783
1785 dataCube = eris_ifu_jitter_reconstruct_cube(
1786 waveDataImg,
1787 params.slitletDetectionMode,
1788 params.fineTuneMode,
1789 params.firstCol,
1790 sof->distances,
1791 sof->positions));
1792 cpl_image_reject_from_mask(waveErrImg, cpl_image_get_bpm_const(waveDataImg));
1794 errCube = eris_ifu_jitter_reconstruct_cube(
1795 waveErrImg,
1796 params.slitletDetectionMode,
1797 params.fineTuneMode,
1798 params.firstCol,
1799 sof->distances,
1800 sof->positions));
1802 cube = hdrl_imagelist_create(dataCube, errCube);
1803 cpl_imagelist_delete(dataCube);
1804 cpl_imagelist_delete(errCube);
1805 cpl_propertylist_update_int(objEntry->cubeHdr,NAXIS1,64);
1806 cpl_propertylist_update_int(objEntry->cubeHdr,NAXIS2,64);
1807 cpl_propertylist_update_int(objEntry->cubeHdr,NAXIS3,
1809
1810 if(objEntry->cubeBpm != NULL) {
1811 cpl_imagelist_delete(objEntry->cubeBpm);
1812 }
1813 // AMO: commented to fix PIPE-11106 TODO: Why a multiplication by 2??? That was creating a NAN in collapsed cube
1814 cpl_image_multiply_scalar(bpmImg2, 2.0);
1815
1817 objEntry->cubeBpm = eris_ifu_jitter_reconstruct_cube(
1818 bpmImg2,
1819 params.slitletDetectionMode,
1820 params.fineTuneMode,
1821 params.firstCol,
1822 sof->distances,
1823 sof->positions));
1824
1825 }
1826 CATCH
1827 {
1828 }
1829 /* TODO: AMo does not understand why objEntry is created and cannot be
1830 * erased. In particular objEntry->cubeBpm is an object created but not
1831 * erased
1832 */
1833 //eris_free_exposureEntry(objEntry);
1834 eris_ifu_free_hdrl_image(&waveImg);
1835 eris_ifu_free_hdrl_image(&image1);
1836 eris_ifu_free_hdrl_image(&image2);
1837 eris_ifu_free_hdrl_image(&badPixelMaskImg);
1838 eris_ifu_free_image(&badPixelMaskImg1);
1839 eris_ifu_free_image(&badPixelMaskImg2);
1840 eris_ifu_free_image(&waveDataImg);
1841 eris_ifu_free_image(&waveErrImg);
1842 eris_ifu_free_image(&waveMap);
1843 eris_ifu_free_hdrl_image(&bpmImg1);
1844 eris_ifu_free_image(&bpmImg2);
1845 eris_check_error_code("eris_ifu_jitter_build_cube");
1846 return cube;
1847}
1848
1849cpl_error_code
1850eris_image_get_valid_data_range(cpl_image* image,
1851 cpl_size* min, cpl_size* max)
1852{
1853 cpl_size sx = cpl_image_get_size_x(image);
1854 cpl_size sy = cpl_image_get_size_y(image);
1855 float* pdata = cpl_image_get_data(image);
1856 cpl_size rows2check = 200;
1857 cpl_size nan_counter = 0;
1858 double nan_thresh = 0.5;
1859 *min = 0;
1860 *max = sy;
1861 for(cpl_size j = 0; j < rows2check; j++) {
1862 nan_counter = 0;
1863 for(cpl_size i = 0; i < sx; i++) {
1864 if(isnan(pdata[i + j * sx])) {
1865 nan_counter++;
1866 }
1867 }
1868
1869 if(nan_counter > nan_thresh * sx) {
1870 *min = j;
1871 }
1872 }
1873
1874 for(cpl_size j = sy-1; j >= sy - rows2check; j--) {
1875 nan_counter = 0;
1876 for(cpl_size i = 0; i < sx; i++) {
1877 if(isnan(pdata[i + j * sx])) {
1878 nan_counter++;
1879 }
1880 }
1881 if(nan_counter > nan_thresh * sx) {
1882 *max = j;
1883 }
1884 }
1885 cpl_msg_info(cpl_func,"min: %lld max: %lld", *min, *max);
1886
1887 return cpl_error_get_code();
1888}
1910cpl_imagelist * eris_ifu_jitter_reconstruct_cube(
1911 cpl_image *resampledDetImage,
1912 slitletDetectionModes mode,
1913 int fineTuneMode,
1914 double firstCol,
1915 cpl_vector *distancesV,
1916 cpl_bivector *positionsVV)
1917{
1918
1919 cpl_ensure(resampledDetImage, CPL_ERROR_NULL_INPUT, NULL);
1920 cpl_ensure((mode >= UNSET) && (mode <= GRID), CPL_ERROR_ILLEGAL_INPUT, NULL);
1921 cpl_ensure(fineTuneMode >= -5, CPL_ERROR_ILLEGAL_INPUT, NULL);
1922 cpl_ensure(firstCol >= 0 && firstCol <= ERIS_IFU_DETECTOR_SIZE_X, CPL_ERROR_ILLEGAL_INPUT, NULL);
1923 //cpl_ensure(distancesV, CPL_ERROR_NULL_INPUT, NULL);
1924 //cpl_ensure(positionsVV, CPL_ERROR_NULL_INPUT, NULL);
1925
1926 cpl_imagelist *cube = NULL;
1927 cpl_image *slide = NULL;
1928 cpl_size inx;
1929 cpl_size onx;
1930 cpl_size ony;
1931 cpl_size onz;
1932 int beginCol[SLITLET_CNT] = {0};
1933 double start[SLITLET_CNT] = {0.};
1934 // variables needed for mode DISTANCES
1935 double di;
1936 double *distances = NULL;
1937 // variables needed for mode EDGES
1938 double center;
1939 double *left_edges = NULL;
1940 double *right_edges = NULL;
1941 float *pi = NULL;
1942 float *po = NULL;
1943 cpl_binary *mi = NULL;
1944 cpl_binary *mo = NULL;
1945 double *pt1 = NULL;
1946 double *pt2 = NULL;
1947 double *xi = NULL;
1948 double *xt = NULL;
1949 int icol;
1950 float tmp;
1951
1952 TRY
1953 {
1954 inx = cpl_image_get_size_x(resampledDetImage);
1955 onx = inx / SLITLET_CNT;
1956 ony = SLITLET_CNT * 2;
1957 onz = cpl_image_get_size_y(resampledDetImage);
1958 cube = cpl_imagelist_new();
1959 /*
1960 cpl_size iz_min = 0;
1961 cpl_size iz_max = onz;
1962 eris_image_get_valid_data_range(resampledDetImage, &iz_min, &iz_max);
1963 */
1964 if (distancesV == NULL) { // new ERIS way of simple re-sampling
1965 pi = cpl_image_get_data_float(resampledDetImage);
1966 mi = cpl_mask_get_data(cpl_image_get_bpm(resampledDetImage));
1967
1968 for (int iz=0; iz<onz; iz++) {
1970 slide = cpl_image_new(onx, ony, CPL_TYPE_FLOAT));
1971 po = cpl_image_get_data_float(slide);
1972 mo = cpl_mask_get_data(cpl_image_get_bpm(slide));
1973
1974 // flip x-axis to correct east direction (shall go to the left)
1975 for (int slitlet=0; slitlet<SLITLET_CNT; slitlet++) {
1976 for (int col=0; col < onx; col++) {
1977 tmp = (float) pi[onx-1-col + slitlet*onx + iz*inx];
1978 /* this step expands of a factor 2 along Y the
1979 * rectangular spaxel to a make it appear as square
1980 * as it is on the Sky. To conserve flux we need to
1981 * divide by 2 (or multiply by 0.5)
1982 */
1983 tmp *= 0.5;
1984 po[col + onx*(rowIndices[slitlet]*2)] = tmp;
1985 po[col + onx*(rowIndices[slitlet]*2+1)] = tmp;
1986 if (mi[onx-1-col + slitlet*onx + iz*inx] == BAD_PIX) {
1987 mo[col + onx*(rowIndices[slitlet]*2)] = BAD_PIX;
1988 mo[col + onx*(rowIndices[slitlet]*2+1)] = BAD_PIX;
1989 }
1990
1991 }
1992 }
1993
1995 cpl_imagelist_set(cube, slide, iz));
1996 }
1997 } else { // old SINFONI way
1998 if (mode == DISTANCES) {
1999 if (distancesV == NULL) {
2000 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
2001 "missing data about slitlet distances");
2002 }
2003 if (cpl_vector_get_size(distancesV) != SLITLET_CNT-1) {
2004 BRK_WITH_ERROR_MSG(CPL_ERROR_INCOMPATIBLE_INPUT,
2005 "distances vector has wrong number of elements "
2006 "(got %lld but exepected %d)",
2007 cpl_vector_get_size(distancesV), SLITLET_CNT-1);
2008 }
2009 distances = cpl_vector_get_data(distancesV);
2010 } else if (mode == EDGES) {
2011 if (positionsVV == NULL) {
2012 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
2013 "missing data about slitlet positions");
2014 }
2015 if (cpl_bivector_get_size(positionsVV) != SLITLET_CNT) {
2016 BRK_WITH_ERROR_MSG(CPL_ERROR_INCOMPATIBLE_INPUT,
2017 "slit pos bivector has wrong number of elements "
2018 "(got %lld but exepected %d)",
2019 cpl_bivector_get_size(positionsVV), SLITLET_CNT);
2020 }
2021 left_edges = cpl_vector_get_data(
2022 cpl_bivector_get_x(positionsVV));
2023 right_edges = cpl_vector_get_data(
2024 cpl_bivector_get_y(positionsVV));
2025 }
2026
2027 di = 0;
2028 for (int slitlet=0; slitlet<SLITLET_CNT; slitlet++) {
2029 if (mode == DISTANCES) {
2030 if (slitlet == 0) {
2031 start[slitlet] = firstCol;
2032 } else {
2033 di += distances[slitlet-1];
2034 start[slitlet] = firstCol + di;
2035 }
2036 } else if (mode == EDGES) {
2037 center = (left_edges[slitlet] + right_edges[slitlet]) / 2.;
2038 start[slitlet] = center - (double) (onx -1 )/2.;
2039 }else if (mode == GRID) {
2040 start[slitlet] = (double) (onx * slitlet);
2041 }
2042 beginCol[slitlet] =
2043 start[slitlet] > 0 ?
2044 (int)(start[slitlet]+.5) : (int)(start[slitlet]-.5);
2045 // double shift[SLITLET_CNT];
2046 // shift[rowIndices[slitlet]] = start[slitlet] -
2047 // (double) beginCol[slitlet];
2048 }
2049
2051 xi = cpl_calloc(onx, sizeof(double)));
2053 xt = cpl_calloc(onx, sizeof(double)));
2055 pt1 = cpl_calloc(onx, sizeof(double)));
2057 pt2 = cpl_calloc(onx, sizeof(double)));
2058 pi = cpl_image_get_data_float(resampledDetImage);
2059
2060 for (int iz=0; iz<onz; iz++) {
2062 slide = cpl_image_new(onx, ony, CPL_TYPE_FLOAT));
2063 po = cpl_image_get_data_float(slide);
2064
2065 for (int slitlet=0; slitlet<SLITLET_CNT; slitlet++) {
2066 for (int col=0; col < onx; col++) {
2067 xi[col] = (double) (beginCol[slitlet] + col);
2068 xt[col] = start[slitlet] + col;
2069 icol = beginCol[slitlet] + col;
2070 if (icol < 0) {
2071 pt1[col] = pi[0 + iz * inx];
2072 } else if (icol >= inx) {
2073 pt1[col] = pi[(inx - 1) + iz * inx];
2074 } else {
2075 pt1[col] = pi[icol + iz * inx];
2076 }
2077 }
2078 if (fineTuneMode == 0) {
2079 for (int col=0; col < onx; col++) {
2080 pt2[col] = pt1[col];
2081 }
2082 } else {
2084 eris_ifu_1d_interpolation(xi, pt1, (int) onx,
2085 xt, pt2, (int) onx, fineTuneMode));
2086 }
2087 for (int col=0; col < onx; col++) {
2088 /* this step expands of a factor 2 along Y the
2089 * rectangular spaxel to a make it appear as square
2090 * as it is on the Sky. To conserve flux we need to
2091 * divide by 2 (or multiply by 0.5)
2092 * TODO: why cast to float? It should be all in double
2093 * precision
2094 */
2095 tmp = (float) (pt2[col] * 0.5);
2096 po[col + onx*(rowIndices[slitlet]*2)] = tmp;
2097 po[col + onx*(rowIndices[slitlet]*2+1)] = tmp;
2098 }
2099 }
2101 cpl_imagelist_set(cube, slide, iz));
2102 }
2103 }
2105 }
2106 CATCH
2107 {
2109 }
2110 return cube;
2111}
2119cpl_error_code
2120eris_ifu_jitter_get_procatg_and_filename(cubeType type, char **proCatg,
2121 char **filenamePrefix)
2122{
2123 cpl_ensure_code(proCatg, CPL_ERROR_NULL_INPUT);
2124 cpl_ensure_code(filenamePrefix, CPL_ERROR_NULL_INPUT);
2125
2126 switch (type) {
2127 case OBJECT_CUBE_COADD:
2128 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_OBJ_CUBE_COADD);
2129 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_OBJ_CUBE_COADD_FN);
2130 break;
2131 case TWEAKED_CUBE_COADD:
2132 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_TWK_CUBE_COADD);
2133 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_TWK_CUBE_COADD_FN);
2134 break;
2135 case DAR_CUBE_COADD:
2136 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE_COADD);
2137 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE_COADD_FN);
2138 break;
2139 case DAR_STD_CUBE_COADD:
2140 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_COADD);
2141 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_COADD_FN);
2142 break;
2143 case STD_CUBE_COADD:
2144 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_COADD);
2145 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_COADD_FN);
2146 break;
2147 case STD_FLUX_CUBE_COADD:
2148 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD);
2149 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD_FN);
2150 break;
2151 case STD_FLUX_CUBE_COADD_NOFLAT:
2152 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD_NOFLAT);
2153 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD_NOFLAT_FN);
2154 break;
2155 case STD_CUBE_COADD_NOFLAT:
2156 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_COADD_NOFLAT);
2157 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_COADD_NOFLAT_FN);
2158 break;
2159 case PSF_CUBE_COADD:
2160 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD);
2161 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD_FN);
2162 break;
2163 case OBJECT_CUBE:
2164 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_OBJ_CUBE);
2165 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_OBJ_CUBE_FN);
2166 break;
2167 case STD_CUBE:
2168 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE);
2169 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_FN);
2170 break;
2171 case STD_FLUX_CUBE:
2172 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE);
2173 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_FN);
2174 break;
2175 case STD_CUBE_NOFLAT:
2176 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_NOFLAT);
2177 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_NOFLAT_FN);
2178 break;
2179 case PSF_CUBE:
2180 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE);
2181 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE_FN);
2182 break;
2183 case SKY_OBJECT_CUBE:
2184 case SKY_STD_CUBE:
2185 case SKY_STD_FLUX_CUBE:
2186 case SKY_PSF_CUBE:
2187 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_SKY_CUBE);
2188 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_SKY_CUBE_FN);
2189 break;
2190 case TWEAKED_CUBE:
2191 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_TWK_CUBE);
2192 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_TWK_CUBE_FN);
2193 break;
2194 case TWEAKED_STD_CUBE:
2195 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE);
2196 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_FN);
2197 break;
2198 case DAR_CUBE:
2199 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE);
2200 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE_FN);
2201 break;
2202 //PIPPO
2203 case DAR_PSF_CUBE_COADD:
2204 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD);
2205 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD_FN);
2206 break;
2207 case DAR_STD_CUBE:
2208 //*proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE);
2209 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE);
2210 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_CUBE_FN);
2211 break;
2212 case DAR_STD_FLUX_CUBE:
2213 //*proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE);
2214 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE);
2215 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_FN);
2216 break;
2217 case DAR_PSF_CUBE:
2218 //*proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_DAR_CUBE);
2219 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE);
2220 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_PSF_CUBE_FN);
2221 break;
2222 case BPM_CUBE:
2223 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_BPM_CUBE);
2224 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_BPM_CUBE_FN);
2225 break;
2226 case JITTER_CUBE:
2227 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_CUBE);
2228 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_CUBE_FN);
2229 break;
2230 default:
2231 cpl_msg_warning(cpl_func,"default case %d",type);
2232 *proCatg = cpl_sprintf(ERIS_IFU_PRO_JITTER_CUBE);
2233 *filenamePrefix = cpl_sprintf(ERIS_IFU_PRO_JITTER_CUBE_FN);
2234 break;
2235 }
2236 cpl_msg_debug(cpl_func,"proCatg: %s",*proCatg);
2237 cpl_msg_debug(cpl_func,"filenamePrefix: %s",*filenamePrefix);
2238 return cpl_error_get_code();
2239}
2240
2241
2242
2253cpl_error_code eris_ifu_extract_spec(
2254 const cpl_imagelist *data_in,
2255 const cpl_imagelist *noise_in,
2256 cpl_image *mask,
2257 cpl_vector **spec_data_out,
2258 cpl_vector **spec_noise_out)
2259{
2260 cpl_error_code ret_error = CPL_ERROR_NONE;
2261
2262 const cpl_image *tmp_img = NULL;
2263 const cpl_mask *bpm = NULL;
2264 const cpl_binary *bpm_data = NULL;
2265 cpl_mask *empty_mask = NULL;
2266
2267 int nx = 0,
2268 ny = 0,
2269 nz = 0,
2270 i = 0,
2271 j = 0,
2272 g = 0;
2273
2274 const float *pmask = NULL;
2275 const double *ptmp_img = NULL;
2276
2277 double sum = 0.0,
2278 weights = 0.0,
2279 *pvec = NULL,
2280 *pvecn = NULL;
2281
2282 TRY
2283 {
2284 ASSURE((data_in != NULL) &&
2285 (spec_data_out != NULL),
2286 CPL_ERROR_NULL_INPUT,
2287 "Not all input data is provided!");
2288
2290 tmp_img = cpl_imagelist_get_const(data_in, 0));
2291
2292 nx = cpl_image_get_size_x(tmp_img);
2293 ny = cpl_image_get_size_y(tmp_img);
2294 nz = cpl_imagelist_get_size(data_in);
2295
2296 if (mask != NULL) {
2297 ASSURE((nx == cpl_image_get_size_x(mask)) &&
2298 (ny == cpl_image_get_size_y(mask)),
2299 CPL_ERROR_ILLEGAL_INPUT,
2300 "Data and mask don't have same dimensions!");
2301
2303 pmask = cpl_image_get_data_float_const(mask));
2304 }
2305
2306 if (noise_in != NULL) {
2307 ASSURE(spec_noise_out != NULL,
2308 CPL_ERROR_NULL_INPUT,
2309 "Not all input data is provided!");
2310
2312 tmp_img = cpl_imagelist_get_const(noise_in, 0));
2313
2314 ASSURE((nx == cpl_image_get_size_x(tmp_img)) &&
2315 (ny == cpl_image_get_size_y(tmp_img)) &&
2316 (nz == cpl_imagelist_get_size(noise_in)),
2317 CPL_ERROR_ILLEGAL_INPUT,
2318 "Data and noise don't have same dimensions!");
2319 }
2320
2322 *spec_data_out = cpl_vector_new(nz));
2323
2325 pvec = cpl_vector_get_data(*spec_data_out));
2326
2327 if (noise_in != NULL) {
2329 *spec_noise_out = cpl_vector_new(nz));
2330
2332 pvecn = cpl_vector_get_data(*spec_noise_out));
2333 }
2334
2336 empty_mask = cpl_mask_new(nx,ny));
2337
2338 // loop over all spatial slices
2339 for (g = 0; g < nz; g++) {
2341 tmp_img = cpl_imagelist_get_const(data_in, g));
2343 ptmp_img = cpl_image_get_data_double_const(tmp_img));
2344
2345 bpm = cpl_image_get_bpm_const(tmp_img);
2346 if (bpm == NULL) {
2347 bpm = empty_mask;
2348 }
2350 bpm_data = cpl_mask_get_data_const(bpm));
2351
2352 // extract spectrum for data
2353 sum = 0.0;
2354 weights = 0.0;
2355 for (j = 0; j < ny; j++) {
2356 for (i = 0; i < nx; i++) {
2357 // sum weighted pixels in spatial plane
2358 if ((bpm_data[i+j*nx] == GOOD_PIX) && isfinite(ptmp_img[i+j*nx])) {
2359 if (mask != NULL) {
2360 sum += ptmp_img[i+j*nx] * pmask[i+j*nx];
2361 weights += pmask[i+j*nx];
2362 } else {
2363 sum += ptmp_img[i+j*nx];
2364 weights += 1.;
2365 }
2366 }
2367 }
2368 }
2369 pvec[g] = sum/weights;
2370
2371
2372 // extract spectrum for noise
2373 if (noise_in != NULL) {
2375 tmp_img = cpl_imagelist_get_const(noise_in, g));
2377 ptmp_img = cpl_image_get_data_double_const(tmp_img));
2378
2379 sum = 0.0;
2380 weights = 0.0;
2381 for (j = 0; j < ny; j++) {
2382 for (i = 0; i < nx; i++) {
2383 // combine weighted pixels in spatial plane
2384 if ((bpm_data[i+j*nx] == GOOD_PIX) && isfinite(ptmp_img[i+j*nx])) {
2385 if (mask != NULL) {
2386 sum += pow(ptmp_img[i+j*nx], 2) * pow(pmask[i+j*nx], 2);
2387 weights += pow(pmask[i+j*nx], 2);
2388 } else {
2389 sum += pow(ptmp_img[i+j*nx], 2);
2390 weights += 1.;
2391 }
2392 }
2393 }
2394 }
2395 pvecn[g] = sqrt(sum/weights);
2396 }
2397 }
2398 }
2399 CATCH
2400 {
2401 CATCH_MSG();
2402 ret_error = cpl_error_get_code();
2403 }
2404
2405 if (empty_mask != NULL) {cpl_mask_delete(empty_mask);}
2406
2407 return ret_error;
2408}
2409
2425static
2426cpl_error_code eris_ifu_jitter_spec_save_products(
2427 cpl_frameset* frames,
2428 const cpl_parameterlist * parlist,
2429 struct esSofStruct sof,
2430 cpl_bivector *spectrum,
2431 cpl_vector *error,
2432 cpl_vector *totalFlux,
2433 productDepthType productDepth,
2434 cpl_boolean is_sdp_format,
2435 const char* recipe_name)
2436{
2437 cpl_table *pro_tab = NULL;
2438 cpl_propertylist *pl;
2439 cpl_vector *lambda = NULL;
2440 cpl_vector *data = NULL;
2441 cpl_array *waveArray = NULL;
2442 cpl_array *fluxArray = NULL;
2443 cpl_array *errArray = NULL;
2444 cpl_array *totalFluxArray = NULL;
2445 double firstLambda;
2446 double deltaLambda;
2447 cpl_size spectrumSize;
2448
2449 TRY
2450 {
2451 spectrumSize = cpl_bivector_get_size(spectrum);
2452 BRK_IF_NULL(lambda = cpl_bivector_get_x(spectrum));
2453 BRK_IF_NULL(data = cpl_bivector_get_y(spectrum));
2454 firstLambda = cpl_vector_get(lambda,0);
2455 deltaLambda = cpl_vector_get(lambda,1) - firstLambda;
2456
2457 if (productDepth >= PD_AUXILLIARY) {
2458 pl = cpl_propertylist_duplicate(sof.header);
2459 cpl_propertylist_update_string(pl, CPL_DFS_PRO_CATG, "SPECTRUM");
2460 cpl_propertylist_update_string(pl, "CTYPE1", "WAVE");
2461 cpl_propertylist_update_double(pl, "CRPIX1", 1.);
2462 cpl_propertylist_update_double(pl, "CRVAL1", firstLambda);
2463 cpl_propertylist_update_double(pl, "CDELT1", deltaLambda);
2464 cpl_propertylist_erase(pl, "CTYPE2");
2465 cpl_propertylist_erase(pl, "CRPIX2");
2466 cpl_propertylist_erase(pl, "CRVAL2");
2467 cpl_propertylist_erase(pl, "CDELT2");
2468 cpl_propertylist_erase(pl, "CTYPE3");
2469 cpl_propertylist_erase(pl, "CRPIX3");
2470 cpl_propertylist_erase(pl, "CRVAL3");
2471 cpl_propertylist_erase(pl, "CDELT3");
2472 cpl_propertylist_update_double(pl, "CD1_1", 0.);
2473 cpl_propertylist_update_double(pl, "CD1_2", deltaLambda);
2474 cpl_propertylist_erase(pl, "CD1_3");
2475 cpl_propertylist_erase(pl, "CD2_1");
2476 cpl_propertylist_erase(pl, "CD2_2");
2477 cpl_propertylist_erase(pl, "CD2_3");
2478 cpl_propertylist_erase(pl, "CD3_1");
2479 cpl_propertylist_erase(pl, "CD3_2");
2480 cpl_propertylist_erase(pl, "CD3_3");
2481
2484 cpl_vector_save(data, "spectrum_vector.fits",
2485 CPL_TYPE_DOUBLE, pl, CPL_IO_CREATE));
2486 cpl_propertylist_delete(pl);
2487 }
2488 pl = cpl_propertylist_duplicate(sof.header);
2489
2490 if(strstr(recipe_name,"no_flat") != NULL) {
2491 cpl_msg_info(cpl_func,"recipe_name: %s",recipe_name);
2492 cpl_propertylist_update_string(pl, CPL_DFS_PRO_CATG,
2493 ERIS_IFU_PRO_JITTER_SPECTRUM_NOFLAT);
2494 } else {
2495 cpl_msg_info(cpl_func,"recipe_name: %s",recipe_name);
2496 cpl_propertylist_update_string(pl, CPL_DFS_PRO_CATG,
2497 ERIS_IFU_PRO_JITTER_SPECTRUM);
2498 }
2499
2500
2501
2502 cpl_propertylist_update_string(pl, "ESO PRO REC1 ID","eris_ifu_jitter");
2503 if(is_sdp_format) {
2504 waveArray = cpl_array_wrap_double(cpl_vector_get_data(lambda),
2505 spectrumSize);
2506 fluxArray = cpl_array_wrap_double(cpl_vector_get_data(data),
2507 spectrumSize);
2508 errArray = cpl_array_wrap_double(cpl_vector_get_data(error),
2509 spectrumSize);
2510 if (totalFlux != NULL) {
2511 totalFluxArray = cpl_array_wrap_double(cpl_vector_get_data(totalFlux),
2512 spectrumSize);
2513 }
2514
2515
2516 pro_tab = cpl_table_new(1);
2517 cpl_table_new_column_array(pro_tab, "WAVE",
2518 CPL_TYPE_DOUBLE, spectrumSize);
2519 cpl_table_new_column_array(pro_tab, "FLUX",
2520 CPL_TYPE_DOUBLE, spectrumSize);
2521 cpl_table_new_column_array(pro_tab, "ERR",
2522 CPL_TYPE_DOUBLE, spectrumSize);
2523 cpl_table_new_column_array(pro_tab, "TOT_FLUX",
2524 CPL_TYPE_DOUBLE, spectrumSize);
2525 cpl_table_set_array(pro_tab, "WAVE", 0, waveArray);
2526 cpl_table_set_array(pro_tab, "FLUX", 0, fluxArray);
2527 cpl_table_set_array(pro_tab, "ERR", 0, errArray);
2528 if (totalFlux != NULL) {
2529 cpl_table_set_array(pro_tab, "TOT_FLUX", 0, totalFluxArray);
2530 }
2531 //cpl_table_save(pro_tab, pl, NULL, "spectrum.fits", CPL_IO_CREATE);
2532 } else {
2533 pro_tab = cpl_table_new(spectrumSize);
2534 cpl_table_wrap_double(pro_tab, cpl_vector_get_data(lambda), "WAVE");
2535 if (totalFlux != NULL) {
2536 cpl_table_wrap_double(pro_tab, cpl_vector_get_data(data), "FLUX");
2537 } else {
2538 cpl_table_wrap_double(pro_tab, cpl_vector_get_data(data), "TOT_FLUX");
2539 }
2540 cpl_table_wrap_double(pro_tab, cpl_vector_get_data(error), "ERR");
2541 if (totalFlux != NULL) {
2542 cpl_table_wrap_double(pro_tab, cpl_vector_get_data(totalFlux), "TOT_FLUX");
2543 }
2544 }
2545 char *filename = cpl_sprintf("%s_spectrum.fits", recipe_name);
2546 cpl_propertylist_append_string(pl, "PRODCATG", "SCIENCE.SPECTRUM");
2547 cpl_dfs_save_table(frames, NULL, parlist, frames, NULL,
2548 pro_tab, NULL, recipe_name, pl,
2549 NULL, PACKAGE "/" PACKAGE_VERSION, filename);
2550
2551 cpl_free(filename);
2552 cpl_propertylist_delete(pl);
2553 if(is_sdp_format) {
2554 cpl_array_unwrap(waveArray);
2555 cpl_array_unwrap(fluxArray);
2556 cpl_array_unwrap(errArray);
2557 if (totalFlux != NULL) {
2558 cpl_array_unwrap(totalFluxArray);
2559 }
2560 } else {
2561 cpl_table_unwrap(pro_tab,"WAVE");
2562 if (totalFlux != NULL) {
2563 cpl_table_unwrap(pro_tab,"FLUX");
2564 } else {
2565 cpl_table_unwrap(pro_tab,"TOT_FLUX");
2566 }
2567 cpl_table_unwrap(pro_tab,"ERR");
2568 if (totalFlux != NULL) {
2569 cpl_table_unwrap(pro_tab,"TOT_FLUX");
2570 }
2571 }
2572 cpl_table_delete(pro_tab);
2574
2575 } CATCH{
2576 }
2577 eris_check_error_code("eris_ifu_jitter_spec_save_products");
2578 return cpl_error_get_code();
2579}
2580
2581
2591cpl_error_code eris_ifu_extract_spec_fetch_params(
2592 const cpl_parameterlist * parlist,
2593 struct esParamStruct *params,
2594 const char* context)
2595{
2596 TRY
2597 {
2598 const char* methodString;
2599 char* param_name = NULL;
2600
2601 param_name = cpl_sprintf("%s.mask_method", context);
2602
2603 methodString = cpl_parameter_get_string(
2604 cpl_parameterlist_find_const(parlist, param_name));
2605 cpl_free(param_name);
2606
2607
2608 if (strncasecmp(methodString, "mask", strlen("mask")) == 0) {
2609 params->mask_method = MASK;
2610 } else if (strncasecmp(methodString, "position", strlen("position")) == 0) {
2611 params->mask_method = POSITION;
2612 } else if (strncasecmp(methodString, "max", strlen("max")) == 0) {
2613 params->mask_method = MAX;
2614 } else if (strncasecmp(methodString, "fit", strlen("fit")) == 0) {
2615 params->mask_method = FIT;
2616 } else if (strncasecmp(methodString, "optimal", strlen("optimal")) == 0) {
2617 params->mask_method = OPTIMAL;
2618 } else {
2619 cpl_msg_error(cpl_func, "The maks_method parameter must be one "
2620 "of the list: mask, position, max, fit");
2621 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
2622 "Error reading recipe parameter, unknown mask method %s",
2623 methodString);
2624
2625 }
2626
2627 const char* center;
2628 param_name = cpl_sprintf("%s.center", context);
2629 center = cpl_parameter_get_string(
2630 cpl_parameterlist_find_const(parlist, param_name));
2631 cpl_free(param_name);
2632
2633 int nFields;
2634 int end;
2635 nFields = sscanf(center, "%d,%d%n",
2636 &params->center_x, &params->center_y, &end);
2637 if (nFields != 2 || end != (int)strlen(center)) {
2638 cpl_msg_error(cpl_func, "The center parameter must be "
2639 "a list of two integers separated by a comma");
2640 BRK_WITH_ERROR_MSG(CPL_ERROR_ILLEGAL_INPUT,
2641 "Error reading recipe parameter, cannot properly read center spec %s",
2642 center);
2643 printf("Error reading center string\n");
2644 }
2645
2646 param_name = cpl_sprintf("%s.radius", context);
2647 params->radius = cpl_parameter_get_double(
2648 cpl_parameterlist_find_const(parlist, param_name));
2649 cpl_free(param_name);
2650
2651 param_name = cpl_sprintf("%s.product_depth", context);
2652 params->productDepth = cpl_parameter_get_int(
2653 cpl_parameterlist_find_const(parlist, param_name));
2654 cpl_free(param_name);
2655
2657 } CATCH
2658 {
2659 }
2660
2661 return cpl_error_get_code();
2662}
2663
2664
2676cpl_error_code
2677eris_ifu_jitter_extract(cpl_frameset * frameset,
2678 const cpl_parameterlist *parlist,
2679 cubeType obj_type,
2680 const char* pcatg,
2681 struct stdParamStruct stdParams,
2682 const char* pipefile_prefix,
2683 const char* context)
2684{
2685 double startLambda = 0.,
2686 deltaLambda = 0.,
2687 refPixel = 0.;
2688 cpl_frame *frame_cube_coadd = NULL;
2689 cpl_image *mask = NULL;
2690 hdrl_image *collapsedCube = NULL;
2691 cpl_bivector *spectrum = NULL;
2692 cpl_vector *error = NULL;
2693 cpl_vector *totalFlux = NULL;
2694 cpl_vector *qual = NULL;
2695 cpl_propertylist *plist = NULL;
2696 char *fnamePrefix = NULL,
2697 *proCatg = NULL;
2698 const char *fname = NULL;
2699 struct esParamStruct esParams;
2700 struct esSofStruct esSof;
2701
2702 TRY {
2703 cpl_msg_info(cpl_func,"Extracting data source from %s", pcatg);
2704
2705 frame_cube_coadd = cpl_frameset_find(frameset, pcatg);
2706 fname = cpl_frame_get_filename(frame_cube_coadd);
2707
2708 /* WCS are in header of data extention, first one */
2709 plist = cpl_propertylist_load(fname, 1);
2710 refPixel = cpl_propertylist_get_double(plist, "CRPIX3");
2711 startLambda = cpl_propertylist_get_double(plist, "CRVAL3");
2712 if(cpl_propertylist_has(plist, "CDELT3")) {
2713 deltaLambda = cpl_propertylist_get_double(plist, "CDELT3");
2714 } else {
2715 deltaLambda = cpl_propertylist_get_double(plist, "CD3_3");
2716 }
2717
2718 startLambda = startLambda - (refPixel - 1.) * deltaLambda;
2719
2721 eris_ifu_extract_spec_fetch_params(parlist, &esParams, context));
2722
2723 //eris_ifu_jitter_get_cube_type_string(obj_type);
2724 cubeType coadd_obj_type = eris_ifu_jitter_get_coadd_obj_type(obj_type);
2725 eris_ifu_jitter_get_cube_type_string(coadd_obj_type);
2727 eris_ifu_jitter_extract_spec_processSof(obj_type, frameset,
2728 esParams, &esSof));
2729
2730 eris_ifu_jitter_get_procatg_and_filename(obj_type, &proCatg, &fnamePrefix);
2731
2732 cpl_image *contribMap = NULL;
2733 collapsedCube = eris_ifu_extract_spec_collapse(esSof.cube, &contribMap);
2734 eris_ifu_free_image(&contribMap);
2735
2736 char* pro_catg = cpl_sprintf("%s_MEDIAN",proCatg);
2737 cpl_free(proCatg);
2738 cpl_free(fnamePrefix);
2739 cpl_propertylist_update_string(plist, CPL_DFS_PRO_CATG, pro_catg);
2740 char *filename = cpl_sprintf("%s_cube_median.fits", pipefile_prefix);
2741 /* compute QC */
2742 if( strstr(pro_catg, "STD") != NULL ||
2743 strstr(pro_catg, "PSF") != NULL ){
2744 cpl_propertylist* qcheader =
2745 eris_compute_psf_qc(collapsedCube, parlist, context);
2746
2747 cpl_propertylist_append(plist, qcheader);
2748 cpl_propertylist_delete(qcheader);
2749 }
2750
2751 cpl_image* mask_ima = cpl_image_new_from_mask(hdrl_image_get_mask(collapsedCube));
2752
2753 eris_ifu_save_deq_image(frameset, NULL, parlist,frameset, NULL,
2754 pipefile_prefix, plist, "RADECSYS", filename,
2755 hdrl_image_get_image(collapsedCube),
2756 hdrl_image_get_error(collapsedCube),
2757 rmse, mask_ima, flag16bit, UNIT_ADU);
2758 cpl_image_delete(mask_ima);
2759
2760 cpl_free(filename);
2761 cpl_free(pro_catg);
2762
2763// const cpl_parameter *par = cpl_parameterlist_find_const(parlist, "edge-trim");
2764// if (par != NULL) {
2765// edge_trim = cpl_parameter_get_int(par);
2766// }
2767// agudo: eventually take edge_trim in respect when creating mask?
2769 mask = eris_ifu_extract_spec_create_mask(esParams, esSof,
2770 collapsedCube,
2771 esParams.productDepth));
2772
2773 cpl_propertylist_update_string(plist, CPL_DFS_PRO_CATG,
2774 ERIS_IFU_PRO_JITTER_EXTRACTION_MASK);
2775 filename = cpl_sprintf("%s_extraction_mask.fits", pipefile_prefix);
2776 cpl_dfs_save_image(frameset, plist, parlist, frameset, NULL,
2777 mask, CPL_TYPE_FLOAT, pipefile_prefix,
2778 plist, "RADECSYS",
2779 PACKAGE "/" PACKAGE_VERSION,
2780 filename);
2781
2782 cpl_free(filename);
2783
2784 if (esParams.mask_method == OPTIMAL) {
2786 spectrum = eris_ifu_optimal_extraction(esSof.cube,
2787 esSof.qualImagelist,
2788 mask,
2789 startLambda, deltaLambda,
2790 esParams.productDepth,
2791 &error));
2792 } else {
2794 spectrum = eris_ifu_extract_spectrum(esSof.cube, mask,
2795 startLambda, deltaLambda,
2796 &error, &totalFlux, &qual));
2797 }
2798
2799 eris_ifu_jitter_spec_save_products(frameset, parlist, esSof, spectrum,
2800 error, totalFlux, stdParams.productDepth, CPL_TRUE,
2801 pipefile_prefix);
2802 } CATCH
2803 {
2804 CATCH_MSG();
2805 }
2806
2807 //The following free make crush
2808 if (esSof.mask != mask) {
2809 eris_ifu_free_image(&mask);
2810 }
2812 eris_ifu_extract_free_esSofStruct(&esSof);
2813 eris_ifu_free_hdrl_image(&collapsedCube);
2814 eris_ifu_free_bivector(&spectrum);
2815 eris_ifu_free_vector(&error);
2816 eris_ifu_free_vector(&totalFlux);
2817 eris_check_error_code("eris_ifu_jitter_extract");
2818 return cpl_error_get_code();
2819}
2820
2830cpl_error_code
2831eris_ifu_jitter_extract_spec_processSof(
2832 cubeType obj_type,
2833 cpl_frameset* frames,
2834 struct esParamStruct params,
2835 struct esSofStruct *sof)
2836{
2837 cpl_frame *frame = NULL;
2838
2839 TRY
2840 {
2841
2842 if (frames == NULL) {
2843 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
2844 "missing frameset");
2845 }
2846
2847 if (cpl_frameset_is_empty(frames)) {
2848 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
2849 "SOF file is empty or missing");
2850 }
2852
2853
2854
2855 // get data cube
2856 char *proCatg = NULL;
2857 char *fnamePrefix = NULL;
2858 eris_ifu_jitter_get_procatg_and_filename(obj_type, &proCatg, &fnamePrefix);
2859 frame = cpl_frameset_find(frames, proCatg);
2860 cpl_free(fnamePrefix);
2861
2863 if (frame != NULL) {
2866 cpl_frame_get_filename(frame),
2867 &sof->header, &sof->qualImagelist, &sof->qualityType));
2868 sof->nx = hdrl_imagelist_get_size_x(sof->cube);
2869 sof->ny = hdrl_imagelist_get_size_y(sof->cube);
2870 sof->nz = hdrl_imagelist_get_size(sof->cube);
2871 } else {
2872 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
2873 "missing \"%s\" tag in the SOF, input data cube",
2874 proCatg);
2875
2876 }
2877 cpl_free(proCatg);
2878
2879 sof->mask = NULL;
2880 if (params.mask_method == MASK) {
2881 frame = cpl_frameset_find(frames, ERIS_IFU_UTIL_MASK);
2883 if (frame != NULL) {
2885 sof->mask = cpl_image_load(
2886 cpl_frame_get_filename(frame),
2887 CPL_TYPE_DOUBLE, 0, 0));
2888 } else {
2889 BRK_WITH_ERROR_MSG(CPL_ERROR_NULL_INPUT,
2890 "missing \"%s\" tag in the SOF, extraction mask",
2891 ERIS_IFU_UTIL_MASK);
2892 }
2893 }
2894 } CATCH
2895 {
2896 // CATCH_MSGS();
2897 }
2898 eris_check_error_code("eris_ifu_jitter_extract_spec_processSof");
2899 return cpl_error_get_code();
2900
2901}
2902
2913cpl_error_code eris_ifu_dar_correction(
2914 hdrl_imagelist *cube,
2915 cpl_propertylist *hdr,
2916// cpl_imagelist *cubeBpm,
2917 int method,
2918 double radius,
2919 int length)
2920{
2921 cpl_ensure_code(cube,CPL_ERROR_NULL_INPUT);
2922 cpl_ensure_code(hdr,CPL_ERROR_NULL_INPUT);
2923 //cpl_ensure_code(radius > 0,CPL_ERROR_ILLEGAL_INPUT);
2924 //cpl_ensure_code(length > 0,CPL_ERROR_ILLEGAL_INPUT);
2925
2926 TRY {
2927 double airmass = (
2928 cpl_propertylist_get_double(hdr, "ESO TEL AIRM START") +
2929 cpl_propertylist_get_double(hdr, "ESO TEL AIRM END")) / 2.;
2930 double parang = (
2931 cpl_propertylist_get_double(hdr, "ESO TEL PARANG START") +
2932 cpl_propertylist_get_double(hdr, "ESO TEL PARANG END")) / 2.;
2933 double posang =
2934 cpl_propertylist_get_double(hdr, "ESO ADA POSANG");
2935 double temp =
2936 cpl_propertylist_get_double(hdr, "ESO TEL AMBI TEMP");
2937 double rhum =
2938 cpl_propertylist_get_double(hdr, "ESO TEL AMBI RHUM");
2939 double pres = (
2940 cpl_propertylist_get_double(hdr, "ESO TEL AMBI PRES START") +
2941 cpl_propertylist_get_double(hdr, "ESO TEL AMBI PRES END")) / 2.;
2942
2943 cpl_wcs *wcs = cpl_wcs_new_from_propertylist(hdr);
2945
2946 hdrl_parameter *darParams = NULL;
2947 darParams = hdrl_dar_parameter_create(
2948 (hdrl_value) {airmass, 0.},
2949 (hdrl_value) {parang, 0.},
2950 (hdrl_value) {posang, 0.},
2951 (hdrl_value) {temp, 0.},
2952 (hdrl_value) {rhum, 0.},
2953 (hdrl_value) {pres, 0.},
2954 wcs);
2955 //BRK_IF_ERROR(hdrl_dar_parameter_verify(darParams));
2956
2957 cpl_vector *lambdaIn = NULL;
2958 double lambdaRef;
2960 cpl_vector_multiply_scalar(lambdaIn, 10000.); // convert microns to A
2961 lambdaRef = cpl_vector_get(lambdaIn, cpl_vector_get_size(lambdaIn)/2);
2962 int naxis3 = cpl_propertylist_get_int(hdr, NAXIS3);
2963 cpl_vector *xShift = cpl_vector_new(naxis3);
2964 cpl_vector *yShift = cpl_vector_new(naxis3);
2965 cpl_vector *xShiftErr = cpl_vector_new(naxis3);
2966 cpl_vector *yShiftErr = cpl_vector_new(naxis3);
2968
2969 BRK_IF_ERROR(hdrl_dar_compute( darParams,
2970 (hdrl_value) {lambdaRef, 0.}, lambdaIn,
2971 xShift, yShift, xShiftErr, yShiftErr ));
2972 cpl_msg_info(cpl_func, "DAR correction shift in X min/max: %.1f/%.1f, "
2973 "in Y min/max: %.1f/%.1f",
2974 cpl_vector_get_min(xShift), cpl_vector_get_max(xShift),
2975 cpl_vector_get_min(yShift), cpl_vector_get_max(yShift));
2976
2977 if (radius <= 0) {
2978 radius = CPL_KERNEL_DEF_WIDTH;
2979 }
2980 if (length == 0) {
2981 length = CPL_KERNEL_DEF_SAMPLES;
2982 }
2983
2984 const char *kernelName[] = {
2985 "TANH",
2986 "SINC",
2987 "SINC2",
2988 "LANCZOS",
2989 "HAMMING",
2990 "HANN",
2991 "NEAREST",
2992 "bilinear",
2993 "bicubic"};
2994 cpl_msg_info(cpl_func,"DAR correction: shift method %s, radius %.1f, length %d",
2995 kernelName[method], radius, length);
2996
2997 for (cpl_size sx=0; sx<naxis3; sx++) {
2998 hdrl_image *hdrlImg = hdrl_imagelist_get(cube, sx);
2999 cpl_image *inImg = hdrl_image_get_image(hdrlImg);
3000 cpl_image *errImg = hdrl_image_get_error(hdrlImg);
3001 cpl_image *err2Img = cpl_image_duplicate(errImg);
3002
3003 cpl_size nx = cpl_image_get_size_x(inImg);
3004 cpl_size ny = cpl_image_get_size_y(inImg);
3005 cpl_image *outImg = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
3006 cpl_image *out2Img = NULL;
3007
3008 double shiftX = cpl_vector_get(xShift, sx);
3009 double shiftY = cpl_vector_get(yShift, sx);
3010 if (method <= 6) {
3011 out2Img = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
3012 BRK_IF_ERROR(eris_ifu_dar_cpl_shift(inImg, outImg, out2Img, shiftX, shiftY,
3013 method, radius, length));
3014 } else if (method == 7) {
3015 eris_ifu_dar_gsl_shift(inImg, outImg, shiftX, shiftY, gsl_interp2d_bilinear);
3016 } else if (method == 8) {
3017 eris_ifu_dar_gsl_shift(inImg, outImg, shiftX, shiftY, gsl_interp2d_bicubic);
3018 }
3019 cpl_image_reject_from_mask(err2Img, cpl_image_get_bpm(outImg));
3020 hdrl_image *hdrl2Img = hdrl_image_create(outImg, err2Img);
3021
3022 hdrl_imagelist_set(cube, hdrl2Img, sx);
3023 // the previous hdrl_image is deallocated by hdrl_imagelist_set
3024 //hdrl_image_delete(hdrlImg);
3025 //eris_ifu_free_image(&inImg);
3026 //eris_ifu_free_image(&errImg);
3027 eris_ifu_free_image(&out2Img);
3028 cpl_image_delete(outImg);
3029 cpl_image_delete(err2Img);
3030 }
3031
3032 hdrl_parameter_delete(darParams);
3033 eris_ifu_free_vector(&lambdaIn);
3034 eris_ifu_free_vector(&xShift);
3035 eris_ifu_free_vector(&xShiftErr);
3036 eris_ifu_free_vector(&yShift);
3037 eris_ifu_free_vector(&yShiftErr);
3038 cpl_wcs_delete(wcs);
3039 } CATCH
3040 {
3041 // CATCH_MSGS();
3042 }
3043 return cpl_error_get_code();
3044}
3045cpl_error_code eris_ifu_dar_cpl_shift(
3046 cpl_image *inImg,
3047 cpl_image *out1Img,
3048 cpl_image *out2Img,
3049 double xShift,
3050 double yShift,
3051 cpl_kernel kernelType,
3052 double width,
3053 cpl_size kernelSize)
3054{
3055
3056 cpl_ensure_code(inImg, CPL_ERROR_NULL_INPUT);
3057 cpl_ensure_code(out1Img, CPL_ERROR_NULL_INPUT);
3058 cpl_ensure_code(out2Img, CPL_ERROR_NULL_INPUT);
3059
3060
3061 TRY {
3062 cpl_size nx, ny;
3063 cpl_vector *xprofile = NULL;
3064 double xradius;
3065 cpl_vector *yprofile = NULL;
3066 double yradius;
3067 cpl_image *correction_map = NULL;
3068
3069 nx = cpl_image_get_size_x(inImg);
3070 ny = cpl_image_get_size_x(inImg);
3071 cpl_image *deltax = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
3072 cpl_image *deltay = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
3073 cpl_image_add_scalar(deltax, xShift);
3074 cpl_image_add_scalar(deltay, yShift);
3075
3076 xprofile = cpl_vector_new(kernelSize);
3077 cpl_vector_fill_kernel_profile(xprofile, kernelType, width);
3078 xradius = width;
3079 yprofile = cpl_vector_new(kernelSize);
3080 cpl_vector_fill_kernel_profile(yprofile, kernelType, width);
3081 yradius = width;
3083
3084 cpl_image_warp(out1Img, inImg, deltax, deltay, xprofile, xradius, yprofile, yradius);
3086
3087 correction_map = cpl_image_new(cpl_image_get_size_x(out1Img),
3088 cpl_image_get_size_y(out1Img),
3089 cpl_image_get_type(out1Img));
3090 cpl_image_fill_jacobian(correction_map, deltax, deltay);
3091 cpl_image_copy(out2Img, out1Img, 1, 1);
3092 cpl_image_multiply(out2Img, correction_map);
3094
3095 eris_ifu_free_image(&deltax);
3096 eris_ifu_free_image(&deltay);
3097 eris_ifu_free_image(&correction_map);
3098 eris_ifu_free_vector(&xprofile);
3099 eris_ifu_free_vector(&yprofile);
3100
3101 } CATCH
3102 {
3103 // CATCH_MSGS();
3104 }
3105
3106 return cpl_error_get_code();
3107}
3108
3109cpl_error_code eris_ifu_dar_gsl_shift(
3110 cpl_image *inImg,
3111 cpl_image *outImg,
3112 double xShift,
3113 double yShift,
3114 const gsl_interp2d_type *T)
3115{
3116 cpl_size nx, ny;
3117
3118 //cpl_ensure_code(inImg, CPL_ERROR_NULL_INPUT);
3119 //cpl_ensure_code(outImg, CPL_ERROR_NULL_INPUT);
3120 //cpl_ensure_code(T, CPL_ERROR_NULL_INPUT);
3121
3122 gsl_set_error_handler_off();
3123 const double xa[] = {
3124 0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.,13.,14.,15.,
3125 16.,17.,18.,19.,20.,21.,22.,23.,24.,25.,26.,27.,28.,29.,30.,
3126 31.,32.,33.,34.,35.,36.,37.,38.,39.,40.,41.,42.,43.,44.,45.,
3127 46.,47.,48.,49.,50.,51.,52.,53.,54.,55.,56.,57.,58.,59.,60.,
3128 61.,62.,63.
3129 };
3130 const double ya[]= {
3131 0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.,13.,14.,15.,
3132 16.,17.,18.,19.,20.,21.,22.,23.,24.,25.,26.,27.,28.,29.,30.,
3133 31.,32.,33.,34.,35.,36.,37.,38.,39.,40.,41.,42.,43.,44.,45.,
3134 46.,47.,48.,49.,50.,51.,52.,53.,54.,55.,56.,57.,58.,59.,60.,
3135 61.,62.,63.
3136 };
3137 double *za = cpl_image_get_data_double(inImg);
3138
3139 /* initialize interpolation */
3140 nx = cpl_image_get_size_x(outImg);
3141 ny = cpl_image_get_size_y(outImg);
3142 gsl_spline2d *spline = gsl_spline2d_alloc(T, nx, ny);
3143 gsl_interp_accel *xacc = gsl_interp_accel_alloc();
3144 gsl_interp_accel *yacc = gsl_interp_accel_alloc();
3145 gsl_spline2d_init(spline, xa, ya, za, nx, ny);
3146 double z;
3147 //TODO: why error is computed but not used?
3148// int err;
3149 for (int i = 0; i < nx; ++i)
3150 {
3151 double xi = i - xShift;
3152
3153 for (int j = 0; j < nx; ++j)
3154 {
3155 double yj = j - yShift;
3156 if (xi > nx-1 || xi < 0 || yj > ny-1 || yj < 0) {
3157 z = 0.001;
3158 }/* else {
3159 err = gsl_spline2d_eval_e(spline, xi, yj, xacc, yacc, &z);
3160 }*/
3161 cpl_image_set(outImg, i+1, j+1, z);
3162// printf("%d: %d %d %f --> %f %f %f\n", err, i, j, za[j+nx*j], xi, yj, z);
3163 }
3164// printf("\n");
3165 }
3166
3167 gsl_spline2d_free(spline);
3168 gsl_interp_accel_free(xacc);
3169 gsl_interp_accel_free(yacc);
3170 return cpl_error_get_code();
3171}
3178int
3179eris_frameset_count_tag(cpl_frameset * sof, const char* tag)
3180{
3181
3182 cpl_ensure(sof, CPL_ERROR_NULL_INPUT, -1);
3183 cpl_ensure(tag, CPL_ERROR_NULL_INPUT, -1);
3184
3185 int count = 0;
3186 cpl_frameset* loc_sof = cpl_frameset_duplicate(sof);
3187 cpl_frame* frame = cpl_frameset_find(loc_sof, tag);
3188 if(frame != NULL) {
3189 while(frame) {
3190 cpl_frameset_erase_frame(loc_sof, frame);
3191 frame = cpl_frameset_find(loc_sof, tag);
3192 count++;
3193 }
3194 }
3195 cpl_frameset_delete(loc_sof);
3196 return count;
3197
3198}
3205cpl_error_code
3206eris_frameset_duplicate_cube_tag(cpl_frameset* frameset, const char* pcatg,
3207 cpl_boolean apply_flat)
3208{
3209 cpl_ensure(frameset, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
3210 cpl_ensure(pcatg, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
3211 //cpl_msg_warning(cpl_func,"pcatg: %s", pcatg);
3212 //cpl_frameset_dump(frameset,stdout);
3213 cpl_frame* frm_tmp = cpl_frameset_find(frameset, pcatg);
3214 cpl_frame* frm_dup = cpl_frame_duplicate(frm_tmp);
3215 const char* fname = cpl_frame_get_filename(frm_tmp);
3216 const char* fname_new = NULL;
3217 cpl_propertylist* plist = cpl_propertylist_load(fname, 0);
3218 //cpl_msg_info(cpl_func,"pcatg: %s",pcatg);
3219 if(strcmp(pcatg,ERIS_IFU_PRO_JITTER_OBJ_CUBE) == 0) {
3220 //cpl_msg_info(cpl_func,"case OBJ");
3221 fname_new = "eris_ifu_jitter_obj_cube_coadd.fits";
3222 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_OBJ_CUBE_COADD);
3223 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_OBJ_CUBE_COADD);
3224 } else if(strcmp(pcatg,ERIS_IFU_PRO_JITTER_DAR_CUBE) == 0) {
3225 fname_new = "eris_ifu_jitter_dar_cube_coadd.fits";
3226 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_OBJ_DAR_CUBE_COADD);
3227 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_OBJ_DAR_CUBE_COADD);
3228 } else if(strcmp(pcatg,ERIS_IFU_PRO_JITTER_TWK_CUBE) == 0) {
3229 fname_new = "eris_ifu_jitter_twk_cube_coadd.fits";
3230 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_TWK_CUBE_COADD);
3231 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_TWK_CUBE_COADD);
3232 } else if(strcmp(pcatg,ERIS_IFU_PRO_JITTER_PSF_CUBE) == 0) {
3233 //cpl_msg_info(cpl_func,"case PSF");
3234 fname_new = "eris_ifu_stdstar_psf_cube_coadd.fits";
3235 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD);
3236 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_PSF_CUBE_COADD);
3237 } else if(strcmp(pcatg,ERIS_IFU_PRO_JITTER_STD_CUBE) == 0){
3238 //cpl_msg_info(cpl_func,"case STD");
3239 if(apply_flat) {
3240 fname_new = "eris_ifu_stdstar_std_cube_coadd.fits";
3241 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_STD_CUBE_COADD);
3242 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_STD_CUBE_COADD);
3243 } else {
3244 fname_new = "eris_ifu_stdstar_no_flat_std_cube_coadd.fits";
3245 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_STD_CUBE_COADD_NOFLAT);
3246 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_STD_CUBE_COADD_NOFLAT);
3247 }
3248 } else if(strcmp(pcatg,ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE) == 0){
3249 //cpl_msg_info(cpl_func,"case STD_FLUX");
3250 if(apply_flat) {
3251 fname_new = "eris_ifu_stdstar_std_flux_cube_coadd.fits";
3252 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD);
3253 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD);
3254 } else {
3255 fname_new = "eris_ifu_stdstar_no_flat_std_flux_cube_coadd.fits";
3256 cpl_propertylist_update_string(plist, FHDR_PRO_CATG, ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD_NOFLAT);
3257 cpl_frame_set_tag(frm_dup, ERIS_IFU_PRO_JITTER_STD_FLUX_CUBE_COADD_NOFLAT);
3258 }
3259 }
3260
3261 char* cmd = cpl_sprintf("cp %s %s",fname, fname_new);
3262 cpl_msg_debug(cpl_func, "Copying %s", cmd);
3263 int status = system(cmd);
3264 if(status == -1) {
3265 cpl_msg_warning(cpl_func,"call to system() failed");
3266 }
3267 cpl_frame_set_filename(frm_dup, fname_new);
3268 cpl_frame_set_group(frm_dup, CPL_FRAME_GROUP_PRODUCT);
3269 cpl_frame_set_level(frm_dup, CPL_FRAME_LEVEL_FINAL);
3270
3271 cpl_propertylist_save(plist, fname_new, CPL_IO_CREATE);
3272 cpl_propertylist_delete(plist);
3273
3274 plist = cpl_propertylist_load(fname, 1);
3275 cpl_imagelist* data = cpl_imagelist_load(fname,CPL_TYPE_FLOAT, 1);
3276 cpl_imagelist_save(data, fname_new, CPL_TYPE_FLOAT, plist, CPL_IO_EXTEND);
3277 cpl_imagelist_delete(data);
3278 cpl_propertylist_delete(plist);
3279
3280 plist = cpl_propertylist_load(fname, 2);
3281 data = cpl_imagelist_load(fname, CPL_TYPE_FLOAT, 2);
3282 cpl_imagelist_save(data, fname_new, CPL_TYPE_FLOAT, plist, CPL_IO_EXTEND);
3283 cpl_imagelist_delete(data);
3284 cpl_propertylist_delete(plist);
3285
3286 plist = cpl_propertylist_load(fname, 3);
3287 data = cpl_imagelist_load(fname, CPL_TYPE_INT, 3);
3288 cpl_imagelist_save(data, fname_new, CPL_TYPE_INT, plist, CPL_IO_EXTEND);
3289 cpl_imagelist_delete(data);
3290 cpl_propertylist_delete(plist);
3291
3292
3293 //cpl_msg_warning(cpl_func, "insert frame %s with tag %s",
3294 // cpl_frame_get_filename(frm_tmp), cpl_frame_get_tag(frm_tmp));
3295 cpl_frameset_insert(frameset, frm_dup);
3296 cpl_free(cmd);
3297
3298
3299 return cpl_error_get_code();
3300}
3301
3302cpl_error_code eris_ifu_update_wcs_with_OCS_keywords(
3303 struct sofStruct *sof)
3304{
3305 cpl_error_code retval = CPL_ERROR_NONE;
3306 cpl_propertylist *header = NULL;
3307 //const char *filename;
3308 double crval1,
3309 crval2,
3310 crval1New,
3311 crval2New,
3312 crval1Ref,
3313 crval2Ref,
3314 cumOffset1,
3315 cumOffset2;
3316 int sx,
3317 rx;
3318
3319
3320 if (sof->exposureTableCnt < 2) { // nothing to do!
3321 return CPL_ERROR_NONE;
3322 }
3323
3324 TRY{
3325 /*
3326 * find reference exposure
3327 * either the first one with CUMOFFS1 and CUMOFFS1 set to 0.0
3328 * or the the first exposure
3329 */
3330 rx = -1;
3331 for (sx = 0; sx < sof->exposureTableCnt; sx++) {
3332 header = sof->exposureTable[sx].hdr;
3333 cumOffset1 = cpl_propertylist_get_double(header, FHDR_E_CUMOFFS1);
3334 cumOffset2 = cpl_propertylist_get_double(header, FHDR_E_CUMOFFS2);
3336 if (cumOffset1 == 0.0 && cumOffset2 == 0.0) {
3337 rx = sx;
3338 }
3339 cpl_msg_info("update_WCS_with_OCS_keywords",
3340 "%d %s : %f/%f %.1f/%.1f %g %g %g %g",
3341 sx, cpl_frame_get_filename(sof->exposureTable[sx].frame),
3342 cpl_propertylist_get_double(header, FHDR_E_CRVAL1),
3343 cpl_propertylist_get_double(header, FHDR_E_CRVAL2),
3344 cpl_propertylist_get_double(header, "CRPIX1"),
3345 cpl_propertylist_get_double(header, "CRPIX2"),
3346 cpl_propertylist_get_double(header, "CD1_1"),
3347 cpl_propertylist_get_double(header, "CD1_2"),
3348 cpl_propertylist_get_double(header, "CD2_1"),
3349 cpl_propertylist_get_double(header, "CD2_2")
3350 );
3352 }
3353 if (rx == -1) {
3354 rx = 0;
3355 }
3356
3357 header = sof->exposureTable[rx].hdr;
3358 crval1 = cpl_propertylist_get_double(header, FHDR_E_CRVAL1);
3359 crval2 = cpl_propertylist_get_double(header, FHDR_E_CRVAL2);
3360 cumOffset1 = cpl_propertylist_get_double(header, FHDR_E_CUMOFFS1);
3361 cumOffset2 = cpl_propertylist_get_double(header, FHDR_E_CUMOFFS2);
3363
3364 crval1Ref = crval1 - cumOffset1 / 3600.;
3365 crval2Ref = crval2 - cumOffset2 / 3600.;
3366
3367 cpl_msg_info("update_WCS_with_OCS_keywords","ref: %d %f %f",
3368 rx, crval1Ref, crval2Ref);
3369
3370 for (sx = 0; sx < sof->exposureTableCnt; sx++) {
3371 header = sof->exposureTable[sx].hdr;
3372 crval1 = cpl_propertylist_get_double(header, FHDR_E_CRVAL1);
3373 crval2 = cpl_propertylist_get_double(header, FHDR_E_CRVAL2);
3374 cumOffset1 = cpl_propertylist_get_double(header, FHDR_E_CUMOFFS1);
3375 cumOffset2 = cpl_propertylist_get_double(header, FHDR_E_CUMOFFS2);
3376
3377 crval1New = crval1Ref + cumOffset1 / 3600.;
3378 crval2New = crval2Ref + cumOffset2 / 3600.;
3379 cpl_propertylist_set_double(header, FHDR_E_CRVAL1, crval1New);
3380 cpl_propertylist_set_double(header, FHDR_E_CRVAL2, crval2New);
3382
3383 cpl_msg_info("update_WCS_with_OCS_keywords",
3384 "%d %f -> %f (%f) %f -> %f (%f) %f / %f %f / %f %f // %f",
3385 sx,
3386 crval1, crval1New, (crval1-crval1New)*3600.,
3387 crval2, crval2New, (crval2-crval2New)*3600.,
3388 cumOffset1, cumOffset2,
3389 (crval1New-crval1Ref)*3600., (crval2New-crval2Ref)*3600.,
3390 (crval1-crval1Ref)*3600., (crval2-crval2Ref)*3600. );
3391 }
3392 } CATCH {
3393 }
3394 return retval;
3395}
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 the frames with the given tag from a frameset.
Definition: eris_ifu_dfs.c:171
hdrl_imagelist * eris_ifu_load_deq_hdrl_imagelist(const char *filename, cpl_propertylist **primaryHeader, cpl_imagelist **qualImagelist, deqQualityType *qualityType)
Function to load an HDRL imagelist with quality extensions.
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)
Write DFS pipeline product with image, error and data qual.
Definition: eris_ifu_dfs.c:300
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)
Write DFS pipeline product with image, error and data qual.
Definition: eris_ifu_dfs.c:441
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
#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)
eris_ifu_warp_polynomial_image
cpl_polynomial * eris_ifu_lcorr_get(cpl_imagelist *cube, hdrl_imagelist *hdrlCube, const cpl_propertylist *header, cpl_vector *peaks, const int pfit_order)
Main function to create the lcal-correction.
cpl_vector * eris_ifu_lcorr_create_lambda_vector(const cpl_propertylist *header)
Creates a wavelength vector from an input cube.
cpl_imagelist * eris_ifu_sky_tweak(cpl_imagelist *obj, cpl_imagelist *sky, const cpl_propertylist *header, float min_frac, int tbsub, int skip_last, int stretch, int stretch_degree, int stretch_resampling, int plot, cpl_imagelist **new_sky)
Main sky tweaking function.
cpl_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
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)
eris_ifu_get_plane_cut_min_max
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 in input data 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 imagelist for debugging purposes
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)
remove planes from input iml and bpm in the range [0, zmin), (zmax,sz]
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