ERIS Pipeline Reference Manual 1.8.10
eris_nix_utils.c
1/* $Id$
2 *
3 * This file is part of the ERIS/NIX Pipeline
4 * Copyright (C) 2017 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 /*
22 * $Author$
23 * $Date$
24 * $Rev$
25 */
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31/*-----------------------------------------------------------------------------
32 Includes
33 -----------------------------------------------------------------------------*/
34
35#include "eris_nix_utils.h"
36#include "eris_utils.h"
37#include "eris_nix_casu_utils.h"
38#include "eris_nix_dfs.h"
39#include "eris_nix_match.h"
40
41#include <casu_mods.h>
42#include <casu_stats.h>
43#include <hdrl.h>
44#include <libgen.h>
45#include <math.h>
46#include <string.h>
47
48/*----------------------------------------------------------------------------*/
58/*----------------------------------------------------------------------------*/
59
62/*----------------------------------------------------------------------------*/
97/*----------------------------------------------------------------------------*/
98
99cpl_error_code enu_basic_calibrate(located_image * limage,
100 const int read_offsets,
101 const cpl_table * refine_wcs,
102 const master_dark * mdark,
103 const gain_linearity * gain_lin,
104 const master_flat * flatfield_1,
105 const master_flat * flatfield_2,
106 const master_bpm * mbad_pix_map,
107 const int flag_mask,
108 const char * fill_rejected,
109 const double fill_value,
110 const cpl_size x_probe,
111 const cpl_size y_probe) {
112
113 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
114
115 if (limage == NULL) return CPL_ERROR_NONE;
116
117 /* correct the CD matrix if required, same for 'single' or 'cube' data */
118
119 enu_modify_CD_matrix(limage, refine_wcs);
120
121 /* for single images, reduce the image
122 for cube data, reduce each image plane in turn */
123
124 if (limage->himage) {
125 enu_basic_calibrate_himage(limage->himage,
126 limage->confidence,
127 limage->plist,
128 limage->frame,
129 read_offsets,
130 mdark,
131 gain_lin,
132 flatfield_1,
133 flatfield_2,
134 mbad_pix_map,
135 CPL_TRUE,
136 flag_mask,
137 fill_rejected,
138 fill_value,
139 x_probe,
140 y_probe);
141 enu_check_error_code("failure in basic calibration");
142
143 } else if (limage->himagelist) {
144 const cpl_size nplanes = hdrl_imagelist_get_size(limage->himagelist);
145 cpl_error_code didfail = CPL_ERROR_NONE;
146
147#ifdef _OPENMP
148 cpl_errorstate cleanstate = cpl_errorstate_get();
149
150#pragma omp parallel for
151#endif
152 for (cpl_size plane = 0; plane < nplanes; plane++) {
153
154 cpl_error_code errori = cpl_error_get_code();
155
156 /* The total number of iterations must be pre-determined for the
157 parallelism to work. In case of an error we can therefore not
158 break, so instead we skip immediately to the next iteration.
159 FIXME: This check on didfail does not guarantee that only one
160 iteration can cause an error to be dumped, but it is not
161 worse than checking on the thread-local state, errori. */
162 if (didfail) continue;
163
164 do {
165
166 cpl_msg_info(cpl_func, "basic calibrate cube: plane %d",
167 (int)plane);
168
169 /* the confidence array applies to all planes in the cube alike,
170 so only modify it on the first call */
171
172 if (enu_basic_calibrate_himage(hdrl_imagelist_get(limage->himagelist,
173 plane),
174 limage->confidence,
175 limage->plist,
176 limage->frame,
177 read_offsets,
178 mdark,
179 gain_lin,
180 flatfield_1,
181 flatfield_2,
182 mbad_pix_map,
183 (plane == 0),
184 flag_mask,
185 fill_rejected,
186 fill_value,
187 x_probe,
188 y_probe)) {
189 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
190 "Cannot process plane %d/%d",
191 (int)plane+1, (int)nplanes);
192 break;
193 }
194 } while (0);
195
196 if (errori) {
197#ifdef _OPENMP
198 /* Cannot access these errors after the join,
199 so dump them now. :-(((((((((((((((((((( */
200 cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
201 cpl_errorstate_set(cleanstate);
202
203#pragma omp critical(enu_basic_calibrate)
204#endif
205 didfail = errori;
206 }
207 }
208 if (didfail) (void)cpl_error_set_message(cpl_func, didfail,
209 "Cannot process %d plane(s)",
210 (int)nplanes);
211 }
212
213 cleanup:
214
215 return cpl_error_get_code();
216}
217
218
219/*----------------------------------------------------------------------------*/
255/*----------------------------------------------------------------------------*/
256
257cpl_error_code enu_basic_calibrate_himage(hdrl_image * himage,
258 cpl_image * confidence,
259 cpl_propertylist * plist,
260 const cpl_frame * frame,
261 const int read_offsets,
262 const master_dark * mdark,
263 const gain_linearity * gain_lin,
264 const master_flat * flatfield_1,
265 const master_flat * flatfield_2,
266 const master_bpm * mbad_pix_map,
267 const int set_confidence,
268 const int flag_mask,
269 const char * fill_rejected,
270 const double fill_value,
271 const cpl_size x_probe,
272 const cpl_size y_probe) {
273
274 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
275
276 cpl_ensure_code(himage, CPL_ERROR_NULL_INPUT);
277
278 /* window information */
279
280 cpl_size nx = 0;
281 cpl_size ny = 0;
282 int rot = 0;
283 cpl_size strx = 0;
284 cpl_size stry = 0;
285 cpl_size nx_chip = 0;
286 cpl_size ny_chip = 0;
287 cpl_boolean windowed = 0;
289 &ny,
290 &rot,
291 &strx,
292 &stry,
293 &nx_chip,
294 &ny_chip,
295 &windowed,
296 plist);
297 enu_check_error_code("failed to read detector window information");
298 if (windowed) {
299 cpl_msg_info(cpl_func, "detector is windowed!");
300 }
301
302 /* is the instrument ERIS or NACO */
303
304 const char * instrume = cpl_propertylist_get_string(plist, "INSTRUME");
305 const cpl_boolean eris = !strcmp(instrume, "ERIS");
306
307 /* probe pixel specified? */
308
309 int probe = CPL_FALSE;
310 if ((x_probe >= 0) && (y_probe >= 0)) {
311 if (x_probe < nx && y_probe < ny) {
312 probe = CPL_TRUE;
313 }
314 }
315
316 if (probe) {
317 int reject = 0;
318 hdrl_value val = hdrl_image_get_pixel(himage,
319 x_probe,
320 y_probe,
321 &reject);
322 cpl_msg_info(cpl_func,
323 "..basic_calibrate probe (%d,%d) entry(v,e,r)=%5.3e %5.3e %d",
324 (int) x_probe, (int)y_probe, val.data, val.error,
325 reject);
326 val = hdrl_image_get_median(himage);
327 cpl_msg_info(cpl_func,
328 "..basic_calibrate probe (median) entry(v,e)=%5.3e %5.3e",
329 val.data, val.error);
330 }
331
332 if (windowed) {
333
334 /* correct wcs centre, this will have to been set assuming the data
335 are full frame */
336
337 cpl_msg_info(cpl_func, "basic calibrate: correcting wcs for windowed data");
338 const double crpix1 = cpl_propertylist_get_double(plist, "CRPIX1");
339 cpl_propertylist_update_double(plist, "CRPIX1",
340 crpix1 - (double)strx + 1.0);
341 const double crpix2 = cpl_propertylist_get_double(plist, "CRPIX2");
342 cpl_propertylist_update_double(plist, "CRPIX2",
343 crpix2 - (double)stry + 1.0);
344 cpl_msg_info(cpl_func, "..crpix %f %f -> %f %f", crpix1, crpix2,
345 crpix1 - (double)strx + 1.0,
346 crpix2 - (double)stry + 1.0);
347 }
348
349 /* read offset removal only applies to ERIS */
350
351 if (read_offsets && eris) {
352 cpl_msg_info(cpl_func, "basic calibrate: removing read-offsets and "
353 "blanking edges");
354 enu_remove_read_offsets(himage, plist, confidence, set_confidence);
355 enu_check_error_code("error removing read-offsets");
356
357 if (probe) {
358 int reject = 0;
359 hdrl_value val = hdrl_image_get_pixel(himage,
360 x_probe,
361 y_probe,
362 &reject);
363 cpl_msg_info(cpl_func,
364 "..basic_calibrate probe (%d,%d) after "
365 "read_offsets(v,e,r)=%5.3e %5.3e %d",
366 (int) x_probe, (int)y_probe,
367 val.data, val.error, reject);
368 val = hdrl_image_get_median(himage);
369 cpl_msg_info(cpl_func,
370 "..basic_calibrate probe (median) after "
371 "read_offsets(v,e)=%5.3e %5.3e", val.data, val.error);
372 }
373 }
374
375 if (mdark) {
376 cpl_msg_info(cpl_func, "basic calibrate: subtracting master dark");
377
378 /* Check that DIT, detector mode and windowing are compatible.
379 Should work for both ERIS and NACO-style keywords */
380
381 int compatible = enu_check_conformance(
382 plist,
383 mdark->plist,
384 "^ESO DET SEQ1 DIT$|"
385 "^ESO DET READ CURNAME$|"
386 "^ESO DET SEQ1 WIN NX$|"
387 "^ESO DET SEQ1 WIN NY$|"
388 "^ESO DET SEQ1 WIN ROT$|"
389 "^ESO DET SEQ1 WIN STRX$|"
390 "^ESO DET SEQ1 WIN STRY$|"
391 "^ESO DET DIT$|"
392 "^ESO DET NCORRS NAME$|"
393 "^ESO DET WIN NX$|"
394 "^ESO DET WIN NY$|"
395 "^ESO DET WIN STARTX$|"
396 "^ESO DET WIN STARTY$");
397 const char * filename = NULL;
398 if (frame) {
399 filename = cpl_frame_get_filename(frame);
400 }
401 if (filename == NULL) {
402 enu_check(compatible, CPL_ERROR_INCOMPATIBLE_INPUT,
403 "MASTER_DARK does not match frame");
404 } else {
405 enu_check(compatible, CPL_ERROR_INCOMPATIBLE_INPUT,
406 "MASTER_DARK does not match %s", filename);
407 }
408
409 /* subtract the dark and copy its gain value to propertylist */
410
411 hdrl_image_sub_image(himage, mdark->dark);
412 double gain = cpl_propertylist_get_double(mdark->plist,
413 "ESO QC GAIN");
414 cpl_propertylist_update_double(plist, "ESO DARK GAIN", gain);
415 cpl_propertylist_set_comment(plist, "ESO DARK GAIN",
416 "GAIN from master_dark [e-/ADU]");
417 enu_check_error_code("error subtracting DARK");
418
419 if (probe) {
420 int reject = 0;
421 hdrl_value val = hdrl_image_get_pixel(himage,
422 x_probe,
423 y_probe,
424 &reject);
425 int reject2 = 0;
426 hdrl_value dark = hdrl_image_get_pixel(mdark->dark,
427 x_probe,
428 y_probe,
429 &reject2);
430 cpl_msg_info(cpl_func,
431 "..basic_calibrate probe (%d,%d) after dark_subtract "
432 "dark(v,e,r)=%5.3e %5.3e %d "
433 "data(v,e,r)=%5.3e %5.3e %d",
434 (int) x_probe, (int)y_probe,
435 dark.data, dark.error, reject2,
436 val.data, val.error, reject);
437 val = hdrl_image_get_median(himage);
438 dark = hdrl_image_get_median(mdark->dark);
439 cpl_msg_info(cpl_func,
440 "..basic_calibrate probe (median) after dark_subtract "
441 "dark(v,e)=%5.3e %5.3e data(v,e)=%5.3e %5.3e",
442 dark.data, dark.error,
443 val.data, val.error);
444 }
445 }
446
447 if (gain_lin) {
448 hdrl_image * himage_copy = NULL;
449
450 /* Apply linearization correction */
451
452 cpl_msg_info(cpl_func, "basic calibrate: linearizing and estimating "
453 "frame variance");
454
455 himage_copy = end_linearize_and_variance_detmon(gain_lin,
456 mdark,
457 himage,
458 plist,
459 x_probe,
460 y_probe);
461 hdrl_image_copy(himage, himage_copy, 1, 1);
462 hdrl_image_delete(himage_copy);
463 enu_check_error_code("error estimating variance");
464
465 /* add saturation level associated with linearisation to the
466 frames propertylists */
467
468 cpl_propertylist_update_double(plist,
469 "ESO DETMON SATURATION",
470 gain_lin->saturation_limit);
471 cpl_propertylist_set_comment(plist,
472 "ESO DETMON SATURATION",
473 "saturation level from "
474 "linearisation [ADU]");
475
476 /* as part of error calculation the data are divided by DIT, so
477 BUNIT -> adu/s */
478
479 cpl_propertylist_update_string(plist, "BUNIT", "adu/s");
480
481 if (probe) {
482 int reject = 0;
483 hdrl_value val = hdrl_image_get_pixel(himage,
484 x_probe,
485 y_probe,
486 &reject);
487 cpl_msg_info(cpl_func,
488 "..basic_calibrate probe (%d,%d) "
489 "after linearize/calc_variance "
490 "data(v,e,r)=%5.3e %5.3e %d",
491 (int) x_probe, (int)y_probe, val.data, val.error,
492 reject);
493 val = hdrl_image_get_median(himage);
494 cpl_msg_info(cpl_func,
495 "..basic_calibrate probe (median) "
496 "after linearize/calc_variance "
497 "data(v,e)=%5.3e %5.3e", val.data, val.error);
498 }
499 }
500
501 if (flatfield_1) {
502 cpl_msg_info(cpl_func, "basic calibrate: dividing by flatfield 1");
503
504 /* the flatfield will cover the full detector, get the part it
505 that covers the detector window of the image */
506
507 /* extract the window */
508
509 hdrl_image * flat_window = !windowed ? NULL :
510 hdrl_image_extract(flatfield_1->flat,
511 strx, stry,
512 strx - 1 + nx,
513 stry - 1 + ny);
514 const hdrl_image * flat_use = !windowed ? flatfield_1->flat
515 : flat_window;
516
517 enu_check_error_code("error extracting window from flatfield 1");
518
519 /* divide by the flat */
520
521 hdrl_image_div_image(himage, flat_use);
522
523 /* update the confidence */
524
525 if (set_confidence) {
526
527 /* copy the confidence array from the flatfield. Set to 0
528 confidence pixels where the image itself is bad. The
529 confidence array itself should have no mask - it and the
530 image mask are 'parallel' descriptions of the bad pixels */
531
532 cpl_image * flat_conf_window = !windowed ? NULL :
533 cpl_image_extract(flatfield_1->confidence,
534 strx, stry,
535 strx - 1 + nx,
536 stry - 1 + ny);
537 const cpl_image * flat_conf_use = !windowed ? flatfield_1->confidence
538 : flat_conf_window;
539
540 enu_check_error_code("error extracting window from flatfield 1 "
541 "confidence");
542 cpl_image_copy(confidence, flat_conf_use, 1, 1);
543 cpl_image_delete(flat_conf_window);
544
545 /* set confidence to 0 where the image mask is already bad */
546 if (cpl_image_get_bpm_const(hdrl_image_get_image(himage))) {
547 cpl_mask * old_mask =
548 cpl_image_set_bpm(confidence,
549 cpl_image_get_bpm(hdrl_image_get_image(himage)));
550 cpl_mask_delete(old_mask);
551 cpl_image_fill_rejected(confidence, 0.0);
552 (void)cpl_image_unset_bpm(confidence);
553 } else {
554 cpl_image_accept_all(confidence); /* FIXME: Is this reachable ? */
555 }
556 }
557
558 enu_check_error_code("error dividing by flatfield 1");
559
560 if (probe) {
561 int reject = 0;
562 hdrl_value val = hdrl_image_get_pixel(himage,
563 x_probe,
564 y_probe,
565 &reject);
566 int reject2 = 0;
567 hdrl_value flat = hdrl_image_get_pixel(flat_use,
568 x_probe,
569 y_probe,
570 &reject2);
571 cpl_msg_info(cpl_func,
572 "..basic_calibrate probe (%d,%d) after flatfield1 "
573 "flat(v,e,r)=%5.3e %5.3e %d "
574 "data(v,e,r)=%5.3e %5.3e %d",
575 (int) x_probe, (int)y_probe,
576 flat.data, flat.error, reject2,
577 val.data, val.error, reject);
578 val = hdrl_image_get_median(himage);
579 flat = hdrl_image_get_median(flat_use);
580 cpl_msg_info(cpl_func,
581 "..basic_calibrate probe (median) after flatfield1 "
582 "flat(v,e)=%5.3e %5.3e data(v,e)=%5.3e %5.3e",
583 flat.data, flat.error,
584 val.data, val.error);
585 }
586
587 hdrl_image_delete(flat_window);
588 }
589
590 if (flatfield_2) {
591 cpl_msg_info(cpl_func, "basic calibrate: dividing by flatfield 2");
592
593 hdrl_image * flat_window = !windowed ? NULL :
594 hdrl_image_extract(flatfield_2->flat,
595 strx, stry,
596 strx - 1 + nx,
597 stry - 1 + ny);
598 const hdrl_image * flat_use = !windowed ? flatfield_2->flat
599 : flat_window;
600
601 enu_check_error_code("error extracting window from flatfield 2");
602
603 hdrl_image_div_image(himage, flat_use);
604
605 if (set_confidence) {
606 cpl_image * flat_conf_window = !windowed ? NULL :
607 cpl_image_extract(flatfield_2->confidence,
608 strx, stry,
609 strx - 1 + nx,
610 stry - 1 + ny);
611 const cpl_image * flat_conf_use = !windowed ? flatfield_2->confidence
612 : flat_conf_window;
613
614 enu_check_error_code("error extracting window from flatfield 1 "
615 "confidence");
616
617 cpl_image_copy(confidence, flat_conf_use, 1, 1);
618 cpl_image_delete(flat_conf_window);
619
620 /* set confidence to 0 where the image mask is already bad */
621 if (cpl_image_get_bpm_const(hdrl_image_get_image(himage))) {
622 cpl_mask * old_mask =
623 cpl_image_set_bpm(confidence,
624 cpl_image_get_bpm(hdrl_image_get_image(himage)));
625 cpl_mask_delete(old_mask);
626 cpl_image_fill_rejected(confidence, 0.0);
627 (void)cpl_image_unset_bpm(confidence);
628 } else {
629 cpl_image_accept_all(confidence); /* FIXME: Is this reachable ? */
630 }
631 }
632
633 enu_check_error_code("error dividing by flatfield 2");
634
635 if (probe) {
636 int reject = 0;
637 hdrl_value val = hdrl_image_get_pixel(himage,
638 x_probe,
639 y_probe,
640 &reject);
641 int reject2 = 0;
642 hdrl_value flat = hdrl_image_get_pixel(flat_use,
643 x_probe,
644 y_probe,
645 &reject2);
646 cpl_msg_info(cpl_func,
647 "..basic_calibrate probe (%d,%d) after flatfield2 "
648 "flat(v,e,r)=%5.3e %5.3e %d "
649 "data(v,e,r)=%5.3e %5.3e %d",
650 (int) x_probe, (int)y_probe,
651 flat.data, flat.error, reject2,
652 val.data, val.error, reject);
653 val = hdrl_image_get_median(himage);
654 flat = hdrl_image_get_median(flat_use);
655 cpl_msg_info(cpl_func,
656 "..basic_calibrate probe (median) after flatfield2 "
657 "flat(v,e)=%5.3e %5.3e data(v,e)=%5.3e %5.3e",
658 flat.data, flat.error,
659 val.data, val.error);
660 }
661 hdrl_image_delete(flat_window);
662 }
663
664 if (mbad_pix_map) {
665 cpl_msg_info(cpl_func, "basic calibrate: associating with master_bpm");
666 cpl_mask * new_mask = en_master_bpm_get_mask(mbad_pix_map, flag_mask);
667
668 /* window the bpm mask appropriate to the image */
669
670 cpl_mask * new_mask_window = !windowed ? NULL :
671 cpl_mask_extract(new_mask,
672 strx, stry,
673 strx - 1 + nx,
674 stry - 1 + ny);
675 const cpl_mask * new_mask_use = !windowed ? new_mask : new_mask_window;
676
677 enu_check_error_code("error extracting window from bpm mask");
678
679 /* 'or' the mbad_pix_map mask with that already on the image */
680
681 cpl_mask * current_mask = hdrl_image_get_mask(himage);
682 cpl_mask_or(current_mask, new_mask_use);
683 enu_check_error_code("error setting new mask");
684
685 if (set_confidence) {
686
687 /* set rejected confidence to zero */
688
689 double * conf_data = cpl_image_get_data(confidence);
690 cpl_binary * mask_data = cpl_mask_get_data(current_mask);
691 cpl_size nx_mask = cpl_mask_get_size_x(current_mask);
692 cpl_size ny_mask = cpl_mask_get_size_y(current_mask);
693 for (cpl_size i = 0; i < nx_mask * ny_mask; i++) {
694 if (mask_data[i] == CPL_BINARY_1) {
695 conf_data[i] = 0.0;
696 }
697 }
698 }
699
700 if (probe) {
701 int reject = 0;
702 hdrl_value val = hdrl_image_get_pixel(himage,
703 x_probe,
704 y_probe,
705 &reject);
706 int ignore = 0;
707 double conf = cpl_image_get(confidence, x_probe, y_probe, &ignore);
708 cpl_msg_info(cpl_func, "..basic_calibrate probe (%d,%d) "
709 "after associate_mask(v,e,r,c)=%5.3e %5.3e %d %5.3e",
710 (int) x_probe, (int)y_probe, val.data, val.error,
711 reject, conf);
712 }
713 cpl_mask_delete(new_mask);
714 cpl_mask_delete(new_mask_window);
715 }
716
717 if (!strcmp(fill_rejected, "noop")) {
718 cpl_msg_info(cpl_func, "not modifying rejected pixels");
719 } else {
720 double fill = 0.0;
721 if (!strcmp(fill_rejected, "set_NaN")) {
722 fill = NAN;
723 cpl_msg_info(cpl_func, "basic calibrate: setting rejected pixels "
724 "to NaN");
725 } else if (!strcmp(fill_rejected, "set_value")) {
726 fill = fill_value;
727 cpl_msg_info(cpl_func, "basic calibrate: setting rejected pixels "
728 "to %f", fill);
729 } else {
730 enu_check(CPL_FALSE, CPL_ERROR_UNSPECIFIED,
731 "bad fill-rejected value: programming error");
732 }
733 cpl_image_fill_rejected(hdrl_image_get_image(himage), fill);
734 cpl_image_fill_rejected(hdrl_image_get_error(himage), fill);
735 enu_check_error_code("error setting rejected pixels to %f",
736 fill_value);
737
738 if (probe) {
739 int reject = 0;
740 hdrl_value val = hdrl_image_get_pixel(himage,
741 x_probe,
742 y_probe,
743 &reject);
744 int ignore = 0;
745 double conf = cpl_image_get(confidence, x_probe, y_probe, &ignore);
746 cpl_msg_info(cpl_func,
747 "..basic_calibrate probe (%d,%d) after "
748 "fill-rejected(v,e,r,c)=%5.3e %5.3e %d %5.3e",
749 (int) x_probe, (int)y_probe, val.data, val.error,
750 reject, conf);
751 }
752 }
753
754 cleanup:
755 return cpl_error_get_code();;
756}
757
758
759/*----------------------------------------------------------------------------*/
770/*----------------------------------------------------------------------------*/
771
772hdrl_image * enu_calc_flat(hdrl_imagelist * himlist,
773 const int min_coadds,
774 const hdrl_parameter * collapse_params,
775 const cpl_size filter_size_x,
776 const cpl_size filter_size_y,
777 const hdrl_flat_method method) {
778
779 /* entry check */
780
781 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
782 cpl_ensure(himlist, CPL_ERROR_NULL_INPUT, NULL);
783 cpl_ensure(collapse_params, CPL_ERROR_NULL_INPUT, NULL);
784
785 cpl_image * contribution = NULL;
786 hdrl_parameter * flat_params = NULL;
787 hdrl_image * result = NULL;
788
789 /* verify that we have enough difference results */
790
791 const cpl_size size = hdrl_imagelist_get_size(himlist);
792 enu_check(size >= min_coadds, CPL_ERROR_ILLEGAL_INPUT,
793 "insufficient frames for flat (%d<min:%d)",
794 (int) size, min_coadds);
795
796 /* calculate the flatfield */
797
798 flat_params = hdrl_flat_parameter_create(filter_size_x,
799 filter_size_y,
800 method);
801 if (method == HDRL_FLAT_FREQ_HIGH) {
802 cpl_msg_info(cpl_func, "Calculating high freq flatfield");
803 } else if (method == HDRL_FLAT_FREQ_LOW) {
804 cpl_msg_info(cpl_func, "Calculating low freq flatfield");
805 }
806 cpl_msg_info(cpl_func, "..smoothing filter sizes %d %d",
807 (int)filter_size_x, (int)filter_size_y);
808 hdrl_flat_compute(himlist, NULL, collapse_params,
809 flat_params, &result, &contribution);
810 enu_check_error_code("error computing flat-field");
811
812 cleanup:
813 cpl_image_delete(contribution);
814 hdrl_parameter_delete(flat_params);
815 if (cpl_error_get_code() != CPL_ERROR_NONE) {
816 hdrl_image_delete(result);
817 result = NULL;
818 }
819 return result;
820}
821
822
823/*----------------------------------------------------------------------------*/
834/*----------------------------------------------------------------------------*/
835
836cpl_error_code enu_calc_maglim(const located_image * limage,
837 const double photzp,
838 const double fwhm_pix,
839 double * abmaglim) {
840
841 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
842 cpl_ensure_code(limage, CPL_ERROR_NULL_INPUT);
843 cpl_ensure_code(abmaglim, CPL_ERROR_NULL_INPUT);
844
845 /* bad data in gives bad result */
846 if (fwhm_pix <= 0.0) {
847 *abmaglim = -1.0;
848 return CPL_ERROR_NONE;
849 }
850
851 /* calculate magnitude limit using HDRL */
852 /* ..set mode calculation following HDRL docs example */
853
854 double histo_min = 10.;
855 double histo_max = 1.;
856 double bin_size = 0.;
857 cpl_size error_niter = 0;
858 hdrl_mode_type mode_method = HDRL_MODE_MEDIAN;
859 hdrl_parameter * mode_parameter = NULL;
860 mode_parameter = hdrl_collapse_mode_parameter_create(histo_min,
861 histo_max,
862 bin_size,
863 mode_method,
864 error_niter);
866 photzp,
867 fwhm_pix,
868 ((int) (3.0 * fwhm_pix) / 2) * 2 + 1,
869 ((int) (3.0 * fwhm_pix) / 2) * 2 + 1,
870 HDRL_IMAGE_EXTEND_MIRROR,
871 mode_parameter,
872 abmaglim);
873 hdrl_parameter_delete(mode_parameter);
874
875 return cpl_error_get_code();
876}
877
878
879/*----------------------------------------------------------------------------*/
890/*----------------------------------------------------------------------------*/
891
892cpl_error_code enu_calc_pixel_coords(cpl_table * catalogue,
893 const cpl_propertylist * wcs_plist) {
894
895 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
896 cpl_ensure_code(catalogue, CPL_ERROR_NULL_INPUT);
897 cpl_ensure_code(wcs_plist, CPL_ERROR_NULL_INPUT);
898
899 cpl_array * conv_status = NULL;
900 cpl_matrix * ref_phys = NULL;
901 cpl_matrix * ref_world = NULL;
902 cpl_wcs * wcs = NULL;
903
904 /* write files with inputs for regression testing - uncomment if required
905 cpl_propertylist * wcs_plist_copy = cpl_propertylist_duplicate(wcs_plist);
906 cpl_propertylist_erase_regexp(wcs_plist_copy, CPL_WCS_REGEXP, 1);
907 cpl_propertylist_save(wcs_plist_copy, "enu_calc_pixel_coords_test_wcs.fits",
908 CPL_IO_CREATE);
909 cpl_table_save(catalogue, NULL, NULL,
910 "enu_calc_pixel_coords_test_input_table.fits",
911 CPL_IO_CREATE);
912 */
913
914 cpl_size nobj = cpl_table_get_nrow(catalogue);
915 const double * ra = cpl_table_get_data_double_const(catalogue, "RA");
916 const double * dec = NULL;
917// if (cpl_table_has_column(catalogue, "Dec")) {
918// dec = cpl_table_get_data_double_const(catalogue, "Dec");
919// } else if (cpl_table_has_column(catalogue, "DEC")) {
920 if (cpl_table_has_column(catalogue, "DEC")) {
921 dec = cpl_table_get_data_double_const(catalogue, "DEC");
922 }
923 ref_world = cpl_matrix_new(nobj, 2);
924 for (cpl_size iobj = 0; iobj < nobj; iobj++) {
925 cpl_matrix_set(ref_world, iobj, 0, ra[iobj]);
926 cpl_matrix_set(ref_world, iobj, 1, dec[iobj]);
927 }
928
929 wcs = cpl_wcs_new_from_propertylist(wcs_plist);
930
931 cpl_wcs_convert(wcs, ref_world, &ref_phys, &conv_status,
932 CPL_WCS_WORLD2PHYS);
933 enu_check_error_code("failure calculating predicted positions");
934
935 /* Store the predicted positions in columns X_coordinate and
936 Y_coordinate, create thes if necessary */
937
938 if (!cpl_table_has_column(catalogue, "X_coordinate")) {
939 cpl_table_new_column(catalogue, "X_coordinate", CPL_TYPE_DOUBLE);
940 }
941 if (!cpl_table_has_column(catalogue, "Y_coordinate")) {
942 cpl_table_new_column(catalogue, "Y_coordinate", CPL_TYPE_DOUBLE);
943 }
944
945 for (cpl_size iobj = 0; iobj < nobj; iobj++) {
946 cpl_table_set_double(catalogue, "X_coordinate", iobj,
947 cpl_matrix_get(ref_phys, iobj, 0));
948 cpl_table_set_double(catalogue, "Y_coordinate", iobj,
949 cpl_matrix_get(ref_phys, iobj, 1));
950 }
951
952 /* write file with output for regression testing - uncomment if required
953 cpl_table_save(catalogue, NULL, NULL,
954 "enu_calc_pixel_coords_test_output_table.fits",
955 CPL_IO_CREATE);
956 */
957
958 cleanup:
959 cpl_array_delete(conv_status);
960 cpl_matrix_delete(ref_phys);
961 cpl_matrix_delete(ref_world);
962 cpl_wcs_delete(wcs);
963
964 return cpl_error_get_code();
965}
966
967
968/*----------------------------------------------------------------------------*/
983/*----------------------------------------------------------------------------*/
984
985hdrl_catalogue_result * enu_catalogue_compute(
986 const hdrl_image * himage,
987 const cpl_image * confidence,
988 const cpl_wcs * wcs,
989 hdrl_parameter * params) {
990
991 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
992
993 cpl_ensure(himage, CPL_ERROR_NULL_INPUT, NULL);
994/*
995 cpl_ensure(confidence, CPL_ERROR_NULL_INPUT, NULL);
996*/
997 cpl_ensure(wcs, CPL_ERROR_NULL_INPUT, NULL);
998 cpl_ensure(params, CPL_ERROR_NULL_INPUT, NULL);
999
1000 hdrl_catalogue_result * result = NULL;
1001
1002 if (confidence) {
1003
1004 /* Check that the confidence array for the image is not zero -
1005 this causes a non-obvious error to be generated deep in the
1006 casu routines */
1007
1008 cpl_ensure(cpl_image_get_max(confidence) > 0.0, CPL_ERROR_ILLEGAL_INPUT,
1009 NULL);
1010 }
1011
1013 confidence, wcs, params);
1014
1015 /* REMOVE THE FOLLOWING FOR NOW. IT WAS A FUDGE TO TRY AND IMPROVE
1016 SOURCE MATCHING BETWEN JITTERS - BUT BETTER TO LEAVE IT IN AND
1017 FILTER LATER AS REQUIRED */
1018 /* Remove catalogue entries with low Av_conf.
1019 CASU documentation: Av_conf = the average confidence level within the
1020 default rcore aperture useful for
1021 spotting spurious outliers in various
1022 parameter selection spaces.
1023 The NIX detector has patches with a low density of working pixels
1024 which equate to areas of low confidence */
1025/*
1026 cpl_table_and_selected_double(result->catalogue, "Av_conf", CPL_LESS_THAN,
1027 90.);
1028 cpl_table_erase_selected(result->catalogue);
1029*/
1030
1031 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1032
1033 /* Return NULL on error */
1034
1036 result = NULL;
1037
1038 /* but trap case where simply no objects were present
1039 - for our purposes this is not an error */
1040
1041 const char * message = cpl_error_get_message();
1042 cpl_msg_info(cpl_func, "catalogue %s", message);
1043
1044 if (strstr(message, "No objects found in image")) {
1045 cpl_msg_warning(cpl_func, "No objects found in image");
1046 cpl_error_reset();
1047 }
1048 }
1049
1050 return result;
1051}
1052
1053
1054/*----------------------------------------------------------------------------*/
1063/*----------------------------------------------------------------------------*/
1064
1065cpl_vector * enu_bracket_skys(const located_image * target,
1066 const double timerange,
1067 const located_imagelist * pool,
1068 const int debug) {
1069
1070 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
1071
1072 cpl_ensure(target, CPL_ERROR_NULL_INPUT, NULL);
1073 cpl_ensure(timerange > 0.0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1074 cpl_ensure(pool, CPL_ERROR_NULL_INPUT, NULL);
1075
1076 cpl_vector * result = NULL;
1077 cpl_vector * result_diff = NULL;
1078
1079 double target_mjd = cpl_propertylist_get_double(target->plist, "MJD-OBS");
1080
1081 for (cpl_size j = 0; j < pool->size; j++) {
1082 double mjd_j = cpl_propertylist_get_double((pool->limages[j])->
1083 plist, "MJD-OBS");
1084 double diff = (target_mjd - mjd_j) * 3600.0 * 24.0;
1085
1086 if (fabs(diff) < timerange/2.0) {
1087 if (result == NULL) {
1088 result = cpl_vector_new(1);
1089 result_diff = cpl_vector_new(1);
1090 cpl_vector_set(result, 0, (double)j);
1091 cpl_vector_set(result_diff, 0, diff);
1092 } else {
1093 cpl_size size = cpl_vector_get_size(result);
1094 cpl_vector_set_size(result, size + 1);
1095 cpl_vector_set_size(result_diff, size + 1);
1096 cpl_vector_set(result, size, (double)j);
1097 cpl_vector_set(result_diff, size, diff);
1098 }
1099 }
1100 }
1101 enu_check_error_code("error in enu_bracket_skys: %s",
1102 cpl_error_get_message());
1103 enu_check(result && cpl_vector_get_size(result) > 0,
1104 CPL_ERROR_INCOMPATIBLE_INPUT,
1105 "no sky frames found within %f sec of target frame", timerange/2.0);
1106
1107 if (debug) {
1108 cpl_size size = cpl_vector_get_size(result);
1109 if (size > 0) {
1110 cpl_msg_info(" ", ".. enu_bracket_skys: timerange %5.1f", timerange);
1111 cpl_msg_info(" ", ".. j# diff(sec)");
1112 }
1113 for (cpl_size i = 0; i < size; i++) {
1114 int j = cpl_vector_get(result, i);
1115 double diff = cpl_vector_get(result_diff, i);
1116 cpl_msg_info(" ", ".. %3d %7.1f", j, diff);
1117 }
1118 }
1119
1120 cleanup:
1121 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1122 cpl_vector_delete(result);
1123 result = NULL;
1124 }
1125 cpl_vector_delete(result_diff);
1126
1127 return result;
1128}
1129
1130
1131/*----------------------------------------------------------------------------*/
1139/*----------------------------------------------------------------------------*/
1140
1141cpl_error_code enu_catalogue_limlist(located_imagelist * limlist,
1142 hdrl_parameter * params) {
1143
1144 cpl_ensure_code(cpl_error_get_code() == CPL_ERROR_NONE,
1145 cpl_error_get_code());
1146 cpl_ensure_code(limlist, CPL_ERROR_NULL_INPUT);
1147 cpl_ensure_code(params, CPL_ERROR_NULL_INPUT);
1148
1149 cpl_size njitters = limlist->size;
1150 cpl_msg_info(cpl_func, "cataloguing %d images", (int) njitters);
1151
1152 for (cpl_size i = 0; i < njitters; i++) {
1153 cpl_wcs * wcs = cpl_wcs_new_from_propertylist
1154 (limlist->limages[i]->plist);
1155 cpl_msg_info(cpl_func, "cataloguing image %d", (int) i);
1156 //TODO AMO: the following call generates a memory leak
1157 limlist->limages[i]->objects = enu_catalogue_compute(
1158 limlist->limages[i]->himage,
1159 limlist->limages[i]->confidence,
1160 wcs,
1161 params);
1162 cpl_wcs_delete(wcs);
1163
1164 if (cpl_error_get_code() != CPL_ERROR_NONE) break;
1165 }
1166
1167 return cpl_error_get_code();
1168}
1169
1170
1171/*----------------------------------------------------------------------------*/
1186/*----------------------------------------------------------------------------*/
1187
1188int enu_check_conformance(const cpl_propertylist * plist1,
1189 const cpl_propertylist * plist2,
1190 const char * regexp) {
1191
1192 if (cpl_error_get_code() != CPL_ERROR_NONE) return 0;
1193
1194 /* Check parameters not NULL */
1195
1196 cpl_ensure(plist1 && plist2 && regexp, CPL_ERROR_NULL_INPUT, 0);
1197
1198 int result = CPL_TRUE;
1199 char * reason = NULL;
1200
1201 /* Create the two subsets to be compared */
1202
1203 cpl_propertylist * subset1 = cpl_propertylist_new();
1204 cpl_propertylist_copy_property_regexp(subset1, plist1, regexp, 0);
1205 cpl_propertylist * subset2 = cpl_propertylist_new();
1206 cpl_propertylist_copy_property_regexp(subset2, plist2, regexp, 0);
1207 enu_check_error_code("error deriving subset of propertylist");
1208
1209 /* Compare them */
1210
1211 cpl_size size1 = cpl_propertylist_get_size(subset1);
1212 cpl_size size2 = cpl_propertylist_get_size(subset2);
1213 if (size1 != size2) {
1214 result = CPL_FALSE;
1215 reason = cpl_sprintf("propertylist sizes do not match %s", " ");
1216 } else {
1217 for (cpl_size i=0; i<size1; i++) {
1218 const cpl_property * prop1 = cpl_propertylist_get(subset1, i);
1219 const char * name = cpl_property_get_name(prop1);
1220
1221 /* does the second list have a property of that name? */
1222
1223 if (!cpl_propertylist_has(subset2, name)) {
1224 result = CPL_FALSE;
1225 reason = cpl_sprintf("name mismatch: %s", name);
1226 break;
1227 }
1228
1229 /* do the values match? */
1230
1231 const cpl_property * prop2 = cpl_propertylist_get_property_const(
1232 subset2, name);
1233
1234 const cpl_type type1 = cpl_property_get_type(prop1);
1235 const cpl_type type2 = cpl_property_get_type(prop2);
1236 if (type1 != type2) {
1237 result = CPL_FALSE;
1238 reason = cpl_sprintf("type mismatch: name %s: types %s and %s",
1239 name,
1240 cpl_type_get_name(cpl_property_get_type(prop1)),
1241 cpl_type_get_name(cpl_property_get_type(prop2)));
1242 break;
1243 }
1244
1245 int ival1 = 0;
1246 int ival2 = 0;
1247 double dval1 = 0.0;
1248 double dval2 = 0.0;
1249 const char * sval1 = NULL;
1250 const char * sval2 = NULL;
1251
1252 switch (type1) {
1253 case CPL_TYPE_INT:
1254 ival1 = cpl_property_get_int(prop1);
1255 ival2 = cpl_property_get_int(prop2);
1256 if (ival1 != ival2) {
1257 result = CPL_FALSE;
1258 reason = cpl_sprintf("value mismatch: name %s: values "
1259 "%d and %d",
1260 name, ival1, ival2);
1261 }
1262 break;
1263
1264 case CPL_TYPE_DOUBLE:
1265 dval1 = cpl_property_get_double(prop1);
1266 dval2 = cpl_property_get_double(prop2);
1267 if (dval1 != dval2) {
1268 result = CPL_FALSE;
1269 reason = cpl_sprintf("value mismatch: name %s: values "
1270 "%4.2e and %4.2e",
1271 name, dval1, dval2);
1272 }
1273 break;
1274
1275 case CPL_TYPE_STRING:
1276 sval1 = cpl_property_get_string(prop1);
1277 sval2 = cpl_property_get_string(prop2);
1278 if (strcmp(sval1, sval2)) {
1279 result = CPL_FALSE;
1280 reason = cpl_sprintf("value mismatch: name %s: values "
1281 "%s, %s", name, sval1, sval2);
1282 }
1283 break;
1284 default:
1285 cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
1286 "name %s, type not handled %s",
1287 name, cpl_type_get_name(
1288 cpl_property_get_type(prop1)));
1289 break;
1290
1291 if (result == CPL_FALSE) break;
1292 }
1293 }
1294 }
1295
1296cleanup:
1297
1298 cpl_propertylist_delete(subset1);
1299 cpl_propertylist_delete(subset2);
1300
1301
1302 /* Always return False on error */
1303
1304 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1305 result = CPL_FALSE;
1306 } else {
1307 if (result == CPL_FALSE) {
1308 cpl_msg_info(cpl_func, "propertylist match failed: %s", reason);
1309 }
1310 }
1311 cpl_free(reason);
1312 return result;
1313}
1314
1315
1316/*----------------------------------------------------------------------------*/
1328/*----------------------------------------------------------------------------*/
1329
1330cpl_error_code enu_check_wcs(const located_image * limage) {
1331
1332 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
1333 cpl_ensure_code(limage, CPL_ERROR_NULL_INPUT);
1334
1335 cpl_boolean bad = CPL_FALSE;
1336
1337 if (!cpl_propertylist_has(limage->plist, "CTYPE1")) {
1338 bad = CPL_TRUE;;
1339 }
1340 if (!bad) {
1341 const char * ctype1 = cpl_propertylist_get_string(
1342 limage->plist, "CTYPE1");
1343 if (strstr(ctype1, "PIXEL")) {
1344 bad = CPL_TRUE;
1345 }
1346 }
1347
1348 if (!bad) {
1349 if (!cpl_propertylist_has(limage->plist, "CTYPE2")) {
1350 bad = CPL_TRUE;
1351 }
1352 }
1353 if (!bad) {
1354 const char * ctype2 = cpl_propertylist_get_string(limage->plist,
1355 "CTYPE2");
1356 if (strstr(ctype2, "PIXEL")) {
1357 bad = CPL_TRUE;
1358 }
1359 }
1360
1361 cpl_error_code result = cpl_error_get_code();
1362 if (result == CPL_ERROR_NONE && bad) {
1363 result = cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1364 "missing or bad WCS keywords in "
1365 "input file %s",
1366 cpl_frame_get_filename(limage->frame));
1367 }
1368
1369 return result;
1370}
1371
1372
1373/*----------------------------------------------------------------------------*/
1386/*----------------------------------------------------------------------------*/
1387
1388cpl_error_code enu_debug_limlist_save(const int debug,
1389 const located_imagelist * limlist,
1390 const char * nameroot,
1391 const char * recipename,
1392 cpl_frameset * frameset,
1393 const cpl_parameterlist * parlist,
1394 const cpl_frameset * used) {
1395
1396 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
1397 if (!debug) return CPL_ERROR_NONE;
1398 cpl_ensure_code(limlist, CPL_ERROR_NULL_INPUT);
1399 cpl_ensure_code(nameroot, CPL_ERROR_NULL_INPUT);
1400 cpl_ensure_code(recipename, CPL_ERROR_NULL_INPUT);
1401 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
1402 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
1403 cpl_ensure_code(used, CPL_ERROR_NULL_INPUT);
1404
1405 char * fname_copy = NULL;
1406 char * out_fname = NULL;
1407
1408 /* loop through images */
1409
1410 cpl_size nimages = limlist->size;
1411 for (cpl_size j = 0; j < nimages; j++) {
1412
1413 /* generate name of output file */
1414
1415 if (limlist->limages[j]->frame) {
1416 const char * fname = cpl_frame_get_filename(
1417 limlist->limages[j]->frame);
1418 fname_copy = cpl_strdup(fname);
1419 } else {
1420 const char * fname = "debug.fits";
1421 fname_copy = cpl_strdup(fname);
1422 }
1423 out_fname = cpl_sprintf("%s_%s", nameroot, basename(fname_copy));
1424
1425 cpl_msg_info(cpl_func, "..(debug) writing %s", out_fname);
1426
1427 /* some dummy info to keep dfs happy */
1428
1429 cpl_propertylist * applist = cpl_propertylist_new();
1430 cpl_propertylist_update_string(applist,
1431 CPL_DFS_PRO_CATG,
1432 "debug");
1433 cpl_propertylist_update_string(applist, "PRODCATG", "ANCILLARY.IMAGE");
1434
1435 cpl_frameset * provenance = cpl_frameset_new();
1436 cpl_frameset_insert(provenance, cpl_frame_duplicate(
1437 limlist->limages[j]->frame));
1438
1439 enu_dfs_save_limage(frameset,
1440 parlist,
1441 provenance,
1442 CPL_TRUE,
1443 limlist->limages[j],
1444 recipename,
1445 limlist->limages[j]->frame,
1446 applist,
1447 "test",
1448 out_fname);
1449
1450 cpl_frameset_delete(provenance);
1451 cpl_propertylist_delete(applist);
1452 }
1453
1454 /* tidy up */
1455
1456 cpl_free(fname_copy);
1457 cpl_free(out_fname);
1458
1459 return cpl_error_get_code();
1460}
1461
1462
1463/*----------------------------------------------------------------------------*/
1476/*----------------------------------------------------------------------------*/
1477
1478cpl_error_code enu_flat_save(const char * pro_catg,
1479 const hdrl_image * flat,
1480 const cpl_image * confidence,
1481 const cpl_mask * cold_bpm,
1482 cpl_frameset * frameset,
1483 const cpl_parameterlist * parlist,
1484 const char * filename,
1485 const char * recipe_name,
1486 const cpl_propertylist* qclog) {
1487
1488 /* checks */
1489
1490 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
1491 cpl_ensure_code(pro_catg, CPL_ERROR_NULL_INPUT);
1492 cpl_ensure_code(flat, CPL_ERROR_NULL_INPUT);
1493 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
1494 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
1495 cpl_ensure_code(filename, CPL_ERROR_NULL_INPUT);
1496
1497 mef_extension_list * mefs = NULL;
1498 cpl_propertylist * plist = NULL;
1499
1500 /* make output propertylist */
1501
1502 plist = cpl_propertylist_new();
1503 cpl_propertylist_append_string(plist, CPL_DFS_PRO_CATG, pro_catg);
1504 cpl_propertylist_update_string(plist, "PRODCATG", "ANCILLARY.IMAGE");
1505
1506 /* add QC parameters */
1507
1508 hdrl_value flat_median = hdrl_image_get_median(flat);
1509 cpl_propertylist_append_double(plist, "ESO QC FLAT MED",
1510 (double) flat_median.data);
1511 cpl_propertylist_set_comment(plist,"ESO QC FLAT MED",
1512 "[ADU] Median flat value");
1513 hdrl_value flat_mean = hdrl_image_get_mean(flat);
1514 cpl_propertylist_append_double(plist, "ESO QC FLAT MEAN",
1515 (double) flat_mean.data);
1516 cpl_propertylist_set_comment(plist,"ESO QC FLAT MEAN",
1517 "[ADU] Mean flat value");
1518 double flat_rms = hdrl_image_get_stdev(flat);
1519 cpl_propertylist_append_double(plist, "ESO QC FLAT RMS", flat_rms);
1520 cpl_propertylist_set_comment(plist,"ESO QC FLAT RMS",
1521 "[ADU] RMS flat value");
1522 /* the normalisation factor is not returned by hdrl_flat_compute,
1523 and is cumbersome to obtain otherwise */
1524
1525 cpl_msg_warning(cpl_func, "TBD: calculate normalisation value");
1526 double norm = -1.0;
1527 cpl_propertylist_append_double(plist, "ESO QC FLAT NORM", norm);
1528 cpl_propertylist_set_comment(plist,"ESO QC FLAT NORM",
1529 "Flat normalisation value");
1530 if(cold_bpm) {
1531 cpl_size ncold = cpl_mask_count(cold_bpm);
1532 cpl_propertylist_append_double(plist, "ESO QC NUMBER COLD PIXELS",
1533 ncold);
1534 cpl_propertylist_set_comment(plist,"ESO QC NUMBER COLD PIXELS",
1535 "Number of cold pixels");
1536 }
1537 enu_check_error_code("error constructing output propertylist");
1538
1539 /* save the flat to a DFS-compliant MEF file */
1540
1541 if (!cold_bpm) {
1543 mefs->mef[0] = enu_mef_new_image("CONFIDENCE", confidence, NULL);
1544 } else {
1546 mefs->mef[0] = enu_mef_new_mask("COLD_BPM", cold_bpm, NULL);
1547 mefs->mef[1] = enu_mef_new_image("CONFIDENCE", confidence, NULL);
1548 }
1549 if(qclog != NULL) {
1550 cpl_propertylist_append(plist, qclog);
1551 }
1552 enu_dfs_save_himage(frameset,
1553 parlist,
1554 frameset,
1555 CPL_TRUE,
1556 flat,
1557 NULL,
1558 mefs,
1559 recipe_name,
1560 NULL,
1561 plist,
1562 NULL,
1563 PACKAGE "/" PACKAGE_VERSION,
1564 filename);
1565
1566 cleanup:
1568 cpl_propertylist_delete(plist);
1569
1570 return cpl_error_get_code();
1571}
1572
1573
1574/*----------------------------------------------------------------------------*/
1588/*----------------------------------------------------------------------------*/
1589double enu_get_airmass(const cpl_propertylist * plist) {
1590
1591 if (cpl_error_get_code() != CPL_ERROR_NONE) return 0;
1592
1593 double airmass = 0.0;
1594 if (cpl_propertylist_has(plist, "AIRMASS")) {
1595 /* NACO */
1596 airmass = cpl_propertylist_get_double(plist, "AIRMASS");
1597 } else if (cpl_propertylist_has(plist, "ESO TEL AIRM START")) {
1598 /* NIX */
1599 const double astart = cpl_propertylist_get_double(plist,
1600 "ESO TEL AIRM START");
1601 const double aend = cpl_propertylist_get_double(plist,
1602 "ESO TEL AIRM END");
1603 airmass = (astart + aend) / 2.0;
1604
1605 /* check for failure to set AIRM keywords correctly */
1606 const double alt = cpl_propertylist_get_double(plist,
1607 "ESO TEL ALT");
1608 double airmass_alt = 1.0 /cos ((90.0 - alt) * CPL_MATH_PI / 180.0);
1609 if (fabs(airmass - airmass_alt) > 1.0e-5) {
1610 cpl_msg_warning(cpl_func, "discrepency - airmass %f -> %f", airmass,
1611 airmass_alt);
1612 airmass = airmass_alt;
1613 }
1614 } else {
1615 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1616 "unable to find airmass information");
1617 }
1618
1619 return airmass;
1620}
1621
1622
1623/*----------------------------------------------------------------------------*/
1642/*----------------------------------------------------------------------------*/
1643
1644cpl_error_code enu_get_rcore_and_mesh_size(const char * context,
1645 const cpl_parameterlist * parlist,
1646 const cpl_propertylist * plist,
1647 double * obj_core_radius,
1648 int * bkg_mesh_size) {
1649
1650 char * param_name = NULL;
1651 const cpl_parameter * p = NULL;
1652 cpl_parameter * par = NULL;
1653
1654 cpl_error_code error_code = CPL_ERROR_NONE;
1655
1656 if (cpl_error_get_code() != CPL_ERROR_NONE) return CPL_ERROR_NONE;
1657 cpl_ensure_code(context, CPL_ERROR_NULL_INPUT);
1658 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
1659 cpl_ensure_code(plist, CPL_ERROR_NULL_INPUT);
1660 cpl_ensure_code(obj_core_radius, CPL_ERROR_NULL_INPUT);
1661 cpl_ensure_code(bkg_mesh_size, CPL_ERROR_NULL_INPUT);
1662
1663 *obj_core_radius = -1.0;
1664 *bkg_mesh_size = -1;
1665
1666 /* find out if to set catalogue.core-radius and mesh-size to defaults
1667 depending on AOMODE, or to read them from parameters */
1668
1669 param_name = cpl_sprintf("%s.catalogue.ao-params", context);
1670 cpl_msg_info(cpl_func, "%s", param_name);
1671 p = cpl_parameterlist_find_const(parlist, param_name);
1672 const char * ao_params = cpl_parameter_get_string(p);
1673 cpl_free(param_name);
1674 enu_check_error_code("failed to read ao-params");
1675
1676 if (!strcmp(ao_params, "auto") &&
1677 cpl_propertylist_has(plist, "ESO OBS AOMODE")) {
1678 const char * aomode = cpl_propertylist_get_string(plist,
1679 "ESO OBS AOMODE");
1680 cpl_msg_info(cpl_func, "AOMODE: %s", aomode);
1681
1682 if (!strcmp(aomode, "FULL_AO")) {
1683 *obj_core_radius = 10.0;
1684 *bkg_mesh_size = 64;
1685 if(!strstr(context,"skysub")) {
1686
1687 param_name = cpl_sprintf("%s.catalogue.obj.core-radius", context);
1688 par = (cpl_parameter*) cpl_parameterlist_find_const(parlist, param_name);
1689 cpl_parameter_set_double(par, *obj_core_radius);
1690 cpl_free(param_name);
1691
1692 }
1693
1694 param_name = cpl_sprintf("%s.catalogue.bkg.mesh-size", context);
1695 par = (cpl_parameter*) cpl_parameterlist_find_const(parlist, param_name);
1696 cpl_parameter_set_int(par, *bkg_mesh_size);
1697 cpl_free(param_name);
1698
1699 } else if (!strcmp(aomode, "NO_AO")) {
1700 *obj_core_radius = 25.0;
1701 *bkg_mesh_size = 128;
1702 if(!strstr(context,"skysub")) {
1703
1704 param_name = cpl_sprintf("%s.catalogue.obj.core-radius", context);
1705 par = (cpl_parameter*) cpl_parameterlist_find_const(parlist, param_name);
1706 cpl_parameter_set_double(par, *obj_core_radius);
1707 cpl_free(param_name);
1708
1709 }
1710 param_name = cpl_sprintf("%s.catalogue.bkg.mesh-size", context);
1711 par = (cpl_parameter*) cpl_parameterlist_find_const(parlist, param_name);
1712 cpl_parameter_set_int(par, *bkg_mesh_size);
1713 cpl_free(param_name);
1714 } else {
1715 error_code = CPL_ERROR_DATA_NOT_FOUND;
1716 }
1717
1718 } else {
1719 if(!strstr(context,"skysub")) {
1720 param_name = cpl_sprintf("%s.catalogue.obj.core-radius", context);
1721 p = cpl_parameterlist_find_const(parlist, param_name);
1722 *obj_core_radius = cpl_parameter_get_double(p);
1723 cpl_free(param_name);
1724 }
1725
1726 param_name = cpl_sprintf("%s.catalogue.bkg.mesh-size", context);
1727 p = cpl_parameterlist_find_const(parlist, param_name);
1728 *bkg_mesh_size = cpl_parameter_get_int(p);
1729 cpl_free(param_name);
1730 }
1731 cpl_msg_info(cpl_func, "catalogue AO-related params: %s %f %d",
1732 ao_params, *obj_core_radius, *bkg_mesh_size);
1733
1734 cleanup:
1735 return error_code;
1736}
1737
1738
1739/*----------------------------------------------------------------------------*/
1750/*----------------------------------------------------------------------------*/
1751double enu_get_tel_alt(const cpl_propertylist * plist) {
1752
1753 if (cpl_error_get_code() != CPL_ERROR_NONE) return 0;
1754
1755 double tel_alt = 0.0;
1756 if (cpl_propertylist_has(plist, "ESO TEL ALT")) {
1757 /* NACO */
1758 tel_alt = cpl_propertylist_get_double(plist, "ESO TEL ALT");
1759 } else {
1760 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1761 "unable to find ESO TEL ALT information");
1762 }
1763
1764 return tel_alt;
1765}
1766
1767
1768/*----------------------------------------------------------------------------*/
1780/*----------------------------------------------------------------------------*/
1781double enu_get_dit(const cpl_propertylist * plist) {
1782
1783 if (cpl_error_get_code() != CPL_ERROR_NONE) return 0;
1784
1785 double dit = 0.0;
1786 if (cpl_propertylist_has(plist, "ESO DET DIT")) {
1787 dit = cpl_propertylist_get_double(plist, "ESO DET DIT");
1788 } else if (cpl_propertylist_has(plist, "ESO DET SEQ1 DIT")) {
1789 dit = cpl_propertylist_get_double(plist, "ESO DET SEQ1 DIT");
1790 } else {
1791 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1792 "no keyword ESO.DET.DIT or ESO.DET.SEQ1.DIT");
1793 }
1794
1795 return dit;
1796}
1797
1798
1799/*----------------------------------------------------------------------------*/
1811/*----------------------------------------------------------------------------*/
1812const char * enu_get_det_mode(const cpl_propertylist * plist) {
1813
1814 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
1815
1816 const char * result = NULL;
1817 if (cpl_propertylist_has(plist, "ESO DET NCORRS NAME")) {
1818 result = cpl_propertylist_get_string(plist, "ESO DET NCORRS NAME");
1819 } else if (cpl_propertylist_has(plist, "ESO DET READ CURNAME")) {
1820 result = cpl_propertylist_get_string(plist, "ESO DET READ CURNAME");
1821 } else {
1822 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1823 "no keyword ESO.DET.NCORRS.NAME or "
1824 "ESO.DET.READ.CURNAME");
1825 }
1826
1827 return result;
1828}
1829
1830
1831/*----------------------------------------------------------------------------*/
1847/*----------------------------------------------------------------------------*/
1848const char * enu_get_filter(const cpl_propertylist * plist) {
1849
1850 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
1851 cpl_ensure(plist, CPL_ERROR_NULL_INPUT, NULL);
1852
1853 const char * filter = NULL;
1854
1855 if (cpl_propertylist_has(plist, "FILTER")) {
1856 filter = cpl_propertylist_get_string(plist, "FILTER");
1857 } else if (cpl_propertylist_has(plist, "INSTRUME")) {
1858 const char * instrume = cpl_propertylist_get_string(plist, "INSTRUME");
1859
1860 if (!strcmp(instrume, "NAOS+CONICA")) {
1861 filter = cpl_propertylist_get_string(plist, "ESO INS OPTI4 NAME");
1862 cpl_msg_info(cpl_func, "OPTI4 %s", filter);
1863 if (!strcmp(filter, "clear") || !strcmp(filter, "empty")) {
1864 filter = cpl_propertylist_get_string(plist, "ESO INS OPTI5 NAME");
1865 cpl_msg_info(cpl_func, "OPTI5 %s", filter);
1866 }
1867 if (!strcmp(filter, "clear") || !strcmp(filter, "empty")) {
1868 filter = cpl_propertylist_get_string(plist, "ESO INS OPTI6 NAME");
1869 cpl_msg_info(cpl_func, "OPTI6 %s", filter);
1870 }
1871 } else if (!strcmp(instrume, "ERIS")) {
1872 filter = cpl_propertylist_get_string(plist, "ESO INS2 NXFW NAME");
1873 } else {
1874 cpl_error_set(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT);
1875 }
1876 } else {
1877 filter = "unknown";
1878 }
1879
1880 return filter;
1881}
1882
1883
1884/*----------------------------------------------------------------------------*/
1897/*----------------------------------------------------------------------------*/
1898
1899double enu_get_filter_wavelength(const char * filter) {
1900
1901 if (cpl_error_get_code() != CPL_ERROR_NONE) return -1.0;
1902 cpl_ensure(filter, CPL_ERROR_NULL_INPUT, -1.0);
1903
1904 double lambda = 1.0;
1905 if (!strcmp(filter, "J")) {
1906 lambda = 1.28;
1907 } else if (!strcmp(filter, "H")) {
1908 lambda = 1.66;
1909 } else if (!strcmp(filter, "Ks")) {
1910 lambda = 2.18;
1911 } else if (!strcmp(filter, "Short-Lp")) {
1912 lambda = 3.32;
1913 } else if (!strcmp(filter, "L-Broad")) {
1914 lambda = 3.57;
1915 } else if (!strcmp(filter, "Lp")) {
1916 lambda = 3.79;
1917 } else if (!strcmp(filter, "Mp")) {
1918 lambda = 4.78;
1919 } else if (!strcmp(filter, "Pa-b")) {
1920 lambda = 1.282;
1921 } else if (!strcmp(filter, "Fe-II")) {
1922 lambda = 1.644;
1923 } else if (!strcmp(filter, "H2-cont")) {
1924 lambda = 2.068;
1925 } else if (!strcmp(filter, "H2-1-0S")) {
1926 lambda = 2.120;
1927 } else if (!strcmp(filter, "Br-g")) {
1928 lambda = 2.172;
1929 } else if (!strcmp(filter, "K-peak")) {
1930 lambda = 2.198;
1931 } else if (!strcmp(filter, "IB-2.42")) {
1932 lambda = 2.420;
1933 } else if (!strcmp(filter, "IB-2.48")) {
1934 lambda = 2.479;
1935 } else if (!strcmp(filter, "Br-a-cont")) {
1936 lambda = 3.965;
1937 } else if (!strcmp(filter, "Br-a")) {
1938 lambda = 4.051;
1939 } else {
1940 cpl_msg_warning(cpl_func, "filter %s not recognized", filter);
1941 }
1942
1943 return lambda;
1944}
1945
1946
1947/*----------------------------------------------------------------------------*/
1955/*----------------------------------------------------------------------------*/
1956const char * enu_get_license(void) {
1957
1958 const char * eris_nix_license =
1959 "This file is part of the ERIS/NIX Instrument Pipeline\n"
1960 "Copyright (C) 2017 European Southern Observatory\n"
1961 "\n"
1962 "This program is free software; you can redistribute it and/or modify\n"
1963 "it under the terms of the GNU General Public License as published by\n"
1964 "the Free Software Foundation; either version 2 of the License, or\n"
1965 "(at your option) any later version.\n"
1966 "\n"
1967 "This program is distributed in the hope that it will be useful,\n"
1968 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1969 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1970 "GNU General Public License for more details.\n"
1971 "\n"
1972 "You should have received a copy of the GNU General Public License\n"
1973 "along with this program; if not, write to the Free Software\n"
1974 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, \n"
1975 "MA 02110-1301 USA";
1976 return eris_nix_license;
1977}
1978
1979
1980/*----------------------------------------------------------------------------*/
1987/*----------------------------------------------------------------------------*/
1988
1989cpl_error_code enu_get_ra_dec(const cpl_wcs * wcs, double * ra, double * dec) {
1990
1991 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
1992 cpl_ensure(wcs, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
1993 cpl_ensure(ra, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
1994 cpl_ensure(dec, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
1995
1996 /* get the axis centre */
1997
1998 const cpl_array * dims = cpl_wcs_get_image_dims(wcs);
1999 cpl_matrix * from = cpl_matrix_new(1, 2);
2000 int ignore = 0;
2001 double dim = cpl_array_get(dims, 0, &ignore);
2002 cpl_matrix_set(from, 0, 0, dim / 2.0);
2003 dim = cpl_array_get(dims, 1, &ignore);
2004 cpl_matrix_set(from, 0, 1, dim / 2.0);
2005
2006 /* convert to world */
2007
2008 cpl_matrix * to = NULL;
2009 cpl_array * status = NULL;
2010 cpl_wcs_convert(wcs, from, &to, &status, CPL_WCS_PHYS2WORLD);
2011
2012 *ra = cpl_matrix_get(to, 0, 0);
2013 *dec = cpl_matrix_get(to, 0, 1);
2014
2015 /* tidy up */
2016
2017 cpl_matrix_delete(from);
2018 cpl_matrix_delete(to);
2019 cpl_array_delete(status);
2020
2021 return cpl_error_get_code();
2022}
2023
2024
2025/*----------------------------------------------------------------------------*/
2043/*----------------------------------------------------------------------------*/
2044cpl_error_code enu_get_window_info(cpl_size * nx, cpl_size * ny, int * rot,
2045 cpl_size * strx, cpl_size * stry,
2046 cpl_size * nx_chip, cpl_size * ny_chip,
2047 cpl_boolean * windowed,
2048 const cpl_propertylist * plist) {
2049
2050 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
2051
2052 cpl_ensure_code(plist, CPL_ERROR_NULL_INPUT);
2053 enu_check(cpl_propertylist_has(plist, "INSTRUME") == 1,
2054 CPL_ERROR_DATA_NOT_FOUND,
2055 "propertylist does not contain INSTRUME keyword");
2056
2057 /* get window information */
2058
2059 const char * instrume = cpl_propertylist_get_string(plist, "INSTRUME");
2060
2061 cpl_size nxw = 0;
2062 cpl_size nyw = 0;
2063 int rotw = 0;
2064 cpl_size strxw = 0;
2065 cpl_size stryw = 0;
2066
2067 if (!strcmp(instrume, "ERIS")) {
2068 nxw = cpl_propertylist_get_int(plist, "ESO DET SEQ1 WIN NX");
2069 nyw = cpl_propertylist_get_int(plist, "ESO DET SEQ1 WIN NY");
2070 rotw = cpl_propertylist_get_int(plist, "ESO DET SEQ1 WIN ROT");
2071 strxw = cpl_propertylist_get_int(plist, "ESO DET SEQ1 WIN STRX");
2072 stryw = cpl_propertylist_get_int(plist, "ESO DET SEQ1 WIN STRY");
2073 } else {
2074 /* for NACO */
2075 /* STARTX,Y can be stored as double or int */
2076 nxw = cpl_propertylist_get_int(plist, "ESO DET WIN NX");
2077 nyw = cpl_propertylist_get_int(plist, "ESO DET WIN NY");
2078 if (cpl_propertylist_get_type(plist, "ESO DET WIN STARTX") ==
2079 CPL_TYPE_DOUBLE) {
2080 strxw = (int) cpl_propertylist_get_double(plist,
2081 "ESO DET WIN STARTX");
2082 stryw = (int) cpl_propertylist_get_double(plist,
2083 "ESO DET WIN STARTY");
2084 } else {
2085 strxw = cpl_propertylist_get_int(plist, "ESO DET WIN STARTX");
2086 stryw = cpl_propertylist_get_int(plist, "ESO DET WIN STARTY");
2087 }
2088 }
2089
2090 cpl_size nx_chipw = 2048;
2091 cpl_size ny_chipw = 2048;
2092
2093 if(cpl_propertylist_has(plist, "ESO DET CHIP NX")) {
2094 nx_chipw = cpl_propertylist_get_int(plist,"ESO DET CHIP NX");
2095 } else {
2096 nx_chipw = cpl_propertylist_get_int(plist,"ESO DET CHIP1 NX");
2097 }
2098
2099 if(cpl_propertylist_has(plist, "ESO DET CHIP NY")) {
2100 ny_chipw = cpl_propertylist_get_int(plist,"ESO DET CHIP NY");
2101 } else {
2102 ny_chipw = cpl_propertylist_get_int(plist,"ESO DET CHIP1 NY");
2103 }
2104
2105 enu_check_error_code("failed to read detector mode information");
2106 enu_check(rotw == 0, CPL_ERROR_UNSUPPORTED_MODE,
2107 "detector window rot must be 0");
2108
2109 cpl_boolean windowedw = (rotw != 0) ||
2110 (strxw != 1) ||
2111 (stryw != 1) ||
2112 (nxw != nx_chipw) ||
2113 (nyw != ny_chipw);
2114 cpl_msg_info(cpl_func, "flatfield rot=%d strx=%d stry=%d nx=%d ny=%d",
2115 (int)rotw, (int)strxw, (int)stryw, (int)nxw, (int)nyw);
2116
2117 /* only now copy to external variables in case these are
2118 all the same - which would have screwed up the logic above */
2119
2120 *nx = nxw;
2121 *ny = nyw;
2122 *rot = rotw;
2123 *strx = strxw;
2124 *stry = stryw;
2125 *nx_chip = nx_chipw;
2126 *ny_chip = ny_chipw;
2127 *windowed = windowedw;
2128
2129 cleanup:
2130 return cpl_error_get_code();
2131}
2132
2133
2134/*----------------------------------------------------------------------------*/
2140/*----------------------------------------------------------------------------*/
2142 const hdrl_catalogue_result * target) {
2143 cpl_ensure(target, CPL_ERROR_NULL_INPUT, NULL);
2144
2145 hdrl_catalogue_result * result = cpl_malloc(sizeof(hdrl_catalogue_result));
2146
2147 result->catalogue = cpl_table_duplicate(target->catalogue);
2148 result->background = cpl_image_duplicate(target->background);
2149 result->segmentation_map = cpl_image_duplicate(target->segmentation_map);
2150 result->qclist = cpl_propertylist_duplicate(target->qclist);
2151
2152 return result;
2153}
2154
2155
2156/*----------------------------------------------------------------------------*/
2167/*----------------------------------------------------------------------------*/
2168
2169cpl_error_code enu_himage_load_from_fits(const char * filename,
2170 hdrl_image ** result,
2171 mef_extension_list ** mef_extensions,
2172 cpl_propertylist ** plist) {
2173
2174 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
2175
2176 cpl_propertylist * plist1 = NULL;
2177 cpl_propertylist * plist2 = NULL;
2178 cpl_propertylist * plist3 = NULL;
2179 cpl_image * data = NULL;
2180 cpl_image * error = NULL;
2181 cpl_mask * bpm = NULL;
2182 cpl_mask * old_bpm = NULL;
2183
2184 /* check parameters */
2185
2186 cpl_ensure_code(filename, CPL_ERROR_NULL_INPUT);
2187
2188 /* check FITS files has enough extensions */
2189
2190 cpl_size size = cpl_fits_count_extensions(filename);
2191 cpl_ensure_code(size >= 3, CPL_ERROR_BAD_FILE_FORMAT);
2192
2193 /* Get main propertylist from HDU 0 in the file */
2194
2195 *plist = cpl_propertylist_load(filename, 0);
2196 enu_check_error_code("accessing HDU 0 header");
2197
2198 /* Access HDU 1 in the file, this should contain the data */
2199
2200 plist1 = cpl_propertylist_load(filename, 1);
2201 enu_check_error_code("accessing HDU 1 header");
2202
2203 const char * extname = cpl_propertylist_get_string(plist1, "EXTNAME");
2204 const char * hduclass = cpl_propertylist_get_string(plist1, "HDUCLASS");
2205 const char * hdudoc = cpl_propertylist_get_string(plist1, "HDUDOC");
2206 //const char * hduvers = cpl_propertylist_get_string(plist1, "HDUVERS");
2207 const char * hduclas1 = cpl_propertylist_get_string(plist1, "HDUCLAS1");
2208 const char * hduclas2 = cpl_propertylist_get_string(plist1, "HDUCLAS2");
2209 enu_check_error_code("accessing HDU 1 propertylist");
2210 enu_check(strstr(extname, "DATA") != NULL &&
2211 strstr(hduclass, "ESO") != NULL &&
2212 strstr(hdudoc, "SDP") != NULL &&
2213 strstr(hduclas1, "IMAGE") != NULL &&
2214 strstr(hduclas2, "DATA") != NULL,
2215 CPL_ERROR_BAD_FILE_FORMAT, "bad HD1 format");
2216 data = cpl_image_load(filename, HDRL_TYPE_DATA, 0, 1);
2217 enu_check_error_code("accessing HDU 1 data");
2218
2219 /* the wcs items are stored with the image planes, merge
2220 them back into plist - order is import for the NAXIS*
2221 keywords so the properties are inserted after NAXIS
2222 in reverse order*/
2223
2224 const char * wcs_items = "NAXIS WCSAXES CRPIX1 CRPIX2 "
2225 "CD1_1 CD1_2 CD2_1 CD2_2 CUNIT1 CUNIT2 "
2226 "CTYPE1 CTYPE2 CRVAL1 CRVAL2 LONPOLE "
2227 "LATPOLE CSYER1 CSYER2 EQUINOX MJD-OBS "
2228 "DATE-OBS NAXIS2 NAXIS1";
2229 cpl_size plist1_size = cpl_propertylist_get_size(plist1);
2230 for (cpl_size ip=plist1_size; ip>0; ip--) {
2231 const cpl_property * newprop = cpl_propertylist_get_const(plist1, ip-1);
2232 const char * name = cpl_property_get_name(newprop);
2233 if (strstr(wcs_items, name) != NULL) {
2234 if (cpl_propertylist_has(*plist, name)) {
2235 cpl_propertylist_copy_property(*plist, plist1, name);
2236 } else {
2237 cpl_propertylist_insert_after_property(*plist, "NAXIS",
2238 newprop);
2239 }
2240 }
2241 }
2242
2243 /* Access HDU 2 in the file, this should contain the data error */
2244
2245 plist2 = cpl_propertylist_load(filename, 2);
2246 enu_check_error_code("accessing HDU 2");
2247 extname = cpl_propertylist_get_string(plist2, "EXTNAME");
2248 hduclass = cpl_propertylist_get_string(plist2, "HDUCLASS");
2249 hdudoc = cpl_propertylist_get_string(plist2, "HDUDOC");
2250 //hduvers = cpl_propertylist_get_string(plist2, "HDUVERS");
2251 hduclas1 = cpl_propertylist_get_string(plist2, "HDUCLAS1");
2252 hduclas2 = cpl_propertylist_get_string(plist2, "HDUCLAS2");
2253 enu_check_error_code("accessing HDU 2 propertylist");
2254 enu_check(strstr(extname, "ERR") != NULL &&
2255 strstr(hduclass, "ESO") != NULL &&
2256 strstr(hdudoc, "SDP") != NULL &&
2257 strstr(hduclas1, "IMAGE") != NULL &&
2258 strstr(hduclas2, "ERROR") != NULL,
2259 CPL_ERROR_BAD_FILE_FORMAT, "bad HD2 format");
2260 error = cpl_image_load(filename, HDRL_TYPE_ERROR, 0, 2);
2261 enu_check_error_code("accessing HDU 1 data error");
2262
2263 /* Access HDU 3 in the file, this should contain the data quality */
2264
2265 plist3 = cpl_propertylist_load(filename, 3);
2266 enu_check_error_code("accessing HDU 3");
2267 extname = cpl_propertylist_get_string(plist3, "EXTNAME");
2268 hduclass = cpl_propertylist_get_string(plist3, "HDUCLASS");
2269 hdudoc = cpl_propertylist_get_string(plist3, "HDUDOC");
2270 //hduvers = cpl_propertylist_get_string(plist3, "HDUVERS");
2271 hduclas1 = cpl_propertylist_get_string(plist3, "HDUCLAS1");
2272 hduclas2 = cpl_propertylist_get_string(plist3, "HDUCLAS2");
2273 enu_check_error_code("accessing HDU 3 propertylist");
2274 enu_check(strstr(extname, "DQ") != NULL &&
2275 strstr(hduclass, "ESO") != NULL &&
2276 strstr(hdudoc, "SDP") != NULL &&
2277 strstr(hduclas1, "IMAGE") != NULL &&
2278 strstr(hduclas2, "QUALITY") != NULL,
2279 CPL_ERROR_BAD_FILE_FORMAT, "bad HD3 format");
2280
2281 /* attach the mask to the data, construct the hdrl image */
2282
2283 bpm = cpl_mask_load(filename, 0, 3);
2284 enu_check_error_code("accessing HDU 3 data mask");
2285 old_bpm = cpl_image_set_bpm(data, bpm);
2286 cpl_mask_delete(old_bpm); old_bpm = NULL;
2287 *result = hdrl_image_create(data, error);
2288
2289 /* Read any further extensions into a mef_extension_list */
2290
2291 int n_ext = size - 3;
2292 *mef_extensions = enu_mef_extension_list_new(n_ext);
2293 for (int ext=0; ext<n_ext; ext++) {
2294
2295 /* get the extension name... */
2296
2297 cpl_propertylist * ext_plist = cpl_propertylist_load(filename, ext+4);
2298 const char * name = cpl_propertylist_get_string(ext_plist, "EXTNAME");
2299 const char * mef_type = cpl_propertylist_get_string(ext_plist,
2300 "ERIS_NIX_MEF_TYPE");
2301
2302 /* ...and value, type keyed on extension name */
2303
2304 if (!strcmp(mef_type, MEF_EXTENSION_CONTAINING_MASK)) {
2305 cpl_mask * mask = cpl_mask_load(filename, 0, ext+4);
2306 mef_extension * new = enu_mef_new_mask(name, mask, NULL);
2307 (*mef_extensions)->mef[ext] = new;
2308 cpl_mask_delete(mask);
2309 } else if (!strcmp(mef_type, MEF_EXTENSION_CONTAINING_IMAGE)) {
2310 cpl_image * image = cpl_image_load(filename, HDRL_TYPE_DATA, 0,
2311 ext+4);
2312 mef_extension * new = enu_mef_new_image(name, image, NULL);
2313 (*mef_extensions)->mef[ext] = new;
2314 cpl_image_delete(image);
2315 } else if (!strcmp(mef_type, MEF_EXTENSION_CONTAINING_TABLE)) {
2316 cpl_table * table = cpl_table_load(filename, ext+4, 0);
2317 mef_extension * new = enu_mef_new_table(name, table, ext_plist);
2318 (*mef_extensions)->mef[ext] = new;
2319 cpl_table_delete(table);
2320 } else {
2321 cpl_error_set_message("enu_himage_load_from_fits",
2322 CPL_ERROR_UNSUPPORTED_MODE,
2323 "unsupported extension name: %s", name);
2324 }
2325
2326 cpl_propertylist_delete(ext_plist);
2327 }
2328
2329 cleanup:
2330 cpl_propertylist_delete(plist1);
2331 cpl_propertylist_delete(plist2);
2332 cpl_propertylist_delete(plist3);
2333 cpl_image_delete(data);
2334 cpl_image_delete(error);
2335 cpl_mask_delete(old_bpm);
2336 if (cpl_error_get_code() != CPL_ERROR_NONE) {
2337 cpl_propertylist_delete(*plist);
2338 *plist = NULL;
2339 hdrl_image_delete(*result);
2340 *result = NULL;
2341 enu_mef_extension_list_delete(*mef_extensions);
2342 *mef_extensions = NULL;
2343 }
2344
2345 return cpl_error_get_code();
2346}
2347
2348
2349/*----------------------------------------------------------------------------*/
2364/*----------------------------------------------------------------------------*/
2365
2366located_image * enu_load_limage_from_frame(const cpl_frame * frame,
2367 cpl_image ** pcopyconf,
2368 const cpl_boolean collapse_cube) {
2369
2370 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
2371
2372 cpl_ensure(frame, CPL_ERROR_NULL_INPUT, NULL);
2373 cpl_ensure(cpl_frame_get_filename(frame), CPL_ERROR_NULL_INPUT, NULL);
2374
2375 located_image * result = NULL;
2376 mef_extension_list * mefs = NULL;
2377 cpl_image * data = NULL;
2378 cpl_image * err = NULL;
2379 cpl_image * qual = NULL;
2380 cpl_image * conf = NULL;
2381 cpl_image * bkg = NULL;
2382 cpl_image * bkg_err = NULL;
2383 cpl_image * bkg_conf = NULL;
2384
2385 const char * filename = cpl_frame_get_filename(frame);
2386 cpl_msg_info(cpl_func, "..reading %s", filename);
2387
2388 /* treatment depends on number of extensions, name of first extension, and
2389 ESO DET FRAM FORMAT (single image or cube).
2390 Get this information */
2391
2392 cpl_size next = cpl_fits_count_extensions(filename);
2393
2394 cpl_propertylist * plist = cpl_propertylist_load(filename, 0);
2395
2396 /* is this an ERIS file or NACO */
2397 const char * instrume = cpl_propertylist_get_string(plist, "INSTRUME");
2398 const cpl_boolean eris = !strcmp(instrume, "ERIS");
2399
2400 char * first_ext = NULL;
2401 if (eris && (next > 0)) {
2402 cpl_propertylist * plist1 = cpl_propertylist_load(filename, 1);
2403 if (cpl_propertylist_has(plist1, "EXTNAME")) {
2404 first_ext = cpl_sprintf("%s", cpl_propertylist_get_string(plist1, "EXTNAME"));
2405 }
2406 cpl_propertylist_delete(plist1);
2407 //cpl_msg_info(cpl_func, "extname %s", first_ext);
2408 }
2409
2410 char * frame_format = NULL;
2411 if (cpl_propertylist_has(plist, "ESO DET FRAM FORMAT")) {
2412 frame_format = cpl_sprintf("%s", cpl_propertylist_get_string(plist, "ESO DET FRAM FORMAT"));
2413 cpl_msg_info(cpl_func, "..format %s", frame_format);
2414 }
2415
2416 /* Now read the file appropriately */
2417
2418 if (!eris) {
2419 cpl_msg_info(cpl_func, "NACO data");
2420
2421 /* It is a raw FITS file with header and 2d image data,
2422 plus extensions to be ignored */
2423
2424 data = cpl_image_load(filename, HDRL_TYPE_DATA, 0, 0);
2425 enu_check_error_code("failed to read file: %s", filename);
2426 hdrl_image * himage = hdrl_image_create(data, NULL);
2427 cpl_image_delete(data); data = NULL;
2428 const cpl_size nx = hdrl_image_get_size_x(himage);
2429 const cpl_size ny = hdrl_image_get_size_y(himage);
2430
2431 /* confidence set to 100 everywhere */
2432
2433 cpl_image * confidence;
2434 if (pcopyconf != NULL && *pcopyconf != NULL &&
2435 cpl_image_get_size_x(*pcopyconf) == nx &&
2436 cpl_image_get_size_y(*pcopyconf) == ny) {
2437 confidence = *pcopyconf;
2438 *pcopyconf = NULL;
2439 } else {
2440 confidence = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
2441 cpl_image_fill_window(confidence, 1, 1, nx, ny, 100.0);
2442 }
2443
2444 cpl_frame_dump(frame, NULL);
2445 result = enu_located_image_new(himage,
2446 NULL,
2447 confidence,
2448 NULL,
2449 NULL,
2450 plist,
2451 NULL,
2452 NULL,
2453 NULL,
2454 NULL,
2455 cpl_frame_duplicate(frame));
2456 plist = NULL;
2457
2458 } else if ((next == 0) ||
2459 (next == 1 &&
2460 frame_format &&
2461 !strcmp(first_ext, "ASM_DATA"))) {
2462
2463 if (next == 1) {
2464
2465 /* read IA_FWHM from the ASM table and store it in the
2466 FITS header */
2467
2468 cpl_table * asm_table = cpl_table_load(filename, 1, CPL_TRUE);
2469 cpl_size nrow = cpl_table_get_nrow(asm_table);
2470 if(cpl_table_has_column(asm_table,"IA_FWHM")) {
2471 double * ia_fwhm_data = cpl_table_get_data_double(asm_table,
2472 "IA_FWHM");
2473 cpl_vector * ia_fwhm = cpl_vector_wrap(nrow, ia_fwhm_data);
2474 double ia_fwhm_mean = cpl_vector_get_mean(ia_fwhm);
2475
2476 const char * filter = enu_get_filter(plist);
2477 double lambda = enu_get_filter_wavelength(filter);
2478
2479 /* correct the FWHM for wavelength, check PIPE-10981 docs for
2480 explanation of formula */
2481
2482 double ia_fwhm_corr = ia_fwhm_mean * pow(0.5/lambda, 1./5.);
2483
2484 cpl_propertylist_update_double(plist, "PSF_FWHM", ia_fwhm_corr);
2485 cpl_propertylist_set_comment(plist, "PSF_FWHM", "PSF fwhm derived "
2486 "from AO ASM table [arcsec]");
2487
2488 cpl_vector_unwrap(ia_fwhm);
2489 } else {
2490 cpl_msg_warning(cpl_func,"ASM table miss IA_FWHM column. PSF_FWHM not computed");
2491 }
2492 cpl_table_delete(asm_table);
2493
2494 } else {
2495
2496 /* NO ASM table is present, AO was not used. Estimate the
2497 fwhm from DIMM instead. Again, see PIPE-10981 for background */
2498
2499 if (cpl_propertylist_has(plist, "ESO TEL AMBI FWHM START") &&
2500 cpl_propertylist_has(plist, "ESO TEL AMBI FWHM END") &&
2501 cpl_propertylist_has(plist, "ESO TEL AIRM START") &&
2502 cpl_propertylist_has(plist, "ESO TEL AIRM END")) {
2503
2504 double dimm1 = cpl_propertylist_get_double(plist,
2505 "ESO TEL AMBI FWHM START");
2506 double dimm2 = cpl_propertylist_get_double(plist,
2507 "ESO TEL AMBI FWHM END");
2508 double airmass1 = cpl_propertylist_get_double(plist,
2509 "ESO TEL AIRM START");
2510 double airmass2 = cpl_propertylist_get_double(plist,
2511 "ESO TEL AIRM END");
2512
2513 const char * filter = enu_get_filter(plist);
2514 double lambda = enu_get_filter_wavelength(filter);
2515
2516 /* correct DIMM values for wavelength, then average */
2517
2518 dimm1 = dimm1 *
2519 pow(0.5/lambda, 1./5.) *
2520 pow(airmass1, 3./5.) *
2521 (1. - 78.08 *
2522 (pow(lambda/1.e6, 2./5.) *
2523 pow(airmass1, -1./5.) /
2524 pow(dimm1, 1./3.)
2525 )
2526 );
2527 dimm2 = dimm2 *
2528 pow(0.5/lambda, 1./5.) *
2529 pow(airmass2, 3./5.) *
2530 (1. - 78.08 *
2531 (pow(lambda/1.e6, 2./5.) *
2532 pow(airmass2, -1./5.) /
2533 pow(dimm2, 1./3.)
2534 )
2535 );
2536
2537 cpl_propertylist_update_double(plist, "PSF_FWHM",
2538 (dimm1 + dimm2) / 2.0);
2539 cpl_propertylist_set_comment(plist, "PSF_FWHM",
2540 "PSF fwhm derived "
2541 "from DIMM [arcsec]");
2542 }
2543 }
2544
2545 if (!strcmp(frame_format, "single")) {
2546
2547 /* It is a raw FITS file with header and 2d image data */
2548
2549 data = cpl_image_load(filename, HDRL_TYPE_DATA, 0, 0);
2550 enu_check_error_code("failed to read file: %s", filename);
2551 hdrl_image * himage = hdrl_image_create(data, NULL);
2552 cpl_image_delete(data); data = NULL;
2553 const cpl_size nx = hdrl_image_get_size_x(himage);
2554 const cpl_size ny = hdrl_image_get_size_y(himage);
2555
2556 /* confidence set to 100 everywhere */
2557
2558 cpl_image * confidence;
2559 if (pcopyconf != NULL && *pcopyconf != NULL &&
2560 cpl_image_get_size_x(*pcopyconf) == nx &&
2561 cpl_image_get_size_y(*pcopyconf) == ny) {
2562 confidence = *pcopyconf;
2563 *pcopyconf = NULL;
2564 } else {
2565 confidence = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
2566 cpl_image_fill_window(confidence, 1, 1, nx, ny, 100.0);
2567 }
2568
2569 result = enu_located_image_new(himage,
2570 NULL,
2571 confidence,
2572 NULL,
2573 NULL,
2574 plist,
2575 NULL,
2576 NULL,
2577 NULL,
2578 NULL,
2579 cpl_frame_duplicate(frame));
2580 plist = NULL;
2581
2582 } else if (!strcmp(frame_format, "cube")) {
2583
2584 /* It is a raw FITS file with header and 3d image data (cube) */
2585
2586 cpl_imagelist * datalist = cpl_imagelist_load(filename,
2587 HDRL_TYPE_DATA, 0);
2588 enu_check_error_code("failed to read file: %s", filename);
2589 hdrl_imagelist * himagelist = hdrl_imagelist_create(datalist,
2590 NULL);
2591 cpl_imagelist_delete(datalist); datalist = NULL;
2592 const cpl_size nx = hdrl_imagelist_get_size_x(himagelist);
2593 const cpl_size ny = hdrl_imagelist_get_size_y(himagelist);
2594
2595 /* confidence set to 100 everywhere */
2596
2597 cpl_image * confidence;
2598 if (pcopyconf != NULL && *pcopyconf != NULL &&
2599 cpl_image_get_size_x(*pcopyconf) == nx &&
2600 cpl_image_get_size_y(*pcopyconf) == ny) {
2601 confidence = *pcopyconf;
2602 *pcopyconf = NULL;
2603 } else {
2604 confidence = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
2605 cpl_image_fill_window(confidence, 1, 1, nx, ny, 100.0);
2606 }
2607
2608 if(collapse_cube) {
2609 hdrl_image * himage = NULL;
2610 cpl_image* conf_ima = NULL;
2611 if(collapse_cube == 1) {
2612 hdrl_imagelist_collapse_mean(himagelist,&himage,&conf_ima);
2613 } else if(collapse_cube == 2) {
2614 hdrl_imagelist_collapse_median(himagelist,&himage,&conf_ima);
2615 } else if(collapse_cube == 3) {
2616 hdrl_imagelist_collapse_weighted_mean(himagelist,&himage,&conf_ima);
2617 }
2618 cpl_image_delete(conf_ima);
2619 result = enu_located_image_new(himage,
2620 NULL,
2621 confidence,
2622 NULL,
2623 NULL,
2624 plist,
2625 NULL,
2626 NULL,
2627 NULL,
2628 NULL,
2629 cpl_frame_duplicate(frame));
2630 } else {
2631 result = enu_located_image_new(NULL,
2632 himagelist,
2633 confidence,
2634 NULL,
2635 NULL,
2636 plist,
2637 NULL,
2638 NULL,
2639 NULL,
2640 NULL,
2641 cpl_frame_duplicate(frame));
2642 }
2643 plist = NULL;
2644 }
2645 } else {
2646
2647 /* It is a mef: it should be in ESO Data Products Standard format */
2648
2649 cpl_propertylist_delete(plist);
2650 plist = NULL;
2651 mefs = enu_load_mef_components(filename, &plist);
2652 enu_check_error_code("Unable to load components for file");
2653
2654 /* look in first extension for HDU keywords */
2655
2656 const char * hduclass = cpl_propertylist_get_string(
2657 mefs->mef[0]->plist, "HDUCLASS");
2658 const char * hdudoc = cpl_propertylist_get_string(
2659 mefs->mef[0]->plist, "HDUDOC");
2660 const char * hduvers = cpl_propertylist_get_string(
2661 mefs->mef[0]->plist, "HDUVERS");
2662 enu_check_error_code("Unable to read ESO DPS keywords from header");
2663
2664 enu_check(strstr(hduclass, "ESO") != NULL &&
2665 strstr(hdudoc, "SDP") != NULL &&
2666 strstr(hduvers, "SDP version") != NULL,
2667 CPL_ERROR_BAD_FILE_FORMAT, "file not in ESO DPS format");
2668
2669 /* Read the names of the extensions holding standard data
2670 components */
2671
2672 const char * scidata = NULL;
2673 if (mefs->size > 0 &&
2674 cpl_propertylist_has(mefs->mef[1]->plist, "SCIDATA")){
2675 scidata = cpl_propertylist_get_string(mefs->mef[1]->plist,
2676 "SCIDATA");
2677 }
2678 const char * errdata = NULL;
2679 if (cpl_propertylist_has(mefs->mef[0]->plist, "ERRDATA")){
2680 errdata = cpl_propertylist_get_string(mefs->mef[0]->plist,
2681 "ERRDATA");
2682 }
2683 const char * qualdata = NULL;
2684 if (cpl_propertylist_has(mefs->mef[0]->plist, "QUALDATA")){
2685 qualdata = cpl_propertylist_get_string(mefs->mef[0]->plist,
2686 "QUALDATA");
2687 }
2688 const char * confdata = NULL;
2689 if (cpl_propertylist_has(mefs->mef[0]->plist, "CONFDATA")){
2690 confdata = cpl_propertylist_get_string(mefs->mef[0]->plist,
2691 "CONFDATA");
2692 }
2693 const char * bkgdata = NULL;
2694 if (cpl_propertylist_has(mefs->mef[0]->plist, "BKGDATA")){
2695 bkgdata = cpl_propertylist_get_string(mefs->mef[0]->plist,
2696 "BKGDATA");
2697 }
2698 const char * bkgerr = NULL;
2699 if (cpl_propertylist_has(mefs->mef[0]->plist, "BKGERR")){
2700 bkgerr = cpl_propertylist_get_string(mefs->mef[0]->plist,
2701 "BKGERR");
2702 }
2703 const char * bkgconf = NULL;
2704 if (cpl_propertylist_has(mefs->mef[0]->plist, "BKGCONF")){
2705 bkgconf = cpl_propertylist_get_string(mefs->mef[0]->plist,
2706 "BKGCONF");
2707 }
2708 enu_check_error_code("accessing DPS standard extensions");
2709
2710 /* now loop through extensions filling standard data elements */
2711
2712 for (cpl_size i=0; i<next; i++) {
2713 const char * extname = cpl_propertylist_get_string(
2714 mefs->mef[i]->plist, "EXTNAME");
2715
2716 /* the returned plist is a merge of the plist for the
2717 science image and the header plist.*/
2718
2719 if (scidata && !strcmp(scidata, extname)) {
2720 data = enu_load_component(mefs->mef[i], "SCIDATA",
2721 "IMAGE", "DATA");
2722 enu_check_error_code("accessing SCIDATA extension");
2723
2724 /* Start with the science image plist (for the data and
2725 wcs keywords)*/
2726
2727 cpl_propertylist * primary_plist = plist;
2728
2729 /* remove the SDP7 keywords which were appropriate to
2730 the science data extension but will
2731 confuse the enu_limage_save routine if left in the
2732 main header */
2733
2734 plist = cpl_propertylist_duplicate(mefs->mef[i]->plist);
2735 const char * sdp7_items = " EXTNAME HDUCLAS1 HDUCLAS2"
2736 " HDUCLAS3 ";
2737 cpl_size psize = cpl_propertylist_get_size(plist);
2738 for (cpl_size ip = psize; ip > 0; ip--) {
2739 const cpl_property * prop = cpl_propertylist_get_const(
2740 plist, ip-1);
2741 const char * name = cpl_property_get_name(prop);
2742
2743 /* pad the keyword name with spaces which will
2744 stop strstr misidentifying a keyword that
2745 matches _part_ of an SDP7 keyword */
2746
2747 char * padded_name = cpl_sprintf(" %s ", name);
2748 if (strstr(sdp7_items, padded_name) != NULL) {
2749 cpl_propertylist_erase(plist, name);
2750 }
2751 cpl_free(padded_name);
2752 }
2753
2754 /* merge info from the primary header */
2755
2756 psize = cpl_propertylist_get_size(primary_plist);
2757 for (cpl_size ip = psize; ip > 0; ip--) {
2758 const cpl_property * prop = cpl_propertylist_get_const(
2759 primary_plist, ip-1);
2760 const char * name = cpl_property_get_name(prop);
2761 if (!cpl_propertylist_has(plist, name)) {
2762 cpl_propertylist_copy_property(plist, primary_plist,
2763 name);
2764 }
2765 }
2766 cpl_propertylist_delete(primary_plist);
2767
2768 } else if (errdata && !strcmp(errdata, extname)) {
2769 err = enu_load_component(mefs->mef[i], "SCIERR",
2770 "IMAGE", "ERROR");
2771 enu_check_error_code("accessing SCIERR extension");
2772 } else if (qualdata && !strcmp(qualdata, extname)) {
2773 qual = enu_load_component(mefs->mef[i], "QUALDATA",
2774 "IMAGE", "QUALITY");
2775 enu_check_error_code("accessing QUALDATA extension");
2776 } else if (confdata && !strcmp(confdata, extname)) {
2777 conf = enu_load_component(mefs->mef[i], "CONFDATA",
2778 "IMAGE", "CONF");
2779 enu_check_error_code("accessing CONFDATA extension");
2780 } else if (bkgdata && !strcmp(bkgdata, extname)) {
2781 bkg = enu_load_component(mefs->mef[i], "BKGDATA",
2782 "IMAGE", "BKG_DATA");
2783 enu_check_error_code("accessing BKGDATA extension");
2784 } else if (bkgerr && !strcmp(bkgerr, extname)) {
2785 bkg_err = enu_load_component(mefs->mef[i], "BKGERR",
2786 "IMAGE", "BKG_ERR");
2787 enu_check_error_code("accessing BKGERR extension");
2788 } else if (bkgconf && !strcmp(bkgconf, extname)) {
2789 bkg_conf = enu_load_component(mefs->mef[i], "BKGCONF",
2790 "IMAGE", "BKG_CONF");
2791 enu_check_error_code("accessing BKGCONF extension");
2792 }
2793 }
2794
2795 /* set the data mask from quality, construct the hdrl image */
2796
2797 enu_check(data != NULL, CPL_ERROR_BAD_FILE_FORMAT, "no data in file");
2798 cpl_mask * bpm = cpl_image_get_bpm(data);
2799 cpl_mask_threshold_image(bpm, qual, 0.9, 1.1, CPL_BINARY_1);
2800 bpm = cpl_image_get_bpm(err);
2801 cpl_mask_threshold_image(bpm, qual, 0.9, 1.1, CPL_BINARY_1);
2802 hdrl_image * hdata = hdrl_image_create(data, err);
2803 hdrl_image * hbkg = NULL;
2804 if (bkg) {
2805 hbkg = hdrl_image_create(bkg, bkg_err);
2806 }
2807
2808 result = enu_located_image_new(hdata,
2809 NULL,
2810 conf,
2811 hbkg,
2812 bkg_conf,
2813 plist,
2814 NULL,
2815 NULL,
2816 NULL,
2817 NULL,
2818 cpl_frame_duplicate(frame));
2819
2820 plist = NULL;
2821 cpl_image_delete(data);
2822 cpl_image_delete(err);
2823 cpl_image_delete(qual);
2824 cpl_image_delete(bkg);
2825 cpl_image_delete(bkg_err);
2826 data = NULL;
2827 err = NULL;
2828 qual = NULL;
2829 conf = NULL;
2830 bkg = NULL;
2831 bkg_err = NULL;
2832 bkg_conf = NULL;
2833 }
2834
2835 cleanup:
2836 cpl_free(frame_format);
2837 cpl_free(first_ext);
2838 cpl_propertylist_delete(plist);
2839 cpl_image_delete(data);
2840 cpl_image_delete(err);
2841 cpl_image_delete(qual);
2842 cpl_image_delete(conf);
2843 cpl_image_delete(bkg);
2844 cpl_image_delete(bkg_err);
2845 cpl_image_delete(bkg_conf);
2847 if (cpl_error_get_code() != CPL_ERROR_NONE) {
2849 result = NULL;
2850 }
2851 return result;
2852}
2853
2854
2855/*----------------------------------------------------------------------------*/
2865/*----------------------------------------------------------------------------*/
2866
2867mef_extension_list * enu_load_mef_components(const char * filename,
2868 cpl_propertylist ** plist) {
2869
2870 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
2871
2872 cpl_ensure(filename, CPL_ERROR_NULL_INPUT, NULL);
2873
2874 /* How many extensions are there, construct result of the correct
2875 size */
2876
2877 cpl_size next = cpl_fits_count_extensions(filename);
2878 mef_extension_list * result = enu_mef_extension_list_new(next);
2879 mef_extension * new = NULL;
2880 cpl_propertylist * eplist = NULL;
2881
2882 /* Read primary HDU header */
2883
2884 *plist = cpl_propertylist_load(filename, 0);
2885 enu_check_error_code("accessing HDU 0 header");
2886
2887 /* Now loop through extensions, loading them in turn */
2888
2889 for (int i=0; i<next; i++) {
2890 int hdu = i + 1;
2891
2892 /* get the extension name... */
2893
2894 cpl_propertylist_delete(eplist);
2895 eplist = cpl_propertylist_load(filename, hdu);
2896 const char * name = cpl_propertylist_get_string(eplist, "EXTNAME");
2897 const char * hduclas1 = cpl_propertylist_get_string(eplist,
2898 "HDUCLAS1");
2899 enu_check_error_code("error accessing keywords in HDU %d", hdu);
2900
2901 /* ...type and value, create appropriate mef_extension */
2902
2903 if (!strcmp(hduclas1, MEF_EXTENSION_CONTAINING_MASK)) {
2904 cpl_mask * mask = cpl_mask_load(filename, 0, hdu);
2905 new = enu_mef_new_mask(name, mask, eplist);
2906 cpl_mask_delete(mask);
2907 } else if (!strcmp(hduclas1, "IMAGE")) {
2908 cpl_image * image = cpl_image_load(filename, HDRL_TYPE_DATA, 0, hdu);
2909 new = enu_mef_new_image(name, image, eplist);
2910 cpl_image_delete(image);
2911 } else if (!strcmp(hduclas1, MEF_EXTENSION_CONTAINING_TABLE)) {
2912 cpl_table * table = cpl_table_load(filename, hdu, 0);
2913 new = enu_mef_new_table(name, table, eplist);
2914 cpl_table_delete(table);
2915 } else {
2916 cpl_error_set_message("enu_load_mef_components",
2917 CPL_ERROR_UNSUPPORTED_MODE,
2918 "extension has unsupported HDUCLAS1: %s %s", name, hduclas1);
2919 }
2920 enu_check_error_code("error accessing HDU %d", hdu);
2921
2922 result->mef[i] = new;
2923 new = NULL;
2924 }
2925
2926 cleanup:
2928 cpl_propertylist_delete(eplist);
2929 if (cpl_error_get_code() != CPL_ERROR_NONE) {
2931 result = NULL;
2932 cpl_propertylist_delete(*plist);
2933 *plist = NULL;
2934 }
2935
2936 return result;
2937}
2938
2939
2940/*----------------------------------------------------------------------------*/
2947/*----------------------------------------------------------------------------*/
2948
2949void enu_located_image_delete(located_image * limage) {
2950
2951 if (limage) {
2952 hdrl_image_delete(limage->himage);
2953 hdrl_imagelist_delete(limage->himagelist);
2954 cpl_image_delete(limage->confidence);
2955 hdrl_image_delete(limage->bkg);
2956 cpl_image_delete(limage->bkg_confidence);
2957 cpl_propertylist_delete(limage->plist);
2958 hdrl_catalogue_result_delete(limage->objects);
2959 cpl_mask_delete(limage->object_mask);
2960 hdrl_catalogue_result_delete(limage->matchstd_wcs);
2961 hdrl_catalogue_result_delete(limage->matchstd_phot);
2962 cpl_frame_delete(limage->frame);
2963 cpl_free(limage);
2964 }
2965}
2966
2967
2968/*----------------------------------------------------------------------------*/
2976/*----------------------------------------------------------------------------*/
2977
2978located_image * enu_located_image_duplicate(const located_image * limage) {
2979
2980 cpl_ensure(limage, CPL_ERROR_NULL_INPUT, NULL);
2981
2982 /* Watch out for NULL components */
2983
2984 hdrl_image * himage = NULL;
2985 if (limage->himage) {
2986 himage = hdrl_image_duplicate(limage->himage);
2987 }
2988 hdrl_imagelist * himagelist = NULL;
2989 if (limage->himagelist) {
2990 himagelist = hdrl_imagelist_duplicate(limage->himagelist);
2991 }
2992 cpl_image * confidence = NULL;
2993 if (limage->confidence) {
2994 confidence = cpl_image_duplicate(limage->confidence);
2995 }
2996 hdrl_image * bkg = NULL;
2997 if (limage->bkg) {
2998 bkg = hdrl_image_duplicate(limage->bkg);
2999 }
3000 cpl_image * bkg_confidence = NULL;
3001 if (limage->bkg_confidence) {
3002 bkg_confidence = cpl_image_duplicate(limage->bkg_confidence);
3003 }
3004 cpl_propertylist * plist = NULL;
3005 if (limage->plist) {
3006 plist = cpl_propertylist_duplicate(limage->plist);
3007 }
3008 hdrl_catalogue_result * objects = NULL;
3009 if (limage->objects) {
3010 objects = enu_hdrl_catalogue_result_duplicate(limage->objects);
3011 }
3012 cpl_mask * object_mask = NULL;
3013 if (limage->object_mask) {
3014 object_mask = cpl_mask_duplicate(limage->object_mask);
3015 }
3016 hdrl_catalogue_result * matchstd_wcs = NULL;
3017 if (limage->matchstd_wcs) {
3019 limage->matchstd_wcs);
3020 }
3021 hdrl_catalogue_result * matchstd_phot = NULL;
3022 if (limage->matchstd_phot) {
3024 limage->matchstd_phot);
3025 }
3026 cpl_frame * frame = NULL;
3027 if (limage->frame) {
3028 frame = cpl_frame_duplicate(limage->frame);
3029 }
3030
3031 located_image * result = enu_located_image_new(himage,
3032 himagelist,
3033 confidence,
3034 bkg,
3035 bkg_confidence,
3036 plist,
3037 objects,
3038 object_mask,
3039 matchstd_wcs,
3040 matchstd_phot,
3041 frame);
3042
3043 return result;
3044}
3045
3046
3047/*----------------------------------------------------------------------------*/
3067/*----------------------------------------------------------------------------*/
3068
3069located_image * enu_located_image_new(hdrl_image * himage,
3070 hdrl_imagelist * himagelist,
3071 cpl_image * confidence,
3072 hdrl_image * bkg,
3073 cpl_image * bkg_confidence,
3074 cpl_propertylist * plist,
3075 hdrl_catalogue_result * objects,
3076 cpl_mask * object_mask,
3077 hdrl_catalogue_result * wcs,
3078 hdrl_catalogue_result * photom,
3079 cpl_frame * frame) {
3080
3081 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3082
3083 /* store either image or cube (imagelist) */
3084 cpl_ensure(!(himage && himagelist), CPL_ERROR_ILLEGAL_INPUT, NULL);
3085
3086 located_image * result = cpl_malloc(sizeof(located_image));
3087 result->himage = himage;
3088 result->himagelist = himagelist;
3089 result->confidence = confidence;
3090 result->bkg = bkg;
3091 result->bkg_confidence = bkg_confidence;
3092 result->plist = plist;
3093 result->objects = objects;
3094 result->object_mask = object_mask;
3095 result->matchstd_wcs = wcs;
3096 result->matchstd_phot = photom;
3097 result->frame = frame;
3098
3099 return result;
3100}
3101
3102
3103/*----------------------------------------------------------------------------*/
3114/*----------------------------------------------------------------------------*/
3115
3117 cpl_frameset * frameset,
3118 const char * tag,
3119 cpl_frameset * used) {
3120
3121 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3122 cpl_ensure(frameset, CPL_ERROR_NULL_INPUT, NULL);
3123 cpl_ensure(tag, CPL_ERROR_NULL_INPUT, NULL);
3124 cpl_ensure(used, CPL_ERROR_NULL_INPUT, NULL);
3125
3126 located_imagelist * result = NULL;
3127 cpl_frameset_iterator * frameset_iter = NULL;
3128 mef_extension_list * mefs = NULL;
3129 cpl_image * data = NULL;
3130 cpl_image * err = NULL;
3131 cpl_image * qual = NULL;
3132 cpl_image * conf = NULL;
3133 cpl_image * bkg = NULL;
3134 cpl_image * bkg_err = NULL;
3135 cpl_image * bkg_conf = NULL;
3136 cpl_propertylist * plist = NULL;
3137
3138 /* first, find how big the located_imagelist needs to be */
3139
3140 frameset_iter = cpl_frameset_iterator_new(frameset);
3141 cpl_size size = 0;
3142
3143 for (cpl_frame * frame = NULL;
3144 (frame = cpl_frameset_iterator_get(frameset_iter)) &&
3145 (cpl_error_get_code() == CPL_ERROR_NONE);
3146 cpl_frameset_iterator_advance(frameset_iter, 1)) {
3147
3148 const char * frametag = cpl_frame_get_tag(frame);
3149 if (!strcmp(tag, frametag)) {
3150 size++;
3151 }
3152 }
3153 result = enu_located_imagelist_new(size);
3154
3155 /* go through the frameset again and populate the container */
3156
3157 cpl_frameset_iterator_reset(frameset_iter);
3158 cpl_size position = 0;
3159 for (cpl_frame * frame = NULL;
3160 (frame = cpl_frameset_iterator_get(frameset_iter)) &&
3161 (cpl_error_get_code() == CPL_ERROR_NONE);
3162 cpl_frameset_iterator_advance(frameset_iter, 1)) {
3163
3164 /* if frametag is among those wanted, create a located image with
3165 the data and insert it into the located image list */
3166
3167 const char * frametag = cpl_frame_get_tag(frame);
3168
3169 if (!strcmp(tag, frametag)) {
3170
3171 /* we want this file, treatment depends on number of extensions
3172 it has and on the name of the first extension if present */
3173
3174 located_image * limage = enu_load_limage_from_frame(frame,
3175 NULL,
3176 CPL_FALSE);
3177
3178/*
3179 const char * filename = cpl_frame_get_filename(frame);
3180 cpl_msg_info(cpl_func, "..reading %s", filename);
3181 cpl_size next = cpl_fits_count_extensions(filename);
3182 located_image * limage = NULL;
3183
3184 plist = cpl_propertylist_load(filename, 0);
3185
3186 char * first_ext = NULL;
3187 if (next > 0) {
3188 cpl_propertylist * plist1 = cpl_propertylist_load(filename, 1);
3189 if (cpl_propertylist_has(plist1, "EXTNAME")) {
3190 first_ext = cpl_sprintf("%s", cpl_propertylist_get_string(plist1, "EXTNAME"));
3191 }
3192 cpl_propertylist_delete(plist1);
3193 }
3194
3195 char * frame_format = NULL;
3196 if (cpl_propertylist_has(plist, "ESO DET FRAM FORMAT")) {
3197 frame_format = cpl_sprintf("%s", cpl_propertylist_get_string(plist, "ESO DET FRAM FORMAT"));
3198 }
3199
3200 if ((next == 0) ||
3201 (next == 1 &&
3202 !strcmp(first_ext, "ASM_DATA") &&
3203 !strcmp(frame_format, "single"))) {
3204*/
3205 /* raw FITS file with header and 2d image data */
3206/*
3207 data = cpl_image_load(filename, HDRL_TYPE_DATA, 0, 0);
3208 enu_check_error_code("failed to read file: %s", filename);
3209 hdrl_image * himage = hdrl_image_create(data, NULL);
3210 cpl_image_delete(data); data = NULL;
3211 const cpl_size nx = hdrl_image_get_size_x(himage);
3212 const cpl_size ny = hdrl_image_get_size_y(himage);
3213*/
3214 /* confidence set to 100 everywhere */
3215/*
3216 cpl_image * confidence = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
3217 cpl_image_fill_window(confidence, 1, 1, nx, ny, 100.0);
3218
3219 limage = enu_located_image_new(himage, NULL, confidence, NULL,
3220 NULL, plist, NULL, NULL, NULL,
3221 NULL,
3222 cpl_frame_duplicate(frame));
3223 plist = NULL;
3224
3225 } else if (next == 1 &&
3226 !strcmp(first_ext, "ASM_DATA") &&
3227 !strcmp(frame_format, "cube")) {
3228*/
3229 /* raw FITS file with header and 3d image data (cube) */
3230/*
3231 cpl_imagelist * datalist = cpl_imagelist_load(filename,
3232 HDRL_TYPE_DATA,
3233 0);
3234 enu_check_error_code("failed to read file: %s", filename);
3235 hdrl_imagelist * himagelist = hdrl_imagelist_create(datalist,
3236 NULL);
3237 cpl_imagelist_delete(datalist); datalist = NULL;
3238 const cpl_size nx = hdrl_imagelist_get_size_x(himagelist);
3239 const cpl_size ny = hdrl_imagelist_get_size_y(himagelist);
3240*/
3241 /* confidence set to 100 everywhere */
3242/*
3243 cpl_image * confidence = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
3244 cpl_image_fill_window(confidence, 1, 1, nx, ny, 100.0);
3245
3246 limage = enu_located_image_new(NULL, himagelist, confidence,
3247 NULL, NULL, plist, NULL, NULL,
3248 NULL, NULL,
3249 cpl_frame_duplicate(frame));
3250 plist = NULL;
3251
3252 } else {
3253*/
3254 /* If it's a mef it should be in ESO Data Products Standard
3255 format */
3256/*
3257 cpl_propertylist_delete(plist);
3258 plist = NULL;
3259 enu_mef_extension_list_delete(mefs);
3260 mefs = enu_load_mef_components(filename, &plist);
3261 enu_check_error_code("Unable to load components for file");
3262*/
3263 /* look in first extension for HDU keywords */
3264/*
3265 const char * hduclass = cpl_propertylist_get_string(
3266 mefs->mef[0]->plist, "HDUCLASS");
3267 const char * hdudoc = cpl_propertylist_get_string(
3268 mefs->mef[0]->plist, "HDUDOC");
3269 //const char * hduvers = cpl_propertylist_get_string(
3270 // mefs->mef[0]->plist, "HDUVERS");
3271 enu_check_error_code("Unable to read ESO DPS keywords from header");
3272
3273 enu_check(strstr(hduclass, "ESO") != NULL &&
3274 // strstr(hduvers, "SDP version 8") != NULL &&
3275 strstr(hdudoc, "SDP") != NULL,
3276 CPL_ERROR_BAD_FILE_FORMAT, "file not in ESO DPS format");
3277*/
3278 /* now loop through extensions filling standard data elements */
3279/*
3280 for (cpl_size i=0; i<next; i++) {
3281 const char * hduclas2 = cpl_propertylist_get_string(
3282 mefs->mef[i]->plist, "HDUCLAS2");
3283*/
3284 /* the returned plist is a merge of the plist for the
3285 science image and the header plist.*/
3286/*
3287 if (hduclas2 && !strcmp(hduclas2, "DATA")) {
3288 data = enu_load_component(mefs->mef[i], "SCIDATA",
3289 "IMAGE", "DATA");
3290 enu_check_error_code("accessing SCIDATA extension");
3291*/
3292 /* Start with the science image plist (for the data and
3293 wcs keywords)*/
3294/*
3295 cpl_propertylist * primary_plist = plist;
3296*/
3297 /* remove the SDP7 keywords which were appropriate to
3298 the science data extension but will
3299 confuse the enu_limage_save routine if left in the
3300 main header */
3301/*
3302 plist = cpl_propertylist_duplicate(
3303 mefs->mef[i]->plist);
3304 const char * sdp7_items = " EXTNAME HDUCLAS1 HDUCLAS2"
3305 " HDUCLAS3 ";
3306 cpl_size psize = cpl_propertylist_get_size(plist);
3307 for (cpl_size ip=psize; ip>0; ip--) {
3308 const cpl_property * prop =
3309 cpl_propertylist_get_const(
3310 plist, ip-1);
3311 const char * name = cpl_property_get_name(prop);
3312*/
3313 /* pad the keyword name with spaces which will
3314 stop strstr misidentifying a keyword that
3315 matches _part_ of an SDP7 keyword */
3316/*
3317 char * padded_name = cpl_sprintf(" %s ", name);
3318 if (strstr(sdp7_items, padded_name) != NULL) {
3319 cpl_propertylist_erase(plist, name);
3320 }
3321 cpl_free(padded_name);
3322 }
3323*/
3324 /* merge info from the primary header */
3325/*
3326 psize = cpl_propertylist_get_size(primary_plist);
3327 for (cpl_size ip=psize; ip>0; ip--) {
3328 const cpl_property * prop =
3329 cpl_propertylist_get_const(
3330 primary_plist, ip-1);
3331 const char * name = cpl_property_get_name(prop);
3332 if (!cpl_propertylist_has(plist, name)) {
3333 cpl_propertylist_copy_property(plist,
3334 primary_plist,
3335 name);
3336 }
3337 }
3338 cpl_propertylist_delete(primary_plist);
3339
3340 } else if (hduclas2 && !strcmp(hduclas2, "ERROR")) {
3341 err = enu_load_component(mefs->mef[i], "SCIERR",
3342 "IMAGE", "ERROR");
3343 enu_check_error_code("accessing SCIERR extension");
3344 } else if (hduclas2 && !strcmp(hduclas2, "QUALITY")) {
3345 qual = enu_load_component(mefs->mef[i], "QUALDATA",
3346 "IMAGE", "QUALITY");
3347 enu_check_error_code("accessing QUALDATA extension");
3348 } else if (hduclas2 && !strcmp(hduclas2, "CONF")) {
3349 conf = enu_load_component(mefs->mef[i], "CONFDATA",
3350 "IMAGE", "CONF");
3351 enu_check_error_code("accessing CONFDATA extension");
3352 } else if (hduclas2 && !strcmp(hduclas2, "BKG_DATA")) {
3353 bkg = enu_load_component(mefs->mef[i], "BKGDATA",
3354 "IMAGE", "BKG_DATA");
3355 enu_check_error_code("accessing BKGDATA extension");
3356 } else if (hduclas2 && !strcmp(hduclas2, "BKG_ERR")) {
3357 bkg_err = enu_load_component(mefs->mef[i], "BKGERR",
3358 "IMAGE", "BKG_ERR");
3359 enu_check_error_code("accessing BKGERR extension");
3360 } else if (hduclas2 && !strcmp(hduclas2, "BKG_CONF")) {
3361 bkg_conf = enu_load_component(mefs->mef[i], "BKGCONF",
3362 "IMAGE", "BKG_CONF");
3363 enu_check_error_code("accessing BKGCONF extension");
3364 }
3365 }
3366*/
3367 /* set the data mask from quality, construct the hdrl image */
3368/*
3369 enu_check(data != NULL, CPL_ERROR_BAD_FILE_FORMAT,
3370 "no data in file");
3371 cpl_mask * bpm = cpl_image_get_bpm(data);
3372 cpl_mask_threshold_image(bpm, qual, 0.9, 1.1, CPL_BINARY_1);
3373 bpm = cpl_image_get_bpm(err);
3374 cpl_mask_threshold_image(bpm, qual, 0.9, 1.1, CPL_BINARY_1);
3375 hdrl_image * hdata = hdrl_image_create(data, err);
3376 hdrl_image * hbkg = NULL;
3377 if (bkg) {
3378 hbkg = hdrl_image_create(bkg, bkg_err);
3379 }
3380
3381 limage = enu_located_image_new(hdata, NULL, conf, hbkg,
3382 bkg_conf,
3383 plist, NULL, NULL, NULL, NULL,
3384 cpl_frame_duplicate(frame));
3385 plist = NULL;
3386 cpl_image_delete(data);
3387 cpl_image_delete(err);
3388 cpl_image_delete(qual);
3389 cpl_image_delete(bkg);
3390 cpl_image_delete(bkg_err);
3391 data = NULL;
3392 err = NULL;
3393 qual = NULL;
3394 conf = NULL;
3395 bkg = NULL;
3396 bkg_err = NULL;
3397 bkg_conf = NULL;
3398 }
3399 if(frame_format != NULL) {
3400 cpl_free(frame_format);
3401 }
3402 if(first_ext != NULL) {
3403 cpl_free(first_ext);
3404 }
3405*/
3406 /* insert new located_image into list */
3407
3408 enu_located_imagelist_insert(result, limage, position);
3409
3410 /* Update used_frameset */
3411
3412 cpl_frame * dup_frame = cpl_frame_duplicate(frame);
3413 cpl_frameset_insert(used, dup_frame);
3414
3415 position++;
3416 }
3417 }
3418
3419 //cleanup:
3420
3421 cpl_propertylist_delete(plist);
3422 cpl_image_delete(data);
3423 cpl_image_delete(err);
3424 cpl_image_delete(qual);
3425 cpl_image_delete(conf);
3426 cpl_image_delete(bkg);
3427 cpl_image_delete(bkg_err);
3428 cpl_image_delete(bkg_conf);
3430 cpl_frameset_iterator_delete(frameset_iter);
3431 if (cpl_error_get_code() != CPL_ERROR_NONE) {
3433 result = NULL;
3434 }
3435
3436 return result;
3437}
3438
3439
3440/*----------------------------------------------------------------------------*/
3452/*----------------------------------------------------------------------------*/
3453
3454cpl_image * enu_load_component(mef_extension * mef,
3455 const char * dps_name,
3456 const char * hduclas1,
3457 const char * hduclas2) {
3458
3459 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3460 cpl_ensure(mef, CPL_ERROR_NULL_INPUT, NULL);
3461 cpl_ensure(dps_name, CPL_ERROR_NULL_INPUT, NULL);
3462 cpl_ensure(hduclas1, CPL_ERROR_NULL_INPUT, NULL);
3463 cpl_ensure(hduclas2, CPL_ERROR_NULL_INPUT, NULL);
3464
3465 cpl_image * result = NULL;
3466
3467 cpl_propertylist * plist = mef->plist;
3468 const char * hduclass = cpl_propertylist_get_string(plist, "HDUCLASS");
3469 const char * hdudoc = cpl_propertylist_get_string(plist, "HDUDOC");
3470 //const char * hduvers = cpl_propertylist_get_string(plist, "HDUVERS");
3471 const char * my_hduclas1 = cpl_propertylist_get_string(plist, "HDUCLAS1");
3472 const char * my_hduclas2 = cpl_propertylist_get_string(plist, "HDUCLAS2");
3473
3474 enu_check(strstr(hduclass, "ESO") != NULL &&
3475 strstr(hdudoc, "SDP") != NULL &&
3476 //strstr(hduvers, "SDP version 8") != NULL &&
3477 strstr(my_hduclas1, hduclas1) != NULL &&
3478 strstr(my_hduclas2, hduclas2) != NULL,
3479 CPL_ERROR_BAD_FILE_FORMAT, "bad %s format", dps_name);
3480
3481 result = mef->data;
3482
3483 cleanup:
3484 if (cpl_error_get_code() != CPL_ERROR_NONE) {
3485 result = NULL;
3486 }
3487 if (result != NULL) mef->data = NULL;
3488
3489 return result;
3490}
3491
3492
3493/*----------------------------------------------------------------------------*/
3501/*----------------------------------------------------------------------------*/
3502
3503void enu_located_imagelist_delete(located_imagelist * limlist) {
3504
3505 if (limlist) {
3506 for (cpl_size i = 0; i < limlist->size; i++) {
3507 enu_located_image_delete(limlist->limages[i]);
3508 }
3509 cpl_free(limlist->limages);
3510 cpl_free(limlist);
3511 }
3512}
3513
3514
3515/*----------------------------------------------------------------------------*/
3523/*----------------------------------------------------------------------------*/
3524
3526 const located_imagelist * limlist) {
3527
3528 cpl_ensure(limlist, CPL_ERROR_NULL_INPUT, NULL);
3529
3530 located_imagelist * result = enu_located_imagelist_new(limlist->size);
3531 for (cpl_size i = 0; i < limlist->size; i++) {
3534 limlist->limages[i]), i);
3535 }
3536
3537 return result;
3538}
3539
3540
3541/*----------------------------------------------------------------------------*/
3552/*----------------------------------------------------------------------------*/
3553
3554cpl_error_code enu_located_imagelist_insert(located_imagelist * limlist,
3555 located_image * limage,
3556 cpl_size position) {
3557
3558 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
3559
3560 /* position valid? */
3561
3562 cpl_ensure_code(position >= 0 && position < limlist->size,
3563 CPL_ERROR_ACCESS_OUT_OF_RANGE);
3564 limlist->limages[position] = limage;
3565
3566 return cpl_error_get_code();
3567}
3568
3569
3570/*----------------------------------------------------------------------------*/
3579/*----------------------------------------------------------------------------*/
3580
3581located_imagelist * enu_located_imagelist_new(cpl_size size) {
3582
3583 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3584
3585 located_imagelist * limlist = cpl_malloc(sizeof(located_imagelist));
3586 limlist->size = size;
3587 limlist->limages = cpl_calloc(size, sizeof(located_image));
3588 for (cpl_size i = 0; i < limlist->size; i++) {
3589 limlist->limages[i] = NULL;
3590 }
3591 return limlist;
3592}
3593
3594
3595/*----------------------------------------------------------------------------*/
3603/*----------------------------------------------------------------------------*/
3604
3605void enu_mef_extension_delete(mef_extension * mef) {
3606
3607 if (mef) {
3608 if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_IMAGE)) {
3609 cpl_image_delete((cpl_image *) (mef->data));
3610 } else if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_MASK)) {
3611 cpl_mask_delete((cpl_mask *) mef->data);
3612 } else if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_TABLE)) {
3613 cpl_table_delete((cpl_table *) mef->data);
3614 } else if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_VECTOR)) {
3615 cpl_vector_delete((cpl_vector *) mef->data);
3616 } else {
3617 cpl_error_set("enu_mef_extension_delete",
3618 CPL_ERROR_UNSUPPORTED_MODE);
3619 }
3620 cpl_propertylist_delete(mef->plist);
3621 cpl_free(mef->name);
3622 cpl_free(mef);
3623 }
3624}
3625
3626
3627/*----------------------------------------------------------------------------*/
3635/*----------------------------------------------------------------------------*/
3636
3637void enu_mef_extension_list_delete(mef_extension_list * list) {
3638
3639 if (list) {
3640 for (cpl_size i = 0; i < list->size; i++) {
3641 enu_mef_extension_delete(list->mef[i]);
3642 }
3643 cpl_free(list->mef);
3644 cpl_free(list);
3645 }
3646}
3647
3648
3649/*----------------------------------------------------------------------------*/
3659/*----------------------------------------------------------------------------*/
3660
3661cpl_mask * enu_mef_extension_list_get_mask(mef_extension_list * meflist,
3662 const char * target) {
3663
3664 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3665
3666 cpl_ensure(meflist, CPL_ERROR_NULL_INPUT, NULL);
3667 cpl_ensure(target, CPL_ERROR_NULL_INPUT, NULL);
3668
3669 /* Search for extension */
3670
3671 cpl_mask * result = NULL;
3672 for (int i=0; i<meflist->size; i++) {
3673 if (!strcmp(meflist->mef[i]->name, target)) {
3674 cpl_ensure(!strcmp(meflist->mef[i]->data_type,
3675 MEF_EXTENSION_CONTAINING_MASK),
3676 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
3677 result = cpl_mask_duplicate((const cpl_mask *) meflist->mef[i]->data);
3678 break;
3679 }
3680 }
3681
3682 /* Check that the extensions was found */
3683
3684 cpl_ensure(result, CPL_ERROR_DATA_NOT_FOUND, NULL);
3685
3686 return result;
3687}
3688
3689
3690/*----------------------------------------------------------------------------*/
3699/*----------------------------------------------------------------------------*/
3700
3701mef_extension_list * enu_mef_extension_list_new(cpl_size size) {
3702
3703 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3704
3705 mef_extension_list * mef_list = cpl_malloc(sizeof(mef_extension_list));
3706 mef_list->size = size;
3707 mef_list->mef = cpl_calloc(size, sizeof(mef_extension));
3708 for (cpl_size i = 0; i < size; i++) {
3709 mef_list->mef[i] = NULL;
3710 }
3711
3712 return mef_list;
3713}
3714
3715
3716/*----------------------------------------------------------------------------*/
3730/*----------------------------------------------------------------------------*/
3731
3732mef_extension * enu_mef_new_image(const char * name,
3733 const cpl_image * data,
3734 const cpl_propertylist * plist) {
3735
3736 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3737
3738 /* check parameters */
3739
3740 cpl_ensure(name && data, CPL_ERROR_NULL_INPUT, NULL);
3741
3742 mef_extension * result = cpl_malloc(sizeof(mef_extension));
3743 result->name = cpl_strdup(name);
3744 result->data = (void *) cpl_image_duplicate(data);
3745 result->data_type = MEF_EXTENSION_CONTAINING_IMAGE;
3746 if (plist) {
3747 result->plist = cpl_propertylist_duplicate(plist);
3748 } else {
3749 result->plist = NULL;
3750 }
3751 return result;
3752}
3753
3754
3755/*----------------------------------------------------------------------------*/
3769/*----------------------------------------------------------------------------*/
3770
3771mef_extension * enu_mef_new_mask(const char * name,
3772 const cpl_mask * data,
3773 const cpl_propertylist * plist) {
3774
3775 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3776
3777 /* check parameters */
3778
3779 cpl_ensure(name && data, CPL_ERROR_NULL_INPUT, NULL);
3780
3781 mef_extension * result = cpl_malloc(sizeof(mef_extension));
3782 result->name = cpl_strdup(name);
3783 result->data = (void *) cpl_mask_duplicate(data);
3784 result->data_type = MEF_EXTENSION_CONTAINING_MASK;
3785 if (plist) {
3786 result->plist = cpl_propertylist_duplicate(plist);
3787 } else {
3788 result->plist = NULL;
3789 }
3790 return result;
3791}
3792
3793
3794/*----------------------------------------------------------------------------*/
3808/*----------------------------------------------------------------------------*/
3809
3810mef_extension * enu_mef_new_table(const char * name,
3811 const cpl_table * table,
3812 const cpl_propertylist * plist) {
3813
3814 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3815 cpl_ensure(name, CPL_ERROR_NULL_INPUT, NULL);
3816 cpl_ensure(table, CPL_ERROR_NULL_INPUT, NULL);
3817
3818 mef_extension * result = cpl_malloc(sizeof(mef_extension));
3819 result->name = cpl_strdup(name);
3820 result->data = (void *) cpl_table_duplicate(table);
3821 result->plist = NULL;
3822 if (plist) {
3823 result->plist = cpl_propertylist_duplicate(plist);
3824 } else {
3825 result->plist = NULL;
3826 }
3827 result->data_type = MEF_EXTENSION_CONTAINING_TABLE;
3828
3829 return result;
3830}
3831
3832
3833/*----------------------------------------------------------------------------*/
3847/*----------------------------------------------------------------------------*/
3848
3849mef_extension * enu_mef_new_vector(const char * name,
3850 const cpl_vector * vector,
3851 const cpl_propertylist * plist) {
3852
3853 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3854 cpl_ensure(name, CPL_ERROR_NULL_INPUT, NULL);
3855 cpl_ensure(vector, CPL_ERROR_NULL_INPUT, NULL);
3856
3857 mef_extension * result = cpl_malloc(sizeof(mef_extension));
3858 result->name = cpl_strdup(name);
3859 result->data = (void *) cpl_vector_duplicate(vector);
3860 result->plist = NULL;
3861 if (plist) {
3862 result->plist = cpl_propertylist_duplicate(plist);
3863 } else {
3864 result->plist = NULL;
3865 }
3866 result->data_type = MEF_EXTENSION_CONTAINING_VECTOR;
3867
3868 return result;
3869}
3870
3871
3872/*----------------------------------------------------------------------------*/
3884/*----------------------------------------------------------------------------*/
3885
3886cpl_error_code enu_mef_extension_save(const mef_extension * mef,
3887 const char * filename,
3888 const cpl_propertylist * plist,
3889 unsigned mode) {
3890
3891 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
3892
3893 cpl_msg_debug(cpl_func, "enu_mef_extension_save entry");
3894
3895 cpl_propertylist * plist_copy = NULL;
3896
3897 /* check parameters, only one of the data types can be set */
3898
3899 cpl_ensure_code(mef, CPL_ERROR_NULL_INPUT);
3900 cpl_ensure_code(filename, CPL_ERROR_NULL_INPUT);
3901 cpl_ensure_code(plist, CPL_ERROR_NULL_INPUT);
3902
3903 plist_copy = cpl_propertylist_duplicate(plist);
3904 cpl_propertylist_update_string(plist_copy, "ERIS_NIX_MEF_TYPE",
3905 mef->data_type);
3906
3907 if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_IMAGE)) {
3908 if (cpl_propertylist_has(plist, "CD3_3")) {
3909 //double cd3_3 = cpl_propertylist_get_double(plist, "CD3_3");
3910
3911 /* the existence of CD3_3 in the header means that this
3912 data has ndim=3. In the LSS case that 3rd
3913 dimension is degenerate but allows the wcs decription to
3914 work.
3915
3916 To get CPL to store NDIM=3 we have to store the
3917 2d data as one image in an imagelist. */
3918
3919 cpl_msg_info(cpl_func, "..saving data with NDIM=3");
3920
3921 cpl_imagelist * imlist = cpl_imagelist_new();
3922 cpl_imagelist_set(imlist, mef->data, 0);
3923 cpl_imagelist_save(imlist,
3924 filename,
3925 CPL_TYPE_UNSPECIFIED,
3926 plist_copy,
3927 mode);
3928 /* let image data be deleted with mef */
3929 cpl_imagelist_unset(imlist, 0);
3930 cpl_imagelist_delete(imlist);
3931
3932 } else {
3933 cpl_image_save((const cpl_image *) (mef->data),
3934 filename,
3935 CPL_TYPE_UNSPECIFIED,
3936 plist_copy,
3937 mode);
3938 }
3939 } else if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_MASK)) {
3940 cpl_mask_save((const cpl_mask *) (mef->data),
3941 filename,
3942 plist_copy,
3943 mode);
3944 } else if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_TABLE)) {
3945 cpl_table_save((const cpl_table *) (mef->data),
3946 NULL,
3947 plist_copy,
3948 filename,
3949 mode);
3950 } else if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_VECTOR)) {
3951 cpl_vector_save((const cpl_vector *) (mef->data),
3952 filename,
3953 CPL_TYPE_DOUBLE,
3954 plist_copy,
3955 mode);
3956 } else {
3957 cpl_error_set_message("enu_mef_extension_save",
3958 CPL_ERROR_UNSUPPORTED_MODE,
3959 "unsupported extension type: %s", mef->data_type);
3960 }
3961
3962 cpl_propertylist_delete(plist_copy);
3963
3964 return cpl_error_get_code();
3965}
3966
3967
3968/*----------------------------------------------------------------------------*/
3982/*----------------------------------------------------------------------------*/
3983
3984cpl_error_code enu_opm_limlist(const int obj_min_pixels,
3985 const double obj_threshold,
3986 const int bkg_mesh_size,
3987 const double bkg_smooth_fwhm,
3988 located_imagelist * limlist) {
3989
3990 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
3991
3992 /* parameter check */
3993
3994 cpl_ensure_code(limlist, CPL_ERROR_NULL_INPUT);
3995
3996 casu_fits ** indata = NULL;
3997 casu_fits ** inconf = NULL;
3998 casu_fits ** invar = NULL;
3999
4000 /* translate located_imagelist to casu_fits components */
4001
4002 encu_limlist_to_casu_fits(limlist, &indata, &inconf, &invar);
4003
4004 /* loop through the located_images, calculate the object mask
4005 for each, copy that mask to the object_mask in the located_image */
4006
4007 int casu_status = CASU_OK;
4008 int niter = 3;
4009
4010 cpl_msg_info(cpl_func, ".. calculating object masks");
4011 for (cpl_size j = 0; j < limlist->size; j++) {
4012 casu_opm(indata[j], inconf[j], obj_min_pixels, obj_threshold,
4013 bkg_mesh_size, bkg_smooth_fwhm, niter, &casu_status);
4014 enu_check(casu_status == CASU_OK, CPL_ERROR_UNSPECIFIED,
4015 "CASU error calculating object mask");
4016 limlist->limages[j]->object_mask = cpl_mask_duplicate(
4017 cpl_image_get_bpm(indata[j]->image));
4018 }
4019
4020 cleanup:
4021
4022 for (cpl_size j = 0; j < limlist->size; j++) {
4023 casu_fits_delete(indata[j]);
4024 casu_fits_delete(inconf[j]);
4025 casu_fits_delete(invar[j]);
4026 }
4027 cpl_free(indata);
4028 cpl_free(inconf);
4029 cpl_free(invar);
4030
4031 return cpl_error_get_code();
4032}
4033
4034
4035/*----------------------------------------------------------------------------*/
4051/*----------------------------------------------------------------------------*/
4052
4053cpl_error_code enu_opm_lss_limlist(located_imagelist * limlist,
4054 const int nsigma_cut) {
4055
4056 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
4057 cpl_ensure_code(limlist, CPL_ERROR_NULL_INPUT);
4058
4059 cpl_msg_info(cpl_func, "..calculating LSS object pixel mask");
4060
4061 /* loop through the located_images, calculate the object mask
4062 for each, copy that mask to the object_mask in the located_image */
4063
4064 for (cpl_size j = 0; j < limlist->size; j++) {
4065 cpl_size nx = hdrl_image_get_size_x(limlist->limages[j]->himage);
4066 cpl_size ny = hdrl_image_get_size_y(limlist->limages[j]->himage);
4067 cpl_image * collapsed = cpl_image_collapse_median_create(
4069 limlist->limages[j]->himage), 0, 0, 0);
4070
4071 /* mask for pixels that are unusually high */
4072
4073 double csigma = 0.0;
4074 double cmedian = cpl_image_get_median_dev(collapsed, &csigma);
4075 double maxval = cpl_image_get_max(collapsed);
4076 cpl_mask * collapsed_opm = cpl_mask_threshold_image_create(
4077 collapsed, cmedian + nsigma_cut * csigma,
4078 2.0 * maxval);
4079
4080 /* 'grow' the masked areas to try and catch lower level emission */
4081
4082 cpl_mask * kernel = cpl_mask_new(11, 1);
4083 cpl_mask_not(kernel);
4084 cpl_mask * dilated_collapsed_opm = cpl_mask_new(nx, 1);
4085 cpl_mask_filter(dilated_collapsed_opm, collapsed_opm, kernel,
4086 CPL_FILTER_DILATION, CPL_BORDER_NOP);
4087 cpl_mask_delete(kernel);
4088
4089 /* grow the 1d mask to a 2d image */
4090
4091 const cpl_binary * collapsed_opm_data = cpl_mask_get_data_const(
4092 dilated_collapsed_opm);
4093 cpl_mask * opm = cpl_mask_new(nx, ny);
4094 cpl_binary * opm_data = cpl_mask_get_data(opm);
4095 for (cpl_size iy=0; iy < ny; iy++) {
4096 memcpy(opm_data + iy * (nx * sizeof(*opm_data)),
4097 collapsed_opm_data,
4098 nx * sizeof(*opm_data));
4099 }
4100
4101 /* set the object_mask of the located_image */
4102
4103 cpl_mask_delete(limlist->limages[j]->object_mask);
4104 limlist->limages[j]->object_mask = opm;
4105
4106 cpl_image_delete(collapsed);
4107 cpl_mask_delete(collapsed_opm);
4108 cpl_mask_delete(dilated_collapsed_opm);
4109 }
4110
4111 return cpl_error_get_code();
4112}
4113
4114
4115/*----------------------------------------------------------------------------*/
4128/*----------------------------------------------------------------------------*/
4129
4130cpl_error_code enu_correct_wcs(const cpl_table * refcat,
4131 const char * wcs_method,
4132 const char * catalogue,
4133 located_image * limage,
4134 const double match_rad,
4135 cpl_table ** matched_stds,
4136 cpl_matrix ** xy_shift) {
4137
4138 cpl_matrix * celestial = NULL;
4139 cpl_array * colnames = NULL;
4140 cpl_array * conv_status = NULL;
4141 cpl_table * refcat_copy = NULL;
4142 cpl_matrix * ref_phys = NULL;
4143 cpl_matrix * ref_world = NULL;
4144 cpl_matrix * xy = NULL;
4145 cpl_wcs * wcs = NULL;
4146
4147 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
4148
4149 cpl_msg_info(cpl_func, "correcting %s", cpl_frame_get_filename(limage->frame));
4150
4151 *xy_shift = NULL;
4152
4153 cpl_msg_info(cpl_func, " ..%s", cpl_frame_get_filename(limage->frame));
4154
4155 /* calculate predicted positions of refcat objects for this wcs */
4156
4157 cpl_size nref = cpl_table_get_nrow(refcat);
4158 const double * ra = cpl_table_get_data_double_const(refcat, "RA");
4159 const double * dec = NULL;
4160 if (cpl_table_has_column(refcat, "DEC")) {
4161 dec = cpl_table_get_data_double_const(refcat, "DEC");
4162 }
4163 ref_world = cpl_matrix_new(nref, 2);
4164 for (cpl_size iobj = 0; iobj < nref; iobj++) {
4165 cpl_matrix_set(ref_world, iobj, 0, ra[iobj]);
4166 cpl_matrix_set(ref_world, iobj, 1, dec[iobj]);
4167 }
4168 wcs = cpl_wcs_new_from_propertylist(limage->plist);
4169 cpl_wcs_convert(wcs, ref_world, &ref_phys, &conv_status,
4170 CPL_WCS_WORLD2PHYS);
4171 enu_check_error_code("failure calculating predicted positions");
4172
4173 /* Store the predicted positions in columns of a duplicate refcat
4174 but with all columns removed except RA, DEC, 'Std index',
4175 Aper_flux_3 */
4176
4177 refcat_copy = cpl_table_duplicate(refcat);
4178 colnames = cpl_table_get_column_names(refcat_copy);
4179 cpl_size ncol = cpl_array_get_size(colnames);
4180 for (cpl_size ic = 0; ic < ncol; ic++) {
4181 const char * colname = cpl_array_get_string(colnames, ic);
4182 if (strcmp(colname, "RA") &&
4183 strcmp(colname, "DEC") &&
4184 strcmp(colname, "Aper_flux_3") &&
4185 strcmp(colname, "Std index")) {
4186 cpl_table_erase_column(refcat_copy, colname);
4187 }
4188 }
4189
4190 /* add xpredict and ypredict columns */
4191
4192 cpl_table_new_column(refcat_copy, "xpredict", CPL_TYPE_DOUBLE);
4193 cpl_table_new_column(refcat_copy, "ypredict", CPL_TYPE_DOUBLE);
4194 for (cpl_size iobj = 0; iobj < nref; iobj++) {
4195 cpl_table_set_double(refcat_copy, "xpredict", iobj,
4196 cpl_matrix_get(ref_phys, iobj, 0));
4197 cpl_table_set_double(refcat_copy, "ypredict", iobj,
4198 cpl_matrix_get(ref_phys, iobj, 1));
4199 }
4200 enu_check_error_code("failure while creating predicted positions");
4201
4202 /* Match detected sources with refcat_copy */
4203
4204 cpl_msg_info(cpl_func, " ..matching sources");
4205 cpl_size nobj = 0;
4206 if (limage->objects && limage->objects->catalogue) {
4207 nobj = cpl_table_get_nrow(limage->objects->catalogue);
4208 }
4209
4210 if (min(nref, nobj) > 0) {
4211
4212 cpl_msg_info(cpl_func, " ..calling enm_try_all_associations");
4213
4214 enm_try_all_associations(limage->objects->catalogue,
4215 refcat_copy,
4216 match_rad,
4217 matched_stds);
4218 enu_check_error_code("enu_correct_wcs failure at "
4219 "try_all_associations");
4220
4221 enm_correct_crpix(wcs_method,
4222 catalogue,
4223 *matched_stds,
4224 limage,
4225 xy_shift);
4226 enu_check_error_code("failure to correct wcs");
4227
4228 } else {
4229 cpl_msg_info(cpl_func, " ..no catalogued objects, cannot correct wcs");
4230 }
4231
4232 cleanup:
4233 cpl_matrix_delete(celestial);
4234 cpl_array_delete(colnames);
4235 cpl_array_delete(conv_status);
4236 cpl_table_delete(refcat_copy);
4237 cpl_matrix_delete(ref_phys);
4238 cpl_matrix_delete(ref_world);
4239 cpl_matrix_delete(xy);
4240 cpl_wcs_delete(wcs);
4241
4242 return cpl_error_get_code();
4243}
4244
4245
4246/*----------------------------------------------------------------------------*/
4256/*----------------------------------------------------------------------------*/
4257
4258cpl_error_code enu_modify_CD_matrix(located_image * limage,
4259 const cpl_table * refine_wcs) {
4260
4261 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
4262 cpl_ensure_code(limage, CPL_ERROR_NULL_INPUT);
4263
4264 if (!refine_wcs) return CPL_ERROR_NONE;
4265
4266 const char * camera = cpl_propertylist_get_string(limage->plist,
4267 "ESO INS2 NXCW NAME");
4268 enu_check(camera != NULL,
4269 CPL_ERROR_ILLEGAL_INPUT,
4270 "failed to read NIX camera from ESO.INS2.NXCW.NAME");
4271
4272 cpl_size nrow = cpl_table_get_nrow(refine_wcs);
4273 cpl_boolean match = CPL_FALSE;
4274
4275 double cd1_1 = 0.0;
4276 double cd1_2 = 0.0;
4277 double cd2_1 = 0.0;
4278 double cd2_2 = 0.0;
4279
4280 for (cpl_size row = 0; row < nrow; row++) {
4281 const char * row_cam = cpl_table_get_string(refine_wcs, "camera", row);
4282
4283 if (!strcmp(camera, row_cam)) {
4284 match = CPL_TRUE;
4285
4286 int ignore = 0;
4287 cd1_1 = cpl_table_get_double(refine_wcs, "CD1_1", row, &ignore);
4288 cd1_2 = cpl_table_get_double(refine_wcs, "CD1_2", row, &ignore);
4289 cd2_1 = cpl_table_get_double(refine_wcs, "CD2_1", row, &ignore);
4290 cd2_2 = cpl_table_get_double(refine_wcs, "CD2_2", row, &ignore);
4291 /*
4292 cpl_msg_info(cpl_func,
4293 "camera %s %s cd1_1 %10.8e cd1_2 %10.8e cd2_1 %10.8e cd2_2 %10.8e",
4294 camera, row_cam, cd1_1, cd1_2, cd2_1, cd2_2);
4295 */
4296 cpl_propertylist_update_double(limage->plist, "CD1_1", cd1_1);
4297 cpl_propertylist_update_double(limage->plist, "CD1_2", cd1_2);
4298 cpl_propertylist_update_double(limage->plist, "CD2_1", cd2_1);
4299 cpl_propertylist_update_double(limage->plist, "CD2_2", cd2_2);
4300 }
4301 }
4302
4303 if (!match) {
4304 cpl_error_set_message(cpl_func,
4305 CPL_ERROR_ILLEGAL_INPUT,
4306 "camera name not matched: %s",
4307 camera);
4308 } else {
4309 cd1_1 = cpl_propertylist_get_double(limage->plist, "CD1_1");
4310 cd1_2 = cpl_propertylist_get_double(limage->plist, "CD1_2");
4311 cd2_1 = cpl_propertylist_get_double(limage->plist, "CD2_1");
4312 cd2_2 = cpl_propertylist_get_double(limage->plist, "CD2_2");
4313 cpl_msg_info(cpl_func, "..set CD matrix cd1_1=%10.8e cd1_2=%10.8e "
4314 "cd_2_1=%10.8e cd2_2=%10.8e",
4315 cd1_1, cd1_2, cd2_1, cd2_2);
4316 }
4317
4318 cleanup:
4319
4320 return cpl_error_get_code();
4321}
4322
4323
4324/*----------------------------------------------------------------------------*/
4334/*----------------------------------------------------------------------------*/
4335
4336cpl_error_code enu_normalise_confidence(cpl_image * confidence) {
4337
4338 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
4339 cpl_ensure_code(confidence, CPL_ERROR_NULL_INPUT);
4340
4341 const cpl_size nx = cpl_image_get_size_x(confidence);
4342 const cpl_size ny = cpl_image_get_size_y(confidence);
4343 double * data = cpl_image_get_data_double(confidence);
4344 /* Avoid creation + checking of empty bpm */
4345 const cpl_mask * bpm = cpl_image_get_bpm_const(confidence);
4346 cpl_mask * mask = bpm ? cpl_image_get_bpm(confidence) : NULL;
4347 cpl_binary * mask_data = bpm ? cpl_mask_get_data(mask) : NULL;
4348
4349 double sum = 0.0;
4350 int nonzero = 0;
4351
4352 for (cpl_size i = 0; i < nx*ny; i++) {
4353 if (mask_data != NULL && mask_data[i] == CPL_TRUE) {
4354 mask_data[i] = CPL_FALSE;
4355 data[i] = 0.0;
4356 }
4357 if (data[i] < 0.0) data[i] = 0.0;
4358 sum += data[i];
4359 if (data[i] > 0.0) nonzero++;
4360 }
4361
4362 if (sum > 0.0) {
4363 cpl_image_multiply_scalar(confidence, 100.0 * (double)nonzero / sum);
4364 }
4365
4366 return cpl_error_get_code();
4367}
4368
4369
4370/*----------------------------------------------------------------------------*/
4404/*----------------------------------------------------------------------------*/
4405
4406
4407cpl_error_code enu_remove_read_offsets(hdrl_image * himage,
4408 const cpl_propertylist * plist,
4409 cpl_image * confidence,
4410 const int set_confidence) {
4411
4412 cpl_image * himg = hdrl_image_get_image(himage);
4413 cpl_image * eimg = hdrl_image_get_error(himage);
4414 double * hdata = cpl_image_get_data_double(himg);
4415 double * edata = cpl_image_get_data_double(eimg);
4416 cpl_binary* hbpm = cpl_mask_get_data(cpl_image_get_bpm(himg));
4417 cpl_binary* ebpm = cpl_mask_get_data(cpl_image_get_bpm(eimg));
4418 const int mx = cpl_image_get_size_x(himg);
4419 cpl_boolean is_fast_uncorr = CPL_FALSE;
4420 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
4421
4422 /* check that the image data is double */
4423 cpl_ensure_code(hdata != NULL, CPL_ERROR_UNSUPPORTED_MODE);
4424 cpl_ensure_code(edata != NULL, CPL_ERROR_UNSUPPORTED_MODE);
4425 cpl_ensure_code(hbpm != NULL, CPL_ERROR_UNSUPPORTED_MODE);
4426 cpl_ensure_code(ebpm != NULL, CPL_ERROR_UNSUPPORTED_MODE);
4427
4428 cpl_ensure_code(plist, CPL_ERROR_NULL_INPUT);
4429
4430 /* get window information */
4431
4432 cpl_size nx = 0;
4433 cpl_size ny = 0;
4434 int rot = 0;
4435 cpl_size strx = 0;
4436 cpl_size stry = 0;
4437 cpl_size nx_chip = 0;
4438 cpl_size ny_chip = 0;
4439 cpl_boolean windowed = 0;
4441 &ny,
4442 &rot,
4443 &strx,
4444 &stry,
4445 &nx_chip,
4446 &ny_chip,
4447 &windowed,
4448 plist);
4449 enu_check_error_code("failed to read detector window information");
4450
4451 /* determine whether bottom edge of detector is corrupted by
4452 problem with short DITDELAY. Base this on the MJD of the
4453 observation - the fix was applied around 1-Mar-2023 = MJD 60004 */
4454
4455 double mjd = cpl_propertylist_get_double(plist, "MJD-OBS");
4456 enu_check_error_code("failed to read MJD-OBS");
4457 if (mjd <= 60004) {
4458 cpl_msg_info(cpl_func, "PIPE-10417 DITDELAY bug, "
4459 "remove_read_offsets will ignore bottom 4 rows "
4460 "of chip");
4461 }
4462 const char * curr_name = cpl_propertylist_get_string(plist, "ESO DET READ CURNAME");
4463 if (strcmp(curr_name, "FAST_UNCORR") == 0) {
4464 is_fast_uncorr = CPL_TRUE;
4465 }
4466 cpl_size top_width = 4;
4467 cpl_size bottom_width = 4;
4468 cpl_msg_debug(cpl_func,
4469 "..offsets from %d top rows and %d bottom rows of chip",
4470 (int) top_width, (int) bottom_width);
4471
4472 cpl_size nread_chan = nx_chip / 64;
4473
4474 /* Calculate and remove the read offsets */
4475 /* ..loop through the read channels */
4476 cpl_vector* voff = cpl_vector_new(nread_chan);
4477 double* pvoff = cpl_vector_get_data(voff);
4478 for (cpl_size read_chan = 0; read_chan < nread_chan; read_chan++) {
4479
4480 /* calculate the offsets */
4481
4482 cpl_array * offset_data = cpl_array_new(0, CPL_TYPE_DOUBLE);
4483 cpl_size ndata = 0;
4484
4485 for (cpl_size x = 64 * read_chan; x < 64 * (read_chan+1); x++) {
4486
4487 /* are we in the x window */
4488 /* window/pixel coords are 1-based, C index 0-based */
4489
4490 if (x+1 >= strx && x+1 < strx+nx) {
4491
4492 for (cpl_size y = 0; y < bottom_width; y++) {
4493
4494 /* are we in the y window */
4495
4496 if (y+1 >= stry && y+1 < stry+ny) {
4497 const int ipos = x-strx+1 + mx * (y-stry+1);
4498
4499 if (!hbpm[ipos]) {
4500 if (mjd > 60004) {
4501 const double pixval = hdata[ipos];
4502 /* bottom channels OK, include them in
4503 offsets */
4504 ndata++;
4505 cpl_array_set_size(offset_data, ndata);
4506 cpl_array_set(offset_data, ndata-1, pixval);
4507 }
4508 /* reject the bottom channels for subsequent use */
4509 hbpm[ipos] = CPL_BINARY_1;
4510 ebpm[ipos] = CPL_BINARY_1;
4511
4512 if (set_confidence && confidence) {
4513 cpl_image_set(confidence,
4514 x-strx+2,
4515 y-stry+2,
4516 0.0);
4517 }
4518 }
4519 }
4520 }
4521
4522 for (cpl_size y = ny_chip-top_width; y < ny_chip; y++) {
4523 if (y+1 >= stry && y+1 < stry+ny) {
4524 const int ipos = x-strx+1 + mx * (y-stry+1);
4525
4526 if (!hbpm[ipos]) {
4527 const double pixval = hdata[ipos];
4528 ndata++;
4529 cpl_array_set_size(offset_data, ndata);
4530 cpl_array_set(offset_data, ndata-1, pixval);
4531 hbpm[ipos] = CPL_BINARY_1;
4532 ebpm[ipos] = CPL_BINARY_1;
4533 if (set_confidence && confidence) {
4534 cpl_image_set(confidence,
4535 x-strx+2,
4536 y-stry+2,
4537 0.0);
4538 }
4539 }
4540 }
4541 }
4542 }
4543 }
4544
4545 /* ..Remove the offset */
4546
4547 hdrl_value offset = {0.0, 0.0};
4548 if (ndata > 0) {
4549 cpl_msg_debug(cpl_func, "read_chan %d", (int)read_chan);
4550 cpl_msg_debug(cpl_func, "ndata %d", (int)ndata);
4551 cpl_msg_debug(cpl_func, "median %f", cpl_array_get_median(offset_data));
4552 cpl_msg_debug(cpl_func, "mean %f", cpl_array_get_mean(offset_data));
4553 cpl_msg_debug(cpl_func, "std %f", cpl_array_get_stdev(offset_data));
4554
4555 /* simple rejection of biggest outliers, there seem to be some
4556 hot pixels even in the unused borders of the chip */
4557
4558 double mean = cpl_array_get_mean(offset_data);
4559 double stdev = cpl_array_get_stdev(offset_data);
4560 int nflagged = 0;
4561 for (cpl_size i = 0; i < cpl_array_get_size(offset_data); i++) {
4562 int invalid = 0;
4563 double datum = cpl_array_get_double(offset_data, i, &invalid);
4564 if (!invalid && fabs(datum - mean) > 5 * stdev) {
4565 cpl_array_set_invalid(offset_data, i);
4566 nflagged++;
4567 }
4568 }
4569
4570 offset.data = cpl_array_get_mean(offset_data);
4571 offset.error = cpl_array_get_stdev(offset_data);
4572 pvoff[read_chan] = offset.data;
4573
4574 cpl_msg_debug(cpl_func, "..removing offset %f (%f) for read "
4575 "channel %d", offset.data, offset.error,
4576 (int) read_chan);
4577
4578 for (cpl_size x = 64 * read_chan; x < 64 * (read_chan+1); x++) {
4579 for (cpl_size y = 0; y < ny_chip; y++) {
4580
4581 if (x+1 >= strx && x+1 < strx+nx &&
4582 y+1 >= stry && y+1 < stry+ny) {
4583 const int ipos = x-strx+1 + mx * (y-stry+1);
4584
4585 if (!hbpm[ipos]) {
4586 hdata[ipos] -= offset.data;
4587 edata[ipos] = hypot(edata[ipos], offset.error);
4588 }
4589 }
4590 }
4591 }
4592 }
4593 cpl_array_delete(offset_data);
4594 }
4595
4596
4597 /* if fast mode add back offset of offsets */
4598 if(is_fast_uncorr) {
4599 cpl_image_add_scalar(himg,cpl_vector_get_mean(voff));
4600 }
4601
4602 /* reject blanked pixels at left/right edges of detector */
4603
4604 for (cpl_size y = 0; y < ny_chip; y++) {
4605 for (cpl_size x = 0; x < 4; x++) {
4606 /* in window? */
4607 if (x+1 >= strx && x+1 < strx+nx &&
4608 y+1 >= stry && y+1 < stry+ny) {
4609 const int ipos = x-strx+1 + mx * (y-stry+1);
4610
4611 hbpm[ipos] = CPL_BINARY_1;
4612 ebpm[ipos] = CPL_BINARY_1;
4613
4614 if (set_confidence && confidence) {
4615 cpl_image_set(confidence,
4616 x-strx+2,
4617 y-stry+2,
4618 0.0);
4619 }
4620 }
4621 }
4622 }
4623
4624 for (cpl_size y = 0; y < ny_chip; y++) {
4625 for (cpl_size x = nx_chip-4; x < nx_chip; x++) {
4626 /* in window? */
4627 if (x+1 >= strx && x+1 < strx+nx &&
4628 y+1 >= stry && y+1 < stry+ny) {
4629
4630 hdrl_image_reject(himage,
4631 x-strx+2,
4632 y-stry+2);
4633 if (set_confidence && confidence) {
4634 cpl_image_set(confidence,
4635 x-strx+2,
4636 y-stry+2,
4637 0.0);
4638 }
4639 }
4640 }
4641 }
4642
4643 cpl_vector_delete(voff);
4644 /* re-normalise the confidence array after the changes */
4645
4646 if (set_confidence && confidence) {
4647 enu_normalise_confidence(confidence);
4648 }
4649
4650 cleanup:
4651
4652 return cpl_error_get_code();
4653}
4654
4655
4656/*----------------------------------------------------------------------------*/
4663/*----------------------------------------------------------------------------*/
4664
4665char * enu_repreface(const char * filename,
4666 const char * preface) {
4667
4668 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
4669
4670 char * in_name = cpl_strdup(filename);
4671
4672 /* expect data files to start with either ERIS.20xx or NACO.20xx */
4673 char * pch = strstr(filename, "ERIS.20");
4674 if (!pch) {
4675 pch = strstr(filename, "NACO.20");
4676 }
4677
4678 char * outname = cpl_sprintf("%s.%s", preface, pch);
4679 cpl_free(in_name);
4680
4681 return outname;
4682}
4683
4684
4685/*----------------------------------------------------------------------------*/
4700/*----------------------------------------------------------------------------*/
4701
4702
4703cpl_error_code enu_sky_backgrounds(const char * method,
4704 const char * select_method,
4705 const double timerange,
4706 const located_imagelist * target_list,
4707 const located_imagelist * sky_list,
4708 const cpl_size x_probe,
4709 const cpl_size y_probe,
4710 hdrl_imagelist ** sky_himagelist,
4711 cpl_imagelist ** sky_confidence_list) {
4712
4713 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
4714
4715 cpl_image * contrib = NULL;
4716 hdrl_imagelist * skylist = NULL;
4717 cpl_image * sky_confidence = NULL;
4718 hdrl_image * sky_himage = NULL;
4719 cpl_vector * sky_indeces = NULL;
4720
4721 cpl_msg_debug(cpl_func, "enu_sky_backgrounds entry");
4722
4723 /* parameter validation */
4724
4725 cpl_ensure_code(method, CPL_ERROR_NULL_INPUT);
4726 cpl_ensure_code(select_method, CPL_ERROR_NULL_INPUT);
4727 cpl_ensure_code(target_list, CPL_ERROR_NULL_INPUT);
4728 cpl_ensure_code(sky_list, CPL_ERROR_NULL_INPUT);
4729 cpl_ensure_code(!strcmp(select_method, "bracket") &&
4730 (timerange > 0.0), CPL_ERROR_ILLEGAL_INPUT);
4731
4732 *sky_himagelist = hdrl_imagelist_new();
4733 *sky_confidence_list = cpl_imagelist_new();
4734
4735 /* some variables used for probe pixel debugging */
4736
4737 int debug = CPL_FALSE;
4738 cpl_vector * data = NULL;
4739 cpl_vector * error = NULL;
4740 cpl_vector * reject = NULL;
4741 cpl_vector * confidence = NULL;
4742
4743 cpl_msg_info(cpl_func, "..calculating skys");
4744
4745 /* loop through target images */
4746
4747 cpl_size njitters = target_list->size;
4748 for (cpl_size j = 0; j < njitters; j++) {
4749
4750 /* Get the indices of relevant sky images */
4751
4752 if (strstr(select_method, "bracket") != NULL) {
4753 sky_indeces = enu_bracket_skys(target_list->limages[j], timerange,
4754 sky_list, x_probe > -1);
4755 }
4756 enu_check_error_code("failure in enu_bracket_skys");
4757
4758 cpl_size skysize = cpl_vector_get_size(sky_indeces);
4759 debug = CPL_FALSE;
4760 if (x_probe > 0 && skysize > 0) {
4761 const cpl_size x_size = hdrl_image_get_size_x(
4762 sky_list->limages[0]->himage);
4763 const cpl_size y_size = hdrl_image_get_size_y(
4764 sky_list->limages[0]->himage);
4765 if (x_probe > 0 && x_probe <= x_size &&
4766 y_probe > 0 && y_probe <= y_size) {
4767 debug = CPL_TRUE;
4768 if (skysize > 0) {
4769 data = cpl_vector_new(skysize);
4770 error = cpl_vector_new(skysize);
4771 reject = cpl_vector_new(skysize);
4772 confidence = cpl_vector_new(skysize);
4773 }
4774 }
4775 }
4776
4777 if (strstr(method, "collapse-median") != NULL) {
4778
4779 /* construct an hdrl_imagelist of the jitters to be combined,
4780 accumulate coadd of confidence arrays, apply object_masks
4781 if such defined in the located_images */
4782
4783 skylist = hdrl_imagelist_new();
4784 for (int k = 0; k < (int)skysize; k++) {
4785 int i = (int)cpl_vector_get(sky_indeces, k);
4786 hdrl_image * imcopy = hdrl_image_duplicate(sky_list->
4787 limages[i]->himage);
4788 cpl_image * confcopy = cpl_image_duplicate(sky_list->
4789 limages[i]->confidence);
4790 if (sky_list->limages[i]->object_mask != NULL) {
4791 cpl_mask_or(cpl_image_get_bpm(hdrl_image_get_image(imcopy)),
4792 sky_list->limages[i]->object_mask);
4793 cpl_mask_or(cpl_image_get_bpm(confcopy),
4794 sky_list->limages[i]->object_mask);
4795 cpl_image_fill_rejected(confcopy, 0.0);
4796 cpl_image_accept_all(confcopy);
4797 }
4798
4799 if (debug) {
4800 int rejected = 1;
4801 hdrl_value himval = hdrl_image_get_pixel(imcopy,
4802 x_probe, y_probe, &rejected);
4803 int ignore = 1;
4804 double conf = cpl_image_get(confcopy,
4805 x_probe, y_probe,
4806 &ignore);
4807 cpl_vector_set(data, k, himval.data);
4808 cpl_vector_set(error, k, himval.error);
4809 cpl_vector_set(reject, k, (double)rejected);
4810 cpl_vector_set(confidence, k, conf);
4811 }
4812
4813 hdrl_imagelist_set(skylist, imcopy,
4814 hdrl_imagelist_get_size(skylist));
4815
4816 if (sky_confidence == NULL) {
4817 sky_confidence = confcopy;
4818 } else {
4819 cpl_image_add(sky_confidence, confcopy);
4820 cpl_image_delete(confcopy);
4821 }
4822 }
4823 cpl_msg_debug(cpl_func, "after skylist %s",
4824 cpl_error_get_message());
4825
4826 /* Combine the images to give the result */
4827
4828 hdrl_imagelist_collapse(skylist, HDRL_COLLAPSE_MEDIAN, &sky_himage,
4829 &contrib);
4830 cpl_image_delete(contrib);
4831 contrib = NULL;
4832 cpl_msg_debug(cpl_func, "after collapse %s",
4833 cpl_error_get_message());
4834
4835 /* Re-normalise the confidence array */
4836
4837 enu_normalise_confidence(sky_confidence);
4838
4839 if (debug) {
4840 cpl_msg_info(" ",
4841 ".. enu_sky_backgrounds: probe pixel %d,%d",
4842 (int)x_probe, (int)y_probe);
4843 cpl_msg_info(" ", ".. jitter %d" , (int)j);
4844 cpl_msg_info(" ", "... j# q c d (e)");
4845
4846 for (cpl_size k = 0; k < skysize; k++) {
4847 cpl_msg_info(" ", "... %3d %3d %3d %8.2f(%4.2f)",
4848 (int)cpl_vector_get(sky_indeces, k),
4849 (int)cpl_vector_get(reject, k),
4850 (int)cpl_vector_get(confidence, k),
4851 cpl_vector_get(data, k),
4852 cpl_vector_get(error, k));
4853 }
4854 int rejected = 0;
4855 int ignore = 0;
4856 hdrl_value hval = hdrl_image_get_pixel(sky_himage,
4857 x_probe, y_probe, &rejected);
4858 double cval = cpl_image_get(sky_confidence, x_probe,
4859 y_probe, &ignore);
4860 cpl_msg_info(" ", "... -> %3d %3d %8.2f(%4.2f)",
4861 rejected, (int)cval, hval.data, hval.error);
4862
4863 cpl_vector_delete(data);
4864 cpl_vector_delete(error);
4865 cpl_vector_delete(reject);
4866 cpl_vector_delete(confidence);
4867 }
4868
4869 hdrl_imagelist_delete(skylist); skylist=NULL;
4870 enu_check_error_code("failure in collapse-median");
4871
4872 } else if (strstr(method, "median-median") != NULL) {
4873
4874 /* construct a CPL array of the median of the jitters
4875 selected */
4876
4877 cpl_array * sky_medians = cpl_array_new(0, CPL_TYPE_DOUBLE);
4878
4879 for (int k = 0; k < (int)skysize; k++) {
4880 int i = (int)cpl_vector_get(sky_indeces, k);
4881
4882 /* get a copy of the image with the object mask applied */
4883
4884 hdrl_image * imcopy = hdrl_image_duplicate(
4885 sky_list->limages[i]->himage);
4886 if (sky_list->limages[i]->object_mask != NULL) {
4887 cpl_mask_or(cpl_image_get_bpm(hdrl_image_get_image(imcopy)),
4888 sky_list->limages[i]->object_mask);
4889 }
4890 hdrl_value bkg = hdrl_image_get_median(imcopy);
4891 hdrl_image_delete(imcopy);
4892
4893 cpl_size asize = cpl_array_get_size(sky_medians);
4894 cpl_array_set_size(sky_medians, asize+1);
4895 cpl_array_set_double(sky_medians, asize, bkg.data);
4896
4897 if (debug) {
4898 cpl_vector_set(data, k, bkg.data);
4899 cpl_vector_set(error, k, bkg.error);
4900 cpl_vector_set(confidence, k, 100.0);
4901 cpl_vector_set(reject, k, 0.0);
4902 }
4903 }
4904
4905 /* The result is an image filled with the median of sky_medians
4906 ..the error plane is the stdev of sky_medians */
4907
4908 double sky_med_med = cpl_array_get_median(sky_medians);
4909 double sky_med_stdev = cpl_array_get_stdev(sky_medians);
4910 cpl_size nx = hdrl_image_get_size_x(sky_list->limages[0]->himage);
4911 cpl_size ny = hdrl_image_get_size_y(sky_list->limages[0]->himage);
4912 cpl_image * sky_data = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
4913 cpl_image_fill_window(sky_data, 1, 1, nx, ny, sky_med_med);
4914 cpl_image * sky_error = cpl_image_new(nx, ny, HDRL_TYPE_ERROR);
4915 cpl_image_fill_window(sky_error, 1, 1, nx, ny, sky_med_stdev);
4916 sky_himage = hdrl_image_create(sky_data, sky_error);
4917 cpl_image_delete(sky_data);
4918 cpl_image_delete(sky_error);
4919
4920 sky_confidence = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
4921 cpl_image_fill_window(sky_confidence, 1, 1, nx, ny, 100.0);
4922
4923 cpl_array_delete(sky_medians);
4924
4925 if (debug) {
4926 cpl_msg_info(" ",
4927 ".. enu_sky_backgrounds: median of images");
4928 cpl_msg_info(" ", ".. jitter %d" , (int)j);
4929 cpl_msg_info(" ", "... j# c d (e)");
4930
4931 for (cpl_size k = 0; k < skysize; k++) {
4932 cpl_msg_info(" ", "... %3d %3d %8.2f(%4.2f)",
4933 (int)cpl_vector_get(sky_indeces, k),
4934 (int)cpl_vector_get(confidence, k),
4935 cpl_vector_get(data, k),
4936 cpl_vector_get(error, k));
4937 }
4938 int rejected = 0;
4939 int ignore = 0;
4940 hdrl_value hval = hdrl_image_get_pixel(sky_himage,
4941 1, 1, &rejected);
4942 double cval = cpl_image_get(sky_confidence, 1, 1, &ignore);
4943 cpl_msg_info(" ", "... -> %3d %3d %8.2f(%4.2f)",
4944 rejected, (int)cval, hval.data, hval.error);
4945
4946 cpl_vector_delete(data);
4947 cpl_vector_delete(error);
4948 cpl_vector_delete(confidence);
4949 }
4950 enu_check_error_code("failure in median-median");
4951 }
4952
4953 /* append to lists */
4954
4955 hdrl_imagelist_set(*sky_himagelist, sky_himage,
4956 hdrl_imagelist_get_size(*sky_himagelist));
4957 cpl_imagelist_set(*sky_confidence_list, sky_confidence,
4958 cpl_imagelist_get_size(*sky_confidence_list));
4959 cpl_vector_delete(sky_indeces); sky_indeces = NULL;
4960 }
4961
4962 cleanup:
4963 hdrl_imagelist_delete(skylist);
4964 cpl_vector_delete(sky_indeces);
4965 if (cpl_error_get_code() != CPL_ERROR_NONE) {
4966 hdrl_imagelist_delete(*sky_himagelist);
4967 *sky_himagelist = NULL;
4968 cpl_imagelist_delete(*sky_confidence_list);
4969 *sky_confidence_list = NULL;
4970 }
4971
4972 return cpl_error_get_code();
4973}
4974
4975
4976/*----------------------------------------------------------------------------*/
4988/*----------------------------------------------------------------------------*/
4989
4990cpl_error_code enu_stack(located_imagelist * limages,
4991 const double stk_lthr, const double stk_hthr,
4992 const char * stk_method, const int stk_fast,
4993 located_image ** result) {
4994
4995 cpl_ensure_code(cpl_error_get_code() == CPL_ERROR_NONE,
4996 cpl_error_get_code());
4997
4998 casu_fits ** indata = NULL;
4999 casu_fits ** inconf = NULL;
5000 casu_fits ** invar = NULL;
5001 casu_fits * out = NULL;
5002 casu_fits * outc = NULL;
5003 casu_fits * outv = NULL;
5004
5005 /* parameter validation */
5006
5007 cpl_ensure_code(limages, CPL_ERROR_NULL_INPUT);
5008 cpl_ensure_code((stk_fast == 0) || (stk_fast == 1),
5009 CPL_ERROR_ILLEGAL_INPUT);
5010
5011 /* parameter translation */
5012
5013 const int casu_stk_method = (!strcmp(stk_method, "nearest") ? 0 : 1);
5014
5015 /* translate located_imagelist to casu_fits components */
5016
5017 encu_limlist_to_casu_fits(limages, &indata, &inconf, &invar);
5018
5019 /* do the stacking */
5020
5021 int njitters = (int) limages->size;
5022 int casu_status = CASU_OK;
5023 casu_imstack(indata, inconf, invar, NULL, (int)njitters, (int)njitters,
5024 stk_lthr, stk_hthr, casu_stk_method, 0, stk_fast, 0,
5025 "ESO DET DIT", &out, &outc, &outv, &casu_status);
5026 *result = enu_located_image_new(hdrl_image_create(out->image, outv->image),
5027 NULL,
5028 cpl_image_duplicate(outc->image),
5029 NULL, NULL,
5030 out->ehu,
5031 NULL, NULL, NULL, NULL, NULL);
5032 freespace(out);
5033 freespace(outc);
5034 freespace(outv);
5035
5036 return cpl_error_get_code();
5037}
5038
5039
5040/*----------------------------------------------------------------------------*/
5053/*----------------------------------------------------------------------------*/
5054
5055cpl_error_code enu_sky_subtract_limlist(const char * method,
5056 const char * select_method,
5057 const double timerange,
5058 const located_imagelist * sky_data,
5059 const cpl_size x_probe,
5060 const cpl_size y_probe,
5061 located_imagelist * target_data) {
5062
5063 cpl_ensure_code(cpl_error_get_code() == CPL_ERROR_NONE,
5064 cpl_error_get_code());
5065 cpl_ensure_code(method, CPL_ERROR_NULL_INPUT);
5066 cpl_ensure_code(select_method, CPL_ERROR_NULL_INPUT);
5067 cpl_ensure_code(target_data, CPL_ERROR_NULL_INPUT);
5068
5069 cpl_imagelist * sky_conf_list = NULL;
5070 hdrl_imagelist * sky_himlist = NULL;
5071
5072 cpl_msg_info(cpl_func,
5073 "enu_sky_subtract called: method=%s, sky_selector=%s, "
5074 "bracket=%6.2f",
5075 method, select_method, timerange);
5076 cpl_size njitters = target_data->size;
5077 cpl_msg_info(cpl_func, "number of jitters to be reduced %d",
5078 (int) njitters);
5079
5080 /* Derive sky backgrounds */
5081
5082 enu_sky_backgrounds(method, select_method, timerange, target_data,
5083 sky_data, x_probe, y_probe, &sky_himlist,
5084 &sky_conf_list);
5085 enu_check_error_code("failure in enu_sky_backgrounds");
5086
5087 /* Subtract the sky backgrounds */
5088
5089 hdrl_value before = {0.0, 0.0};
5090 double bconf = 0.0;
5091 hdrl_value bkg = {0.0, 0.0};
5092 double bkgconf = 0.0;
5093 hdrl_value after = {0.0, 0.0};
5094 double aconf = 0.0;
5095 int brejected = 1;
5096 int bkgrejected = 1;
5097 int arejected = 1;
5098 int ignore = 1;
5099 int header_printed = CPL_FALSE;
5100
5101 for (cpl_size i = 0; i < njitters; i++) {
5102
5103 /* probe pixel debug stuff */
5104
5105 const cpl_size x_size = hdrl_image_get_size_x(
5106 target_data->limages[i]->himage);
5107 const cpl_size y_size = hdrl_image_get_size_y(
5108 target_data->limages[i]->himage);
5109 if (x_probe > 0 && x_probe <= x_size &&
5110 y_probe > 0 && y_probe <= y_size) {
5111 before = hdrl_image_get_pixel(target_data->limages[i]->himage,
5112 x_probe, y_probe, &brejected);
5113 bconf = cpl_image_get(target_data->limages[i]->confidence,
5114 x_probe, y_probe, &ignore);
5115 }
5116
5117 /* this bit does the actual subtraction. */
5118
5119 hdrl_image_sub_image(target_data->limages[i]->himage,
5120 hdrl_imagelist_get_const(sky_himlist, i));
5121 target_data->limages[i]->bkg = hdrl_image_duplicate(
5122 hdrl_imagelist_get(sky_himlist, i));
5123 target_data->limages[i]->bkg_confidence = cpl_image_duplicate(
5124 cpl_imagelist_get(sky_conf_list, i));
5125
5126 /* Confidence array remains that of the target, on the assumption
5127 that the S/N of the 'sky' is much higher */
5128
5129 /* Or could do it this way... */
5130 /* Confidence arrays are combined as if inverse variances */
5131 /* COMMENTED OUT
5132 cpl_image * temp = cpl_image_add_create(
5133 target_data->limages[i]->confidence,
5134 target_data->limages[i]->bkg_confidence);
5135 cpl_image_multiply(target_data->limages[i]->confidence,
5136 target_data->limages[i]->bkg_confidence);
5137 cpl_image_divide(target_data->limages[i]->confidence, temp);
5138 cpl_image_delete(temp);
5139 */
5140
5141 /* normalise the new confidence */
5142
5143 cpl_image_fill_rejected(target_data->limages[i]->confidence, 0.0);
5144 cpl_image_accept_all(target_data->limages[i]->confidence);
5145 enu_normalise_confidence(target_data->limages[i]->confidence);
5146
5147 /* more probe pixel debug stuff */
5148
5149 if (x_probe > 0 && x_probe <= x_size &&
5150 y_probe > 0 && y_probe <= y_size) {
5151 after = hdrl_image_get_pixel(target_data->limages[i]->himage,
5152 x_probe, y_probe, &arejected);
5153 aconf = cpl_image_get(target_data->limages[i]->confidence,
5154 x_probe, y_probe, &ignore);
5155 bkg = hdrl_image_get_pixel(target_data->limages[i]->bkg,
5156 x_probe, y_probe, &bkgrejected);
5157 bkgconf = cpl_image_get(target_data->limages[i]->bkg_confidence,
5158 x_probe, y_probe, &ignore);
5159
5160 if (!header_printed) {
5161 header_printed = CPL_TRUE;
5162 cpl_msg_info(" ", "..Subtracting sky backgrounds: probe pixel %d,%d",
5163 (int)x_probe, (int)y_probe);
5164 cpl_msg_info(" ", " j# before sky after");
5165 cpl_msg_info(" ", " q c d e q c d e q c d e");
5166 }
5167 cpl_msg_info(" ",
5168 "..%3d %d %3.0f %4.2e(%4.2e)) %d %3.0f %4.2e(%4.2e) %d %3.0f %10.2e(%4.2e)",
5169 (int)i,
5170 brejected, bconf, before.data, before.error,
5171 bkgrejected, bkgconf, bkg.data, bkg.error,
5172 arejected, aconf, after.data, after.error);
5173 }
5174 }
5175
5176 cleanup:
5177 cpl_imagelist_delete(sky_conf_list);
5178 hdrl_imagelist_delete(sky_himlist);
5179
5180 return cpl_error_get_code();
5181}
5182
5183
5184/*----------------------------------------------------------------------------*/
5193/*----------------------------------------------------------------------------*/
5194
5195cpl_error_code
5196eris_nix_get_badpix_qc_from_ima(const master_bpm* mbad_pix_map,
5197 cpl_propertylist* qc_list,
5198 const char* prefix)
5199{
5200 cpl_ensure_code(mbad_pix_map != NULL, CPL_ERROR_NULL_INPUT);
5201 cpl_ensure_code(qc_list != NULL, CPL_ERROR_NULL_INPUT);
5202 cpl_ensure_code(prefix != NULL, CPL_ERROR_NULL_INPUT);
5203
5204 int flag_mask = 0;
5205 cpl_mask * bpm_mask = NULL;
5206
5207 flag_mask = ~flag_mask;
5208 bpm_mask = en_master_bpm_get_mask(mbad_pix_map, flag_mask);
5209 int nbad = cpl_mask_count(bpm_mask);
5210 cpl_propertylist_append_int(qc_list, "ESO QC NUMBER BAD PIXELS", nbad);
5211 cpl_size sx = cpl_mask_get_size_x(bpm_mask);
5212 cpl_size sy = cpl_mask_get_size_y(bpm_mask);
5213 double fraction = (double) nbad / (sx * sy);
5214 cpl_propertylist_append_double(qc_list, "ESO QC FRACTION BAD PIXELS",fraction);
5215 return cpl_error_get_code();
5216}
5217
5218
5219/*----------------------------------------------------------------------------*/
5231/*----------------------------------------------------------------------------*/
5232
5233cpl_propertylist*
5234enu_raw_flats_qc(located_imagelist* lamp_on_limlist,
5235 cpl_mask* bp_map_nl_mask,
5236 const cpl_parameterlist* parlist,
5237 const char* context,
5238 const double threshold_pos,
5239 const cpl_boolean verbose,
5240 const cpl_boolean rescale_by_dit){
5241
5242 cpl_ensure(lamp_on_limlist != NULL, CPL_ERROR_NULL_INPUT, NULL);
5243 cpl_ensure(bp_map_nl_mask != NULL, CPL_ERROR_NULL_INPUT, NULL);
5244 cpl_ensure(parlist != NULL, CPL_ERROR_NULL_INPUT, NULL);
5245 cpl_ensure(context != NULL, CPL_ERROR_NULL_INPUT, NULL);
5246
5247
5248 cpl_propertylist* qc;
5249 //located_image* loc_img;
5250 cpl_mask* mask;
5251 double mean = 0;
5252 double median = 0;
5253 double rms = 0;
5254 char* key_name;
5255 char* key_comm;
5256
5257 qc = cpl_propertylist_new();
5258 double threshold_neg = - 4.3e7;
5259 threshold_neg = 300.;
5260 long nthresh_pos = 0;
5261 long nthresh_neg = 0;
5262
5263 const cpl_parameter* param;
5264 char* pname;
5265
5266 /* negative saturation maybe not to be checked as no pixels are sat */
5267 pname = cpl_sprintf("%s%s",context,".saturation_neg");
5268 cpl_msg_warning(cpl_func,"pname: %s",pname);
5269 param = cpl_parameterlist_find_const(parlist,pname);
5270 threshold_neg = cpl_parameter_get_double(param);
5271 cpl_free(pname);
5272 //cpl_msg_info(cpl_func,"threshold_neg: %g",threshold_neg);
5273 //cpl_msg_info(cpl_func,"threshold_pos: %g",threshold_pos);
5274 //char* fname;
5275 cpl_image* ima;
5276 double mean_min = DBL_MAX;
5277 double median_min = DBL_MAX;
5278
5279 double mean_max = -DBL_MIN;
5280 double median_max = -DBL_MIN;
5281 double nthresh_pos_max = 0;
5282 double nthresh_neg_max = 0;
5283 /*
5284 cpl_msg_info(cpl_func,"mean_min: %g",mean_min);
5285 cpl_msg_info(cpl_func,"mean_max: %g",mean_max);
5286 cpl_msg_info(cpl_func,"median_min: %g",median_min);
5287 cpl_msg_info(cpl_func,"median_max: %g",median_max);
5288 */
5289 double dit = 1;
5290 cpl_propertylist* plist = NULL;
5291 for(cpl_size i = 0; i < lamp_on_limlist->size; i++) {
5292 //fname = cpl_sprintf("raw_ima_%lld.fits",i);
5293 mask = hdrl_image_get_mask(lamp_on_limlist->limages[i]->himage);
5294 /*
5295 cpl_image_save(hdrl_image_get_image(lamp_on_limlist->limages[i]->himage),
5296 fname,CPL_TYPE_DOUBLE,NULL,CPL_IO_DEFAULT);
5297 */
5298
5299 cpl_mask_or(mask, bp_map_nl_mask);
5300
5301 hdrl_image_reject_from_mask(lamp_on_limlist->limages[i]->himage, mask);
5302 ima = hdrl_image_get_image(lamp_on_limlist->limages[i]->himage);
5303 plist = lamp_on_limlist->limages[i]->plist;
5304 if(cpl_propertylist_has(plist,"ESO DET SEQ1 DIT")) {
5305 dit = cpl_propertylist_get_double(plist,"ESO DET SEQ1 DIT");
5306 }
5307 nthresh_neg = eris_image_get_threshpix(ima, threshold_neg, CPL_FALSE);
5308 nthresh_pos = eris_image_get_threshpix(ima, threshold_pos, CPL_TRUE);
5309
5310 eris_image_flag_threshpix(&ima, threshold_neg, CPL_FALSE);
5311 mean = cpl_image_get_mean(ima);
5312 median = cpl_image_get_median(ima);
5313 rms = cpl_image_get_stdev(ima);
5314 //cpl_mask_delete(mask);
5315
5316 //nsat = nthresh_neg + nthresh_pos;
5317 //nsat = nthresh_neg;
5318 if(rescale_by_dit) {
5319 mean *= dit;
5320 median *= dit;
5321 rms *= dit;
5322 }
5323 if(verbose) {
5324 key_name = cpl_sprintf("ESO QC FLAT_ON%lld NPOSSAT",i);
5325 key_comm = cpl_sprintf("Number of flat pixels above threshold");
5326 cpl_propertylist_append_int(qc, key_name, nthresh_pos);
5327 cpl_propertylist_set_comment(qc, key_name, key_comm);
5328 cpl_free(key_name);
5329 cpl_free(key_comm);
5330
5331 key_name = cpl_sprintf("ESO QC FLAT_ON%lld NNEGSAT",i);
5332 key_comm = cpl_sprintf("Number of flat pixels below neg threshold");
5333 cpl_propertylist_append_int(qc, key_name, nthresh_neg);
5334 cpl_propertylist_set_comment(qc, key_name, key_comm);
5335 cpl_free(key_name);
5336 cpl_free(key_comm);
5337
5338 key_name = cpl_sprintf("ESO QC FLAT_ON%lld MEAN",i);
5339 key_comm = cpl_sprintf("[ADU] Mean of flat");
5340 cpl_propertylist_append_double(qc, key_name, mean);
5341 cpl_propertylist_set_comment(qc,key_name,key_comm);
5342 cpl_free(key_name);
5343 cpl_free(key_comm);
5344
5345 key_name = cpl_sprintf("ESO QC FLAT_ON%lld MEDIAN",i);
5346 key_comm = cpl_sprintf("[ADU] Median of flat");
5347 cpl_propertylist_append_double(qc, key_name, median);
5348 cpl_propertylist_set_comment(qc,key_name,key_comm);
5349 cpl_free(key_name);
5350 cpl_free(key_comm);
5351
5352 key_name = cpl_sprintf("ESO QC FLAT_ON%lld STDEV",i);
5353 key_comm = cpl_sprintf("[ADU] Stdev of flat");
5354 cpl_propertylist_append_double(qc, key_name, rms);
5355 cpl_propertylist_set_comment(qc,key_name,key_comm);
5356 cpl_free(key_name);
5357 cpl_free(key_comm);
5358 }
5359
5360 if(mean > mean_max) {
5361 mean_max = mean;
5362 }
5363 if(median > median_max) {
5364 median_max = median;
5365 }
5366
5367
5368 if(mean < mean_min) {
5369 mean_min = mean;
5370 }
5371 if(median < median_min) {
5372 median_min = median;
5373 }
5374
5375
5376 if(nthresh_pos > nthresh_pos_max) {
5377 nthresh_pos_max = nthresh_pos;
5378 }
5379 if(nthresh_neg > nthresh_neg_max) {
5380 nthresh_neg_max = nthresh_neg;
5381 }
5382 }
5383 cpl_msg_info(cpl_func,"mean_min: %g",mean_min);
5384 cpl_msg_info(cpl_func,"mean_max: %g",mean_max);
5385 cpl_msg_info(cpl_func,"median_min: %g",median_min);
5386 cpl_msg_info(cpl_func,"median_max: %g",median_max);
5387 cpl_msg_info(cpl_func,"f1: %g",mean_min / mean_max);
5388 cpl_msg_info(cpl_func,"f2: %g",median_min / median_max);
5389
5390 key_name = cpl_sprintf("ESO QC FLAT_ON MEAN MIN");
5391 key_comm = cpl_sprintf("[ADU] Min of Means of flat");
5392 cpl_propertylist_append_double(qc, key_name, mean_min);
5393 cpl_propertylist_set_comment(qc,key_name,key_comm);
5394 cpl_free(key_name);
5395 cpl_free(key_comm);
5396
5397 key_name = cpl_sprintf("ESO QC FLAT_ON MEDIAN MIN");
5398 key_comm = cpl_sprintf("[ADU] Min of Medians of flat");
5399 cpl_propertylist_append_double(qc, key_name, median_min);
5400 cpl_propertylist_set_comment(qc,key_name,key_comm);
5401 cpl_free(key_name);
5402 cpl_free(key_comm);
5403
5404 key_name = cpl_sprintf("ESO QC FLAT_ON MEAN MAX");
5405 key_comm = cpl_sprintf("[ADU] Max of Means of flat");
5406 cpl_propertylist_append_double(qc, key_name, mean_max);
5407 cpl_propertylist_set_comment(qc,key_name,key_comm);
5408 cpl_free(key_name);
5409 cpl_free(key_comm);
5410
5411 key_name = cpl_sprintf("ESO QC FLAT_ON MEDIAN MAX");
5412 key_comm = cpl_sprintf("[ADU] Max of Medians of flat");
5413 cpl_propertylist_append_double(qc, key_name, median_max);
5414 cpl_propertylist_set_comment(qc,key_name,key_comm);
5415 cpl_free(key_name);
5416 cpl_free(key_comm);
5417
5418
5419 key_name = cpl_sprintf("ESO QC FLAT_ON MEAN FRAC");
5420 key_comm = cpl_sprintf("Min/Max of Means of flat");
5421 cpl_propertylist_append_double(qc, key_name, mean_min / mean_max);
5422 cpl_propertylist_set_comment(qc,key_name,key_comm);
5423 cpl_free(key_name);
5424 cpl_free(key_comm);
5425
5426
5427 key_name = cpl_sprintf("ESO QC FLAT_ON MEDIAN FRAC");
5428 key_comm = cpl_sprintf("Min/Max of Medians of flat");
5429 cpl_propertylist_append_double(qc, key_name, median_min / median_max);
5430 cpl_propertylist_set_comment(qc,key_name,key_comm);
5431 cpl_free(key_name);
5432 cpl_free(key_comm);
5433
5434
5435
5436 key_name = cpl_sprintf("ESO QC FLAT_ON NPOSSAT MAX");
5437 key_comm = cpl_sprintf("Max of Number of flat pixels above threshold");
5438 cpl_propertylist_append_int(qc, key_name, nthresh_pos_max);
5439 cpl_propertylist_set_comment(qc, key_name, key_comm);
5440 cpl_free(key_name);
5441 cpl_free(key_comm);
5442
5443 key_name = cpl_sprintf("ESO QC FLAT_ON NNEGSAT MAX");
5444 key_comm = cpl_sprintf("MAX Number of flat pixels below neg threshold");
5445 cpl_propertylist_append_int(qc, key_name, nthresh_neg_max);
5446 cpl_propertylist_set_comment(qc, key_name, key_comm);
5447 cpl_free(key_name);
5448 cpl_free(key_comm);
5449
5450
5451
5452
5453 return qc;
5454}
cpl_error_code encu_limlist_to_casu_fits(located_imagelist *limlist, casu_fits ***indata, casu_fits ***inconf, casu_fits ***invar)
Translate a located_imagelist to arrays of casu_fits structs.
cpl_error_code enu_dfs_save_limage(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *provenance, const cpl_boolean prov_raw, const located_image *limage, const char *recipe, const cpl_frame *inherit, cpl_propertylist *applist, const char *pipe_id, const char *filename)
Save a located image structure to a MEF.
Definition: eris_nix_dfs.c:907
cpl_error_code enu_dfs_save_himage(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *provenance, const cpl_boolean prov_raw, const hdrl_image *image, const hdrl_imagelist *imagelist, const mef_extension_list *mefs, const char *recipe, const cpl_frame *inherit_frame, const cpl_propertylist *applist, const cpl_propertylist *wcs_plist, const char *pipe_id, const char *filename)
Save an hdrl_image/imagelist as a DFS-compliant MEF pipeline product.
Definition: eris_nix_dfs.c:421
cpl_error_code enm_correct_crpix(const char *wcs_method, const char *catalogue, cpl_table *matched_stds, located_image *limage, cpl_matrix **xy_shift)
Apply median offsets from matched standards table to image.
cpl_error_code enm_try_all_associations(cpl_table *objtab, cpl_table *stdtab, const double match_rad, cpl_table **matchtab)
Match standards with objects by trying all possibilities and selecting best.
located_image * enu_located_image_duplicate(const located_image *limage)
Make a deep copy of a located_image and its contents.
cpl_mask * enu_mef_extension_list_get_mask(mef_extension_list *meflist, const char *target)
Get a cpl_mask from a named mef_extension in a list.
cpl_vector * enu_bracket_skys(const located_image *target, const double timerange, const located_imagelist *pool, const int debug)
Find images taken within a given time of a target image.
cpl_error_code enu_modify_CD_matrix(located_image *limage, const cpl_table *refine_wcs)
Update the CD matrix to reduce image distortion and rotation.
void enu_located_imagelist_delete(located_imagelist *limlist)
Delete a located_imagelist and its contents.
cpl_error_code enu_located_imagelist_insert(located_imagelist *limlist, located_image *limage, cpl_size position)
Insert a located_image at a specified point in a located_imagelist.
void enu_mef_extension_delete(mef_extension *mef)
Delete a mef_extension and its contents.
cpl_error_code eris_nix_get_badpix_qc_from_ima(const master_bpm *mbad_pix_map, cpl_propertylist *qc_list, const char *prefix)
Compute QC on input master bpm.
mef_extension * enu_mef_new_mask(const char *name, const cpl_mask *data, const cpl_propertylist *plist)
Create a mef_extension struct holding a cpl_mask.
cpl_propertylist * enu_raw_flats_qc(located_imagelist *lamp_on_limlist, cpl_mask *bp_map_nl_mask, const cpl_parameterlist *parlist, const char *context, const double threshold_pos, const cpl_boolean verbose, const cpl_boolean rescale_by_dit)
Compute QC on input raw flats.
cpl_error_code enu_flat_save(const char *pro_catg, const hdrl_image *flat, const cpl_image *confidence, const cpl_mask *cold_bpm, cpl_frameset *frameset, const cpl_parameterlist *parlist, const char *filename, const char *recipe_name, const cpl_propertylist *qclog)
Save a flatfield result.
int enu_check_conformance(const cpl_propertylist *plist1, const cpl_propertylist *plist2, const char *regexp)
Check that the specified subset of two propertylists match.
located_image * enu_load_limage_from_frame(const cpl_frame *frame, cpl_image **pcopyconf, const cpl_boolean collapse_cube)
Load components of a located_image from a frame.
hdrl_catalogue_result * enu_hdrl_catalogue_result_duplicate(const hdrl_catalogue_result *target)
Return a deep copy of the given hdrl_catalogue_result object.
located_imagelist * enu_located_imagelist_duplicate(const located_imagelist *limlist)
Make a deep copy of a located_imagelist and its contents.
cpl_error_code enu_calc_maglim(const located_image *limage, const double photzp, const double fwhm_pix, double *abmaglim)
Calculate magnitude limit of image.
cpl_error_code enu_opm_lss_limlist(located_imagelist *limlist, const int nsigma_cut)
Calculate object masks for LSS images in a located_imagelist.
double enu_get_tel_alt(const cpl_propertylist *plist)
Get telescope altitude of an observation.
mef_extension * enu_mef_new_image(const char *name, const cpl_image *data, const cpl_propertylist *plist)
Create a mef_extension to hold a cpl_image.
cpl_error_code enu_get_ra_dec(const cpl_wcs *wcs, double *ra, double *dec)
Get RA and Dec at centre of image with given wcs.
hdrl_image * enu_calc_flat(hdrl_imagelist *himlist, const int min_coadds, const hdrl_parameter *collapse_params, const cpl_size filter_size_x, const cpl_size filter_size_y, const hdrl_flat_method method)
Calculate a flatfield result.
cpl_error_code enu_get_window_info(cpl_size *nx, cpl_size *ny, int *rot, cpl_size *strx, cpl_size *stry, cpl_size *nx_chip, cpl_size *ny_chip, cpl_boolean *windowed, const cpl_propertylist *plist)
Get the detector 'window' information.
cpl_error_code enu_basic_calibrate(located_image *limage, const int read_offsets, const cpl_table *refine_wcs, const master_dark *mdark, const gain_linearity *gain_lin, const master_flat *flatfield_1, const master_flat *flatfield_2, const master_bpm *mbad_pix_map, const int flag_mask, const char *fill_rejected, const double fill_value, const cpl_size x_probe, const cpl_size y_probe)
Do basic calibration of located_image (single or cube)
cpl_error_code enu_catalogue_limlist(located_imagelist *limlist, hdrl_parameter *params)
Calculate object catalogues for a list of images.
cpl_error_code enu_sky_subtract_limlist(const char *method, const char *select_method, const double timerange, const located_imagelist *sky_data, const cpl_size x_probe, const cpl_size y_probe, located_imagelist *target_data)
Estimate and subtract sky backgrounds for a list of target images.
cpl_error_code enu_himage_load_from_fits(const char *filename, hdrl_image **result, mef_extension_list **mef_extensions, cpl_propertylist **plist)
Load an hdrl_image from a multi-extension FITS file.
cpl_error_code enu_debug_limlist_save(const int debug, const located_imagelist *limlist, const char *nameroot, const char *recipename, cpl_frameset *frameset, const cpl_parameterlist *parlist, const cpl_frameset *used)
Save a list of intermediate image results for use in debugging.
mef_extension * enu_mef_new_table(const char *name, const cpl_table *table, const cpl_propertylist *plist)
Create a mef_extension struct holding a cpl_table.
mef_extension_list * enu_mef_extension_list_new(cpl_size size)
Construct a new mef_extension_list.
located_image * enu_located_image_new(hdrl_image *himage, hdrl_imagelist *himagelist, cpl_image *confidence, hdrl_image *bkg, cpl_image *bkg_confidence, cpl_propertylist *plist, hdrl_catalogue_result *objects, cpl_mask *object_mask, hdrl_catalogue_result *wcs, hdrl_catalogue_result *photom, cpl_frame *frame)
Create a located_image structure and initialise the contents.
double enu_get_airmass(const cpl_propertylist *plist)
Get the mean airmass of an observation.
cpl_error_code enu_calc_pixel_coords(cpl_table *catalogue, const cpl_propertylist *wcs_plist)
Calculate predicted positions of catalogue objects for given wcs.
located_imagelist * enu_limlist_load_from_frameset(cpl_frameset *frameset, const char *tag, cpl_frameset *used)
Load tagged data from a frameset into a located_imagelist.
void enu_located_image_delete(located_image *limage)
Delete a located_image and its contents.
mef_extension * enu_mef_new_vector(const char *name, const cpl_vector *vector, const cpl_propertylist *plist)
Create a mef_extension struct holding a cpl_vector.
cpl_error_code enu_remove_read_offsets(hdrl_image *himage, const cpl_propertylist *plist, cpl_image *confidence, const int set_confidence)
Function to remove read offsets from an himage and set blank pixels
cpl_error_code enu_normalise_confidence(cpl_image *confidence)
Normalise confidence array so that mean of good pixels is 100.
cpl_error_code enu_stack(located_imagelist *limages, const double stk_lthr, const double stk_hthr, const char *stk_method, const int stk_fast, located_image **result)
Stack a set of images.
cpl_error_code enu_correct_wcs(const cpl_table *refcat, const char *wcs_method, const char *catalogue, located_image *limage, const double match_rad, cpl_table **matched_stds, cpl_matrix **xy_shift)
Correct the wcs of an image.
cpl_error_code enu_basic_calibrate_himage(hdrl_image *himage, cpl_image *confidence, cpl_propertylist *plist, const cpl_frame *frame, const int read_offsets, const master_dark *mdark, const gain_linearity *gain_lin, const master_flat *flatfield_1, const master_flat *flatfield_2, const master_bpm *mbad_pix_map, const int set_confidence, const int flag_mask, const char *fill_rejected, const double fill_value, const cpl_size x_probe, const cpl_size y_probe)
Do basic calibration of an hdrl_image.
cpl_error_code enu_mef_extension_save(const mef_extension *mef, const char *filename, const cpl_propertylist *plist, unsigned mode)
Save a mef_extension struct to FITS file.
char * enu_repreface(const char *filename, const char *preface)
Preface a raw filename with a string.
const char * enu_get_license(void)
Get the pipeline copyright and license.
void enu_mef_extension_list_delete(mef_extension_list *list)
Delete a mef_extension_list and its contents.
cpl_image * enu_load_component(mef_extension *mef, const char *dps_name, const char *hduclas1, const char *hduclas2)
Load data from a MEF component of specified type.
const char * enu_get_filter(const cpl_propertylist *plist)
Get the filter used in an observation.
cpl_error_code enu_check_wcs(const located_image *limage)
Check that the image has valid WCS keywords.
cpl_error_code enu_get_rcore_and_mesh_size(const char *context, const cpl_parameterlist *parlist, const cpl_propertylist *plist, double *obj_core_radius, int *bkg_mesh_size)
Get catalogue core-radius and mesh-size appropriate to AO mode.
located_imagelist * enu_located_imagelist_new(cpl_size size)
Return a pointer to a new located_imagelist.
hdrl_catalogue_result * enu_catalogue_compute(const hdrl_image *himage, const cpl_image *confidence, const cpl_wcs *wcs, hdrl_parameter *params)
Wrapper for hdrl_catalogue_compute.
cpl_error_code enu_opm_limlist(const int obj_min_pixels, const double obj_threshold, const int bkg_mesh_size, const double bkg_smooth_fwhm, located_imagelist *limlist)
Calculate object masks for images in a located_imagelist.
const char * enu_get_det_mode(const cpl_propertylist *plist)
Get the detector mode of an integration.
cpl_error_code enu_sky_backgrounds(const char *method, const char *select_method, const double timerange, const located_imagelist *target_list, const located_imagelist *sky_list, const cpl_size x_probe, const cpl_size y_probe, hdrl_imagelist **sky_himagelist, cpl_imagelist **sky_confidence_list)
Get sky backgrounds for a list of target images.
double enu_get_dit(const cpl_propertylist *plist)
Get the DIT of an integration.
double enu_get_filter_wavelength(const char *filter)
Get the effective wavelength of a filter.
mef_extension_list * enu_load_mef_components(const char *filename, cpl_propertylist **plist)
Load components of a multi-extension FITS file.
hdrl_catalogue_result * hdrl_catalogue_compute(const cpl_image *image_, const cpl_image *confidence_map, const cpl_wcs *wcs, hdrl_parameter *param_)
build object catalog
void hdrl_catalogue_result_delete(hdrl_catalogue_result *result)
delete hdrl parameter result object
hdrl_parameter * hdrl_collapse_mode_parameter_create(double histo_min, double histo_max, double bin_size, hdrl_mode_type mode_method, cpl_size error_niter)
create a parameter object for the mode
hdrl_parameter * hdrl_flat_parameter_create(cpl_size filter_size_x, cpl_size filter_size_y, hdrl_flat_method method)
Creates FLAT Parameters object.
Definition: hdrl_flat.c:173
cpl_error_code hdrl_flat_compute(hdrl_imagelist *hdrl_data, const cpl_mask *stat_mask, const hdrl_parameter *collapse_params, hdrl_parameter *flat_params, hdrl_image **master, cpl_image **contrib_map)
compute high or low frequency master flat with median filtering
Definition: hdrl_flat.c:405
hdrl_value hdrl_image_get_pixel(const hdrl_image *self, cpl_size xpos, cpl_size ypos, int *pis_rejected)
get pixel values of hdrl_image
Definition: hdrl_image.c:559
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
double hdrl_image_get_stdev(const hdrl_image *self)
computes the standard deviation of the data of an image
cpl_error_code hdrl_image_copy(hdrl_image *dst, const hdrl_image *src, cpl_size xpos, cpl_size ypos)
Copy one image into another.
Definition: hdrl_image.c:686
cpl_mask * hdrl_image_get_mask(hdrl_image *himg)
get cpl bad pixel mask from image
Definition: hdrl_image.c:157
hdrl_image * hdrl_image_extract(const hdrl_image *self, cpl_size llx, cpl_size lly, cpl_size urx, cpl_size ury)
extract copy of window from image
Definition: hdrl_image.c:625
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_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
Definition: hdrl_image.c:540
cpl_size hdrl_image_get_size_x(const hdrl_image *self)
return size of X dimension of image
Definition: hdrl_image.c:525
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
cpl_error_code hdrl_image_reject(hdrl_image *self, cpl_size xpos, cpl_size ypos)
mark pixel as bad
Definition: hdrl_image.c:427
const cpl_image * hdrl_image_get_image_const(const hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:118
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
Definition: hdrl_image.c:379
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.
const hdrl_image * hdrl_imagelist_get_const(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
cpl_error_code hdrl_imagelist_collapse(const hdrl_imagelist *himlist, const hdrl_parameter *param, hdrl_image **out, cpl_image **contrib)
collapsing of image list
hdrl_imagelist * hdrl_imagelist_new(void)
Create an empty imagelist.
cpl_error_code hdrl_imagelist_collapse_median(const hdrl_imagelist *himlist, hdrl_image **out, cpl_image **contrib)
Median collapsing of image list.
hdrl_imagelist * hdrl_imagelist_duplicate(const hdrl_imagelist *himlist)
Duplicate an image list.
cpl_size hdrl_imagelist_get_size_x(const hdrl_imagelist *himlist)
Get number of colums of images in the imagelist.
cpl_error_code hdrl_imagelist_collapse_weighted_mean(const hdrl_imagelist *himlist, hdrl_image **out, cpl_image **contrib)
Weighted Mean collapsing of image list.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
cpl_error_code hdrl_maglim_compute(const cpl_image *image, const double zeropoint, const double fwhm, const cpl_size kernel_size_x, const cpl_size kernel_size_y, const hdrl_image_extend_method image_extend_method, const hdrl_parameter *mode_parameter, double *limiting_magnitude)
Computes the limiting magnitude of an image.
Definition: hdrl_maglim.c:114
void hdrl_parameter_delete(hdrl_parameter *obj)
shallow delete of a parameter
double fraction(double x, double y, double r_out)
Fraction of pixel bounded.