ERIS Pipeline Reference Manual 1.8.15
eris_ifu_combine_hdrl.c
1/* $Id: eris_ifu_flat.c,v 0.1 2018-07-22 06:06:06 agudo Exp $
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19*/
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
25/*-----------------------------------------------------------------------------
26 Includes
27 -----------------------------------------------------------------------------*/
28#include <cpl.h>
29#include "hdrl.h"
30#include <string.h>
31#include <stdio.h>
32#include "eris_dfs.h"
33#include "eris_utils.h"
34#include "eris_ifu_dfs.h"
35#include "eris_ifu_utils.h"
36#include "eris_ifu_error.h"
37#include "eris_ifu_resample.h"
38#include "eris_ifu_efficiency_response.h"
39#include "eris_ifu_jitter_interface.h"
40
41/*-----------------------------------------------------------------------------
42 Plugin registration
43 -----------------------------------------------------------------------------*/
44/*-----------------------------------------------------------------------------
45 Private function prototypes
46 -----------------------------------------------------------------------------*/
47
48/*-----------------------------------------------------------------------------
49 Static variables
50 -----------------------------------------------------------------------------*/
51#define RECIPE_NAME "eris_ifu_combine_hdrl"
52#define ERIS_IFU_COMBINE_DOCATG "OBJECT_CUBE"
53#define ERIS_IFU_COMBINE_PROCATG "COMBINED_CUBE"
54
55#define MAX_NAME_SIZE 512
56#define CONTEXT "eris.eris_ifu_combine_hdrl"
57static const char eris_ifu_combine_description[] = "\
58Align and combine SPIFFIER data cubes \n\
59\n\
60-----------------------------------------------------------------------------\n\
61Input files:\n\
62 DO CATG Explanation Required #Frames\n\
63 ------- ----------- -------- -------\n\
64 OBJECT_CUBE Science cubes Y >=2 \n\
65 EXTCOEFF_TABLE Table with atmospheric extinction (optional, req. to fluxcal [0,1]\n\
66 RESPONSE Table with instrument response (optional, req. to fluxcal) [0,1]\n\
67\n\
68Output files:\n\
69 PRO CATG Explanation\n\
70 ------- -----------\n\
71 "ERIS_IFU_COMBINE_PROCATG" Combined scince cube using hdrl library functions. \n\
72\n\
73Information on relevant parameters may be found with\n\
74 esorex --params "RECIPE_NAME"\n\
75 esorex --help "RECIPE_NAME"\n\
76---------------------------------------------------------------------------\n\
77\n";
78cpl_recipe_define(eris_ifu_combine_hdrl, ERIS_BINARY_VERSION, "Y. Cao",
79 PACKAGE_BUGREPORT, "2023",
80 "Combine science cubes using hdrl",
81 eris_ifu_combine_description);
82/*-----------------------------------------------------------------------------
83 Function code
84 -----------------------------------------------------------------------------*/
85/*----------------------------------------------------------------------------*/
93/*----------------------------------------------------------------------------*/
94static cpl_error_code eris_ifu_combine_hdrl_fill_parameterlist(cpl_parameterlist *pl)
95{
96 //cpl_recipe * recipe;
97 cpl_parameter * p;
98
99 cpl_ensure_code(pl, CPL_ERROR_NULL_INPUT);
100
101 /* Fill the parameters list */
103 /* Offsets */
104 p = cpl_parameter_new_value(CONTEXT".offset_mode",
105 CPL_TYPE_BOOL, "Offset conventions. If TRUE applies "
106 "reference offset correction. If FALSE: "
107 "take user offsets. The reference offset "
108 "is computed as (min_off+max_off)/2",
109 CONTEXT, CPL_TRUE) ;
110 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "offset_mode") ;
111 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
112 cpl_parameterlist_append(pl, p) ;
113
114 p = cpl_parameter_new_value(CONTEXT".name_i",
115 CPL_TYPE_STRING,
116 "Input filename. This must be provided and allow the user to set X "
117 "and Y cumulative offsets in a two column format",
118 CONTEXT,"offset.list");
119 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "name_i") ;
120 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
121 cpl_parameterlist_append(pl, p) ;
122
123 p = cpl_parameter_new_enum(CONTEXT".offset_unit", CPL_TYPE_STRING,
124 "Offset unit", CONTEXT, "PIXEL",4,
125 "PIXEL", "ARCSEC", "DEGREE", "PIXDEG");
126 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "offset_unit");
127 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
128 cpl_parameterlist_append(pl, p);
129
130
131 /* Resampling method */
132 /* --hdrldemo_resample.method */
133 char *context = NULL;
134 context = cpl_sprintf("eris.%s", RECIPE_NAME);
135 char pName[256];
136 snprintf(pName, sizeof(pName), "%s.%s", context, "method");
137 p = cpl_parameter_new_enum(pName, CPL_TYPE_STRING,
138 "Resampling method", context, "DRIZZLE",6,
139 "NEAREST", "LINEAR", "QUADRATIC", "RENKA",
140 "DRIZZLE","LANCZOS");
141 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method");
142 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
143 cpl_parameterlist_append(pl, p);
144
145 /* --hdrldemo_resample.method.loop-distance */
146 snprintf(pName, sizeof(pName), "%s.%s", context, "method.loop-distance");
147 p = cpl_parameter_new_value(pName, CPL_TYPE_INT,
148 "Loop distance used by all (but NEAREST) "
149 "methods to control the number of surrounding "
150 "voxels that are taken into account. "
151 "A small value allow faster re-sampling but may not give good quality",
152 context, LOOP_DISTANCE);
153 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method.loop-distance");
154 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
155 cpl_parameterlist_append(pl, p);
156
157 /* --hdrldemo_resample.method.use-errorweights*/
158 snprintf(pName, sizeof(pName), "%s.%s", context, "method.use-errorweights");
159 p = cpl_parameter_new_value(pName,
160 CPL_TYPE_BOOL,
161 "Use additional weights of 1/err^2", context,
162 CPL_FALSE);
163 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
164 "method.use-errorweights");
165 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
166 cpl_parameterlist_append(pl, p);
167
168 /* --hdrldemo_resample.method.renka.critical-radius */
169 snprintf(pName, sizeof(pName), "%s.%s", context, "method.renka.critical-radius");
170 p = cpl_parameter_new_value(pName,
171 CPL_TYPE_DOUBLE,"Critical radius of the Renka "
172 "method",
173 context, RENKA_CRITICAL_RADIUS);
174 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
175 "method.renka.critical-radius");
176 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
177 cpl_parameterlist_append(pl, p);
178
179 /* --hdrldemo_resample.method.lanczos.kernel-size */
180 snprintf(pName, sizeof(pName), "%s.%s", context, "method.lanczos.kernel-size");
181 p = cpl_parameter_new_value(pName,
182 CPL_TYPE_INT,"Kernel size of the Lanczos "
183 "method",
184 context, LANCZOS_KERNEL_SIZE);
185 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
186 "method.lanczos.kernel-size");
187 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
188 cpl_parameterlist_append(pl, p);
189
190 /* --hdrldemo_resample.method.drizzle.downscale-x */
191 snprintf(pName, sizeof(pName), "%s.%s", context, "method.drizzle.downscale-x");
192 p = cpl_parameter_new_value(pName,
193 CPL_TYPE_DOUBLE, "Drizzle down-scaling factor "
194 "in x direction",
195 context, DRIZZLE_DOWN_SCALING_FACTOR_X);
196 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
197 "method.drizzle.downscale-x");
198 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
199 cpl_parameterlist_append(pl, p);
200
201 /* --hdrldemo_resample.method.drizzle.downscale-y */
202 snprintf(pName, sizeof(pName), "%s.%s", context, "method.drizzle.downscale-y");
203 p = cpl_parameter_new_value(pName,
204 CPL_TYPE_DOUBLE, "Drizzle down-scaling factor "
205 "in y direction",
206 context, DRIZZLE_DOWN_SCALING_FACTOR_Y);
207 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
208 "method.drizzle.downscale-y");
209 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
210 cpl_parameterlist_append(pl, p);
211
212 /* --hdrldemo_resample.method.drizzle.downscale-z*/
213 snprintf(pName, sizeof(pName), "%s.%s", context, "method.drizzle.downscale-z");
214 p = cpl_parameter_new_value(pName,
215 CPL_TYPE_DOUBLE, "Drizzle down-scaling factor "
216 "in wavelength direction",
217 context, DRIZZLE_DOWN_SCALING_FACTOR_Z);
218 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
219 "method.drizzle.downscale-z");
220 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
221 cpl_parameterlist_append(pl, p);
222
223 /* --hdrldemo_resample.outgrid.ra-min
224 snprintf(pName, sizeof(pName), "%s.%s", context, "outgrid.ra-min");
225 p = cpl_parameter_new_value(pName, CPL_TYPE_DOUBLE,
226 "Minimum right ascension of the output "
227 "image/cube in degree", context, -1.0);
228 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "outgrid.ra-min");
229 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
230 cpl_parameterlist_append(pl, p);
231 */
232
233 /* --hdrldemo_resample.outgrid.ra-max
234 snprintf(pName, sizeof(pName), "%s.%s", context, "outgrid.ra-max");
235 p = cpl_parameter_new_value(pName, CPL_TYPE_DOUBLE,
236 "Maximum right ascension of the output "
237 "image/cube in degree", context, -1.0);
238 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "outgrid.ra-max");
239 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
240 cpl_parameterlist_append(pl, p);
241 */
242
243 /* --hdrldemo_resample.outgrid.dec-min
244 snprintf(pName, sizeof(pName), "%s.%s", context, "outgrid.dec-min");
245 p = cpl_parameter_new_value(pName, CPL_TYPE_DOUBLE,
246 "Minimum declination of the output "
247 "image/cube in degree", context, -1.0);
248 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "outgrid.dec-min");
249 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
250 cpl_parameterlist_append(pl, p);
251 */
252
253 /* --hdrldemo_resample.outgrid.dec-max
254 snprintf(pName, sizeof(pName), "%s.%s", context, "outgrid.dec-max");
255 p = cpl_parameter_new_value(pName, CPL_TYPE_DOUBLE,
256 "Maximum declination of the output "
257 "image/cube in degree", context, -1.0);
258 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "outgrid.dec-max");
259 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
260 cpl_parameterlist_append(pl, p);
261 */
262
263 /* --hdrldemo_resample.lambda
264 snprintf(pName, sizeof(pName), "%s.%s", context, "outgrid.lambda-min");
265 p = cpl_parameter_new_value(pName,
266 CPL_TYPE_DOUBLE, "Minimum wavelength of the "
267 "output cube in meter", context, -1.);
268 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "outgrid.lambda-min");
269 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
270 cpl_parameterlist_append(pl, p);
271 */
272
273 /* --hdrldemo_resample.lambda
274 snprintf(pName, sizeof(pName), "%s.%s", context, "outgrid.lambda-max");
275 p = cpl_parameter_new_value(pName,
276 CPL_TYPE_DOUBLE, "Maximum wavelength of the "
277 "output cube in meter", context, -1.);
278 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "outgrid.lambda-max");
279 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
280 cpl_parameterlist_append(pl, p);
281 */
282
283 /* --hdrldemo_resample.outgrid.delta-ra
284 snprintf(pName, sizeof(pName), "%s.%s", context, "outgrid.delta-ra");
285 p = cpl_parameter_new_value(pName,CPL_TYPE_DOUBLE,
286 "Output step-size in right ascension in degree",
287 context, -1.);
288 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "outgrid.delta-ra");
289 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
290 cpl_parameterlist_append(pl, p);
291 */
292
293 /* --hdrldemo_resample.outgrid.delta-dec
294 snprintf(pName, sizeof(pName), "%s.%s", context, "outgrid.delta-dec");
295 p = cpl_parameter_new_value(pName,
296 CPL_TYPE_DOUBLE, "Output step-size in "
297 "declination in degree",
298 context, -1.);
299 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "outgrid.delta-dec");
300 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
301 cpl_parameterlist_append(pl, p);
302 */
303
304 /* --hdrldemo_resample.outgrid.delta-lambda
305 snprintf(pName, sizeof(pName), "%s.%s", context, "outgrid.delta-lambda");
306 p = cpl_parameter_new_value(pName,
307 CPL_TYPE_DOUBLE, "Output step-size in "
308 "wavelength in meter",
309 context, -1.);
310 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "outgrid.delta-lambda");
311 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
312 cpl_parameterlist_append(pl, p);
313 */
314
315 // /* --hdrldemo_resample.save-table */
316 // snprintf(pName, sizeof(pName), "%s.%s", context, "save-table");
317 // p = cpl_parameter_new_value(pName, CPL_TYPE_BOOL,
318 // "Save the table before resampling", context,
319 // CPL_FALSE);
320 // cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "save-table");
321 // cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
322 // cpl_parameterlist_append(pl, p);
323
324
325 /* --hdrldemo_resample.subtract-background */
326 snprintf(pName, sizeof(pName), "%s.%s", context, "subtract-background");
327 p = cpl_parameter_new_value(pName, CPL_TYPE_BOOL,
328 "Subtract median of the images chanel-by-chanel", context,
329 CPL_FALSE);
330 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "subtract-background");
331 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
332 cpl_parameterlist_append(pl, p);
333
334 /* EXTRA CODE TO FLUX CALIBRATE RESULTS */
335 int jitterMode= M_SCIENCE;
336
337 /* extraction params */
338 eris_ifu_jitter_fill_extract_parameterlist(context, jitterMode, pl);
339 /* flux calibration params */
340 snprintf(pName, sizeof(pName), "%s.%s", context, "flux-calibrate");
341 p = cpl_parameter_new_value(pName, CPL_TYPE_BOOL,
342 "If True flux calibrate the extracted spectrum and data cube (you need to also --extract-source=TRUE)",
343 context, CPL_FALSE);
344 if (jitterMode == M_SCIENCE) {
345 cpl_parameter_set_default_bool(p, CPL_FALSE);
346 }
347 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux-calibrate");
348 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
349 cpl_parameterlist_append(pl, p);
350
351 /* END EXTRA */
352
353
354 /* --hdrldemo_resample.fieldmargin */
355 snprintf(pName, sizeof(pName), "%s.%s", context, "fieldmargin");
356 p = cpl_parameter_new_value(pName, CPL_TYPE_DOUBLE,
357 "Add this margin/border (in percent) to the "
358 "resampled image/cube", context, FIELDMARGIN);
359 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fieldmargin");
360 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
361 cpl_parameterlist_append(pl, p);
362
363 /* --hdrldemo_resample.edge-trim */
364 snprintf(pName, sizeof(pName), "%s.%s", context, "edge-trim");
365 p = cpl_parameter_new_value(pName, CPL_TYPE_INT,
366 "Number or pixels to trim for each plane of the input frames. "
367 "It should be smaller than half image size", context, EDGETRIM);
368 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "edge-trim");
369 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
370 cpl_parameterlist_append(pl, p);
371
372 snprintf(pName, sizeof(pName), "%s.%s", context, "max-cubes-centres-dist");
373 p = cpl_parameter_new_range(pName, CPL_TYPE_INT,
374 "Maximum distance between cube centers to build a mosaic. Mosaic creation "
375 "requires a lot of RAM. Users may trim this value to fit RAM resources",
376 context, 240, 20, 10000);
377 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "max-cubes-centres-dist");
378 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
379 cpl_parameterlist_append(pl, p);
380
381
382
383 snprintf(pName, sizeof(pName), "%s.%s", context, "bpc_iter");
384 p = cpl_parameter_new_value(pName, CPL_TYPE_INT,
385 "No. of iterations for bad pixel correction",
386 context, 1);
387 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "bpc_iter");
388 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
389 cpl_parameterlist_append(pl, p);
390
391
392
393
394 snprintf(pName, sizeof(pName), "%s.%s", context, "chop-nan");
395 p = cpl_parameter_new_value(pName, CPL_TYPE_BOOL,
396 "If true chop cube planes with more than 50% NAN pixels",
397 context, CPL_FALSE);
398 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "chop-nan");
399 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
400 cpl_parameterlist_append(pl, p);
401
402
403
404
405 eris_ifu_free_string(&context);
406
407 return cpl_error_get_code();
408}
409
410
411/*----------------------------------------------------------------------------*/
418/*----------------------------------------------------------------------------*/
419static int eris_ifu_combine_hdrl(
420 cpl_frameset * frameset,
421 const cpl_parameterlist * parlist)
422{
423 const cpl_parameter * par ;
424 //struct paramStruct params;
425 struct stdParamStruct stdParams = stdParamStructInit;
426 //struct sofStruct sof;
427 const char* name_i = NULL;
428 int offset_mode = CPL_TRUE;
429 const char* offunit = NULL;
430 FILE* file_list = NULL;
431 int cnt = 0;
432 float tmpoffx = 0;
433 float tmpoffy = 0;
434
435 int nframes = 0;
436
437
438 float * offsetx = NULL;
439 float * offsety = NULL;
440 float * crpix1_usr = NULL;
441 float * crpix2_usr = NULL;
442 float * crval1_usr = NULL;
443 float * crval2_usr = NULL;
444 double crpix1 = 0;
445 double crpix2 = 0;
446 double crval1 = 0;
447 double crval2 = 0;
448 double alpha = 0;
449 double delta = 0;
450
451 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
452 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
453 cpl_error_ensure(cpl_frameset_get_size(frameset) >= 0, CPL_ERROR_ILLEGAL_INPUT,
454 0, "Missing or empty SOF file");
455
456
457
458 /* Check entries */
459 if (parlist == NULL || frameset == NULL) {
460 cpl_msg_error(__func__, "Null Inputs") ;
461 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ;
462 return (int) cpl_error_get_code() ;
463 }
464 /* check required input tags are present */
465 const int ntags = 1;
466 const char* required_tags[1] = {
467 ERIS_IFU_COMBINE_DOCATG
468 };
469
470 cpl_ensure_code(CPL_ERROR_NONE ==
471 eris_dfs_check_input_tags(frameset, required_tags, ntags, 1),
472 CPL_ERROR_ILLEGAL_INPUT);
473 const int ntags_opt = 1;
474 const char* optional_tags[2] = {
475 ERIS_IFU_CALIB_EXTCOEFF_TABLE,
476 ERIS_IFU_PRO_JITTER_RESPONSE
477 };
478 eris_dfs_check_input_tags(frameset, optional_tags, ntags_opt, 0);
479
480
481
482 /* Initialise */
483
484 /* Get Parameters */
485 par = cpl_parameterlist_find_const(parlist,
486 CONTEXT".offset_mode");
487 offset_mode = cpl_parameter_get_bool(par);
488
489 par = cpl_parameterlist_find_const(parlist,
490 CONTEXT".name_i");
491 name_i = cpl_parameter_get_string(par);
492
493 par = cpl_parameterlist_find_const(parlist,
494 CONTEXT".offset_unit");
495 offunit = cpl_parameter_get_string(par);
496
497
498 /* Identify the RAW and CALIB frames in the input frameset */
499 if (eris_dfs_set_groups(frameset) != 0) {
500 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
501 return (int) cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
502 }
503
504 /* Check the inputs consistency */
505 cpl_ensure_code(CPL_ERROR_NONE ==
506 eris_dfs_check_input_tags(frameset, required_tags, ntags, 1),
507 CPL_ERROR_ILLEGAL_INPUT);
508
509 /* Check the inputs offset list consistency */
510 cpl_frameset* cube_set;
511 cube_set = eris_ifu_extract_frameset(frameset, ERIS_IFU_COMBINE_DOCATG );
512 if (!offset_mode) {
513 cpl_msg_info(__func__, "Use user offsets to combine.") ;
514
515 if ( NULL == (file_list = fopen (name_i, "r" )) ){
516 cpl_msg_error(__func__, "cannot open %s\n", name_i) ;
517 return (int) cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
518 }
519 cnt = 0 ;
520
521 if (strcmp(offunit, "PIXDEG") == 0){
522 while (fscanf( file_list, "%lf %lf %lf %lf",&crpix1,&crpix2, &alpha, &delta ) != EOF ) {
523 cnt ++ ;
524 }
525
526 } else {
527 while ( fscanf( file_list, "%f %f",&tmpoffx, &tmpoffy) != EOF ){
528 cnt ++ ;
529 }
530 }
531 fclose(file_list);
532
533 if (cnt != cpl_frameset_get_size(cube_set)) {
534 cpl_msg_error(__func__, "Input offlist is not consistent with frameset or offunit") ;
535 if (strcmp(offunit, "PIXDEG") == 0){
536 cpl_msg_error(__func__, "If offunit is PIXDEG input ASCII file must have four columns");
537 } else {
538 cpl_msg_error(__func__, "If offunit is not PIXDEG input ASCII file must have two columns");
539 }
540 return (int) cpl_error_set(__func__, CPL_ERROR_INCOMPATIBLE_INPUT) ;
541 }
542 }
543 else {
544 cpl_msg_info(__func__, "Use wcs in each input cube to combine.") ;
545 }
546
547
548 /* Read offset list */
549 if (!offset_mode){
550 cpl_msg_info(__func__, "Reading offset list.") ;
551 //Allocate memories
552 nframes = cnt ;
553 offsetx = (float*) cpl_calloc(nframes, sizeof(float));
554 offsety = (float*) cpl_calloc(nframes, sizeof(float));
555
556 crpix1_usr = (float*) cpl_calloc(nframes, sizeof(float));
557 crpix2_usr = (float*) cpl_calloc(nframes, sizeof(float));
558 crval1_usr = (float*) cpl_calloc(nframes, sizeof(float));
559 crval2_usr = (float*) cpl_calloc(nframes, sizeof(float));
560 if (offsetx == NULL || offsety == NULL){
561 cpl_msg_error(__func__, "Could not allocate memory!") ;
562 cpl_free(offsetx);
563 cpl_free(offsety);
564 return (int) cpl_error_set(__func__, CPL_ERROR_UNSPECIFIED);
565 }
566
567 //Read
568 file_list = fopen (name_i, "r" );
569
570 cnt = 0;
571
572 if (strcmp(offunit, "PIXDEG") == 0){
573 while (fscanf( file_list, "%lf %lf %lf %lf",&crpix1,&crpix2, &alpha, &delta ) != EOF ) {
574 // cpl_frame *frame = cpl_frameset_get_position(frameset, cnt);
575 crpix1_usr[cnt] = crpix1;
576 crpix2_usr[cnt] = crpix2;
577 crval1_usr[cnt] = alpha;
578 crval2_usr[cnt] = delta;
579 cnt ++ ;
580 }
581 nframes = cnt;
582 fclose(file_list);
583 } else {
584 while (fscanf( file_list, "%f %f",&tmpoffx,&tmpoffy ) != EOF ) {
585 // cpl_frame *frame = cpl_frameset_get_position(frameset, cnt);
586 offsetx[cnt] = tmpoffx;
587 offsety[cnt] = tmpoffy;
588 cnt ++ ;
589 }
590 nframes = cnt;
591 fclose(file_list);
592 }
593 }
594
595
596 //char *combDoCatg = ERIS_IFU_COMBINE_DOCATG;
597 int offcode = 0;
598 double as2deg = 1.0/3600.0;
599 double scalex = 1.0;
600 double scaley = 1.0;
601 //cpl_frameset* cube_set = NULL;
602
603 cpl_size ncubes = cpl_frameset_get_size(cube_set);
604 cpl_frame* cube_frm = NULL;
605 cpl_propertylist* plist = NULL;
606 cpl_propertylist* hdata = NULL;
607 const char* fname = NULL;
608 double dit = 0.0;
609 double dit_ref = 0;
610 cpl_vector* factor_vec = cpl_vector_new(ncubes);
611 double* pfactor = cpl_vector_get_data(factor_vec);
612 for(int i = 0; i < ncubes; i++) {
613
614 cube_frm = cpl_frameset_get_position(cube_set, i);
615 cpl_frame_set_group(cube_frm, CPL_FRAME_GROUP_RAW);
616 fname = cpl_frame_get_filename(cube_frm);
617 hdata = cpl_propertylist_load(fname, 0);
618 dit = cpl_propertylist_get_double(hdata, FHDR_E_DIT);
619 cpl_msg_info(cpl_func,"time[%d]=%g",i,dit);
620 if(i == 0) {
621 dit_ref = dit;
622 pfactor[0] = 1;
623 } else {
624 pfactor[i] = dit_ref / dit ;
625 }
626 cpl_propertylist_delete(hdata);
627 }
628 if(cpl_error_get_code() != CPL_ERROR_NONE) {
629 cpl_msg_error(cpl_func,"errors to get exposure time from data. Check your data. Exit.");
630 cpl_vector_delete(factor_vec);
631 cpl_frameset_delete(cube_set);
632 return (int) cpl_error_get_code();
633 }
634 const char* fname_spec_cube = "cube";
635 if (offunit != NULL && offsetx !=NULL && offsety !=NULL){
636 if (strcmp(offunit, "PIXEL") == 0){
637 offcode = 0;
638 cpl_msg_info(cpl_func, "User-defined offset unit in PIXEL");
639 } else if (strcmp(offunit, "DEGREE") == 0){
640 offcode = 1;
641 cpl_msg_info(cpl_func, "User-defined offset unit is DEGREE");
642 } else if (strcmp(offunit, "ARCSEC") == 0){
643 offcode = 2;
644 cpl_msg_info(cpl_func, "User-defined offset unit is ARCSEC");
645 scalex = as2deg;
646 scaley = as2deg;
647 } else if (strcmp(offunit, "PIXDEG") == 0){
648 offcode = 3;
649 cpl_msg_info(cpl_func, "User-defined offset unit is PIXDEG");
650 } else {
651 cpl_msg_error(cpl_func, "User-defined offset unit or offset list is not correct.");
652 }
653
654
655
656
657 char* new_name = NULL;
658 cpl_imagelist* data = NULL;
659 cpl_imagelist* errs = NULL;
660 cpl_imagelist* qual = NULL;
661
662 cpl_propertylist* herrs = NULL;
663 cpl_propertylist* hqual = NULL;
664 for(int i = 0; i < ncubes; i++) {
665 cube_frm = cpl_frameset_get_position(cube_set, i);
666 fname = cpl_frame_get_filename(cube_frm);
667 hdata = cpl_propertylist_load(fname, 1);
668
669 if(offcode == 0) { // PIXEL
670 crpix1 = cpl_propertylist_get_double(hdata, "CRPIX1");
671 crpix2 = cpl_propertylist_get_double(hdata, "CRPIX2");
672 cpl_propertylist_set_double(hdata,"CRPIX1", crpix1 + offsetx[i]);
673 cpl_propertylist_set_double(hdata,"CRPIX2", crpix2 + offsety[i]);
674 } else if (offcode == 1) { // DEGREE
675 crval1 = cpl_propertylist_get_double(hdata, "CRVAL1");
676 crval2 = cpl_propertylist_get_double(hdata, "CRVAL2");
677 cpl_propertylist_set_double(hdata,"CRVAL1", crval1 + offsetx[i]);
678 cpl_propertylist_set_double(hdata,"CRVAL2", crval2 + offsety[i]);
679
680 } else if (offcode == 2) { // ARCSEC
681 crval1 = cpl_propertylist_get_double(hdata, "CRVAL1");
682 crval2 = cpl_propertylist_get_double(hdata, "CRVAL2");
683 cpl_propertylist_set_double(hdata,"CRVAL1", crval1 + offsetx[i] * scalex);
684 cpl_propertylist_set_double(hdata,"CRVAL2", crval2 + offsety[i] * scaley);
685
686 } else if (offcode == 3) { //real coordinates x, y , alpha, delta
687
688 cpl_propertylist_set_double(hdata,"CRPIX1", crpix1_usr[i]);
689 cpl_propertylist_set_double(hdata,"CRPIX2", crpix2_usr[i]);
690
691 cpl_propertylist_set_double(hdata,"CRVAL1", crval1_usr[i]);
692 cpl_propertylist_set_double(hdata,"CRVAL2", crval2_usr[i]);
693
694 }
695
696 plist = cpl_propertylist_load(fname, 0);
697 herrs = cpl_propertylist_load(fname, 2);
698 hqual = cpl_propertylist_load(fname, 3);
699 data = cpl_imagelist_load(fname, CPL_TYPE_DOUBLE, 1);
700 errs = cpl_imagelist_load(fname, CPL_TYPE_DOUBLE, 2);
701 qual = cpl_imagelist_load(fname, CPL_TYPE_INT, 3);
702 /* scale cubes data and error by exposure time to exptime of 1st input frame */
703 cpl_msg_info(cpl_func,"correct[%d] by=%g",i,pfactor[i]);
704 cpl_imagelist_multiply_scalar(data,pfactor[i]);
705 cpl_imagelist_multiply_scalar(errs,sqrt(pfactor[i]));
706 new_name = cpl_sprintf("cube_%2.2d.fits",i);
707 cpl_frame_set_filename(cube_frm, new_name);
708 cpl_propertylist_save(plist, new_name, CPL_IO_CREATE);
709 cpl_imagelist_save(data, new_name, CPL_TYPE_DOUBLE, hdata, CPL_IO_EXTEND);
710 cpl_imagelist_save(errs, new_name, CPL_TYPE_DOUBLE, herrs, CPL_IO_EXTEND);
711 cpl_imagelist_save(qual, new_name, CPL_TYPE_INT, hqual, CPL_IO_EXTEND);
712 cpl_propertylist_delete(plist);
713 cpl_propertylist_delete(hdata);
714 cpl_propertylist_delete(herrs);
715 cpl_propertylist_delete(hqual);
716 cpl_imagelist_delete(data);
717 cpl_imagelist_delete(errs);
718 cpl_imagelist_delete(qual);
719
720 cpl_free(new_name);
721
722 }
723
724
725 if(eris_ifu_combine_pbp(cube_set, parlist,
726 ERIS_IFU_COMBINE_DOCATG, fname_spec_cube,
727 NULL, NULL, offunit,
728 RECIPE_NAME, RECIPE_NAME) != CPL_ERROR_NONE){
729 cpl_msg_error(__func__, "Cannot resampling the cubes for combination.");
730 }
731
732 } else {
733
734
735 char* new_name = NULL;
736 cpl_imagelist* data = NULL;
737 cpl_imagelist* errs = NULL;
738 cpl_imagelist* qual = NULL;
739
740 cpl_propertylist* herrs = NULL;
741 cpl_propertylist* hqual = NULL;
742 /* scaling by exptime */
743 for(int i = 0; i < ncubes; i++) {
744 cube_frm = cpl_frameset_get_position(cube_set, i);
745 fname = cpl_frame_get_filename(cube_frm);
746 hdata = cpl_propertylist_load(fname, 1);
747
748
749
750 plist = cpl_propertylist_load(fname, 0);
751 herrs = cpl_propertylist_load(fname, 2);
752 hqual = cpl_propertylist_load(fname, 3);
753 data = cpl_imagelist_load(fname, CPL_TYPE_DOUBLE, 1);
754 errs = cpl_imagelist_load(fname, CPL_TYPE_DOUBLE, 2);
755 qual = cpl_imagelist_load(fname, CPL_TYPE_INT, 3);
756 /* scale cubes data and error by exposure time to exptime of 1st input frame */
757 cpl_msg_info(cpl_func,"correct[%d] by=%g",i,pfactor[i]);
758 cpl_imagelist_multiply_scalar(data,pfactor[i]);
759 cpl_imagelist_multiply_scalar(errs,sqrt(pfactor[i]));
760 new_name = cpl_sprintf("cube_%2.2d.fits",i);
761 cpl_frame_set_filename(cube_frm, new_name);
762 cpl_propertylist_save(plist, new_name, CPL_IO_CREATE);
763 cpl_imagelist_save(data, new_name, CPL_TYPE_DOUBLE, hdata, CPL_IO_EXTEND);
764 cpl_imagelist_save(errs, new_name, CPL_TYPE_DOUBLE, herrs, CPL_IO_EXTEND);
765 cpl_imagelist_save(qual, new_name, CPL_TYPE_INT, hqual, CPL_IO_EXTEND);
766 cpl_propertylist_delete(plist);
767 cpl_propertylist_delete(hdata);
768 cpl_propertylist_delete(herrs);
769 cpl_propertylist_delete(hqual);
770 cpl_imagelist_delete(data);
771 cpl_imagelist_delete(errs);
772 cpl_imagelist_delete(qual);
773
774 cpl_free(new_name);
775
776 }
777
778
779 if(eris_ifu_combine_pbp(cube_set, parlist,
780 ERIS_IFU_COMBINE_DOCATG, fname_spec_cube,
781 NULL, NULL, offunit,
782 RECIPE_NAME, RECIPE_NAME) != CPL_ERROR_NONE){
783 cpl_msg_error(__func__, "Cannot resampling the cubes for combination.");
784 }
785
786 }
787 cpl_vector_delete(factor_vec);
788
789 if (offsetx != NULL)
790 cpl_free(offsetx);
791 if (offsety != NULL)
792 cpl_free(offsety);
793
794 if (crpix1_usr != NULL)
795 cpl_free(crpix1_usr);
796 if (crpix2_usr != NULL)
797 cpl_free(crpix2_usr);
798
799 if (crval1_usr != NULL)
800 cpl_free(crval1_usr);
801 if (crval2_usr != NULL)
802 cpl_free(crval2_usr);
803
804
805 /* add possibility to extract and flux calibrate combined data cube */
806 cubeType obj_type = OBJECT_CUBE;
807 cubeType resampled_obj_type = OBJECT_CUBE_COADD;
808 const char *proCatg;
809 cpl_frame* frame = NULL;
810 if( NULL != (frame = cpl_frameset_find(frameset, ERIS_IFU_PRO_JITTER_RESPONSE ))) {
811 cpl_frameset_insert(cube_set, cpl_frame_duplicate(frame));
812 //cpl_frameset_erase(frameset, frame);
813
814 }
815
816
817 if( NULL != (frame = cpl_frameset_find(frameset, ERIS_IFU_CALIB_EXTCOEFF_TABLE ))) {
818 cpl_frameset_insert(cube_set, cpl_frame_duplicate(frame));
819 //cpl_frameset_erase(frameset, frame);
820
821 }
822
823 if (cpl_frameset_count_tags(cube_set, ERIS_IFU_PRO_JITTER_DAR_CUBE)
824 > 0) {
825 obj_type = DAR_CUBE;
826 resampled_obj_type = DAR_CUBE_COADD;
827 proCatg = ERIS_IFU_PRO_JITTER_DAR_CUBE;
828 } else if (cpl_frameset_count_tags(cube_set, ERIS_IFU_PRO_JITTER_TWK_CUBE)
829 > 0 ) {
830 obj_type = TWEAKED_CUBE;
831 resampled_obj_type = TWEAKED_CUBE_COADD;
832 proCatg = ERIS_IFU_PRO_JITTER_TWK_CUBE;
833 } else {
834 obj_type = OBJECT_CUBE;
835 resampled_obj_type = OBJECT_CUBE_COADD;
836 proCatg = ERIS_IFU_PRO_JITTER_OBJ_CUBE;
837 }
838
839 /* check if Pupil Tracking */
840 char *combDoCatg = NULL;
841 char *filenameSpec = NULL;
842 eris_ifu_jitter_get_procatg_and_filename(obj_type, &combDoCatg, &filenameSpec);
843
844 eris_ifu_free_string(&combDoCatg);
845 eris_ifu_free_string(&filenameSpec);
846 char* param_name = cpl_sprintf("%s.flux-calibrate", CONTEXT);
847 cpl_boolean flux_calibrate = cpl_parameter_get_bool(
848 cpl_parameterlist_find_const(parlist, param_name));
849 cpl_free(param_name);
850
851 param_name = cpl_sprintf("%s.extract-source", CONTEXT);
852 cpl_boolean extract_source = cpl_parameter_get_bool(
853 cpl_parameterlist_find_const(parlist, param_name));
854 cpl_free(param_name);
855
856
857 /* extract spectra and for STD star computes response and efficiency */
858 if (extract_source && eris_can_extract(cube_set)) {
859 cpl_msg_info(cpl_func,"extracting");
860 eris_ifu_jitter_extract(cube_set, parlist, resampled_obj_type,
861 proCatg, stdParams, RECIPE_NAME, CONTEXT);
862 }
863
864 if(flux_calibrate && eris_can_flux_calibrate(cube_set)) {
865
866 if(extract_source) {
867 cpl_msg_info(cpl_func,"Flux calibrate extracted spectrum");
868 eris_flux_calibrate_spectra(RECIPE_NAME, RECIPE_NAME, parlist,
869 cube_set, cube_set);
870
871 }
872 char* cube_pro_catg = NULL;
873 if(obj_type == DAR_CUBE) {
874 cube_pro_catg = cpl_sprintf("%s",ERIS_IFU_PRO_JITTER_OBJ_DAR_CUBE_COADD);
875 } else if(obj_type == TWEAKED_CUBE) {
876 cube_pro_catg = cpl_sprintf("%s",ERIS_IFU_PRO_JITTER_TWK_CUBE_COADD);
877 } else {
878 cube_pro_catg = cpl_sprintf("%s",ERIS_IFU_PRO_JITTER_OBJ_CUBE_COADD);
879 }
880
881 cpl_msg_info(cpl_func,"proCatg: %s",cube_pro_catg);
882
883 cpl_msg_info(cpl_func,"Flux calibrate combined data cube");
884 if(extract_source) {
885 /*TODO: force to have extracted spectrum as wmin/max is taken from it
886 * we should update this to use the wmin/wmax of the output cube instead
887 */
888 eris_flux_calibrate_cube2(cube_pro_catg, RECIPE_NAME, RECIPE_NAME, parlist,
889 /*frameset, */cube_set);
890 }
891 cpl_free(cube_pro_catg);
892
893 }
894 cpl_frameset_erase(cube_set,ERIS_IFU_COMBINE_DOCATG);
895 cpl_frameset_join(frameset,cube_set);
896
897 char* cmd = cpl_sprintf("rm cube*.fits");
898 int status = system(cmd);
899 cpl_free(cmd);
900 /* end addition */
901 cpl_frameset_delete(cube_set);
902 //Clean up
903 //eris_ifu_jitter_free_sofStruct(&sof);
904 //eris_ifu_free_std_param(&stdParams);
905 return (int) cpl_error_get_code();
906}
cpl_error_code eris_dfs_set_groups(cpl_frameset *self)
Set the group as RAW or CALIB in a frameset.
Definition: eris_dfs.c:57
cpl_frameset * eris_ifu_extract_frameset(const cpl_frameset *in, const char *tag)
Extract frames with a specific tag from a frameset.
Definition: eris_ifu_dfs.c:201
cpl_error_code eris_parlist_config_add_all_recipes(cpl_parameterlist *pl, const char *recname)
Add common configuration parameters for all recipes.
cpl_error_code eris_ifu_jitter_fill_extract_parameterlist(char *context, jitterModes jitterMode, cpl_parameterlist *pl)
Fill parameter list with source extraction parameters.
cpl_error_code eris_ifu_jitter_extract(cpl_frameset *frameset, const cpl_parameterlist *parlist, cubeType obj_type, const char *pcatg, struct stdParamStruct stdParams, const char *pipefile_prefix, const char *context)
Main spectral extraction function.
cpl_error_code eris_ifu_jitter_get_procatg_and_filename(cubeType type, char **proCatg, char **filenamePrefix)
Get the value of the PRO.CATG and the filename as function of the type of cube.
cpl_error_code eris_ifu_combine_pbp(cpl_frameset *frameset, const cpl_parameterlist *parlist, const char *input_cube_pro_catg, const char *filenameSpec, float *offsetx, float *offsety, const char *offunit, const char *recipe_name, const char *pipefile_prefix)
Resample and combine cubes plane-by-plane (2D spatial resampling per wavelength)
void eris_ifu_free_string(char **item)
Free memory and set pointer to null.