KMOS Pipeline Reference Manual 4.5.10
kmo_arithmetic.c
1/*
2 * This file is part of the KMOS Pipeline
3 * Copyright (C) 2002,2003 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24#include <string.h>
25
26#include <math.h>
27#include <cpl.h>
28
29#include "kmo_debug.h"
30#include "kmo_utils.h"
31#include "kmo_dfs.h"
32#include "kmo_error.h"
33#include "kmo_priv_arithmetic.h"
34#include "kmo_constants.h"
35
36#define FORBIDDEN_SCALAR -99999.9
37
38static int kmo_arithmetic_create(cpl_plugin *);
39static int kmo_arithmetic_exec(cpl_plugin *);
40static int kmo_arithmetic_destroy(cpl_plugin *);
41static int kmo_arithmetic(cpl_parameterlist *, cpl_frameset *);
42
43static char kmo_arithmetic_description[] =
44"With this recipe simple arithmetic operations, like addition, subtraction,\n"
45"multiplication, divison and raising to a power can be performed.\n"
46"Since FITS files formatted as F1I, F2I and F3I can contain data (and eventually\n"
47"noise) of either just one IFU or of all 24 IFUs, kmo_arithmetic behaves diffe-\n"
48"rently in these cases.\n"
49"When the number of IFUs is the same for both operands, the first IFU of the\n"
50"first operand is processed with the first IFU of the second operand.\n"
51"When the second operand has only one IFU while the first operand has more IFUs,\n"
52"then the all the IFUs of the first operand are processed individually which the\n"
53"IFU of the second operand.\n"
54"If an operand contains noise and the other doesn't, the noise will not be\n"
55"processed.\n"
56"\n"
57"Noise is only propagated if both operand contain noise extensions. If the\n"
58"second operator is a scalar noise is also propagated, of course.\n"
59"\n"
60"If two cubes are given as operands, they will be combined according to the \n"
61"given operator.If a cube is given as first operand and an image as second,\n"
62"then it operates on each slice of the cube; similarly if a spectrum is given\n"
63"as the second operand, it operates on each spectrum of the cube; and a number\n"
64"as the second operand operates on each pixel of the cube.\n"
65"\n"
66"BASIC PARAMETERS:\n"
67"-----------------\n"
68"--operator\n"
69"Any of the following operations to perform: '+', '-', '*' or '/' (also '^' \n"
70"when the 2nd operand is a scalar\n"
71"\n"
72"--scalar\n"
73"To be provided if a frame should be processed together with a scalar\n"
74"\n"
75"--file_extension\n"
76"Define a string to append to the product filename ARITHMETIC in order to get\n"
77"an unique filename\n"
78"\n"
79"-------------------------------------------------------------------------------\n"
80" Input files:\n"
81"\n"
82" DO KMOS \n"
83" category Type Explanation Required #Frames\n"
84" -------- ----- ----------- -------- -------\n"
85" <none or any> F3I or Data with or Y 1 \n"
86" F2I or without noise frame \n"
87" F1I or \n"
88" F2D or \n"
89" RAW \n"
90" <none or any> F3I or Data with or N 0,1 \n"
91" F2I or without noise frame \n"
92" F1I or \n"
93" F2D or \n"
94" RAW \n"
95"\n"
96" Output files:\n"
97"\n"
98" DO KMOS\n"
99" category Type Explanation\n"
100" -------- ----- -----------\n"
101" ARITHMETIC F3I or \n"
102" F2I or \n"
103" F1I or \n"
104" F2D \n"
105"-------------------------------------------------------------------------------\n"
106"\n";
107
124int cpl_plugin_get_info(cpl_pluginlist *list)
125{
126 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
127 cpl_plugin *plugin = &recipe->interface;
128
129 cpl_plugin_init(plugin,
130 CPL_PLUGIN_API,
131 KMOS_BINARY_VERSION,
132 CPL_PLUGIN_TYPE_RECIPE,
133 "kmo_arithmetic",
134 "Perform basic arithmetic on cubes",
135 kmo_arithmetic_description,
136 "Alex Agudo Berbel",
137 "https://support.eso.org/",
138 kmos_get_license(),
139 kmo_arithmetic_create,
140 kmo_arithmetic_exec,
141 kmo_arithmetic_destroy);
142
143 cpl_pluginlist_append(list, plugin);
144
145 return 0;
146}
147
155static int kmo_arithmetic_create(cpl_plugin *plugin)
156{
157 cpl_recipe *recipe;
158 cpl_parameter *p;
159
160 /* Check that the plugin is part of a valid recipe */
161 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
162 recipe = (cpl_recipe *)plugin;
163 else
164 return -1;
165
166 /* Create the parameters list in the cpl_recipe object */
167 recipe->parameters = cpl_parameterlist_new();
168
169 /* Fill the parameters list */
170 /* --operator */
171 p = cpl_parameter_new_value("kmos.kmo_arithmetic.operator",
172 CPL_TYPE_STRING,
173 "The operator ('+', '-', '*', '/' or '^')",
174 "kmos.kmo_arithmetic",
175 "");
176 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "operator");
177 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
178 cpl_parameterlist_append(recipe->parameters, p);
179
180 /* --scalar */
181 p = cpl_parameter_new_value("kmos.kmo_arithmetic.scalar",
182 CPL_TYPE_DOUBLE,
183 "The scalar operand",
184 "kmos.kmo_arithmetic",
185 FORBIDDEN_SCALAR);
186 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scalar");
187 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
188 cpl_parameterlist_append(recipe->parameters, p);
189
190 /* --file_extension */
191 p = cpl_parameter_new_value("kmos.kmo_arithmetic.file_extension",
192 CPL_TYPE_STRING,
193 "String to add to product filename.",
194 "kmos.kmo_arithmetic",
195 "");
196 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "file_extension");
197 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
198 cpl_parameterlist_append(recipe->parameters, p);
199
200 return 0;
201}
202
208static int kmo_arithmetic_exec(cpl_plugin *plugin)
209{
210 cpl_recipe *recipe;
211
212 /* Get the recipe out of the plugin */
213 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
214 recipe = (cpl_recipe *)plugin;
215 else return -1 ;
216
217 return kmo_arithmetic(recipe->parameters, recipe->frames);
218}
219
225static int kmo_arithmetic_destroy(cpl_plugin *plugin)
226{
227 cpl_recipe *recipe;
228
229 /* Get the recipe out of the plugin */
230 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
231 recipe = (cpl_recipe *)plugin;
232 else return -1 ;
233
234 cpl_parameterlist_delete(recipe->parameters);
235 return 0 ;
236}
237
252static int kmo_arithmetic(cpl_parameterlist *parlist, cpl_frameset *frameset)
253{
254 const char *op = NULL,
255 *file_extension = NULL;
256 char *fn_out = NULL;
257 cpl_imagelist *op1_3d = NULL,
258 *op2_3d = NULL,
259 *op1_noise_3d = NULL,
260 *op2_noise_3d = NULL;
261 cpl_image *op1_2d = NULL,
262 *op2_2d = NULL,
263 *op1_noise_2d = NULL,
264 *op2_noise_2d = NULL;
265 kmclipm_vector *op1_1d = NULL,
266 *op2_1d = NULL,
267 *op1_noise_1d = NULL,
268 *op2_noise_1d = NULL;
269 double op2_scalar = FORBIDDEN_SCALAR;
270 int ret_val = 0,
271 nr_devices = 0,
272 i = 0,
273 single_ifu = FALSE,
274 calc_f3i = FALSE,
275 calc_f2i = FALSE,
276 calc_f1i = FALSE,
277 devnr1 = 0,
278 devnr2 = 0;
279 cpl_propertylist *main_header = NULL,
280 *sub_header_data = NULL,
281 *sub_header_noise = NULL;
282 main_fits_desc desc1,
283 desc2;
284 cpl_frame *op1_frame = NULL,
285 *op2_frame = NULL;
286
287 KMO_TRY
288 {
289 kmo_init_fits_desc(&desc1);
290 kmo_init_fits_desc(&desc2);
291
292 // --- check input ---
293 KMO_TRY_ASSURE((parlist != NULL) &&
294 (frameset != NULL),
295 CPL_ERROR_NULL_INPUT,
296 "Not all input data is provided!");
297
298 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset) == 1,
299 CPL_ERROR_ILLEGAL_INPUT,
300 "Cannot identify RAW and CALIB frames!");
301
302 cpl_msg_info("", "--- Parameter setup for kmo_arithmetic ----");
303
304 op2_scalar = kmo_dfs_get_parameter_double(parlist,
305 "kmos.kmo_arithmetic.scalar");
306 KMO_TRY_CHECK_ERROR_STATE();
307
308 KMO_TRY_ASSURE((cpl_frameset_get_size(frameset) == 2) ||
309 ((cpl_frameset_get_size(frameset) == 1) &&
310 (fabs(op2_scalar-FORBIDDEN_SCALAR) > 1e-3)),
311 CPL_ERROR_NULL_INPUT,
312 "Two fits-files or one fits-file and one "
313 "scalar must be provided!");
314
315 if (cpl_frameset_get_size(frameset) == 1) {
316 KMO_TRY_EXIT_IF_ERROR(
317 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_arithmetic.scalar"));
318 } else {
319 KMO_TRY_EXIT_IF_NULL(
320 op2_frame = kmo_dfs_get_frame(frameset, "1"));
321 }
322 KMO_TRY_EXIT_IF_NULL(
323 op1_frame = kmo_dfs_get_frame(frameset, "0"));
324
325 KMO_TRY_EXIT_IF_NULL(
326 op = kmo_dfs_get_parameter_string(parlist,
327 "kmos.kmo_arithmetic.operator"));
328 KMO_TRY_ASSURE((strcmp(op, "+") == 0) ||
329 (strcmp(op, "-") == 0) ||
330 (strcmp(op, "*") == 0) ||
331 (strcmp(op, "/") == 0) ||
332 (strcmp(op, "^") == 0),
333 CPL_ERROR_ILLEGAL_INPUT,
334 "Operator not valid! Has it been provided?");
335
336 KMO_TRY_EXIT_IF_ERROR(
337 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_arithmetic.operator"));
338
339 file_extension = kmo_dfs_get_parameter_string(parlist,
340 "kmos.kmo_arithmetic.file_extension");
341 KMO_TRY_CHECK_ERROR_STATE();
342
343 KMO_TRY_EXIT_IF_ERROR(
344 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_arithmetic.file_extension"));
345
346 cpl_msg_info("", "-------------------------------------------");
347
348 if (strcmp(file_extension, "") == 0) {
349 fn_out = cpl_sprintf("%s", ARITHMETIC);
350 } else {
351 fn_out = cpl_sprintf("%s_%s", ARITHMETIC, file_extension);
352 }
353
354 // load descriptor, header and data of first operand
355 desc1 = kmo_identify_fits_header(
356 cpl_frame_get_filename(op1_frame));
357 KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem to be "
358 "in KMOS-format!");
359
360 KMO_TRY_ASSURE((desc1.fits_type == f3i_fits) ||
361 (desc1.fits_type == f2i_fits) ||
362 (desc1.fits_type == f1i_fits) ||
363 (desc1.fits_type == f2d_fits) ||
364 (desc1.fits_type == raw_fits),
365 CPL_ERROR_ILLEGAL_INPUT,
366 "First input file hasn't correct data type "
367 "(KMOSTYPE must be F3I, F2I, F1I, F2D or RAW)!");
368
369 // load descriptor, header of second operand
370 if (fabs(op2_scalar-FORBIDDEN_SCALAR) < 1e-3) {
371 desc2 = kmo_identify_fits_header(
372 cpl_frame_get_filename(op2_frame));
373 KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem to "
374 "be in KMOS-format!");
375
376 if (desc1.fits_type == f3i_fits) {
377 KMO_TRY_ASSURE((desc2.fits_type == f3i_fits) ||
378 (desc2.fits_type == f2i_fits)||
379 (desc2.fits_type == f1i_fits),
380 CPL_ERROR_ILLEGAL_INPUT,
381 "For a F3I frame, the 2nd frame must be a "
382 "F3I, F2I or a F1I frame!");
383
384 if (desc2.fits_type == f3i_fits) {
385 KMO_TRY_ASSURE((desc1.naxis1 == desc2.naxis1) &&
386 (desc1.naxis2 == desc2.naxis2) &&
387 (desc1.naxis3 == desc2.naxis3),
388 CPL_ERROR_INCOMPATIBLE_INPUT,
389 "The dimensions of the two operands do "
390 "not match!");
391 } else if (desc2.fits_type == f2i_fits) {
392 KMO_TRY_ASSURE((desc1.naxis1 == desc2.naxis1) &&
393 (desc1.naxis2 == desc2.naxis2),
394 CPL_ERROR_INCOMPATIBLE_INPUT,
395 "The dimensions of the two operands do "
396 "not match!");
397 } else if (desc2.fits_type == f1i_fits) {
398 KMO_TRY_ASSURE((desc1.naxis3 == desc2.naxis1),
399 CPL_ERROR_INCOMPATIBLE_INPUT,
400 "The dimensions of the two operands do "
401 "not match!");
402 }
403 } else if (desc1.fits_type == f2i_fits) {
404 KMO_TRY_ASSURE(desc2.fits_type == f2i_fits,
405 CPL_ERROR_ILLEGAL_INPUT,
406 "For a F2I frame, the 2nd frame must be a "
407 "F2I frame!");
408 KMO_TRY_ASSURE((desc1.naxis1 == desc2.naxis1) &&
409 (desc1.naxis2 == desc2.naxis2),
410 CPL_ERROR_INCOMPATIBLE_INPUT,
411 "The dimensions of the two operands do "
412 "not match!");
413 } else if (desc1.fits_type == f1i_fits) {
414 KMO_TRY_ASSURE(desc2.fits_type == f1i_fits,
415 CPL_ERROR_ILLEGAL_INPUT,
416 "For a F1I frame, the 2nd frame must be a "
417 "F1I frame!");
418 KMO_TRY_ASSURE(desc1.naxis1 == desc2.naxis1,
419 CPL_ERROR_INCOMPATIBLE_INPUT,
420 "The dimensions of the two operands do "
421 "not match!");
422 } else if (desc1.fits_type == f2d_fits) {
423 KMO_TRY_ASSURE((desc2.fits_type == f2d_fits) ||
424 ((desc2.fits_type == raw_fits) && (desc1.ex_noise == FALSE)),
425 CPL_ERROR_ILLEGAL_INPUT,
426 "For a F2D frame, the 2nd frame must be a "
427 "F2D frame!");
428 KMO_TRY_ASSURE((desc1.naxis1 == desc2.naxis1) &&
429 (desc1.naxis2 == desc2.naxis2),
430 CPL_ERROR_INCOMPATIBLE_INPUT,
431 "The dimensions of the two operands do "
432 "not match!");
433 } else if (desc1.fits_type == raw_fits) {
434 KMO_TRY_ASSURE((desc2.fits_type == raw_fits) ||
435 ((desc2.fits_type == f2d_fits) && (desc2.ex_noise == FALSE)),
436 CPL_ERROR_ILLEGAL_INPUT,
437 "For a RAW frame, the 2nd frame must be a "
438 "RAW frame!");
439 KMO_TRY_ASSURE((desc1.naxis1 == desc2.naxis1) &&
440 (desc1.naxis2 == desc2.naxis2),
441 CPL_ERROR_INCOMPATIBLE_INPUT,
442 "The dimensions of the two operands do "
443 "not match!");
444 }
445
446 if (((desc2.nr_ext == 1) &&
447 (desc2.sub_desc[0].valid_data == TRUE))
448 ||
449 ((desc2.nr_ext == 2) &&
450 (desc2.ex_noise == TRUE) &&
451 (desc2.sub_desc[0].valid_data == TRUE) &&
452 (desc2.sub_desc[1].valid_data == TRUE))) {
453 single_ifu = TRUE;
454 } else {
455 if (desc1.ex_noise == desc2.ex_noise) {
456 KMO_TRY_ASSURE(desc1.nr_ext == desc2.nr_ext,
457 CPL_ERROR_INCOMPATIBLE_INPUT,
458 "The number of IFUs of the two operands do "
459 "not match!");
460 } else {
461 KMO_TRY_ASSURE(desc1.nr_ext == desc2.nr_ext * 2,
462 CPL_ERROR_INCOMPATIBLE_INPUT,
463 "The number of IFUs of the two operands do "
464 "not match!");
465 }
466 }
467 }
468
469 // --- load, update & save primary header ---
470 KMO_TRY_EXIT_IF_ERROR(
471 kmo_dfs_save_main_header(frameset, fn_out, "", op1_frame, NULL,
472 parlist, cpl_func));
473
474 //
475 // load data
476 //
477 if (desc1.ex_noise == TRUE) {
478 nr_devices = desc1.nr_ext / 2;
479 } else {
480 nr_devices = desc1.nr_ext;
481 }
482
483 if ((single_ifu == TRUE) &&
484 (desc2.sub_desc[0].valid_data == TRUE))
485 {
486 switch (desc2.fits_type) {
487 case f3i_fits:
488
489 KMO_TRY_EXIT_IF_NULL(
490 op2_3d = kmo_dfs_load_cube(frameset, "1",
491 desc2.sub_desc[0].device_nr,
492 FALSE));
493
494 if ((desc1.ex_noise == TRUE) && (desc2.ex_noise == TRUE)) {
495 KMO_TRY_EXIT_IF_NULL(
496 op2_noise_3d = kmo_dfs_load_cube(frameset, "1",
497 desc2.sub_desc[0].device_nr,
498 TRUE));
499 }
500 break;
501 case f2i_fits:
502 KMO_TRY_EXIT_IF_NULL(
503 op2_2d = kmo_dfs_load_image(frameset, "1",
504 desc2.sub_desc[0].device_nr,
505 FALSE, FALSE, NULL));
506
507 if ((desc1.ex_noise == TRUE) && (desc2.ex_noise == TRUE)) {
508 KMO_TRY_EXIT_IF_NULL(
509 op2_noise_2d = kmo_dfs_load_image(frameset,
510 "1",
511 desc2.sub_desc[0].device_nr,
512 TRUE, FALSE, NULL));
513 }
514 break;
515 case f1i_fits:
516 KMO_TRY_EXIT_IF_NULL(
517 op2_1d = kmo_dfs_load_vector(frameset, "1",
518 desc2.sub_desc[0].device_nr,
519 FALSE));
520
521 if ((desc1.ex_noise == TRUE) && (desc2.ex_noise == TRUE)) {
522 KMO_TRY_EXIT_IF_NULL(
523 op2_noise_1d = kmo_dfs_load_vector(frameset,
524 "1",
525 desc2.sub_desc[0].device_nr,
526 TRUE));
527 }
528 break;
529 default:
530 break;
531 }
532 }
533
534 for (i = 1; i <= nr_devices; i++) {
535 if (desc1.ex_noise == FALSE) {
536 devnr1 = desc1.sub_desc[i - 1].device_nr;
537 } else {
538 devnr1 = desc1.sub_desc[2 * i - 1].device_nr;
539 }
540
541 if (fabs(op2_scalar-FORBIDDEN_SCALAR) < 1e-3) {
542 if (desc2.ex_noise == FALSE) {
543 devnr2 = desc2.sub_desc[i - 1].device_nr;
544 } else {
545 devnr2 = desc2.sub_desc[2 * i - 1].device_nr;
546 }
547 }
548
549 KMO_TRY_EXIT_IF_NULL(
550 sub_header_data = kmo_dfs_load_sub_header(frameset, "0",
551 devnr1,
552 FALSE));
553 switch (desc1.fits_type) {
554 case raw_fits:
555 // load data 1st operand
556 KMO_TRY_EXIT_IF_NULL(
557 op1_2d = kmo_dfs_load_image(frameset, "0", i,
558 FALSE, TRUE, NULL));
559 //
560 // process RAW & RAW
561 // process RAW & F2D
562 //
563 if ((desc2.fits_type == raw_fits) ||
564 (desc2.fits_type == f2d_fits))
565 {
566 /* load data 2nd operand */
567 KMO_TRY_EXIT_IF_NULL(
568 op2_2d = kmo_dfs_load_image(frameset, "1", i,
569 FALSE, TRUE, NULL));
570
571 KMO_TRY_EXIT_IF_ERROR(
572 kmo_arithmetic_2D_2D(op1_2d, op2_2d, NULL, NULL, op));
573 }
574
575 //
576 // process RAW & scalar
577 //
578 else if (fabs(op2_scalar-FORBIDDEN_SCALAR) > 1e-3) {
579 KMO_TRY_EXIT_IF_ERROR(
580 kmo_arithmetic_2D_scalar(op1_2d, op2_scalar, NULL,
581 op));
582 }
583
584// keep EXTNAME from op1 (e.g. CHIP1.INT1 instead of creating DET.1.DATA)
585// KMO_TRY_EXIT_IF_ERROR(
586// kmo_update_sub_keywords(sub_header_data, FALSE, FALSE,
587// detector_frame, i));
588
589 KMO_TRY_EXIT_IF_ERROR(
590 kmo_dfs_save_image(op1_2d, fn_out, "",
591 sub_header_data, 0./0.));
592 break;
593 case f2d_fits:
594 KMO_TRY_EXIT_IF_NULL(
595 op1_2d = kmo_dfs_load_image(frameset, "0", i,
596 FALSE, FALSE, NULL));
597 //
598 // process F2D & F2D
599 // process F2D & RAW
600 //
601 if ((desc2.fits_type == f2d_fits) ||
602 (desc2.fits_type == raw_fits))
603 {
604 KMO_TRY_EXIT_IF_NULL(
605 op2_2d = kmo_dfs_load_image(frameset, "1", i,
606 FALSE, FALSE, NULL));
607 // load noise
608 if ((desc1.ex_noise == TRUE) &&
609 (desc2.ex_noise == TRUE)) {
610 KMO_TRY_EXIT_IF_NULL(
611 op1_noise_2d = kmo_dfs_load_image(frameset,
612 "0", i, TRUE, FALSE, NULL));
613
614 KMO_TRY_EXIT_IF_NULL(
615 op2_noise_2d = kmo_dfs_load_image(frameset,
616 "1", i, TRUE, FALSE, NULL));
617 }
618 KMO_TRY_EXIT_IF_ERROR(
619 kmo_arithmetic_2D_2D(op1_2d, op2_2d,
620 op1_noise_2d, op2_noise_2d,
621 op));
622 }
623 //
624 // process F2D & scalar
625 //
626
627 else if (fabs(op2_scalar-FORBIDDEN_SCALAR) > 1e-3) {
628 // process data & noise
629 if (desc1.ex_noise == TRUE) {
630 KMO_TRY_EXIT_IF_NULL(
631 op1_noise_2d = kmo_dfs_load_image(frameset,
632 "0", i, TRUE, FALSE, NULL));
633 }
634 KMO_TRY_EXIT_IF_ERROR(
635 kmo_arithmetic_2D_scalar(op1_2d,
636 op2_scalar,
637 op1_noise_2d,
638 op));
639 }
640
641 // save data (and noise)
642 KMO_TRY_EXIT_IF_ERROR(
643 kmo_dfs_save_image(op1_2d, fn_out, "",
644 sub_header_data, 0./0.));
645
646 if (op1_noise_2d != NULL) {
647 KMO_TRY_EXIT_IF_NULL(
648 sub_header_noise = kmo_dfs_load_sub_header(frameset,
649 "0", i, TRUE));
650 KMO_TRY_EXIT_IF_ERROR(
651 kmo_dfs_save_image(op1_noise_2d, fn_out, "",
652 sub_header_noise, 0./0.));
653
654 cpl_propertylist_delete(sub_header_noise);
655 sub_header_noise = NULL;
656 }
657 break;
658 case f3i_fits:
659 calc_f3i = FALSE;
660
661 // check if IFUs are valid
662 if (desc1.ex_noise == FALSE) {
663 if (desc1.sub_desc[i - 1].valid_data == TRUE) {
664 if (fabs(op2_scalar-FORBIDDEN_SCALAR) > 1e-3) {
665 calc_f3i = TRUE;
666 } else if (((single_ifu == TRUE) &&
667 (desc2.sub_desc[0].valid_data == TRUE))
668 ||
669 (desc2.sub_desc[i - 1].valid_data == TRUE))
670 {
671 calc_f3i = TRUE;
672 }
673 }
674 }
675 if (desc1.ex_noise == TRUE) {
676 if (desc1.sub_desc[2 * i - 1].valid_data == TRUE) {
677 calc_f3i = TRUE;
678 }
679 }
680 if ((desc1.ex_noise == TRUE) && (desc2.ex_noise == TRUE)) {
681 if (desc1.sub_desc[2 * i - 1].valid_data == TRUE) {
682 if (((single_ifu == TRUE) &&
683 (desc2.sub_desc[1].valid_data == TRUE))
684 ||
685 (desc2.sub_desc[2 * i - 1].valid_data == TRUE))
686 {
687 calc_f3i = TRUE;
688 }
689 }
690 }
691 if ((single_ifu == TRUE) && (desc1.ex_noise == FALSE)) {
692 if ((desc1.sub_desc[i - 1].valid_data == TRUE) &&
693 (desc2.sub_desc[0].valid_data == TRUE)) {
694 calc_f3i = TRUE;
695 }
696 }
697
698 if (calc_f3i == TRUE)
699 {
700 KMO_TRY_EXIT_IF_NULL(
701 op1_3d = kmo_dfs_load_cube(frameset, "0",
702 devnr1, FALSE));
703 //
704 // process F3I & F3I
705 //
706 if (desc2.fits_type == f3i_fits) {
707 if (single_ifu == FALSE) {
708 KMO_TRY_EXIT_IF_NULL(
709 op2_3d = kmo_dfs_load_cube(frameset,
710 "1", devnr2,
711 FALSE));
712 }
713
714 if ((desc1.ex_noise == TRUE) &&
715 (desc2.ex_noise == TRUE))
716 {
717 KMO_TRY_EXIT_IF_NULL(
718 op1_noise_3d = kmo_dfs_load_cube(frameset,
719 "0", devnr1,
720 TRUE));
721
722 if (single_ifu == FALSE) {
723 KMO_TRY_EXIT_IF_NULL(
724 op2_noise_3d = kmo_dfs_load_cube(
725 frameset,
726 "1", devnr2,
727 TRUE));
728 }
729 }
730
731 KMO_TRY_EXIT_IF_ERROR(
732 kmo_arithmetic_3D_3D(op1_3d, op2_3d,
733 op1_noise_3d, op2_noise_3d,
734 op));
735 }
736
737 //
738 // process F3I & F2I
739 //
740 else if (desc2.fits_type == f2i_fits) {
741 if (single_ifu == FALSE) {
742 KMO_TRY_EXIT_IF_NULL(
743 op2_2d = kmo_dfs_load_image(frameset,
744 "1", devnr2,
745 FALSE, FALSE, NULL));
746 }
747
748 if ((desc1.ex_noise == TRUE) &&
749 (desc2.ex_noise == TRUE))
750 {
751 KMO_TRY_EXIT_IF_NULL(
752 op1_noise_3d = kmo_dfs_load_cube(frameset,
753 "0", devnr1,
754 TRUE));
755
756 if (single_ifu == FALSE) {
757 KMO_TRY_EXIT_IF_NULL(
758 op2_noise_2d = kmo_dfs_load_image(
759 frameset,
760 "1", devnr2,
761 TRUE, FALSE, NULL));
762 }
763 }
764
765 KMO_TRY_EXIT_IF_ERROR(
766 kmo_arithmetic_3D_2D(op1_3d, op2_2d,
767 op1_noise_3d, op2_noise_2d,
768 op));
769 }
770 //
771 // process F3I & F1I
772 //
773 else if (desc2.fits_type == f1i_fits) {
774 if (single_ifu == FALSE) {
775 KMO_TRY_EXIT_IF_NULL(
776 op2_1d = kmo_dfs_load_vector(frameset,
777 "1", devnr2,
778 FALSE));
779 }
780
781 if ((desc1.ex_noise == TRUE) &&
782 (desc2.ex_noise == TRUE))
783 {
784 KMO_TRY_EXIT_IF_NULL(
785 op1_noise_3d = kmo_dfs_load_cube(frameset,
786 "0", devnr1,
787 TRUE));
788
789 if (single_ifu == FALSE) {
790 KMO_TRY_EXIT_IF_NULL(
791 op2_noise_1d = kmo_dfs_load_vector(
792 frameset,
793 "1", devnr2,
794 TRUE));
795 }
796 }
797
798 KMO_TRY_EXIT_IF_ERROR(
799 kmo_arithmetic_3D_1D(op1_3d, op2_1d,
800 op1_noise_3d, op2_noise_1d,
801 op));
802 }
803 //
804 // process F3I & scalar
805 //
806 else if (fabs(op2_scalar-FORBIDDEN_SCALAR) > 1e-3) {
807 if (desc1.ex_noise == TRUE) {
808 KMO_TRY_EXIT_IF_NULL(
809 op1_noise_3d = kmo_dfs_load_cube(frameset,
810 "0", devnr1,
811 TRUE));
812 }
813
814 KMO_TRY_EXIT_IF_ERROR(
815 kmo_arithmetic_3D_scalar(op1_3d,
816 op2_scalar,
817 op1_noise_3d,
818 op));
819 }
820
821 // save data (and noise)
822 KMO_TRY_EXIT_IF_ERROR(
823 kmo_dfs_save_cube(op1_3d, fn_out, "",
824 sub_header_data, 0./0.));
825
826 if (op1_noise_3d != NULL) {
827 KMO_TRY_EXIT_IF_NULL(
828 sub_header_noise = kmo_dfs_load_sub_header(
829 frameset,
830 "0", devnr1,
831 TRUE));
832
833 KMO_TRY_EXIT_IF_ERROR(
834 kmo_dfs_save_cube(op1_noise_3d, fn_out, "",
835 sub_header_noise, 0./0.));
836
837 cpl_propertylist_delete(sub_header_noise);
838 sub_header_noise = NULL;
839 }
840 } else {
841 //
842 // invalid IFU, just save sub_header
843 //
844 KMO_TRY_EXIT_IF_ERROR(
845 kmo_dfs_save_sub_header(fn_out, "",
846 sub_header_data));
847
848 // save noise if it has been calculated
849 if ((desc1.ex_noise == TRUE) &&
850 ((((desc2.fits_type == f3i_fits) ||
851 (desc2.fits_type == f2i_fits) ||
852 (desc2.fits_type == f1i_fits)
853 ) &&
854 (desc2.ex_noise == TRUE)
855 ) ||
856 (fabs(op2_scalar-FORBIDDEN_SCALAR) > 1e-3)
857 )
858 )
859 {
860
861 KMO_TRY_EXIT_IF_NULL(
862 sub_header_noise = kmo_dfs_load_sub_header(
863 frameset,
864 "0", devnr1,
865 TRUE));
866 KMO_TRY_EXIT_IF_ERROR(
867 kmo_dfs_save_sub_header(fn_out, "",
868 sub_header_noise));
869
870 cpl_propertylist_delete(sub_header_noise);
871 sub_header_noise = NULL;
872 }
873 }
874 break;
875 case f2i_fits:
876 calc_f2i = FALSE;
877
878 // check if IFUs are valid
879 if (desc1.ex_noise == FALSE) {
880 if (desc1.sub_desc[i - 1].valid_data == TRUE) {
881 if (fabs(op2_scalar-FORBIDDEN_SCALAR) > 1e-3) {
882 calc_f2i = TRUE;
883 } else if (((single_ifu == TRUE) &&
884 (desc2.sub_desc[0].valid_data == TRUE))
885 ||
886 (desc2.sub_desc[i - 1].valid_data == TRUE))
887 {
888 calc_f2i = TRUE;
889 }
890 }
891 }
892 if (desc1.ex_noise == TRUE) {
893 if (desc1.sub_desc[2 * i - 1].valid_data == TRUE) {
894 calc_f2i = TRUE;
895 }
896 }
897 if ((desc1.ex_noise == TRUE) && (desc2.ex_noise == TRUE)) {
898 if (desc1.sub_desc[2 * i - 1].valid_data == TRUE) {
899 if (((single_ifu == TRUE) &&
900 (desc2.sub_desc[1].valid_data == TRUE))
901 ||
902 (desc2.sub_desc[2 * i - 1].valid_data == TRUE))
903 {
904 calc_f2i = TRUE;
905 }
906 }
907 }
908 if ((single_ifu == TRUE) && (desc1.ex_noise == FALSE)) {
909 if ((desc1.sub_desc[i - 1].valid_data == TRUE) &&
910 (desc2.sub_desc[0].valid_data == TRUE)) {
911 calc_f2i = TRUE;
912 }
913 }
914
915 if (calc_f2i == TRUE)
916 {
917 KMO_TRY_EXIT_IF_NULL(
918 op1_2d = kmo_dfs_load_image(frameset, "0",
919 devnr1, FALSE, FALSE, NULL));
920 //
921 // process F2I & F2I
922 //
923 if (desc2.fits_type == f2i_fits) {
924 if (single_ifu == FALSE) {
925 KMO_TRY_EXIT_IF_NULL(
926 op2_2d = kmo_dfs_load_image(frameset, "1",
927 devnr2, FALSE, FALSE, NULL));
928 }
929
930 if ((desc1.ex_noise == TRUE) &&
931 (desc2.ex_noise == TRUE))
932 {
933 KMO_TRY_EXIT_IF_NULL(
934 op1_noise_2d = kmo_dfs_load_image(
935 frameset, "0",
936 devnr1, TRUE, FALSE, NULL));
937
938 if (single_ifu == FALSE) {
939 KMO_TRY_EXIT_IF_NULL(
940 op2_noise_2d = kmo_dfs_load_image(
941 frameset, "1",
942 devnr2, TRUE, FALSE, NULL));
943 }
944 }
945
946 KMO_TRY_EXIT_IF_ERROR(
947 kmo_arithmetic_2D_2D(op1_2d, op2_2d,
948 op1_noise_2d, op2_noise_2d,
949 op));
950 }
951 //
952 // process F2I & scalar
953 //
954 else if (fabs(op2_scalar-FORBIDDEN_SCALAR) > 1e-3) {
955 if (desc1.ex_noise == TRUE) {
956 KMO_TRY_EXIT_IF_NULL(
957 op1_noise_2d = kmo_dfs_load_image(
958 frameset, "0",
959 devnr1, TRUE, FALSE, NULL));
960 }
961
962 KMO_TRY_EXIT_IF_ERROR(
963 kmo_arithmetic_2D_scalar(op1_2d,
964 op2_scalar,
965 op1_noise_2d,
966 op));
967 }
968
969 // save data (and noise)
970 KMO_TRY_EXIT_IF_ERROR(
971 kmo_dfs_save_image(op1_2d, fn_out, "",
972 sub_header_data, 0./0.));
973
974 if (op1_noise_2d != NULL) {
975 KMO_TRY_EXIT_IF_NULL(
976 sub_header_noise = kmo_dfs_load_sub_header(
977 frameset, "0",
978 devnr1, TRUE));
979
980 KMO_TRY_EXIT_IF_ERROR(
981 kmo_dfs_save_image(op1_noise_2d, fn_out, "",
982 sub_header_noise, 0./0.));
983
984 cpl_propertylist_delete(sub_header_noise);
985 sub_header_noise = NULL;
986 }
987 } else {
988 //
989 // invalid IFU, just save sub_header
990 //
991 KMO_TRY_EXIT_IF_ERROR(
992 kmo_dfs_save_sub_header(fn_out, "", sub_header_data));
993
994 // save noise if it has been calculated
995 if ((desc1.ex_noise == TRUE)
996 &&
997 (((desc2.fits_type == f2i_fits) && (desc2.ex_noise == TRUE)) ||
998 (fabs(op2_scalar-FORBIDDEN_SCALAR) > 1e-3)))
999 {
1000
1001 KMO_TRY_EXIT_IF_NULL(
1002 sub_header_noise = kmo_dfs_load_sub_header(
1003 frameset,
1004 "0", devnr1,
1005 TRUE));
1006 KMO_TRY_EXIT_IF_ERROR(
1007 kmo_dfs_save_sub_header(fn_out, "", sub_header_noise));
1008
1009 cpl_propertylist_delete(sub_header_noise);
1010 sub_header_noise = NULL;
1011 }
1012 }
1013 break;
1014 case f1i_fits:
1015 calc_f1i = FALSE;
1016
1017 // check if IFUs are valid
1018 if (desc1.ex_noise == FALSE) {
1019 if (desc1.sub_desc[i - 1].valid_data == TRUE) {
1020 if (fabs(op2_scalar-FORBIDDEN_SCALAR) > 1e-3) {
1021 calc_f1i = TRUE;
1022 } else if (((single_ifu == TRUE) &&
1023 (desc2.sub_desc[0].valid_data == TRUE))
1024 ||
1025 (desc2.sub_desc[i - 1].valid_data == TRUE))
1026 {
1027 calc_f1i = TRUE;
1028 }
1029 }
1030 }
1031 if (desc1.ex_noise == TRUE) {
1032 if (desc1.sub_desc[2 * i - 1].valid_data == TRUE) {
1033 calc_f1i = TRUE;
1034 }
1035 }
1036 if ((desc1.ex_noise == TRUE) && (desc2.ex_noise == TRUE)) {
1037 if (desc1.sub_desc[2 * i - 1].valid_data == TRUE) {
1038 if (((single_ifu == TRUE) &&
1039 (desc2.sub_desc[1].valid_data == TRUE))
1040 ||
1041 (desc2.sub_desc[2 * i - 1].valid_data == TRUE))
1042 {
1043 calc_f1i = TRUE;
1044 }
1045 }
1046 }
1047 if ((single_ifu == TRUE) && (desc1.ex_noise == FALSE)) {
1048 if ((desc1.sub_desc[i - 1].valid_data == TRUE) &&
1049 (desc2.sub_desc[0].valid_data == TRUE)) {
1050 calc_f1i = TRUE;
1051 }
1052 }
1053
1054 if (calc_f1i == TRUE)
1055 {
1056 KMO_TRY_EXIT_IF_NULL(
1057 op1_1d = kmo_dfs_load_vector(frameset, "0",
1058 devnr1, FALSE));
1059 //
1060 // process F1I & F1I
1061 //
1062 if (desc2.fits_type == f1i_fits) {
1063 if (single_ifu == FALSE) {
1064 KMO_TRY_EXIT_IF_NULL(
1065 op2_1d = kmo_dfs_load_vector(frameset, "1",
1066 devnr2, FALSE));
1067 }
1068
1069 if ((desc1.ex_noise == TRUE) &&
1070 (desc2.ex_noise == TRUE))
1071 {
1072 KMO_TRY_EXIT_IF_NULL(
1073 op1_noise_1d = kmo_dfs_load_vector(
1074 frameset, "0",
1075 devnr1, TRUE));
1076
1077 if (single_ifu == FALSE) {
1078 KMO_TRY_EXIT_IF_NULL(
1079 op2_noise_1d = kmo_dfs_load_vector(
1080 frameset, "1",
1081 devnr2, TRUE));
1082 }
1083 }
1084
1085 KMO_TRY_EXIT_IF_ERROR(
1086 kmo_arithmetic_1D_1D(op1_1d, op2_1d,
1087 op1_noise_1d, op2_noise_1d,
1088 op));
1089 }
1090 //
1091 // process F1I & scalar
1092 //
1093 else if (fabs(op2_scalar-FORBIDDEN_SCALAR) > 1e-3) {
1094 if (desc1.ex_noise == TRUE) {
1095 KMO_TRY_EXIT_IF_NULL(
1096 op1_noise_1d = kmo_dfs_load_vector(
1097 frameset, "0",
1098 devnr1, TRUE));
1099 }
1100
1101 KMO_TRY_EXIT_IF_ERROR(
1102 kmo_arithmetic_1D_scalar(op1_1d,
1103 op2_scalar,
1104 op1_noise_1d,
1105 op));
1106 }
1107
1108 // save data (and noise)
1109 KMO_TRY_EXIT_IF_ERROR(
1110 kmo_dfs_save_vector(op1_1d, fn_out, "",
1111 sub_header_data, 0./0.));
1112
1113 if (op1_noise_1d != NULL) {
1114 KMO_TRY_EXIT_IF_NULL(
1115 sub_header_noise = kmo_dfs_load_sub_header(
1116 frameset, "0",
1117 devnr1, TRUE));
1118
1119 KMO_TRY_EXIT_IF_ERROR(
1120 kmo_dfs_save_vector(op1_noise_1d, fn_out, "",
1121 sub_header_noise, 0./0.));
1122
1123 cpl_propertylist_delete(sub_header_noise);
1124 sub_header_noise = NULL;
1125 }
1126 } else {
1127 //
1128 // invalid IFU, just save sub_header
1129 //
1130 KMO_TRY_EXIT_IF_ERROR(
1131 kmo_dfs_save_sub_header(fn_out, "", sub_header_data));
1132
1133 // save noise if it has been calculated
1134 if ((desc1.ex_noise == TRUE)
1135 &&
1136 (((desc2.fits_type == f2i_fits) && (desc2.ex_noise == TRUE)) ||
1137 (fabs(op2_scalar-FORBIDDEN_SCALAR) > 1e-3)))
1138 {
1139
1140 KMO_TRY_EXIT_IF_NULL(
1141 sub_header_noise = kmo_dfs_load_sub_header(
1142 frameset,
1143 "0", devnr1,
1144 TRUE));
1145 KMO_TRY_EXIT_IF_ERROR(
1146 kmo_dfs_save_sub_header(fn_out, "",
1147 sub_header_noise));
1148
1149 cpl_propertylist_delete(sub_header_noise);
1150 sub_header_noise = NULL;
1151 }
1152 }
1153 break;
1154 default:
1155 break;
1156 }
1157
1158 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
1159
1160 cpl_image_delete(op1_2d); op1_2d = NULL;
1161 cpl_imagelist_delete(op1_3d); op1_3d = NULL;
1162
1163 cpl_image_delete(op1_noise_2d); op1_noise_2d = NULL;
1164 cpl_imagelist_delete(op1_noise_3d); op1_noise_3d = NULL;
1165
1166 if (single_ifu == FALSE) {
1167 kmclipm_vector_delete(op2_1d); op2_1d = NULL,
1168 cpl_image_delete(op2_2d); op2_2d = NULL;
1169 cpl_imagelist_delete(op2_3d); op2_3d = NULL;
1170
1171 kmclipm_vector_delete(op2_noise_1d); op2_noise_1d = NULL,
1172 cpl_image_delete(op2_noise_2d); op2_noise_2d = NULL;
1173 cpl_imagelist_delete(op2_noise_3d); op2_noise_3d = NULL;
1174 }
1175 }
1176 }
1177 KMO_CATCH
1178 {
1179 KMO_CATCH_MSG();
1180 ret_val = -1;
1181 }
1182
1183 kmo_free_fits_desc(&desc1);
1184 kmo_free_fits_desc(&desc2);
1185 cpl_free(fn_out); fn_out = NULL;
1186 cpl_propertylist_delete(main_header); main_header = NULL;
1187 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
1188 cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
1189 cpl_image_delete(op1_2d); op1_2d = NULL;
1190 cpl_imagelist_delete(op1_3d); op1_3d = NULL;
1191 kmclipm_vector_delete(op2_1d); op2_1d = NULL;
1192 cpl_image_delete(op2_2d); op2_2d = NULL;
1193 cpl_imagelist_delete(op2_3d); op2_3d = NULL;
1194 cpl_image_delete(op1_noise_2d); op1_noise_2d = NULL;
1195 cpl_imagelist_delete(op1_noise_3d); op1_noise_3d = NULL;
1196 kmclipm_vector_delete(op2_noise_1d); op2_noise_1d = NULL;
1197 cpl_image_delete(op2_noise_2d); op2_noise_2d = NULL;
1198 cpl_imagelist_delete(op2_noise_3d); op2_noise_3d = NULL;
1199
1200 return ret_val;
1201}
1202
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.