ERIS Pipeline Reference Manual 1.9.2
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 eris_check_error_code("enu_basic_calibrate");
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 eris_check_error_code("enu_basic_calibrate_himage");
756 return cpl_error_get_code();;
757}
758
759
760/*----------------------------------------------------------------------------*/
771/*----------------------------------------------------------------------------*/
772
773hdrl_image * enu_calc_flat(hdrl_imagelist * himlist,
774 const int min_coadds,
775 const hdrl_parameter * collapse_params,
776 const cpl_size filter_size_x,
777 const cpl_size filter_size_y,
778 const hdrl_flat_method method) {
779
780 /* entry check */
781
782 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
783 cpl_ensure(himlist, CPL_ERROR_NULL_INPUT, NULL);
784 cpl_ensure(collapse_params, CPL_ERROR_NULL_INPUT, NULL);
785
786 cpl_image * contribution = NULL;
787 hdrl_parameter * flat_params = NULL;
788 hdrl_image * result = NULL;
789
790 /* verify that we have enough difference results */
791
792 const cpl_size size = hdrl_imagelist_get_size(himlist);
793 enu_check(size >= min_coadds, CPL_ERROR_ILLEGAL_INPUT,
794 "insufficient frames for flat (%d<min:%d)",
795 (int) size, min_coadds);
796
797 /* calculate the flatfield */
798
799 flat_params = hdrl_flat_parameter_create(filter_size_x,
800 filter_size_y,
801 method);
802 if (method == HDRL_FLAT_FREQ_HIGH) {
803 cpl_msg_info(cpl_func, "Calculating high freq flatfield");
804 } else if (method == HDRL_FLAT_FREQ_LOW) {
805 cpl_msg_info(cpl_func, "Calculating low freq flatfield");
806 }
807 cpl_msg_info(cpl_func, "..smoothing filter sizes %d %d",
808 (int)filter_size_x, (int)filter_size_y);
809 hdrl_flat_compute(himlist, NULL, collapse_params,
810 flat_params, &result, &contribution);
811 enu_check_error_code("error computing flat-field");
812
813 cleanup:
814 cpl_image_delete(contribution);
815 hdrl_parameter_delete(flat_params);
816 if (cpl_error_get_code() != CPL_ERROR_NONE) {
817 hdrl_image_delete(result);
818 result = NULL;
819 }
820 eris_check_error_code("enu_calc_flat");
821 return result;
822}
823
824
825/*----------------------------------------------------------------------------*/
836/*----------------------------------------------------------------------------*/
837
838cpl_error_code enu_calc_maglim(const located_image * limage,
839 const double photzp,
840 const double fwhm_pix,
841 double * abmaglim) {
842
843 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
844 cpl_ensure_code(limage, CPL_ERROR_NULL_INPUT);
845 cpl_ensure_code(abmaglim, CPL_ERROR_NULL_INPUT);
846
847 /* bad data in gives bad result */
848 if (fwhm_pix <= 0.0) {
849 *abmaglim = -1.0;
850 return CPL_ERROR_NONE;
851 }
852
853 /* calculate magnitude limit using HDRL */
854 /* ..set mode calculation following HDRL docs example */
855
856 double histo_min = 10.;
857 double histo_max = 1.;
858 histo_min=0;
859 histo_max=0;
860 double bin_size = 0.;
861 cpl_size error_niter = 0;
862 hdrl_mode_type mode_method = HDRL_MODE_MEDIAN;
863 hdrl_parameter * mode_parameter = NULL;
864 mode_parameter = hdrl_collapse_mode_parameter_create(histo_min,
865 histo_max,
866 bin_size,
867 mode_method,
868 error_niter);
869 /* AMO: the following is NOT required */
870 double* pdata = cpl_image_get_data_double(hdrl_image_get_image(limage->himage));
871 double* pconf = cpl_image_get_data_double(limage->confidence);
872 cpl_size sx = hdrl_image_get_size_x(limage->himage);
873 cpl_size sy = hdrl_image_get_size_y(limage->himage);
874 cpl_mask* mask_data = cpl_image_get_bpm(hdrl_image_get_image(limage->himage));
875 cpl_mask* mask_errs = cpl_image_get_bpm(hdrl_image_get_error(limage->himage));
876 cpl_binary* pbpm_data = cpl_mask_get_data(mask_data);
877 cpl_binary* pbpm_errs = cpl_mask_get_data(mask_errs);
878 for(cpl_size indexj = 0; indexj < sy; indexj++) {
879 for(cpl_size indexi = 0; indexi < sx; indexi++) {
880 if(!isfinite(pdata[indexi+indexj*sx]) ) {
881 pbpm_data[indexi+indexj*sx] = CPL_BINARY_1;
882 pbpm_errs[indexi+indexj*sx] = CPL_BINARY_1;
883 pconf[indexi+indexj*sx] = CPL_BINARY_1;
884//cpl_msg_warning(cpl_func,"found bad pixel at : [%lld,%lld]",indexi,indexj);
885 }
886 }
887 }
888
889
891 photzp,
892 fwhm_pix,
893 ((int) (3.0 * fwhm_pix) / 2) * 2 + 1,
894 ((int) (3.0 * fwhm_pix) / 2) * 2 + 1,
895 HDRL_IMAGE_EXTEND_MIRROR,
896 mode_parameter,
897 abmaglim);
898 hdrl_parameter_delete(mode_parameter);
899
900 eris_check_error_code("enu_calc_maglim");
901 return cpl_error_get_code();
902}
903
904
905/*----------------------------------------------------------------------------*/
916/*----------------------------------------------------------------------------*/
917
918cpl_error_code enu_calc_pixel_coords(cpl_table * catalogue,
919 const cpl_propertylist * wcs_plist) {
920
921 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
922 cpl_ensure_code(catalogue, CPL_ERROR_NULL_INPUT);
923 cpl_ensure_code(wcs_plist, CPL_ERROR_NULL_INPUT);
924
925 cpl_array * conv_status = NULL;
926 cpl_matrix * ref_phys = NULL;
927 cpl_matrix * ref_world = NULL;
928 cpl_wcs * wcs = NULL;
929
930 /* write files with inputs for regression testing - uncomment if required
931 cpl_propertylist * wcs_plist_copy = cpl_propertylist_duplicate(wcs_plist);
932 cpl_propertylist_erase_regexp(wcs_plist_copy, CPL_WCS_REGEXP, 1);
933 cpl_propertylist_save(wcs_plist_copy, "enu_calc_pixel_coords_test_wcs.fits",
934 CPL_IO_CREATE);
935 cpl_table_save(catalogue, NULL, NULL,
936 "enu_calc_pixel_coords_test_input_table.fits",
937 CPL_IO_CREATE);
938 */
939
940 cpl_size nobj = cpl_table_get_nrow(catalogue);
941 const double * ra = cpl_table_get_data_double_const(catalogue, "RA");
942 const double * dec = NULL;
943// if (cpl_table_has_column(catalogue, "Dec")) {
944// dec = cpl_table_get_data_double_const(catalogue, "Dec");
945// } else if (cpl_table_has_column(catalogue, "DEC")) {
946 if (cpl_table_has_column(catalogue, "DEC")) {
947 dec = cpl_table_get_data_double_const(catalogue, "DEC");
948 }
949 ref_world = cpl_matrix_new(nobj, 2);
950 for (cpl_size iobj = 0; iobj < nobj; iobj++) {
951 cpl_matrix_set(ref_world, iobj, 0, ra[iobj]);
952 cpl_matrix_set(ref_world, iobj, 1, dec[iobj]);
953 }
954
955 wcs = cpl_wcs_new_from_propertylist(wcs_plist);
956
957 cpl_wcs_convert(wcs, ref_world, &ref_phys, &conv_status,
958 CPL_WCS_WORLD2PHYS);
959 enu_check_error_code("failure calculating predicted positions");
960
961 /* Store the predicted positions in columns X_coordinate and
962 Y_coordinate, create thes if necessary */
963
964 if (!cpl_table_has_column(catalogue, "X_coordinate")) {
965 cpl_table_new_column(catalogue, "X_coordinate", CPL_TYPE_DOUBLE);
966 }
967 if (!cpl_table_has_column(catalogue, "Y_coordinate")) {
968 cpl_table_new_column(catalogue, "Y_coordinate", CPL_TYPE_DOUBLE);
969 }
970
971 for (cpl_size iobj = 0; iobj < nobj; iobj++) {
972 cpl_table_set_double(catalogue, "X_coordinate", iobj,
973 cpl_matrix_get(ref_phys, iobj, 0));
974 cpl_table_set_double(catalogue, "Y_coordinate", iobj,
975 cpl_matrix_get(ref_phys, iobj, 1));
976 }
977
978 /* write file with output for regression testing - uncomment if required
979 cpl_table_save(catalogue, NULL, NULL,
980 "enu_calc_pixel_coords_test_output_table.fits",
981 CPL_IO_CREATE);
982 */
983
984 cleanup:
985 cpl_array_delete(conv_status);
986 cpl_matrix_delete(ref_phys);
987 cpl_matrix_delete(ref_world);
988 cpl_wcs_delete(wcs);
989 eris_check_error_code("enu_calc_pixel_coords");
990 return cpl_error_get_code();
991}
992
993
994/*----------------------------------------------------------------------------*/
1009/*----------------------------------------------------------------------------*/
1010
1011hdrl_catalogue_result * enu_catalogue_compute(
1012 const hdrl_image * himage,
1013 const cpl_image * confidence,
1014 const cpl_wcs * wcs,
1015 hdrl_parameter * params) {
1016
1017 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
1018
1019 cpl_ensure(himage, CPL_ERROR_NULL_INPUT, NULL);
1020/*
1021 cpl_ensure(confidence, CPL_ERROR_NULL_INPUT, NULL);
1022*/
1023 cpl_ensure(wcs, CPL_ERROR_NULL_INPUT, NULL);
1024 cpl_ensure(params, CPL_ERROR_NULL_INPUT, NULL);
1025
1026 hdrl_catalogue_result * result = NULL;
1027
1028 if (confidence) {
1029
1030 /* Check that the confidence array for the image is not zero -
1031 this causes a non-obvious error to be generated deep in the
1032 casu routines */
1033
1034 cpl_ensure(cpl_image_get_max(confidence) > 0.0, CPL_ERROR_ILLEGAL_INPUT,
1035 NULL);
1036 }
1037
1039 confidence, wcs, params);
1040
1041 /* REMOVE THE FOLLOWING FOR NOW. IT WAS A FUDGE TO TRY AND IMPROVE
1042 SOURCE MATCHING BETWEN JITTERS - BUT BETTER TO LEAVE IT IN AND
1043 FILTER LATER AS REQUIRED */
1044 /* Remove catalogue entries with low Av_conf.
1045 CASU documentation: Av_conf = the average confidence level within the
1046 default rcore aperture useful for
1047 spotting spurious outliers in various
1048 parameter selection spaces.
1049 The NIX detector has patches with a low density of working pixels
1050 which equate to areas of low confidence */
1051/*
1052 cpl_table_and_selected_double(result->catalogue, "Av_conf", CPL_LESS_THAN,
1053 90.);
1054 cpl_table_erase_selected(result->catalogue);
1055*/
1056
1057 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1058
1059 /* Return NULL on error */
1060
1062 result = NULL;
1063
1064 /* but trap case where simply no objects were present
1065 - for our purposes this is not an error */
1066
1067 const char * message = cpl_error_get_message();
1068 cpl_msg_info(cpl_func, "catalogue %s", message);
1069
1070 if (strstr(message, "No objects found in image")) {
1071 cpl_msg_warning(cpl_func, "No objects found in image");
1072 cpl_error_reset();
1073 }
1074 }
1075 eris_check_error_code("enu_catalogue_compute");
1076 return result;
1077}
1078
1079
1080/*----------------------------------------------------------------------------*/
1089/*----------------------------------------------------------------------------*/
1090
1091cpl_vector * enu_bracket_skys(const located_image * target,
1092 const double timerange,
1093 const located_imagelist * pool,
1094 const int debug) {
1095
1096 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
1097
1098 cpl_ensure(target, CPL_ERROR_NULL_INPUT, NULL);
1099 cpl_ensure(timerange > 0.0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1100 cpl_ensure(pool, CPL_ERROR_NULL_INPUT, NULL);
1101
1102 cpl_vector * result = NULL;
1103 cpl_vector * result_diff = NULL;
1104
1105 double target_mjd = cpl_propertylist_get_double(target->plist, "MJD-OBS");
1106
1107 for (cpl_size j = 0; j < pool->size; j++) {
1108 double mjd_j = cpl_propertylist_get_double((pool->limages[j])->
1109 plist, "MJD-OBS");
1110 double diff = (target_mjd - mjd_j) * 3600.0 * 24.0;
1111
1112 if (fabs(diff) < timerange/2.0) {
1113 if (result == NULL) {
1114 result = cpl_vector_new(1);
1115 result_diff = cpl_vector_new(1);
1116 cpl_vector_set(result, 0, (double)j);
1117 cpl_vector_set(result_diff, 0, diff);
1118 } else {
1119 cpl_size size = cpl_vector_get_size(result);
1120 cpl_vector_set_size(result, size + 1);
1121 cpl_vector_set_size(result_diff, size + 1);
1122 cpl_vector_set(result, size, (double)j);
1123 cpl_vector_set(result_diff, size, diff);
1124 }
1125 }
1126 }
1127 enu_check_error_code("error in enu_bracket_skys: %s",
1128 cpl_error_get_message());
1129 enu_check(result && cpl_vector_get_size(result) > 0,
1130 CPL_ERROR_INCOMPATIBLE_INPUT,
1131 "no sky frames found within %f sec of target frame", timerange/2.0);
1132
1133 if (debug) {
1134 cpl_size size = cpl_vector_get_size(result);
1135 if (size > 0) {
1136 cpl_msg_info(" ", ".. enu_bracket_skys: timerange %5.1f", timerange);
1137 cpl_msg_info(" ", ".. j# diff(sec)");
1138 }
1139 for (cpl_size i = 0; i < size; i++) {
1140 int j = cpl_vector_get(result, i);
1141 double diff = cpl_vector_get(result_diff, i);
1142 cpl_msg_info(" ", ".. %3d %7.1f", j, diff);
1143 }
1144 }
1145
1146 cleanup:
1147 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1148 cpl_vector_delete(result);
1149 result = NULL;
1150 }
1151 cpl_vector_delete(result_diff);
1152 eris_check_error_code("enu_bracket_skys");
1153 return result;
1154}
1155
1156
1157/*----------------------------------------------------------------------------*/
1165/*----------------------------------------------------------------------------*/
1166
1167cpl_error_code enu_catalogue_limlist(located_imagelist * limlist,
1168 hdrl_parameter * params) {
1169
1170 cpl_ensure_code(cpl_error_get_code() == CPL_ERROR_NONE,
1171 cpl_error_get_code());
1172 cpl_ensure_code(limlist, CPL_ERROR_NULL_INPUT);
1173 cpl_ensure_code(params, CPL_ERROR_NULL_INPUT);
1174
1175 cpl_size njitters = limlist->size;
1176 cpl_msg_info(cpl_func, "cataloguing %d images", (int) njitters);
1177
1178 for (cpl_size i = 0; i < njitters; i++) {
1179 cpl_wcs * wcs = cpl_wcs_new_from_propertylist
1180 (limlist->limages[i]->plist);
1181 cpl_msg_info(cpl_func, "cataloguing image %d", (int) i);
1182 /* AMO the following is required to handle bad pixels that were not all flagged */
1183 double* pdata = cpl_image_get_data_double(hdrl_image_get_image((limlist->limages[i])->himage));
1184 //double* perrs = cpl_image_get_data_double(hdrl_image_get_error((limlist->limages[i])->himage));
1185 cpl_size sx = hdrl_image_get_size_x(limlist->limages[i]->himage);
1186 cpl_size sy = hdrl_image_get_size_y(limlist->limages[i]->himage);
1187 cpl_mask* mask = cpl_image_get_bpm(hdrl_image_get_image(limlist->limages[i]->himage));
1188 cpl_mask* mskerr = cpl_image_get_bpm(hdrl_image_get_error(limlist->limages[i]->himage));
1189 double* pconf = cpl_image_get_data_double(limlist->limages[i]->confidence);
1190 cpl_binary* pbpm_data = cpl_mask_get_data(mask);
1191 cpl_binary* pbpm_errs = cpl_mask_get_data(mskerr);
1192 for(cpl_size indexj = 0; indexj < sy; indexj++) {
1193 for(cpl_size indexi = 0; indexi < sx; indexi++) {
1194 if(!isfinite(pdata[indexi+indexj*sx]) ) {
1195 pbpm_data[indexi+indexj*sx] = CPL_BINARY_1;
1196 pbpm_errs[indexi+indexj*sx] = CPL_BINARY_1;
1197 pconf[indexi+indexj*sx] = 0;
1198 }
1199 }
1200 }
1201
1202 //TODO AMO: the following call generates a memory leak
1203 limlist->limages[i]->objects = enu_catalogue_compute(
1204 limlist->limages[i]->himage,
1205 limlist->limages[i]->confidence,
1206 wcs,
1207 params);
1208 cpl_wcs_delete(wcs);
1209
1210 if (cpl_error_get_code() != CPL_ERROR_NONE) break;
1211 }
1212 eris_check_error_code("enu_catalogue_limlist");
1213 return cpl_error_get_code();
1214}
1215
1216
1217/*----------------------------------------------------------------------------*/
1232/*----------------------------------------------------------------------------*/
1233
1234int enu_check_conformance(const cpl_propertylist * plist1,
1235 const cpl_propertylist * plist2,
1236 const char * regexp) {
1237
1238 if (cpl_error_get_code() != CPL_ERROR_NONE) return 0;
1239
1240 /* Check parameters not NULL */
1241
1242 cpl_ensure(plist1 && plist2 && regexp, CPL_ERROR_NULL_INPUT, 0);
1243
1244 int result = CPL_TRUE;
1245 char * reason = NULL;
1246
1247 /* Create the two subsets to be compared */
1248
1249 cpl_propertylist * subset1 = cpl_propertylist_new();
1250 cpl_propertylist_copy_property_regexp(subset1, plist1, regexp, 0);
1251 cpl_propertylist * subset2 = cpl_propertylist_new();
1252 cpl_propertylist_copy_property_regexp(subset2, plist2, regexp, 0);
1253 enu_check_error_code("error deriving subset of propertylist");
1254
1255 /* Compare them */
1256
1257 cpl_size size1 = cpl_propertylist_get_size(subset1);
1258 cpl_size size2 = cpl_propertylist_get_size(subset2);
1259 if (size1 != size2) {
1260 result = CPL_FALSE;
1261 reason = cpl_sprintf("propertylist sizes do not match %s", " ");
1262 } else {
1263 for (cpl_size i=0; i<size1; i++) {
1264 const cpl_property * prop1 = cpl_propertylist_get(subset1, i);
1265 const char * name = cpl_property_get_name(prop1);
1266
1267 /* does the second list have a property of that name? */
1268
1269 if (!cpl_propertylist_has(subset2, name)) {
1270 result = CPL_FALSE;
1271 reason = cpl_sprintf("name mismatch: %s", name);
1272 break;
1273 }
1274
1275 /* do the values match? */
1276
1277 const cpl_property * prop2 = cpl_propertylist_get_property_const(
1278 subset2, name);
1279
1280 const cpl_type type1 = cpl_property_get_type(prop1);
1281 const cpl_type type2 = cpl_property_get_type(prop2);
1282 if (type1 != type2) {
1283 result = CPL_FALSE;
1284 reason = cpl_sprintf("type mismatch: name %s: types %s and %s",
1285 name,
1286 cpl_type_get_name(cpl_property_get_type(prop1)),
1287 cpl_type_get_name(cpl_property_get_type(prop2)));
1288 break;
1289 }
1290
1291 int ival1 = 0;
1292 int ival2 = 0;
1293 double dval1 = 0.0;
1294 double dval2 = 0.0;
1295 const char * sval1 = NULL;
1296 const char * sval2 = NULL;
1297
1298 switch (type1) {
1299 case CPL_TYPE_INT:
1300 ival1 = cpl_property_get_int(prop1);
1301 ival2 = cpl_property_get_int(prop2);
1302 if (ival1 != ival2) {
1303 result = CPL_FALSE;
1304 reason = cpl_sprintf("value mismatch: name %s: values "
1305 "%d and %d",
1306 name, ival1, ival2);
1307 }
1308 break;
1309
1310 case CPL_TYPE_DOUBLE:
1311 dval1 = cpl_property_get_double(prop1);
1312 dval2 = cpl_property_get_double(prop2);
1313 if (dval1 != dval2) {
1314 result = CPL_FALSE;
1315 reason = cpl_sprintf("value mismatch: name %s: values "
1316 "%4.2e and %4.2e",
1317 name, dval1, dval2);
1318 }
1319 break;
1320
1321 case CPL_TYPE_STRING:
1322 sval1 = cpl_property_get_string(prop1);
1323 sval2 = cpl_property_get_string(prop2);
1324 if (strcmp(sval1, sval2)) {
1325 result = CPL_FALSE;
1326 reason = cpl_sprintf("value mismatch: name %s: values "
1327 "%s, %s", name, sval1, sval2);
1328 }
1329 break;
1330 default:
1331 cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
1332 "name %s, type not handled %s",
1333 name, cpl_type_get_name(
1334 cpl_property_get_type(prop1)));
1335 break;
1336
1337 if (result == CPL_FALSE) break;
1338 }
1339 }
1340 }
1341
1342cleanup:
1343
1344 cpl_propertylist_delete(subset1);
1345 cpl_propertylist_delete(subset2);
1346
1347
1348 /* Always return False on error */
1349
1350 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1351 result = CPL_FALSE;
1352 } else {
1353 if (result == CPL_FALSE) {
1354 cpl_msg_info(cpl_func, "propertylist match failed: %s", reason);
1355 }
1356 }
1357 cpl_free(reason);
1358 eris_check_error_code("enu_check_conformance");
1359 return result;
1360}
1361
1362
1363/*----------------------------------------------------------------------------*/
1375/*----------------------------------------------------------------------------*/
1376
1377cpl_error_code enu_check_wcs(const located_image * limage) {
1378
1379 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
1380 cpl_ensure_code(limage, CPL_ERROR_NULL_INPUT);
1381
1382 cpl_boolean bad = CPL_FALSE;
1383
1384 if (!cpl_propertylist_has(limage->plist, "CTYPE1")) {
1385 bad = CPL_TRUE;;
1386 }
1387 if (!bad) {
1388 const char * ctype1 = cpl_propertylist_get_string(
1389 limage->plist, "CTYPE1");
1390 if (strstr(ctype1, "PIXEL")) {
1391 bad = CPL_TRUE;
1392 }
1393 }
1394
1395 if (!bad) {
1396 if (!cpl_propertylist_has(limage->plist, "CTYPE2")) {
1397 bad = CPL_TRUE;
1398 }
1399 }
1400 if (!bad) {
1401 const char * ctype2 = cpl_propertylist_get_string(limage->plist,
1402 "CTYPE2");
1403 if (strstr(ctype2, "PIXEL")) {
1404 bad = CPL_TRUE;
1405 }
1406 }
1407
1408 cpl_error_code result = cpl_error_get_code();
1409 if (result == CPL_ERROR_NONE && bad) {
1410 result = cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1411 "missing or bad WCS keywords in "
1412 "input file %s",
1413 cpl_frame_get_filename(limage->frame));
1414 }
1415 eris_check_error_code("enu_check_wcs");
1416 return result;
1417}
1418
1419
1420/*----------------------------------------------------------------------------*/
1433/*----------------------------------------------------------------------------*/
1434
1435cpl_error_code enu_debug_limlist_save(const int debug,
1436 const located_imagelist * limlist,
1437 const char * nameroot,
1438 const char * recipename,
1439 cpl_frameset * frameset,
1440 const cpl_parameterlist * parlist,
1441 const cpl_frameset * used) {
1442
1443 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
1444 if (!debug) return CPL_ERROR_NONE;
1445 cpl_ensure_code(limlist, CPL_ERROR_NULL_INPUT);
1446 cpl_ensure_code(nameroot, CPL_ERROR_NULL_INPUT);
1447 cpl_ensure_code(recipename, CPL_ERROR_NULL_INPUT);
1448 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
1449 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
1450 cpl_ensure_code(used, CPL_ERROR_NULL_INPUT);
1451
1452 char * fname_copy = NULL;
1453 char * out_fname = NULL;
1454
1455 /* loop through images */
1456
1457 cpl_size nimages = limlist->size;
1458 for (cpl_size j = 0; j < nimages; j++) {
1459
1460 /* generate name of output file */
1461
1462 if (limlist->limages[j]->frame) {
1463 const char * fname = cpl_frame_get_filename(
1464 limlist->limages[j]->frame);
1465 fname_copy = cpl_strdup(fname);
1466 } else {
1467 const char * fname = "debug.fits";
1468 fname_copy = cpl_strdup(fname);
1469 }
1470 out_fname = cpl_sprintf("%s_%s", nameroot, basename(fname_copy));
1471
1472 cpl_msg_info(cpl_func, "..(debug) writing %s", out_fname);
1473
1474 /* some dummy info to keep dfs happy */
1475
1476 cpl_propertylist * applist = cpl_propertylist_new();
1477 cpl_propertylist_update_string(applist,
1478 CPL_DFS_PRO_CATG,
1479 "debug");
1480 cpl_propertylist_update_string(applist, "PRODCATG", "ANCILLARY.IMAGE");
1481
1482 cpl_frameset * provenance = cpl_frameset_new();
1483 cpl_frameset_insert(provenance, cpl_frame_duplicate(
1484 limlist->limages[j]->frame));
1485
1486 enu_dfs_save_limage(frameset,
1487 parlist,
1488 provenance,
1489 CPL_TRUE,
1490 limlist->limages[j],
1491 recipename,
1492 limlist->limages[j]->frame,
1493 applist,
1494 "test",
1495 out_fname);
1496
1497 cpl_frameset_delete(provenance);
1498 cpl_propertylist_delete(applist);
1499 }
1500
1501 /* tidy up */
1502
1503 cpl_free(fname_copy);
1504 cpl_free(out_fname);
1505 eris_check_error_code("enu_debug_limlist_save");
1506 return cpl_error_get_code();
1507}
1508
1509
1510/*----------------------------------------------------------------------------*/
1523/*----------------------------------------------------------------------------*/
1524
1525cpl_error_code enu_flat_save(const char * pro_catg,
1526 const hdrl_image * flat,
1527 const cpl_image * confidence,
1528 const cpl_mask * cold_bpm,
1529 cpl_frameset * frameset,
1530 const cpl_parameterlist * parlist,
1531 const char * filename,
1532 const char * recipe_name,
1533 const cpl_propertylist* qclog) {
1534
1535 /* checks */
1536
1537 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
1538 cpl_ensure_code(pro_catg, CPL_ERROR_NULL_INPUT);
1539 cpl_ensure_code(flat, CPL_ERROR_NULL_INPUT);
1540 cpl_ensure_code(frameset, CPL_ERROR_NULL_INPUT);
1541 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
1542 cpl_ensure_code(filename, CPL_ERROR_NULL_INPUT);
1543
1544 mef_extension_list * mefs = NULL;
1545 cpl_propertylist * plist = NULL;
1546
1547 /* make output propertylist */
1548
1549 plist = cpl_propertylist_new();
1550 cpl_propertylist_append_string(plist, CPL_DFS_PRO_CATG, pro_catg);
1551 cpl_propertylist_update_string(plist, "PRODCATG", "ANCILLARY.IMAGE");
1552
1553 /* add QC parameters */
1554
1555 hdrl_value flat_median = hdrl_image_get_median(flat);
1556 cpl_propertylist_append_double(plist, "ESO QC FLAT MED",
1557 (double) flat_median.data);
1558 cpl_propertylist_set_comment(plist,"ESO QC FLAT MED",
1559 "[ADU] Median flat value");
1560 hdrl_value flat_mean = hdrl_image_get_mean(flat);
1561 cpl_propertylist_append_double(plist, "ESO QC FLAT MEAN",
1562 (double) flat_mean.data);
1563 cpl_propertylist_set_comment(plist,"ESO QC FLAT MEAN",
1564 "[ADU] Mean flat value");
1565 double flat_rms = hdrl_image_get_stdev(flat);
1566 cpl_propertylist_append_double(plist, "ESO QC FLAT RMS", flat_rms);
1567 cpl_propertylist_set_comment(plist,"ESO QC FLAT RMS",
1568 "[ADU] RMS flat value");
1569 /* the normalisation factor is not returned by hdrl_flat_compute,
1570 and is cumbersome to obtain otherwise */
1571
1572 cpl_msg_warning(cpl_func, "TBD: calculate normalisation value");
1573 double norm = -1.0;
1574 cpl_propertylist_append_double(plist, "ESO QC FLAT NORM", norm);
1575 cpl_propertylist_set_comment(plist,"ESO QC FLAT NORM",
1576 "Flat normalisation value");
1577 if(cold_bpm) {
1578 cpl_size ncold = cpl_mask_count(cold_bpm);
1579 cpl_propertylist_append_double(plist, "ESO QC NUMBER COLD PIXELS",
1580 ncold);
1581 cpl_propertylist_set_comment(plist,"ESO QC NUMBER COLD PIXELS",
1582 "Number of cold pixels");
1583 }
1584 enu_check_error_code("error constructing output propertylist");
1585
1586 /* save the flat to a DFS-compliant MEF file */
1587
1588 if (!cold_bpm) {
1590 mefs->mef[0] = enu_mef_new_image("CONFIDENCE", confidence, NULL);
1591 } else {
1593 mefs->mef[0] = enu_mef_new_mask("COLD_BPM", cold_bpm, NULL);
1594 mefs->mef[1] = enu_mef_new_image("CONFIDENCE", confidence, NULL);
1595 }
1596 if(qclog != NULL) {
1597 cpl_propertylist_append(plist, qclog);
1598 }
1599 enu_dfs_save_himage(frameset,
1600 parlist,
1601 frameset,
1602 CPL_TRUE,
1603 flat,
1604 NULL,
1605 mefs,
1606 recipe_name,
1607 NULL,
1608 plist,
1609 NULL,
1610 PACKAGE "/" PACKAGE_VERSION,
1611 filename);
1612
1613 cleanup:
1615 cpl_propertylist_delete(plist);
1616 eris_check_error_code("enu_flat_save");
1617 return cpl_error_get_code();
1618}
1619
1620
1621/*----------------------------------------------------------------------------*/
1635/*----------------------------------------------------------------------------*/
1636double enu_get_airmass(const cpl_propertylist * plist) {
1637
1638 if (cpl_error_get_code() != CPL_ERROR_NONE) return 0;
1639
1640 double airmass = 0.0;
1641 if (cpl_propertylist_has(plist, "AIRMASS")) {
1642 /* NACO */
1643 airmass = cpl_propertylist_get_double(plist, "AIRMASS");
1644 } else if (cpl_propertylist_has(plist, "ESO TEL AIRM START")) {
1645 /* NIX */
1646 const double astart = cpl_propertylist_get_double(plist,
1647 "ESO TEL AIRM START");
1648 const double aend = cpl_propertylist_get_double(plist,
1649 "ESO TEL AIRM END");
1650 airmass = (astart + aend) / 2.0;
1651
1652 /* check for failure to set AIRM keywords correctly */
1653 const double alt = cpl_propertylist_get_double(plist,
1654 "ESO TEL ALT");
1655 double airmass_alt = 1.0 /cos ((90.0 - alt) * CPL_MATH_PI / 180.0);
1656 if (fabs(airmass - airmass_alt) > 1.0e-5) {
1657 cpl_msg_warning(cpl_func, "discrepency - airmass %f -> %f", airmass,
1658 airmass_alt);
1659 airmass = airmass_alt;
1660 }
1661 } else {
1662 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1663 "unable to find airmass information");
1664 }
1665 eris_check_error_code("enu_get_airmass");
1666 return airmass;
1667}
1668
1669
1670/*----------------------------------------------------------------------------*/
1689/*----------------------------------------------------------------------------*/
1690
1691cpl_error_code enu_get_rcore_and_mesh_size(const char * context,
1692 const cpl_parameterlist * parlist,
1693 const cpl_propertylist * plist,
1694 double * obj_core_radius,
1695 int * bkg_mesh_size) {
1696
1697 char * param_name = NULL;
1698 const cpl_parameter * p = NULL;
1699 cpl_parameter * par = NULL;
1700
1701 cpl_error_code error_code = CPL_ERROR_NONE;
1702
1703 if (cpl_error_get_code() != CPL_ERROR_NONE) return CPL_ERROR_NONE;
1704 cpl_ensure_code(context, CPL_ERROR_NULL_INPUT);
1705 cpl_ensure_code(parlist, CPL_ERROR_NULL_INPUT);
1706 cpl_ensure_code(plist, CPL_ERROR_NULL_INPUT);
1707 cpl_ensure_code(obj_core_radius, CPL_ERROR_NULL_INPUT);
1708 cpl_ensure_code(bkg_mesh_size, CPL_ERROR_NULL_INPUT);
1709
1710 *obj_core_radius = -1.0;
1711 *bkg_mesh_size = -1;
1712
1713 /* find out if to set catalogue.core-radius and mesh-size to defaults
1714 depending on AOMODE, or to read them from parameters */
1715
1716 param_name = cpl_sprintf("%s.catalogue.ao-params", context);
1717 cpl_msg_info(cpl_func, "%s", param_name);
1718 p = cpl_parameterlist_find_const(parlist, param_name);
1719 const char * ao_params = cpl_parameter_get_string(p);
1720 cpl_free(param_name);
1721 enu_check_error_code("failed to read ao-params");
1722
1723 if (!strcmp(ao_params, "auto") &&
1724 cpl_propertylist_has(plist, "ESO OBS AOMODE")) {
1725 const char * aomode = cpl_propertylist_get_string(plist,
1726 "ESO OBS AOMODE");
1727 cpl_msg_info(cpl_func, "AOMODE: %s", aomode);
1728
1729 if (!strcmp(aomode, "FULL_AO")) {
1730 *obj_core_radius = 10.0;
1731 *bkg_mesh_size = 64;
1732 if(!strstr(context,"skysub")) {
1733
1734 param_name = cpl_sprintf("%s.catalogue.obj.core-radius", context);
1735 par = (cpl_parameter*) cpl_parameterlist_find_const(parlist, param_name);
1736 cpl_parameter_set_double(par, *obj_core_radius);
1737 cpl_free(param_name);
1738
1739 }
1740
1741 param_name = cpl_sprintf("%s.catalogue.bkg.mesh-size", context);
1742 par = (cpl_parameter*) cpl_parameterlist_find_const(parlist, param_name);
1743 cpl_parameter_set_int(par, *bkg_mesh_size);
1744 cpl_free(param_name);
1745
1746 } else if (!strcmp(aomode, "NO_AO")) {
1747 *obj_core_radius = 25.0;
1748 *bkg_mesh_size = 128;
1749 if(!strstr(context,"skysub")) {
1750
1751 param_name = cpl_sprintf("%s.catalogue.obj.core-radius", context);
1752 par = (cpl_parameter*) cpl_parameterlist_find_const(parlist, param_name);
1753 cpl_parameter_set_double(par, *obj_core_radius);
1754 cpl_free(param_name);
1755
1756 }
1757 param_name = cpl_sprintf("%s.catalogue.bkg.mesh-size", context);
1758 par = (cpl_parameter*) cpl_parameterlist_find_const(parlist, param_name);
1759 cpl_parameter_set_int(par, *bkg_mesh_size);
1760 cpl_free(param_name);
1761 } else {
1762 error_code = CPL_ERROR_DATA_NOT_FOUND;
1763 }
1764
1765 } else {
1766 if(!strstr(context,"skysub")) {
1767 param_name = cpl_sprintf("%s.catalogue.obj.core-radius", context);
1768 p = cpl_parameterlist_find_const(parlist, param_name);
1769 *obj_core_radius = cpl_parameter_get_double(p);
1770 cpl_free(param_name);
1771 }
1772
1773 param_name = cpl_sprintf("%s.catalogue.bkg.mesh-size", context);
1774 p = cpl_parameterlist_find_const(parlist, param_name);
1775 *bkg_mesh_size = cpl_parameter_get_int(p);
1776 cpl_free(param_name);
1777 }
1778 cpl_msg_info(cpl_func, "catalogue AO-related params: %s %f %d",
1779 ao_params, *obj_core_radius, *bkg_mesh_size);
1780
1781 cleanup:
1782 eris_check_error_code("enu_get_rcore_and_mesh_size");
1783 return error_code;
1784}
1785
1786
1787/*----------------------------------------------------------------------------*/
1798/*----------------------------------------------------------------------------*/
1799double enu_get_tel_alt(const cpl_propertylist * plist) {
1800
1801 if (cpl_error_get_code() != CPL_ERROR_NONE) return 0;
1802
1803 double tel_alt = 0.0;
1804 if (cpl_propertylist_has(plist, "ESO TEL ALT")) {
1805 /* NACO */
1806 tel_alt = cpl_propertylist_get_double(plist, "ESO TEL ALT");
1807 } else {
1808 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1809 "unable to find ESO TEL ALT information");
1810 }
1811 eris_check_error_code("enu_get_tel_alt");
1812 return tel_alt;
1813}
1814
1815
1816/*----------------------------------------------------------------------------*/
1828/*----------------------------------------------------------------------------*/
1829double enu_get_dit(const cpl_propertylist * plist) {
1830
1831 if (cpl_error_get_code() != CPL_ERROR_NONE) return 0;
1832
1833 double dit = 0.0;
1834 if (cpl_propertylist_has(plist, "ESO DET DIT")) {
1835 dit = cpl_propertylist_get_double(plist, "ESO DET DIT");
1836 } else if (cpl_propertylist_has(plist, "ESO DET SEQ1 DIT")) {
1837 dit = cpl_propertylist_get_double(plist, "ESO DET SEQ1 DIT");
1838 } else {
1839 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1840 "no keyword ESO.DET.DIT or ESO.DET.SEQ1.DIT");
1841 }
1842 eris_check_error_code("enu_get_dit");
1843 return dit;
1844}
1845
1846
1847/*----------------------------------------------------------------------------*/
1859/*----------------------------------------------------------------------------*/
1860const char * enu_get_det_mode(const cpl_propertylist * plist) {
1861
1862 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
1863
1864 const char * result = NULL;
1865 if (cpl_propertylist_has(plist, "ESO DET NCORRS NAME")) {
1866 result = cpl_propertylist_get_string(plist, "ESO DET NCORRS NAME");
1867 } else if (cpl_propertylist_has(plist, "ESO DET READ CURNAME")) {
1868 result = cpl_propertylist_get_string(plist, "ESO DET READ CURNAME");
1869 } else {
1870 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1871 "no keyword ESO.DET.NCORRS.NAME or "
1872 "ESO.DET.READ.CURNAME");
1873 }
1874 eris_check_error_code("enu_get_det_mode");
1875 return result;
1876}
1877
1878
1879/*----------------------------------------------------------------------------*/
1895/*----------------------------------------------------------------------------*/
1896const char * enu_get_filter(const cpl_propertylist * plist) {
1897
1898 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
1899 cpl_ensure(plist, CPL_ERROR_NULL_INPUT, NULL);
1900
1901 const char * filter = NULL;
1902
1903 if (cpl_propertylist_has(plist, "FILTER")) {
1904 filter = cpl_propertylist_get_string(plist, "FILTER");
1905 } else if (cpl_propertylist_has(plist, "INSTRUME")) {
1906 const char * instrume = cpl_propertylist_get_string(plist, "INSTRUME");
1907
1908 if (!strcmp(instrume, "NAOS+CONICA")) {
1909 filter = cpl_propertylist_get_string(plist, "ESO INS OPTI4 NAME");
1910 cpl_msg_info(cpl_func, "OPTI4 %s", filter);
1911 if (!strcmp(filter, "clear") || !strcmp(filter, "empty")) {
1912 filter = cpl_propertylist_get_string(plist, "ESO INS OPTI5 NAME");
1913 cpl_msg_info(cpl_func, "OPTI5 %s", filter);
1914 }
1915 if (!strcmp(filter, "clear") || !strcmp(filter, "empty")) {
1916 filter = cpl_propertylist_get_string(plist, "ESO INS OPTI6 NAME");
1917 cpl_msg_info(cpl_func, "OPTI6 %s", filter);
1918 }
1919 } else if (!strcmp(instrume, "ERIS")) {
1920 filter = cpl_propertylist_get_string(plist, "ESO INS2 NXFW NAME");
1921 } else {
1922 cpl_error_set(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT);
1923 }
1924 } else {
1925 filter = "unknown";
1926 }
1927 eris_check_error_code("enu_get_filter");
1928 return filter;
1929}
1930
1931
1932/*----------------------------------------------------------------------------*/
1945/*----------------------------------------------------------------------------*/
1946
1947double enu_get_filter_wavelength(const char * filter) {
1948
1949 if (cpl_error_get_code() != CPL_ERROR_NONE) return -1.0;
1950 cpl_ensure(filter, CPL_ERROR_NULL_INPUT, -1.0);
1951
1952 double lambda = 1.0;
1953 if (!strcmp(filter, "J")) {
1954 lambda = 1.28;
1955 } else if (!strcmp(filter, "H")) {
1956 lambda = 1.66;
1957 } else if (!strcmp(filter, "Ks")) {
1958 lambda = 2.18;
1959 } else if (!strcmp(filter, "Short-Lp")) {
1960 lambda = 3.32;
1961 } else if (!strcmp(filter, "L-Broad")) {
1962 lambda = 3.57;
1963 } else if (!strcmp(filter, "Lp")) {
1964 lambda = 3.79;
1965 } else if (!strcmp(filter, "Mp")) {
1966 lambda = 4.78;
1967 } else if (!strcmp(filter, "Pa-b")) {
1968 lambda = 1.282;
1969 } else if (!strcmp(filter, "Fe-II")) {
1970 lambda = 1.644;
1971 } else if (!strcmp(filter, "H2-cont")) {
1972 lambda = 2.068;
1973 } else if (!strcmp(filter, "H2-1-0S")) {
1974 lambda = 2.120;
1975 } else if (!strcmp(filter, "Br-g")) {
1976 lambda = 2.172;
1977 } else if (!strcmp(filter, "K-peak")) {
1978 lambda = 2.198;
1979 } else if (!strcmp(filter, "IB-2.42")) {
1980 lambda = 2.420;
1981 } else if (!strcmp(filter, "IB-2.48")) {
1982 lambda = 2.479;
1983 } else if (!strcmp(filter, "Br-a-cont")) {
1984 lambda = 3.965;
1985 } else if (!strcmp(filter, "Br-a")) {
1986 lambda = 4.051;
1987 } else {
1988 cpl_msg_warning(cpl_func, "filter %s not recognized", filter);
1989 }
1990 eris_check_error_code("enu_get_filter_wavelength");
1991 return lambda;
1992}
1993
1994
1995/*----------------------------------------------------------------------------*/
2003/*----------------------------------------------------------------------------*/
2004const char * enu_get_license(void) {
2005
2006 const char * eris_nix_license =
2007 "This file is part of the ERIS/NIX Instrument Pipeline\n"
2008 "Copyright (C) 2017 European Southern Observatory\n"
2009 "\n"
2010 "This program is free software; you can redistribute it and/or modify\n"
2011 "it under the terms of the GNU General Public License as published by\n"
2012 "the Free Software Foundation; either version 2 of the License, or\n"
2013 "(at your option) any later version.\n"
2014 "\n"
2015 "This program is distributed in the hope that it will be useful,\n"
2016 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2017 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
2018 "GNU General Public License for more details.\n"
2019 "\n"
2020 "You should have received a copy of the GNU General Public License\n"
2021 "along with this program; if not, write to the Free Software\n"
2022 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, \n"
2023 "MA 02110-1301 USA";
2024 return eris_nix_license;
2025}
2026
2027
2028/*----------------------------------------------------------------------------*/
2035/*----------------------------------------------------------------------------*/
2036
2037cpl_error_code enu_get_ra_dec(const cpl_wcs * wcs, double * ra, double * dec) {
2038
2039 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
2040 cpl_ensure(wcs, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2041 cpl_ensure(ra, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2042 cpl_ensure(dec, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
2043
2044 /* get the axis centre */
2045
2046 const cpl_array * dims = cpl_wcs_get_image_dims(wcs);
2047 cpl_matrix * from = cpl_matrix_new(1, 2);
2048 int ignore = 0;
2049 double dim = cpl_array_get(dims, 0, &ignore);
2050 cpl_matrix_set(from, 0, 0, dim / 2.0);
2051 dim = cpl_array_get(dims, 1, &ignore);
2052 cpl_matrix_set(from, 0, 1, dim / 2.0);
2053
2054 /* convert to world */
2055
2056 cpl_matrix * to = NULL;
2057 cpl_array * status = NULL;
2058 cpl_wcs_convert(wcs, from, &to, &status, CPL_WCS_PHYS2WORLD);
2059
2060 *ra = cpl_matrix_get(to, 0, 0);
2061 *dec = cpl_matrix_get(to, 0, 1);
2062
2063 /* tidy up */
2064
2065 cpl_matrix_delete(from);
2066 cpl_matrix_delete(to);
2067 cpl_array_delete(status);
2068 eris_check_error_code("enu_get_ra_dec");
2069 return cpl_error_get_code();
2070}
2071
2072
2073/*----------------------------------------------------------------------------*/
2091/*----------------------------------------------------------------------------*/
2092cpl_error_code enu_get_window_info(cpl_size * nx, cpl_size * ny, int * rot,
2093 cpl_size * strx, cpl_size * stry,
2094 cpl_size * nx_chip, cpl_size * ny_chip,
2095 cpl_boolean * windowed,
2096 const cpl_propertylist * plist) {
2097
2098 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
2099
2100 cpl_ensure_code(plist, CPL_ERROR_NULL_INPUT);
2101 enu_check(cpl_propertylist_has(plist, "INSTRUME") == 1,
2102 CPL_ERROR_DATA_NOT_FOUND,
2103 "propertylist does not contain INSTRUME keyword");
2104
2105 /* get window information */
2106
2107 const char * instrume = cpl_propertylist_get_string(plist, "INSTRUME");
2108
2109 cpl_size nxw = 0;
2110 cpl_size nyw = 0;
2111 int rotw = 0;
2112 cpl_size strxw = 0;
2113 cpl_size stryw = 0;
2114
2115 if (!strcmp(instrume, "ERIS")) {
2116 nxw = cpl_propertylist_get_int(plist, "ESO DET SEQ1 WIN NX");
2117 nyw = cpl_propertylist_get_int(plist, "ESO DET SEQ1 WIN NY");
2118 rotw = cpl_propertylist_get_int(plist, "ESO DET SEQ1 WIN ROT");
2119 strxw = cpl_propertylist_get_int(plist, "ESO DET SEQ1 WIN STRX");
2120 stryw = cpl_propertylist_get_int(plist, "ESO DET SEQ1 WIN STRY");
2121 } else {
2122 /* for NACO */
2123 /* STARTX,Y can be stored as double or int */
2124 nxw = cpl_propertylist_get_int(plist, "ESO DET WIN NX");
2125 nyw = cpl_propertylist_get_int(plist, "ESO DET WIN NY");
2126 if (cpl_propertylist_get_type(plist, "ESO DET WIN STARTX") ==
2127 CPL_TYPE_DOUBLE) {
2128 strxw = (int) cpl_propertylist_get_double(plist,
2129 "ESO DET WIN STARTX");
2130 stryw = (int) cpl_propertylist_get_double(plist,
2131 "ESO DET WIN STARTY");
2132 } else {
2133 strxw = cpl_propertylist_get_int(plist, "ESO DET WIN STARTX");
2134 stryw = cpl_propertylist_get_int(plist, "ESO DET WIN STARTY");
2135 }
2136 }
2137
2138 cpl_size nx_chipw = 2048;
2139 cpl_size ny_chipw = 2048;
2140
2141 if(cpl_propertylist_has(plist, "ESO DET CHIP NX")) {
2142 nx_chipw = cpl_propertylist_get_int(plist,"ESO DET CHIP NX");
2143 } else {
2144 nx_chipw = cpl_propertylist_get_int(plist,"ESO DET CHIP1 NX");
2145 }
2146
2147 if(cpl_propertylist_has(plist, "ESO DET CHIP NY")) {
2148 ny_chipw = cpl_propertylist_get_int(plist,"ESO DET CHIP NY");
2149 } else {
2150 ny_chipw = cpl_propertylist_get_int(plist,"ESO DET CHIP1 NY");
2151 }
2152
2153 enu_check_error_code("failed to read detector mode information");
2154 enu_check(rotw == 0, CPL_ERROR_UNSUPPORTED_MODE,
2155 "detector window rot must be 0");
2156
2157 cpl_boolean windowedw = (rotw != 0) ||
2158 (strxw != 1) ||
2159 (stryw != 1) ||
2160 (nxw != nx_chipw) ||
2161 (nyw != ny_chipw);
2162 cpl_msg_info(cpl_func, "flatfield rot=%d strx=%d stry=%d nx=%d ny=%d",
2163 (int)rotw, (int)strxw, (int)stryw, (int)nxw, (int)nyw);
2164
2165 /* only now copy to external variables in case these are
2166 all the same - which would have screwed up the logic above */
2167
2168 *nx = nxw;
2169 *ny = nyw;
2170 *rot = rotw;
2171 *strx = strxw;
2172 *stry = stryw;
2173 *nx_chip = nx_chipw;
2174 *ny_chip = ny_chipw;
2175 *windowed = windowedw;
2176
2177 cleanup:
2178 eris_check_error_code("enu_get_window_info");
2179 return cpl_error_get_code();
2180}
2181
2182
2183/*----------------------------------------------------------------------------*/
2189/*----------------------------------------------------------------------------*/
2191 const hdrl_catalogue_result * target) {
2192 cpl_ensure(target, CPL_ERROR_NULL_INPUT, NULL);
2193
2194 hdrl_catalogue_result * result = cpl_malloc(sizeof(hdrl_catalogue_result));
2195
2196 result->catalogue = cpl_table_duplicate(target->catalogue);
2197 result->background = cpl_image_duplicate(target->background);
2198 result->segmentation_map = cpl_image_duplicate(target->segmentation_map);
2199 result->qclist = cpl_propertylist_duplicate(target->qclist);
2200
2201 return result;
2202}
2203
2204
2205/*----------------------------------------------------------------------------*/
2216/*----------------------------------------------------------------------------*/
2217
2218cpl_error_code enu_himage_load_from_fits(const char * filename,
2219 hdrl_image ** result,
2220 mef_extension_list ** mef_extensions,
2221 cpl_propertylist ** plist) {
2222
2223 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
2224
2225 cpl_propertylist * plist1 = NULL;
2226 cpl_propertylist * plist2 = NULL;
2227 cpl_propertylist * plist3 = NULL;
2228 cpl_image * data = NULL;
2229 cpl_image * error = NULL;
2230 cpl_mask * bpm = NULL;
2231 cpl_mask * old_bpm = NULL;
2232
2233 /* check parameters */
2234
2235 cpl_ensure_code(filename, CPL_ERROR_NULL_INPUT);
2236
2237 /* check FITS files has enough extensions */
2238
2239 cpl_size size = cpl_fits_count_extensions(filename);
2240 cpl_ensure_code(size >= 3, CPL_ERROR_BAD_FILE_FORMAT);
2241
2242 /* Get main propertylist from HDU 0 in the file */
2243
2244 *plist = cpl_propertylist_load(filename, 0);
2245 enu_check_error_code("accessing HDU 0 header");
2246
2247 /* Access HDU 1 in the file, this should contain the data */
2248
2249 plist1 = cpl_propertylist_load(filename, 1);
2250 enu_check_error_code("accessing HDU 1 header");
2251
2252 const char * extname = cpl_propertylist_get_string(plist1, "EXTNAME");
2253 const char * hduclass = cpl_propertylist_get_string(plist1, "HDUCLASS");
2254 const char * hdudoc = cpl_propertylist_get_string(plist1, "HDUDOC");
2255 //const char * hduvers = cpl_propertylist_get_string(plist1, "HDUVERS");
2256 const char * hduclas1 = cpl_propertylist_get_string(plist1, "HDUCLAS1");
2257 const char * hduclas2 = cpl_propertylist_get_string(plist1, "HDUCLAS2");
2258 enu_check_error_code("accessing HDU 1 propertylist");
2259 enu_check(strstr(extname, "DATA") != NULL &&
2260 strstr(hduclass, "ESO") != NULL &&
2261 strstr(hdudoc, "SDP") != NULL &&
2262 strstr(hduclas1, "IMAGE") != NULL &&
2263 strstr(hduclas2, "DATA") != NULL,
2264 CPL_ERROR_BAD_FILE_FORMAT, "bad HD1 format");
2265 data = cpl_image_load(filename, HDRL_TYPE_DATA, 0, 1);
2266 enu_check_error_code("accessing HDU 1 data");
2267
2268 /* the wcs items are stored with the image planes, merge
2269 them back into plist - order is import for the NAXIS*
2270 keywords so the properties are inserted after NAXIS
2271 in reverse order*/
2272
2273 const char * wcs_items = "NAXIS WCSAXES CRPIX1 CRPIX2 "
2274 "CD1_1 CD1_2 CD2_1 CD2_2 CUNIT1 CUNIT2 "
2275 "CTYPE1 CTYPE2 CRVAL1 CRVAL2 LONPOLE "
2276 "LATPOLE CSYER1 CSYER2 EQUINOX MJD-OBS "
2277 "DATE-OBS NAXIS2 NAXIS1";
2278 cpl_size plist1_size = cpl_propertylist_get_size(plist1);
2279 for (cpl_size ip=plist1_size; ip>0; ip--) {
2280 const cpl_property * newprop = cpl_propertylist_get_const(plist1, ip-1);
2281 const char * name = cpl_property_get_name(newprop);
2282 if (strstr(wcs_items, name) != NULL) {
2283 if (cpl_propertylist_has(*plist, name)) {
2284 cpl_propertylist_copy_property(*plist, plist1, name);
2285 } else {
2286 cpl_propertylist_insert_after_property(*plist, "NAXIS",
2287 newprop);
2288 }
2289 }
2290 }
2291
2292 /* Access HDU 2 in the file, this should contain the data error */
2293
2294 plist2 = cpl_propertylist_load(filename, 2);
2295 enu_check_error_code("accessing HDU 2");
2296 extname = cpl_propertylist_get_string(plist2, "EXTNAME");
2297 hduclass = cpl_propertylist_get_string(plist2, "HDUCLASS");
2298 hdudoc = cpl_propertylist_get_string(plist2, "HDUDOC");
2299 //hduvers = cpl_propertylist_get_string(plist2, "HDUVERS");
2300 hduclas1 = cpl_propertylist_get_string(plist2, "HDUCLAS1");
2301 hduclas2 = cpl_propertylist_get_string(plist2, "HDUCLAS2");
2302 enu_check_error_code("accessing HDU 2 propertylist");
2303 enu_check(strstr(extname, "ERR") != NULL &&
2304 strstr(hduclass, "ESO") != NULL &&
2305 strstr(hdudoc, "SDP") != NULL &&
2306 strstr(hduclas1, "IMAGE") != NULL &&
2307 strstr(hduclas2, "ERROR") != NULL,
2308 CPL_ERROR_BAD_FILE_FORMAT, "bad HD2 format");
2309 error = cpl_image_load(filename, HDRL_TYPE_ERROR, 0, 2);
2310 enu_check_error_code("accessing HDU 1 data error");
2311
2312 /* Access HDU 3 in the file, this should contain the data quality */
2313
2314 plist3 = cpl_propertylist_load(filename, 3);
2315 enu_check_error_code("accessing HDU 3");
2316 extname = cpl_propertylist_get_string(plist3, "EXTNAME");
2317 hduclass = cpl_propertylist_get_string(plist3, "HDUCLASS");
2318 hdudoc = cpl_propertylist_get_string(plist3, "HDUDOC");
2319 //hduvers = cpl_propertylist_get_string(plist3, "HDUVERS");
2320 hduclas1 = cpl_propertylist_get_string(plist3, "HDUCLAS1");
2321 hduclas2 = cpl_propertylist_get_string(plist3, "HDUCLAS2");
2322 enu_check_error_code("accessing HDU 3 propertylist");
2323 enu_check(strstr(extname, "DQ") != NULL &&
2324 strstr(hduclass, "ESO") != NULL &&
2325 strstr(hdudoc, "SDP") != NULL &&
2326 strstr(hduclas1, "IMAGE") != NULL &&
2327 strstr(hduclas2, "QUALITY") != NULL,
2328 CPL_ERROR_BAD_FILE_FORMAT, "bad HD3 format");
2329
2330 /* attach the mask to the data, construct the hdrl image */
2331
2332 bpm = cpl_mask_load(filename, 0, 3);
2333 enu_check_error_code("accessing HDU 3 data mask");
2334 old_bpm = cpl_image_set_bpm(data, bpm);
2335 cpl_mask_delete(old_bpm); old_bpm = NULL;
2336 *result = hdrl_image_create(data, error);
2337
2338 /* Read any further extensions into a mef_extension_list */
2339
2340 int n_ext = size - 3;
2341 *mef_extensions = enu_mef_extension_list_new(n_ext);
2342 for (int ext=0; ext<n_ext; ext++) {
2343
2344 /* get the extension name... */
2345
2346 cpl_propertylist * ext_plist = cpl_propertylist_load(filename, ext+4);
2347 const char * name = cpl_propertylist_get_string(ext_plist, "EXTNAME");
2348 const char * mef_type = cpl_propertylist_get_string(ext_plist,
2349 "ERIS_NIX_MEF_TYPE");
2350
2351 /* ...and value, type keyed on extension name */
2352
2353 if (!strcmp(mef_type, MEF_EXTENSION_CONTAINING_MASK)) {
2354 cpl_mask * mask = cpl_mask_load(filename, 0, ext+4);
2355 mef_extension * new = enu_mef_new_mask(name, mask, NULL);
2356 (*mef_extensions)->mef[ext] = new;
2357 cpl_mask_delete(mask);
2358 } else if (!strcmp(mef_type, MEF_EXTENSION_CONTAINING_IMAGE)) {
2359 cpl_image * image = cpl_image_load(filename, HDRL_TYPE_DATA, 0,
2360 ext+4);
2361 mef_extension * new = enu_mef_new_image(name, image, NULL);
2362 (*mef_extensions)->mef[ext] = new;
2363 cpl_image_delete(image);
2364 } else if (!strcmp(mef_type, MEF_EXTENSION_CONTAINING_TABLE)) {
2365 cpl_table * table = cpl_table_load(filename, ext+4, 0);
2366 mef_extension * new = enu_mef_new_table(name, table, ext_plist);
2367 (*mef_extensions)->mef[ext] = new;
2368 cpl_table_delete(table);
2369 } else {
2370 cpl_error_set_message("enu_himage_load_from_fits",
2371 CPL_ERROR_UNSUPPORTED_MODE,
2372 "unsupported extension name: %s", name);
2373 }
2374
2375 cpl_propertylist_delete(ext_plist);
2376 }
2377
2378 cleanup:
2379 cpl_propertylist_delete(plist1);
2380 cpl_propertylist_delete(plist2);
2381 cpl_propertylist_delete(plist3);
2382 cpl_image_delete(data);
2383 cpl_image_delete(error);
2384 cpl_mask_delete(old_bpm);
2385 if (cpl_error_get_code() != CPL_ERROR_NONE) {
2386 cpl_propertylist_delete(*plist);
2387 *plist = NULL;
2388 hdrl_image_delete(*result);
2389 *result = NULL;
2390 enu_mef_extension_list_delete(*mef_extensions);
2391 *mef_extensions = NULL;
2392 }
2393 eris_check_error_code("enu_himage_load_from_fits");
2394 return cpl_error_get_code();
2395}
2396
2397
2398/*----------------------------------------------------------------------------*/
2413/*----------------------------------------------------------------------------*/
2414
2415located_image * enu_load_limage_from_frame(const cpl_frame * frame,
2416 cpl_image ** pcopyconf,
2417 const cpl_boolean collapse_cube) {
2418
2419 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
2420
2421 cpl_ensure(frame, CPL_ERROR_NULL_INPUT, NULL);
2422 cpl_ensure(cpl_frame_get_filename(frame), CPL_ERROR_NULL_INPUT, NULL);
2423
2424 located_image * result = NULL;
2425 mef_extension_list * mefs = NULL;
2426 cpl_image * data = NULL;
2427 cpl_image * err = NULL;
2428 cpl_image * qual = NULL;
2429 cpl_image * conf = NULL;
2430 cpl_image * bkg = NULL;
2431 cpl_image * bkg_err = NULL;
2432 cpl_image * bkg_conf = NULL;
2433
2434 const char * filename = cpl_frame_get_filename(frame);
2435 cpl_msg_info(cpl_func, "..reading %s", filename);
2436
2437 /* treatment depends on number of extensions, name of first extension, and
2438 ESO DET FRAM FORMAT (single image or cube).
2439 Get this information */
2440
2441 cpl_size next = cpl_fits_count_extensions(filename);
2442
2443 cpl_propertylist * plist = cpl_propertylist_load(filename, 0);
2444
2445 /* is this an ERIS file or NACO */
2446 const char * instrume = cpl_propertylist_get_string(plist, "INSTRUME");
2447 const cpl_boolean eris = !strcmp(instrume, "ERIS");
2448
2449 char * first_ext = NULL;
2450 if (eris && (next > 0)) {
2451 cpl_propertylist * plist1 = cpl_propertylist_load(filename, 1);
2452 if (cpl_propertylist_has(plist1, "EXTNAME")) {
2453 first_ext = cpl_sprintf("%s", cpl_propertylist_get_string(plist1, "EXTNAME"));
2454 }
2455 cpl_propertylist_delete(plist1);
2456 //cpl_msg_info(cpl_func, "extname %s", first_ext);
2457 }
2458
2459 char * frame_format = NULL;
2460 if (cpl_propertylist_has(plist, "ESO DET FRAM FORMAT")) {
2461 frame_format = cpl_sprintf("%s", cpl_propertylist_get_string(plist, "ESO DET FRAM FORMAT"));
2462 cpl_msg_info(cpl_func, "..format %s", frame_format);
2463 }
2464
2465 /* Now read the file appropriately */
2466
2467 if (!eris) {
2468 cpl_msg_info(cpl_func, "NACO data");
2469
2470 /* It is a raw FITS file with header and 2d image data,
2471 plus extensions to be ignored */
2472
2473 data = cpl_image_load(filename, HDRL_TYPE_DATA, 0, 0);
2474 enu_check_error_code("failed to read file: %s", filename);
2475 hdrl_image * himage = hdrl_image_create(data, NULL);
2476 cpl_image_delete(data); data = NULL;
2477 const cpl_size nx = hdrl_image_get_size_x(himage);
2478 const cpl_size ny = hdrl_image_get_size_y(himage);
2479
2480 /* confidence set to 100 everywhere */
2481
2482 cpl_image * confidence;
2483 if (pcopyconf != NULL && *pcopyconf != NULL &&
2484 cpl_image_get_size_x(*pcopyconf) == nx &&
2485 cpl_image_get_size_y(*pcopyconf) == ny) {
2486 confidence = *pcopyconf;
2487 *pcopyconf = NULL;
2488 } else {
2489 confidence = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
2490 cpl_image_fill_window(confidence, 1, 1, nx, ny, 100.0);
2491 }
2492
2493 cpl_frame_dump(frame, NULL);
2494 result = enu_located_image_new(himage,
2495 NULL,
2496 confidence,
2497 NULL,
2498 NULL,
2499 plist,
2500 NULL,
2501 NULL,
2502 NULL,
2503 NULL,
2504 cpl_frame_duplicate(frame));
2505 plist = NULL;
2506
2507 } else if ((next == 0) ||
2508 (next == 1 &&
2509 frame_format &&
2510 !strcmp(first_ext, "ASM_DATA"))) {
2511
2512 if (next == 1) {
2513
2514 /* read IA_FWHM from the ASM table and store it in the
2515 FITS header */
2516
2517 cpl_table * asm_table = cpl_table_load(filename, 1, CPL_TRUE);
2518 cpl_size nrow = cpl_table_get_nrow(asm_table);
2519 if(cpl_table_has_column(asm_table,"IA_FWHM")) {
2520 double * ia_fwhm_data = cpl_table_get_data_double(asm_table,
2521 "IA_FWHM");
2522 cpl_vector * ia_fwhm = cpl_vector_wrap(nrow, ia_fwhm_data);
2523 double ia_fwhm_mean = cpl_vector_get_mean(ia_fwhm);
2524
2525 const char * filter = enu_get_filter(plist);
2526 double lambda = enu_get_filter_wavelength(filter);
2527
2528 /* correct the FWHM for wavelength, check PIPE-10981 docs for
2529 explanation of formula */
2530
2531 double ia_fwhm_corr = ia_fwhm_mean * pow(0.5/lambda, 1./5.);
2532
2533 cpl_propertylist_update_double(plist, "PSF_FWHM", ia_fwhm_corr);
2534 cpl_propertylist_set_comment(plist, "PSF_FWHM", "PSF fwhm derived "
2535 "from AO ASM table [arcsec]");
2536
2537 cpl_vector_unwrap(ia_fwhm);
2538 } else {
2539 cpl_msg_warning(cpl_func,"ASM table miss IA_FWHM column. PSF_FWHM not computed");
2540 }
2541 cpl_table_delete(asm_table);
2542
2543 } else {
2544
2545 /* NO ASM table is present, AO was not used. Estimate the
2546 fwhm from DIMM instead. Again, see PIPE-10981 for background */
2547
2548 if (cpl_propertylist_has(plist, "ESO TEL AMBI FWHM START") &&
2549 cpl_propertylist_has(plist, "ESO TEL AMBI FWHM END") &&
2550 cpl_propertylist_has(plist, "ESO TEL AIRM START") &&
2551 cpl_propertylist_has(plist, "ESO TEL AIRM END")) {
2552
2553 double dimm1 = cpl_propertylist_get_double(plist,
2554 "ESO TEL AMBI FWHM START");
2555 double dimm2 = cpl_propertylist_get_double(plist,
2556 "ESO TEL AMBI FWHM END");
2557 double airmass1 = cpl_propertylist_get_double(plist,
2558 "ESO TEL AIRM START");
2559 double airmass2 = cpl_propertylist_get_double(plist,
2560 "ESO TEL AIRM END");
2561
2562 const char * filter = enu_get_filter(plist);
2563 double lambda = enu_get_filter_wavelength(filter);
2564
2565 /* correct DIMM values for wavelength, then average */
2566
2567 dimm1 = dimm1 *
2568 pow(0.5/lambda, 1./5.) *
2569 pow(airmass1, 3./5.) *
2570 (1. - 78.08 *
2571 (pow(lambda/1.e6, 2./5.) *
2572 pow(airmass1, -1./5.) /
2573 pow(dimm1, 1./3.)
2574 )
2575 );
2576 dimm2 = dimm2 *
2577 pow(0.5/lambda, 1./5.) *
2578 pow(airmass2, 3./5.) *
2579 (1. - 78.08 *
2580 (pow(lambda/1.e6, 2./5.) *
2581 pow(airmass2, -1./5.) /
2582 pow(dimm2, 1./3.)
2583 )
2584 );
2585
2586 cpl_propertylist_update_double(plist, "PSF_FWHM",
2587 (dimm1 + dimm2) / 2.0);
2588 cpl_propertylist_set_comment(plist, "PSF_FWHM",
2589 "PSF fwhm derived "
2590 "from DIMM [arcsec]");
2591 }
2592 }
2593
2594 if (!strcmp(frame_format, "single")) {
2595
2596 /* It is a raw FITS file with header and 2d image data */
2597
2598 data = cpl_image_load(filename, HDRL_TYPE_DATA, 0, 0);
2599 enu_check_error_code("failed to read file: %s", filename);
2600 hdrl_image * himage = hdrl_image_create(data, NULL);
2601 cpl_image_delete(data); data = NULL;
2602 const cpl_size nx = hdrl_image_get_size_x(himage);
2603 const cpl_size ny = hdrl_image_get_size_y(himage);
2604
2605 /* confidence set to 100 everywhere */
2606
2607 cpl_image * confidence;
2608 if (pcopyconf != NULL && *pcopyconf != NULL &&
2609 cpl_image_get_size_x(*pcopyconf) == nx &&
2610 cpl_image_get_size_y(*pcopyconf) == ny) {
2611 confidence = *pcopyconf;
2612 *pcopyconf = NULL;
2613 } else {
2614 confidence = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
2615 cpl_image_fill_window(confidence, 1, 1, nx, ny, 100.0);
2616 }
2617
2618 result = enu_located_image_new(himage,
2619 NULL,
2620 confidence,
2621 NULL,
2622 NULL,
2623 plist,
2624 NULL,
2625 NULL,
2626 NULL,
2627 NULL,
2628 cpl_frame_duplicate(frame));
2629 plist = NULL;
2630
2631 } else if (!strcmp(frame_format, "cube")) {
2632
2633 /* It is a raw FITS file with header and 3d image data (cube) */
2634
2635 cpl_imagelist * datalist = cpl_imagelist_load(filename,
2636 HDRL_TYPE_DATA, 0);
2637 enu_check_error_code("failed to read file: %s", filename);
2638 hdrl_imagelist * himagelist = hdrl_imagelist_create(datalist,
2639 NULL);
2640 cpl_imagelist_delete(datalist); datalist = NULL;
2641 const cpl_size nx = hdrl_imagelist_get_size_x(himagelist);
2642 const cpl_size ny = hdrl_imagelist_get_size_y(himagelist);
2643
2644 /* confidence set to 100 everywhere */
2645
2646 cpl_image * confidence;
2647 if (pcopyconf != NULL && *pcopyconf != NULL &&
2648 cpl_image_get_size_x(*pcopyconf) == nx &&
2649 cpl_image_get_size_y(*pcopyconf) == ny) {
2650 confidence = *pcopyconf;
2651 *pcopyconf = NULL;
2652 } else {
2653 confidence = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
2654 cpl_image_fill_window(confidence, 1, 1, nx, ny, 100.0);
2655 }
2656
2657 if(collapse_cube) {
2658 hdrl_image * himage = NULL;
2659 cpl_image* conf_ima = NULL;
2660 if(collapse_cube == 1) {
2661 hdrl_imagelist_collapse_mean(himagelist,&himage,&conf_ima);
2662 } else if(collapse_cube == 2) {
2663 hdrl_imagelist_collapse_median(himagelist,&himage,&conf_ima);
2664 } else if(collapse_cube == 3) {
2665 hdrl_imagelist_collapse_weighted_mean(himagelist,&himage,&conf_ima);
2666 }
2667 cpl_image_delete(conf_ima);
2668 result = enu_located_image_new(himage,
2669 NULL,
2670 confidence,
2671 NULL,
2672 NULL,
2673 plist,
2674 NULL,
2675 NULL,
2676 NULL,
2677 NULL,
2678 cpl_frame_duplicate(frame));
2679 } else {
2680 result = enu_located_image_new(NULL,
2681 himagelist,
2682 confidence,
2683 NULL,
2684 NULL,
2685 plist,
2686 NULL,
2687 NULL,
2688 NULL,
2689 NULL,
2690 cpl_frame_duplicate(frame));
2691 }
2692 plist = NULL;
2693 }
2694 } else {
2695
2696 /* It is a mef: it should be in ESO Data Products Standard format */
2697
2698 cpl_propertylist_delete(plist);
2699 plist = NULL;
2700 mefs = enu_load_mef_components(filename, &plist);
2701 enu_check_error_code("Unable to load components for file");
2702
2703 /* look in first extension for HDU keywords */
2704
2705 const char * hduclass = cpl_propertylist_get_string(
2706 mefs->mef[0]->plist, "HDUCLASS");
2707 const char * hdudoc = cpl_propertylist_get_string(
2708 mefs->mef[0]->plist, "HDUDOC");
2709 const char * hduvers = cpl_propertylist_get_string(
2710 mefs->mef[0]->plist, "HDUVERS");
2711 enu_check_error_code("Unable to read ESO DPS keywords from header");
2712
2713 enu_check(strstr(hduclass, "ESO") != NULL &&
2714 strstr(hdudoc, "SDP") != NULL &&
2715 strstr(hduvers, "SDP version") != NULL,
2716 CPL_ERROR_BAD_FILE_FORMAT, "file not in ESO DPS format");
2717
2718 /* Read the names of the extensions holding standard data
2719 components */
2720
2721 const char * scidata = NULL;
2722 if (mefs->size > 0 &&
2723 cpl_propertylist_has(mefs->mef[1]->plist, "SCIDATA")){
2724 scidata = cpl_propertylist_get_string(mefs->mef[1]->plist,
2725 "SCIDATA");
2726 }
2727 const char * errdata = NULL;
2728 if (cpl_propertylist_has(mefs->mef[0]->plist, "ERRDATA")){
2729 errdata = cpl_propertylist_get_string(mefs->mef[0]->plist,
2730 "ERRDATA");
2731 }
2732 const char * qualdata = NULL;
2733 if (cpl_propertylist_has(mefs->mef[0]->plist, "QUALDATA")){
2734 qualdata = cpl_propertylist_get_string(mefs->mef[0]->plist,
2735 "QUALDATA");
2736 }
2737 const char * confdata = NULL;
2738 if (cpl_propertylist_has(mefs->mef[0]->plist, "CONFDATA")){
2739 confdata = cpl_propertylist_get_string(mefs->mef[0]->plist,
2740 "CONFDATA");
2741 }
2742 const char * bkgdata = NULL;
2743 if (cpl_propertylist_has(mefs->mef[0]->plist, "BKGDATA")){
2744 bkgdata = cpl_propertylist_get_string(mefs->mef[0]->plist,
2745 "BKGDATA");
2746 }
2747 const char * bkgerr = NULL;
2748 if (cpl_propertylist_has(mefs->mef[0]->plist, "BKGERR")){
2749 bkgerr = cpl_propertylist_get_string(mefs->mef[0]->plist,
2750 "BKGERR");
2751 }
2752 const char * bkgconf = NULL;
2753 if (cpl_propertylist_has(mefs->mef[0]->plist, "BKGCONF")){
2754 bkgconf = cpl_propertylist_get_string(mefs->mef[0]->plist,
2755 "BKGCONF");
2756 }
2757 enu_check_error_code("accessing DPS standard extensions");
2758
2759 /* now loop through extensions filling standard data elements */
2760
2761 for (cpl_size i=0; i<next; i++) {
2762 const char * extname = cpl_propertylist_get_string(
2763 mefs->mef[i]->plist, "EXTNAME");
2764
2765 /* the returned plist is a merge of the plist for the
2766 science image and the header plist.*/
2767
2768 if (scidata && !strcmp(scidata, extname)) {
2769 data = enu_load_component(mefs->mef[i], "SCIDATA",
2770 "IMAGE", "DATA");
2771 enu_check_error_code("accessing SCIDATA extension");
2772
2773 /* Start with the science image plist (for the data and
2774 wcs keywords)*/
2775
2776 cpl_propertylist * primary_plist = plist;
2777
2778 /* remove the SDP7 keywords which were appropriate to
2779 the science data extension but will
2780 confuse the enu_limage_save routine if left in the
2781 main header */
2782
2783 plist = cpl_propertylist_duplicate(mefs->mef[i]->plist);
2784 const char * sdp7_items = " EXTNAME HDUCLAS1 HDUCLAS2"
2785 " HDUCLAS3 ";
2786 cpl_size psize = cpl_propertylist_get_size(plist);
2787 for (cpl_size ip = psize; ip > 0; ip--) {
2788 const cpl_property * prop = cpl_propertylist_get_const(
2789 plist, ip-1);
2790 const char * name = cpl_property_get_name(prop);
2791
2792 /* pad the keyword name with spaces which will
2793 stop strstr misidentifying a keyword that
2794 matches _part_ of an SDP7 keyword */
2795
2796 char * padded_name = cpl_sprintf(" %s ", name);
2797 if (strstr(sdp7_items, padded_name) != NULL) {
2798 cpl_propertylist_erase(plist, name);
2799 }
2800 cpl_free(padded_name);
2801 }
2802
2803 /* merge info from the primary header */
2804
2805 psize = cpl_propertylist_get_size(primary_plist);
2806 for (cpl_size ip = psize; ip > 0; ip--) {
2807 const cpl_property * prop = cpl_propertylist_get_const(
2808 primary_plist, ip-1);
2809 const char * name = cpl_property_get_name(prop);
2810 if (!cpl_propertylist_has(plist, name)) {
2811 cpl_propertylist_copy_property(plist, primary_plist,
2812 name);
2813 }
2814 }
2815 cpl_propertylist_delete(primary_plist);
2816
2817 } else if (errdata && !strcmp(errdata, extname)) {
2818 err = enu_load_component(mefs->mef[i], "SCIERR",
2819 "IMAGE", "ERROR");
2820 enu_check_error_code("accessing SCIERR extension");
2821 } else if (qualdata && !strcmp(qualdata, extname)) {
2822 qual = enu_load_component(mefs->mef[i], "QUALDATA",
2823 "IMAGE", "QUALITY");
2824 enu_check_error_code("accessing QUALDATA extension");
2825 } else if (confdata && !strcmp(confdata, extname)) {
2826 conf = enu_load_component(mefs->mef[i], "CONFDATA",
2827 "IMAGE", "CONF");
2828 enu_check_error_code("accessing CONFDATA extension");
2829 } else if (bkgdata && !strcmp(bkgdata, extname)) {
2830 bkg = enu_load_component(mefs->mef[i], "BKGDATA",
2831 "IMAGE", "BKG_DATA");
2832 enu_check_error_code("accessing BKGDATA extension");
2833 } else if (bkgerr && !strcmp(bkgerr, extname)) {
2834 bkg_err = enu_load_component(mefs->mef[i], "BKGERR",
2835 "IMAGE", "BKG_ERR");
2836 enu_check_error_code("accessing BKGERR extension");
2837 } else if (bkgconf && !strcmp(bkgconf, extname)) {
2838 bkg_conf = enu_load_component(mefs->mef[i], "BKGCONF",
2839 "IMAGE", "BKG_CONF");
2840 enu_check_error_code("accessing BKGCONF extension");
2841 }
2842 }
2843
2844 /* set the data mask from quality, construct the hdrl image */
2845
2846 enu_check(data != NULL, CPL_ERROR_BAD_FILE_FORMAT, "no data in file");
2847 cpl_mask * bpm = cpl_image_get_bpm(data);
2848 cpl_mask_threshold_image(bpm, qual, 0.9, 1.1, CPL_BINARY_1);
2849 bpm = cpl_image_get_bpm(err);
2850 cpl_mask_threshold_image(bpm, qual, 0.9, 1.1, CPL_BINARY_1);
2851 hdrl_image * hdata = hdrl_image_create(data, err);
2852 hdrl_image * hbkg = NULL;
2853 if (bkg) {
2854 hbkg = hdrl_image_create(bkg, bkg_err);
2855 }
2856
2857 result = enu_located_image_new(hdata,
2858 NULL,
2859 conf,
2860 hbkg,
2861 bkg_conf,
2862 plist,
2863 NULL,
2864 NULL,
2865 NULL,
2866 NULL,
2867 cpl_frame_duplicate(frame));
2868
2869 plist = NULL;
2870 cpl_image_delete(data);
2871 cpl_image_delete(err);
2872 cpl_image_delete(qual);
2873 cpl_image_delete(bkg);
2874 cpl_image_delete(bkg_err);
2875 data = NULL;
2876 err = NULL;
2877 qual = NULL;
2878 conf = NULL;
2879 bkg = NULL;
2880 bkg_err = NULL;
2881 bkg_conf = NULL;
2882 }
2883
2884 cleanup:
2885 cpl_free(frame_format);
2886 cpl_free(first_ext);
2887 cpl_propertylist_delete(plist);
2888 cpl_image_delete(data);
2889 cpl_image_delete(err);
2890 cpl_image_delete(qual);
2891 cpl_image_delete(conf);
2892 cpl_image_delete(bkg);
2893 cpl_image_delete(bkg_err);
2894 cpl_image_delete(bkg_conf);
2896 if (cpl_error_get_code() != CPL_ERROR_NONE) {
2898 result = NULL;
2899 }
2900
2901 eris_check_error_code("enu_load_limage_from_frame");
2902 return result;
2903}
2904
2905
2906/*----------------------------------------------------------------------------*/
2916/*----------------------------------------------------------------------------*/
2917
2918mef_extension_list * enu_load_mef_components(const char * filename,
2919 cpl_propertylist ** plist) {
2920
2921 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
2922
2923 cpl_ensure(filename, CPL_ERROR_NULL_INPUT, NULL);
2924
2925 /* How many extensions are there, construct result of the correct
2926 size */
2927
2928 cpl_size next = cpl_fits_count_extensions(filename);
2929 mef_extension_list * result = enu_mef_extension_list_new(next);
2930 mef_extension * new = NULL;
2931 cpl_propertylist * eplist = NULL;
2932
2933 /* Read primary HDU header */
2934
2935 *plist = cpl_propertylist_load(filename, 0);
2936 enu_check_error_code("accessing HDU 0 header");
2937
2938 /* Now loop through extensions, loading them in turn */
2939
2940 for (int i=0; i<next; i++) {
2941 int hdu = i + 1;
2942
2943 /* get the extension name... */
2944
2945 cpl_propertylist_delete(eplist);
2946 eplist = cpl_propertylist_load(filename, hdu);
2947 const char * name = cpl_propertylist_get_string(eplist, "EXTNAME");
2948 const char * hduclas1 = cpl_propertylist_get_string(eplist,
2949 "HDUCLAS1");
2950 enu_check_error_code("error accessing keywords in HDU %d", hdu);
2951
2952 /* ...type and value, create appropriate mef_extension */
2953
2954 if (!strcmp(hduclas1, MEF_EXTENSION_CONTAINING_MASK)) {
2955 cpl_mask * mask = cpl_mask_load(filename, 0, hdu);
2956 new = enu_mef_new_mask(name, mask, eplist);
2957 cpl_mask_delete(mask);
2958 } else if (!strcmp(hduclas1, "IMAGE")) {
2959 cpl_image * image = cpl_image_load(filename, HDRL_TYPE_DATA, 0, hdu);
2960 new = enu_mef_new_image(name, image, eplist);
2961 cpl_image_delete(image);
2962 } else if (!strcmp(hduclas1, MEF_EXTENSION_CONTAINING_TABLE)) {
2963 cpl_table * table = cpl_table_load(filename, hdu, 0);
2964 new = enu_mef_new_table(name, table, eplist);
2965 cpl_table_delete(table);
2966 } else {
2967 cpl_error_set_message("enu_load_mef_components",
2968 CPL_ERROR_UNSUPPORTED_MODE,
2969 "extension has unsupported HDUCLAS1: %s %s", name, hduclas1);
2970 }
2971 enu_check_error_code("error accessing HDU %d", hdu);
2972
2973 result->mef[i] = new;
2974 new = NULL;
2975 }
2976
2977 cleanup:
2979 cpl_propertylist_delete(eplist);
2980 if (cpl_error_get_code() != CPL_ERROR_NONE) {
2982 result = NULL;
2983 cpl_propertylist_delete(*plist);
2984 *plist = NULL;
2985 }
2986 eris_check_error_code("enu_load_mef_components");
2987 return result;
2988}
2989
2990
2991/*----------------------------------------------------------------------------*/
2998/*----------------------------------------------------------------------------*/
2999
3000void enu_located_image_delete(located_image * limage) {
3001
3002 if (limage) {
3003 hdrl_image_delete(limage->himage);
3004 hdrl_imagelist_delete(limage->himagelist);
3005 cpl_image_delete(limage->confidence);
3006 hdrl_image_delete(limage->bkg);
3007 cpl_image_delete(limage->bkg_confidence);
3008 cpl_propertylist_delete(limage->plist);
3009 hdrl_catalogue_result_delete(limage->objects);
3010 cpl_mask_delete(limage->object_mask);
3011 hdrl_catalogue_result_delete(limage->matchstd_wcs);
3012 hdrl_catalogue_result_delete(limage->matchstd_phot);
3013 cpl_frame_delete(limage->frame);
3014 cpl_free(limage);
3015 }
3016}
3017
3018
3019/*----------------------------------------------------------------------------*/
3027/*----------------------------------------------------------------------------*/
3028
3029located_image * enu_located_image_duplicate(const located_image * limage) {
3030
3031 cpl_ensure(limage, CPL_ERROR_NULL_INPUT, NULL);
3032
3033 /* Watch out for NULL components */
3034
3035 hdrl_image * himage = NULL;
3036 if (limage->himage) {
3037 himage = hdrl_image_duplicate(limage->himage);
3038 }
3039 hdrl_imagelist * himagelist = NULL;
3040 if (limage->himagelist) {
3041 himagelist = hdrl_imagelist_duplicate(limage->himagelist);
3042 }
3043 cpl_image * confidence = NULL;
3044 if (limage->confidence) {
3045 confidence = cpl_image_duplicate(limage->confidence);
3046 }
3047 hdrl_image * bkg = NULL;
3048 if (limage->bkg) {
3049 bkg = hdrl_image_duplicate(limage->bkg);
3050 }
3051 cpl_image * bkg_confidence = NULL;
3052 if (limage->bkg_confidence) {
3053 bkg_confidence = cpl_image_duplicate(limage->bkg_confidence);
3054 }
3055 cpl_propertylist * plist = NULL;
3056 if (limage->plist) {
3057 plist = cpl_propertylist_duplicate(limage->plist);
3058 }
3059 hdrl_catalogue_result * objects = NULL;
3060 if (limage->objects) {
3061 objects = enu_hdrl_catalogue_result_duplicate(limage->objects);
3062 }
3063 cpl_mask * object_mask = NULL;
3064 if (limage->object_mask) {
3065 object_mask = cpl_mask_duplicate(limage->object_mask);
3066 }
3067 hdrl_catalogue_result * matchstd_wcs = NULL;
3068 if (limage->matchstd_wcs) {
3070 limage->matchstd_wcs);
3071 }
3072 hdrl_catalogue_result * matchstd_phot = NULL;
3073 if (limage->matchstd_phot) {
3075 limage->matchstd_phot);
3076 }
3077 cpl_frame * frame = NULL;
3078 if (limage->frame) {
3079 frame = cpl_frame_duplicate(limage->frame);
3080 }
3081
3082 located_image * result = enu_located_image_new(himage,
3083 himagelist,
3084 confidence,
3085 bkg,
3086 bkg_confidence,
3087 plist,
3088 objects,
3089 object_mask,
3090 matchstd_wcs,
3091 matchstd_phot,
3092 frame);
3093 eris_check_error_code("enu_located_image_duplicate");
3094
3095 return result;
3096}
3097
3098
3099/*----------------------------------------------------------------------------*/
3119/*----------------------------------------------------------------------------*/
3120
3121located_image * enu_located_image_new(hdrl_image * himage,
3122 hdrl_imagelist * himagelist,
3123 cpl_image * confidence,
3124 hdrl_image * bkg,
3125 cpl_image * bkg_confidence,
3126 cpl_propertylist * plist,
3127 hdrl_catalogue_result * objects,
3128 cpl_mask * object_mask,
3129 hdrl_catalogue_result * wcs,
3130 hdrl_catalogue_result * photom,
3131 cpl_frame * frame) {
3132
3133 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3134
3135 /* store either image or cube (imagelist) */
3136 cpl_ensure(!(himage && himagelist), CPL_ERROR_ILLEGAL_INPUT, NULL);
3137
3138 located_image * result = cpl_malloc(sizeof(located_image));
3139 result->himage = himage;
3140 result->himagelist = himagelist;
3141 result->confidence = confidence;
3142 result->bkg = bkg;
3143 result->bkg_confidence = bkg_confidence;
3144 result->plist = plist;
3145 result->objects = objects;
3146 result->object_mask = object_mask;
3147 result->matchstd_wcs = wcs;
3148 result->matchstd_phot = photom;
3149 result->frame = frame;
3150
3151 return result;
3152}
3153
3154
3155/*----------------------------------------------------------------------------*/
3166/*----------------------------------------------------------------------------*/
3167
3169 cpl_frameset * frameset,
3170 const char * tag,
3171 cpl_frameset * used) {
3172
3173 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3174 cpl_ensure(frameset, CPL_ERROR_NULL_INPUT, NULL);
3175 cpl_ensure(tag, CPL_ERROR_NULL_INPUT, NULL);
3176 cpl_ensure(used, CPL_ERROR_NULL_INPUT, NULL);
3177
3178 located_imagelist * result = NULL;
3179 cpl_frameset_iterator * frameset_iter = NULL;
3180 mef_extension_list * mefs = NULL;
3181 cpl_image * data = NULL;
3182 cpl_image * err = NULL;
3183 cpl_image * qual = NULL;
3184 cpl_image * conf = NULL;
3185 cpl_image * bkg = NULL;
3186 cpl_image * bkg_err = NULL;
3187 cpl_image * bkg_conf = NULL;
3188 cpl_propertylist * plist = NULL;
3189
3190 /* first, find how big the located_imagelist needs to be */
3191
3192 frameset_iter = cpl_frameset_iterator_new(frameset);
3193 cpl_size size = 0;
3194
3195 for (cpl_frame * frame = NULL;
3196 (frame = cpl_frameset_iterator_get(frameset_iter)) &&
3197 (cpl_error_get_code() == CPL_ERROR_NONE);
3198 cpl_frameset_iterator_advance(frameset_iter, 1)) {
3199
3200 const char * frametag = cpl_frame_get_tag(frame);
3201 if (!strcmp(tag, frametag)) {
3202 size++;
3203 }
3204 }
3205 result = enu_located_imagelist_new(size);
3206
3207 /* go through the frameset again and populate the container */
3208
3209 cpl_frameset_iterator_reset(frameset_iter);
3210 cpl_size position = 0;
3211 for (cpl_frame * frame = NULL;
3212 (frame = cpl_frameset_iterator_get(frameset_iter)) &&
3213 (cpl_error_get_code() == CPL_ERROR_NONE);
3214 cpl_frameset_iterator_advance(frameset_iter, 1)) {
3215
3216 /* if frametag is among those wanted, create a located image with
3217 the data and insert it into the located image list */
3218
3219 const char * frametag = cpl_frame_get_tag(frame);
3220
3221 if (!strcmp(tag, frametag)) {
3222
3223 /* we want this file, treatment depends on number of extensions
3224 it has and on the name of the first extension if present */
3225
3226 located_image * limage = enu_load_limage_from_frame(frame,
3227 NULL,
3228 CPL_FALSE);
3229
3230/*
3231 const char * filename = cpl_frame_get_filename(frame);
3232 cpl_msg_info(cpl_func, "..reading %s", filename);
3233 cpl_size next = cpl_fits_count_extensions(filename);
3234 located_image * limage = NULL;
3235
3236 plist = cpl_propertylist_load(filename, 0);
3237
3238 char * first_ext = NULL;
3239 if (next > 0) {
3240 cpl_propertylist * plist1 = cpl_propertylist_load(filename, 1);
3241 if (cpl_propertylist_has(plist1, "EXTNAME")) {
3242 first_ext = cpl_sprintf("%s", cpl_propertylist_get_string(plist1, "EXTNAME"));
3243 }
3244 cpl_propertylist_delete(plist1);
3245 }
3246
3247 char * frame_format = NULL;
3248 if (cpl_propertylist_has(plist, "ESO DET FRAM FORMAT")) {
3249 frame_format = cpl_sprintf("%s", cpl_propertylist_get_string(plist, "ESO DET FRAM FORMAT"));
3250 }
3251
3252 if ((next == 0) ||
3253 (next == 1 &&
3254 !strcmp(first_ext, "ASM_DATA") &&
3255 !strcmp(frame_format, "single"))) {
3256*/
3257 /* raw FITS file with header and 2d image data */
3258/*
3259 data = cpl_image_load(filename, HDRL_TYPE_DATA, 0, 0);
3260 enu_check_error_code("failed to read file: %s", filename);
3261 hdrl_image * himage = hdrl_image_create(data, NULL);
3262 cpl_image_delete(data); data = NULL;
3263 const cpl_size nx = hdrl_image_get_size_x(himage);
3264 const cpl_size ny = hdrl_image_get_size_y(himage);
3265*/
3266 /* confidence set to 100 everywhere */
3267/*
3268 cpl_image * confidence = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
3269 cpl_image_fill_window(confidence, 1, 1, nx, ny, 100.0);
3270
3271 limage = enu_located_image_new(himage, NULL, confidence, NULL,
3272 NULL, plist, NULL, NULL, NULL,
3273 NULL,
3274 cpl_frame_duplicate(frame));
3275 plist = NULL;
3276
3277 } else if (next == 1 &&
3278 !strcmp(first_ext, "ASM_DATA") &&
3279 !strcmp(frame_format, "cube")) {
3280*/
3281 /* raw FITS file with header and 3d image data (cube) */
3282/*
3283 cpl_imagelist * datalist = cpl_imagelist_load(filename,
3284 HDRL_TYPE_DATA,
3285 0);
3286 enu_check_error_code("failed to read file: %s", filename);
3287 hdrl_imagelist * himagelist = hdrl_imagelist_create(datalist,
3288 NULL);
3289 cpl_imagelist_delete(datalist); datalist = NULL;
3290 const cpl_size nx = hdrl_imagelist_get_size_x(himagelist);
3291 const cpl_size ny = hdrl_imagelist_get_size_y(himagelist);
3292*/
3293 /* confidence set to 100 everywhere */
3294/*
3295 cpl_image * confidence = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
3296 cpl_image_fill_window(confidence, 1, 1, nx, ny, 100.0);
3297
3298 limage = enu_located_image_new(NULL, himagelist, confidence,
3299 NULL, NULL, plist, NULL, NULL,
3300 NULL, NULL,
3301 cpl_frame_duplicate(frame));
3302 plist = NULL;
3303
3304 } else {
3305*/
3306 /* If it's a mef it should be in ESO Data Products Standard
3307 format */
3308/*
3309 cpl_propertylist_delete(plist);
3310 plist = NULL;
3311 enu_mef_extension_list_delete(mefs);
3312 mefs = enu_load_mef_components(filename, &plist);
3313 enu_check_error_code("Unable to load components for file");
3314*/
3315 /* look in first extension for HDU keywords */
3316/*
3317 const char * hduclass = cpl_propertylist_get_string(
3318 mefs->mef[0]->plist, "HDUCLASS");
3319 const char * hdudoc = cpl_propertylist_get_string(
3320 mefs->mef[0]->plist, "HDUDOC");
3321 //const char * hduvers = cpl_propertylist_get_string(
3322 // mefs->mef[0]->plist, "HDUVERS");
3323 enu_check_error_code("Unable to read ESO DPS keywords from header");
3324
3325 enu_check(strstr(hduclass, "ESO") != NULL &&
3326 // strstr(hduvers, "SDP version 8") != NULL &&
3327 strstr(hdudoc, "SDP") != NULL,
3328 CPL_ERROR_BAD_FILE_FORMAT, "file not in ESO DPS format");
3329*/
3330 /* now loop through extensions filling standard data elements */
3331/*
3332 for (cpl_size i=0; i<next; i++) {
3333 const char * hduclas2 = cpl_propertylist_get_string(
3334 mefs->mef[i]->plist, "HDUCLAS2");
3335*/
3336 /* the returned plist is a merge of the plist for the
3337 science image and the header plist.*/
3338/*
3339 if (hduclas2 && !strcmp(hduclas2, "DATA")) {
3340 data = enu_load_component(mefs->mef[i], "SCIDATA",
3341 "IMAGE", "DATA");
3342 enu_check_error_code("accessing SCIDATA extension");
3343*/
3344 /* Start with the science image plist (for the data and
3345 wcs keywords)*/
3346/*
3347 cpl_propertylist * primary_plist = plist;
3348*/
3349 /* remove the SDP7 keywords which were appropriate to
3350 the science data extension but will
3351 confuse the enu_limage_save routine if left in the
3352 main header */
3353/*
3354 plist = cpl_propertylist_duplicate(
3355 mefs->mef[i]->plist);
3356 const char * sdp7_items = " EXTNAME HDUCLAS1 HDUCLAS2"
3357 " HDUCLAS3 ";
3358 cpl_size psize = cpl_propertylist_get_size(plist);
3359 for (cpl_size ip=psize; ip>0; ip--) {
3360 const cpl_property * prop =
3361 cpl_propertylist_get_const(
3362 plist, ip-1);
3363 const char * name = cpl_property_get_name(prop);
3364*/
3365 /* pad the keyword name with spaces which will
3366 stop strstr misidentifying a keyword that
3367 matches _part_ of an SDP7 keyword */
3368/*
3369 char * padded_name = cpl_sprintf(" %s ", name);
3370 if (strstr(sdp7_items, padded_name) != NULL) {
3371 cpl_propertylist_erase(plist, name);
3372 }
3373 cpl_free(padded_name);
3374 }
3375*/
3376 /* merge info from the primary header */
3377/*
3378 psize = cpl_propertylist_get_size(primary_plist);
3379 for (cpl_size ip=psize; ip>0; ip--) {
3380 const cpl_property * prop =
3381 cpl_propertylist_get_const(
3382 primary_plist, ip-1);
3383 const char * name = cpl_property_get_name(prop);
3384 if (!cpl_propertylist_has(plist, name)) {
3385 cpl_propertylist_copy_property(plist,
3386 primary_plist,
3387 name);
3388 }
3389 }
3390 cpl_propertylist_delete(primary_plist);
3391
3392 } else if (hduclas2 && !strcmp(hduclas2, "ERROR")) {
3393 err = enu_load_component(mefs->mef[i], "SCIERR",
3394 "IMAGE", "ERROR");
3395 enu_check_error_code("accessing SCIERR extension");
3396 } else if (hduclas2 && !strcmp(hduclas2, "QUALITY")) {
3397 qual = enu_load_component(mefs->mef[i], "QUALDATA",
3398 "IMAGE", "QUALITY");
3399 enu_check_error_code("accessing QUALDATA extension");
3400 } else if (hduclas2 && !strcmp(hduclas2, "CONF")) {
3401 conf = enu_load_component(mefs->mef[i], "CONFDATA",
3402 "IMAGE", "CONF");
3403 enu_check_error_code("accessing CONFDATA extension");
3404 } else if (hduclas2 && !strcmp(hduclas2, "BKG_DATA")) {
3405 bkg = enu_load_component(mefs->mef[i], "BKGDATA",
3406 "IMAGE", "BKG_DATA");
3407 enu_check_error_code("accessing BKGDATA extension");
3408 } else if (hduclas2 && !strcmp(hduclas2, "BKG_ERR")) {
3409 bkg_err = enu_load_component(mefs->mef[i], "BKGERR",
3410 "IMAGE", "BKG_ERR");
3411 enu_check_error_code("accessing BKGERR extension");
3412 } else if (hduclas2 && !strcmp(hduclas2, "BKG_CONF")) {
3413 bkg_conf = enu_load_component(mefs->mef[i], "BKGCONF",
3414 "IMAGE", "BKG_CONF");
3415 enu_check_error_code("accessing BKGCONF extension");
3416 }
3417 }
3418*/
3419 /* set the data mask from quality, construct the hdrl image */
3420/*
3421 enu_check(data != NULL, CPL_ERROR_BAD_FILE_FORMAT,
3422 "no data in file");
3423 cpl_mask * bpm = cpl_image_get_bpm(data);
3424 cpl_mask_threshold_image(bpm, qual, 0.9, 1.1, CPL_BINARY_1);
3425 bpm = cpl_image_get_bpm(err);
3426 cpl_mask_threshold_image(bpm, qual, 0.9, 1.1, CPL_BINARY_1);
3427 hdrl_image * hdata = hdrl_image_create(data, err);
3428 hdrl_image * hbkg = NULL;
3429 if (bkg) {
3430 hbkg = hdrl_image_create(bkg, bkg_err);
3431 }
3432
3433 limage = enu_located_image_new(hdata, NULL, conf, hbkg,
3434 bkg_conf,
3435 plist, NULL, NULL, NULL, NULL,
3436 cpl_frame_duplicate(frame));
3437 plist = NULL;
3438 cpl_image_delete(data);
3439 cpl_image_delete(err);
3440 cpl_image_delete(qual);
3441 cpl_image_delete(bkg);
3442 cpl_image_delete(bkg_err);
3443 data = NULL;
3444 err = NULL;
3445 qual = NULL;
3446 conf = NULL;
3447 bkg = NULL;
3448 bkg_err = NULL;
3449 bkg_conf = NULL;
3450 }
3451 if(frame_format != NULL) {
3452 cpl_free(frame_format);
3453 }
3454 if(first_ext != NULL) {
3455 cpl_free(first_ext);
3456 }
3457*/
3458 /* insert new located_image into list */
3459
3460 enu_located_imagelist_insert(result, limage, position);
3461
3462 /* Update used_frameset */
3463
3464 cpl_frame * dup_frame = cpl_frame_duplicate(frame);
3465 cpl_frameset_insert(used, dup_frame);
3466
3467 position++;
3468 }
3469 }
3470
3471 //cleanup:
3472
3473 cpl_propertylist_delete(plist);
3474 cpl_image_delete(data);
3475 cpl_image_delete(err);
3476 cpl_image_delete(qual);
3477 cpl_image_delete(conf);
3478 cpl_image_delete(bkg);
3479 cpl_image_delete(bkg_err);
3480 cpl_image_delete(bkg_conf);
3482 cpl_frameset_iterator_delete(frameset_iter);
3483 if (cpl_error_get_code() != CPL_ERROR_NONE) {
3485 result = NULL;
3486 }
3487 eris_check_error_code("enu_limlist_load_from_frameset");
3488 return result;
3489}
3490
3491
3492/*----------------------------------------------------------------------------*/
3504/*----------------------------------------------------------------------------*/
3505
3506cpl_image * enu_load_component(mef_extension * mef,
3507 const char * dps_name,
3508 const char * hduclas1,
3509 const char * hduclas2) {
3510
3511 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3512 cpl_ensure(mef, CPL_ERROR_NULL_INPUT, NULL);
3513 cpl_ensure(dps_name, CPL_ERROR_NULL_INPUT, NULL);
3514 cpl_ensure(hduclas1, CPL_ERROR_NULL_INPUT, NULL);
3515 cpl_ensure(hduclas2, CPL_ERROR_NULL_INPUT, NULL);
3516
3517 cpl_image * result = NULL;
3518
3519 cpl_propertylist * plist = mef->plist;
3520 const char * hduclass = cpl_propertylist_get_string(plist, "HDUCLASS");
3521 const char * hdudoc = cpl_propertylist_get_string(plist, "HDUDOC");
3522 //const char * hduvers = cpl_propertylist_get_string(plist, "HDUVERS");
3523 const char * my_hduclas1 = cpl_propertylist_get_string(plist, "HDUCLAS1");
3524 const char * my_hduclas2 = cpl_propertylist_get_string(plist, "HDUCLAS2");
3525
3526 enu_check(strstr(hduclass, "ESO") != NULL &&
3527 strstr(hdudoc, "SDP") != NULL &&
3528 //strstr(hduvers, "SDP version 8") != NULL &&
3529 strstr(my_hduclas1, hduclas1) != NULL &&
3530 strstr(my_hduclas2, hduclas2) != NULL,
3531 CPL_ERROR_BAD_FILE_FORMAT, "bad %s format", dps_name);
3532
3533 result = mef->data;
3534
3535 cleanup:
3536 if (cpl_error_get_code() != CPL_ERROR_NONE) {
3537 result = NULL;
3538 }
3539 if (result != NULL) mef->data = NULL;
3540 eris_check_error_code("enu_load_component");
3541 return result;
3542}
3543
3544
3545/*----------------------------------------------------------------------------*/
3553/*----------------------------------------------------------------------------*/
3554
3555void enu_located_imagelist_delete(located_imagelist * limlist) {
3556
3557 if (limlist) {
3558 for (cpl_size i = 0; i < limlist->size; i++) {
3559 enu_located_image_delete(limlist->limages[i]);
3560 }
3561 cpl_free(limlist->limages);
3562 cpl_free(limlist);
3563 }
3564}
3565
3566
3567/*----------------------------------------------------------------------------*/
3575/*----------------------------------------------------------------------------*/
3576
3578 const located_imagelist * limlist) {
3579
3580 cpl_ensure(limlist, CPL_ERROR_NULL_INPUT, NULL);
3581
3582 located_imagelist * result = enu_located_imagelist_new(limlist->size);
3583 for (cpl_size i = 0; i < limlist->size; i++) {
3586 limlist->limages[i]), i);
3587 }
3588
3589 return result;
3590}
3591
3592
3593/*----------------------------------------------------------------------------*/
3604/*----------------------------------------------------------------------------*/
3605
3606cpl_error_code enu_located_imagelist_insert(located_imagelist * limlist,
3607 located_image * limage,
3608 cpl_size position) {
3609
3610 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
3611
3612 /* position valid? */
3613
3614 cpl_ensure_code(position >= 0 && position < limlist->size,
3615 CPL_ERROR_ACCESS_OUT_OF_RANGE);
3616 limlist->limages[position] = limage;
3617
3618 return cpl_error_get_code();
3619}
3620
3621
3622/*----------------------------------------------------------------------------*/
3631/*----------------------------------------------------------------------------*/
3632
3633located_imagelist * enu_located_imagelist_new(cpl_size size) {
3634
3635 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3636
3637 located_imagelist * limlist = cpl_malloc(sizeof(located_imagelist));
3638 limlist->size = size;
3639 limlist->limages = cpl_calloc(size, sizeof(located_image));
3640 for (cpl_size i = 0; i < limlist->size; i++) {
3641 limlist->limages[i] = NULL;
3642 }
3643 return limlist;
3644}
3645
3646
3647/*----------------------------------------------------------------------------*/
3655/*----------------------------------------------------------------------------*/
3656
3657void enu_mef_extension_delete(mef_extension * mef) {
3658
3659 if (mef) {
3660 if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_IMAGE)) {
3661 cpl_image_delete((cpl_image *) (mef->data));
3662 } else if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_MASK)) {
3663 cpl_mask_delete((cpl_mask *) mef->data);
3664 } else if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_TABLE)) {
3665 cpl_table_delete((cpl_table *) mef->data);
3666 } else if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_VECTOR)) {
3667 cpl_vector_delete((cpl_vector *) mef->data);
3668 } else {
3669 cpl_error_set("enu_mef_extension_delete",
3670 CPL_ERROR_UNSUPPORTED_MODE);
3671 }
3672 cpl_propertylist_delete(mef->plist);
3673 cpl_free(mef->name);
3674 cpl_free(mef);
3675 }
3676}
3677
3678
3679/*----------------------------------------------------------------------------*/
3687/*----------------------------------------------------------------------------*/
3688
3689void enu_mef_extension_list_delete(mef_extension_list * list) {
3690
3691 if (list) {
3692 for (cpl_size i = 0; i < list->size; i++) {
3693 enu_mef_extension_delete(list->mef[i]);
3694 }
3695 cpl_free(list->mef);
3696 cpl_free(list);
3697 }
3698}
3699
3700
3701/*----------------------------------------------------------------------------*/
3711/*----------------------------------------------------------------------------*/
3712
3713cpl_mask * enu_mef_extension_list_get_mask(mef_extension_list * meflist,
3714 const char * target) {
3715
3716 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3717
3718 cpl_ensure(meflist, CPL_ERROR_NULL_INPUT, NULL);
3719 cpl_ensure(target, CPL_ERROR_NULL_INPUT, NULL);
3720
3721 /* Search for extension */
3722
3723 cpl_mask * result = NULL;
3724 for (int i=0; i<meflist->size; i++) {
3725 if (!strcmp(meflist->mef[i]->name, target)) {
3726 cpl_ensure(!strcmp(meflist->mef[i]->data_type,
3727 MEF_EXTENSION_CONTAINING_MASK),
3728 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
3729 result = cpl_mask_duplicate((const cpl_mask *) meflist->mef[i]->data);
3730 break;
3731 }
3732 }
3733
3734 /* Check that the extensions was found */
3735
3736 cpl_ensure(result, CPL_ERROR_DATA_NOT_FOUND, NULL);
3737
3738 return result;
3739}
3740
3741
3742/*----------------------------------------------------------------------------*/
3751/*----------------------------------------------------------------------------*/
3752
3753mef_extension_list * enu_mef_extension_list_new(cpl_size size) {
3754
3755 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3756
3757 mef_extension_list * mef_list = cpl_malloc(sizeof(mef_extension_list));
3758 mef_list->size = size;
3759 mef_list->mef = cpl_calloc(size, sizeof(mef_extension));
3760 for (cpl_size i = 0; i < size; i++) {
3761 mef_list->mef[i] = NULL;
3762 }
3763
3764 return mef_list;
3765}
3766
3767
3768/*----------------------------------------------------------------------------*/
3782/*----------------------------------------------------------------------------*/
3783
3784mef_extension * enu_mef_new_image(const char * name,
3785 const cpl_image * data,
3786 const cpl_propertylist * plist) {
3787
3788 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3789
3790 /* check parameters */
3791
3792 cpl_ensure(name && data, CPL_ERROR_NULL_INPUT, NULL);
3793
3794 mef_extension * result = cpl_malloc(sizeof(mef_extension));
3795 result->name = cpl_strdup(name);
3796 result->data = (void *) cpl_image_duplicate(data);
3797 result->data_type = MEF_EXTENSION_CONTAINING_IMAGE;
3798 if (plist) {
3799 result->plist = cpl_propertylist_duplicate(plist);
3800 } else {
3801 result->plist = NULL;
3802 }
3803 return result;
3804}
3805
3806
3807/*----------------------------------------------------------------------------*/
3821/*----------------------------------------------------------------------------*/
3822
3823mef_extension * enu_mef_new_mask(const char * name,
3824 const cpl_mask * data,
3825 const cpl_propertylist * plist) {
3826
3827 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3828
3829 /* check parameters */
3830
3831 cpl_ensure(name && data, CPL_ERROR_NULL_INPUT, NULL);
3832
3833 mef_extension * result = cpl_malloc(sizeof(mef_extension));
3834 result->name = cpl_strdup(name);
3835 result->data = (void *) cpl_mask_duplicate(data);
3836 result->data_type = MEF_EXTENSION_CONTAINING_MASK;
3837 if (plist) {
3838 result->plist = cpl_propertylist_duplicate(plist);
3839 } else {
3840 result->plist = NULL;
3841 }
3842 return result;
3843}
3844
3845
3846/*----------------------------------------------------------------------------*/
3860/*----------------------------------------------------------------------------*/
3861
3862mef_extension * enu_mef_new_table(const char * name,
3863 const cpl_table * table,
3864 const cpl_propertylist * plist) {
3865
3866 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3867 cpl_ensure(name, CPL_ERROR_NULL_INPUT, NULL);
3868 cpl_ensure(table, CPL_ERROR_NULL_INPUT, NULL);
3869
3870 mef_extension * result = cpl_malloc(sizeof(mef_extension));
3871 result->name = cpl_strdup(name);
3872 result->data = (void *) cpl_table_duplicate(table);
3873 result->plist = NULL;
3874 if (plist) {
3875 result->plist = cpl_propertylist_duplicate(plist);
3876 } else {
3877 result->plist = NULL;
3878 }
3879 result->data_type = MEF_EXTENSION_CONTAINING_TABLE;
3880
3881 return result;
3882}
3883
3884
3885/*----------------------------------------------------------------------------*/
3899/*----------------------------------------------------------------------------*/
3900
3901mef_extension * enu_mef_new_vector(const char * name,
3902 const cpl_vector * vector,
3903 const cpl_propertylist * plist) {
3904
3905 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
3906 cpl_ensure(name, CPL_ERROR_NULL_INPUT, NULL);
3907 cpl_ensure(vector, CPL_ERROR_NULL_INPUT, NULL);
3908
3909 mef_extension * result = cpl_malloc(sizeof(mef_extension));
3910 result->name = cpl_strdup(name);
3911 result->data = (void *) cpl_vector_duplicate(vector);
3912 result->plist = NULL;
3913 if (plist) {
3914 result->plist = cpl_propertylist_duplicate(plist);
3915 } else {
3916 result->plist = NULL;
3917 }
3918 result->data_type = MEF_EXTENSION_CONTAINING_VECTOR;
3919
3920 return result;
3921}
3922
3923
3924/*----------------------------------------------------------------------------*/
3936/*----------------------------------------------------------------------------*/
3937
3938cpl_error_code enu_mef_extension_save(const mef_extension * mef,
3939 const char * filename,
3940 const cpl_propertylist * plist,
3941 unsigned mode) {
3942
3943 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
3944
3945 cpl_msg_debug(cpl_func, "enu_mef_extension_save entry");
3946
3947 cpl_propertylist * plist_copy = NULL;
3948
3949 /* check parameters, only one of the data types can be set */
3950
3951 cpl_ensure_code(mef, CPL_ERROR_NULL_INPUT);
3952 cpl_ensure_code(filename, CPL_ERROR_NULL_INPUT);
3953 cpl_ensure_code(plist, CPL_ERROR_NULL_INPUT);
3954
3955 plist_copy = cpl_propertylist_duplicate(plist);
3956 cpl_propertylist_update_string(plist_copy, "ERIS_NIX_MEF_TYPE",
3957 mef->data_type);
3958
3959 if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_IMAGE)) {
3960 if (cpl_propertylist_has(plist, "CD3_3")) {
3961 //double cd3_3 = cpl_propertylist_get_double(plist, "CD3_3");
3962
3963 /* the existence of CD3_3 in the header means that this
3964 data has ndim=3. In the LSS case that 3rd
3965 dimension is degenerate but allows the wcs decription to
3966 work.
3967
3968 To get CPL to store NDIM=3 we have to store the
3969 2d data as one image in an imagelist. */
3970
3971 cpl_msg_info(cpl_func, "..saving data with NDIM=3");
3972
3973 cpl_imagelist * imlist = cpl_imagelist_new();
3974 cpl_imagelist_set(imlist, mef->data, 0);
3975 cpl_imagelist_save(imlist,
3976 filename,
3977 CPL_TYPE_UNSPECIFIED,
3978 plist_copy,
3979 mode);
3980 /* let image data be deleted with mef */
3981 cpl_imagelist_unset(imlist, 0);
3982 cpl_imagelist_delete(imlist);
3983
3984 } else {
3985 cpl_image_save((const cpl_image *) (mef->data),
3986 filename,
3987 CPL_TYPE_UNSPECIFIED,
3988 plist_copy,
3989 mode);
3990 }
3991 } else if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_MASK)) {
3992 cpl_mask_save((const cpl_mask *) (mef->data),
3993 filename,
3994 plist_copy,
3995 mode);
3996 } else if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_TABLE)) {
3997 cpl_table_save((const cpl_table *) (mef->data),
3998 NULL,
3999 plist_copy,
4000 filename,
4001 mode);
4002 } else if (!strcmp(mef->data_type, MEF_EXTENSION_CONTAINING_VECTOR)) {
4003 cpl_vector_save((const cpl_vector *) (mef->data),
4004 filename,
4005 CPL_TYPE_DOUBLE,
4006 plist_copy,
4007 mode);
4008 } else {
4009 cpl_error_set_message("enu_mef_extension_save",
4010 CPL_ERROR_UNSUPPORTED_MODE,
4011 "unsupported extension type: %s", mef->data_type);
4012 }
4013
4014 cpl_propertylist_delete(plist_copy);
4015 eris_check_error_code("enu_mef_extension_save");
4016 return cpl_error_get_code();
4017}
4018
4019
4020/*----------------------------------------------------------------------------*/
4034/*----------------------------------------------------------------------------*/
4035
4036cpl_error_code enu_opm_limlist(const int obj_min_pixels,
4037 const double obj_threshold,
4038 const int bkg_mesh_size,
4039 const double bkg_smooth_fwhm,
4040 located_imagelist * limlist) {
4041
4042 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
4043
4044 /* parameter check */
4045
4046 cpl_ensure_code(limlist, CPL_ERROR_NULL_INPUT);
4047
4048 casu_fits ** indata = NULL;
4049 casu_fits ** inconf = NULL;
4050 casu_fits ** invar = NULL;
4051
4052 /* translate located_imagelist to casu_fits components */
4053
4054 encu_limlist_to_casu_fits(limlist, &indata, &inconf, &invar);
4055
4056 /* loop through the located_images, calculate the object mask
4057 for each, copy that mask to the object_mask in the located_image */
4058
4059 int casu_status = CASU_OK;
4060 int niter = 3;
4061
4062 cpl_msg_info(cpl_func, ".. calculating object masks");
4063 for (cpl_size j = 0; j < limlist->size; j++) {
4064 casu_opm(indata[j], inconf[j], obj_min_pixels, obj_threshold,
4065 bkg_mesh_size, bkg_smooth_fwhm, niter, &casu_status);
4066 enu_check(casu_status == CASU_OK, CPL_ERROR_UNSPECIFIED,
4067 "CASU error calculating object mask");
4068 limlist->limages[j]->object_mask = cpl_mask_duplicate(
4069 cpl_image_get_bpm(indata[j]->image));
4070 }
4071
4072 cleanup:
4073
4074 for (cpl_size j = 0; j < limlist->size; j++) {
4075 casu_fits_delete(indata[j]);
4076 casu_fits_delete(inconf[j]);
4077 casu_fits_delete(invar[j]);
4078 }
4079 cpl_free(indata);
4080 cpl_free(inconf);
4081 cpl_free(invar);
4082 eris_check_error_code("enu_opm_limlist");
4083 return cpl_error_get_code();
4084}
4085
4086
4087/*----------------------------------------------------------------------------*/
4103/*----------------------------------------------------------------------------*/
4104
4105cpl_error_code enu_opm_lss_limlist(located_imagelist * limlist,
4106 const int nsigma_cut) {
4107
4108 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
4109 cpl_ensure_code(limlist, CPL_ERROR_NULL_INPUT);
4110
4111 cpl_msg_info(cpl_func, "..calculating LSS object pixel mask");
4112
4113 /* loop through the located_images, calculate the object mask
4114 for each, copy that mask to the object_mask in the located_image */
4115
4116 for (cpl_size j = 0; j < limlist->size; j++) {
4117 cpl_size nx = hdrl_image_get_size_x(limlist->limages[j]->himage);
4118 cpl_size ny = hdrl_image_get_size_y(limlist->limages[j]->himage);
4119 cpl_image * collapsed = cpl_image_collapse_median_create(
4121 limlist->limages[j]->himage), 0, 0, 0);
4122
4123 /* mask for pixels that are unusually high */
4124
4125 double csigma = 0.0;
4126 double cmedian = cpl_image_get_median_dev(collapsed, &csigma);
4127 double maxval = cpl_image_get_max(collapsed);
4128 cpl_mask * collapsed_opm = cpl_mask_threshold_image_create(
4129 collapsed, cmedian + nsigma_cut * csigma,
4130 2.0 * maxval);
4131
4132 /* 'grow' the masked areas to try and catch lower level emission */
4133
4134 cpl_mask * kernel = cpl_mask_new(11, 1);
4135 cpl_mask_not(kernel);
4136 cpl_mask * dilated_collapsed_opm = cpl_mask_new(nx, 1);
4137 cpl_mask_filter(dilated_collapsed_opm, collapsed_opm, kernel,
4138 CPL_FILTER_DILATION, CPL_BORDER_NOP);
4139 cpl_mask_delete(kernel);
4140
4141 /* grow the 1d mask to a 2d image */
4142
4143 const cpl_binary * collapsed_opm_data = cpl_mask_get_data_const(
4144 dilated_collapsed_opm);
4145 cpl_mask * opm = cpl_mask_new(nx, ny);
4146 cpl_binary * opm_data = cpl_mask_get_data(opm);
4147 for (cpl_size iy=0; iy < ny; iy++) {
4148 memcpy(opm_data + iy * (nx * sizeof(*opm_data)),
4149 collapsed_opm_data,
4150 nx * sizeof(*opm_data));
4151 }
4152
4153 /* set the object_mask of the located_image */
4154
4155 cpl_mask_delete(limlist->limages[j]->object_mask);
4156 limlist->limages[j]->object_mask = opm;
4157
4158 cpl_image_delete(collapsed);
4159 cpl_mask_delete(collapsed_opm);
4160 cpl_mask_delete(dilated_collapsed_opm);
4161 }
4162 eris_check_error_code("enu_opm_lss_limlist");
4163 return cpl_error_get_code();
4164}
4165
4166
4167/*----------------------------------------------------------------------------*/
4180/*----------------------------------------------------------------------------*/
4181
4182cpl_error_code enu_correct_wcs(const cpl_table * refcat,
4183 const char * wcs_method,
4184 const char * catalogue,
4185 located_image * limage,
4186 const double match_rad,
4187 cpl_table ** matched_stds,
4188 cpl_matrix ** xy_shift) {
4189
4190 cpl_matrix * celestial = NULL;
4191 cpl_array * colnames = NULL;
4192 cpl_array * conv_status = NULL;
4193 cpl_table * refcat_copy = NULL;
4194 cpl_matrix * ref_phys = NULL;
4195 cpl_matrix * ref_world = NULL;
4196 cpl_matrix * xy = NULL;
4197 cpl_wcs * wcs = NULL;
4198
4199 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
4200
4201 cpl_msg_info(cpl_func, "correcting %s", cpl_frame_get_filename(limage->frame));
4202
4203 *xy_shift = NULL;
4204
4205 cpl_msg_info(cpl_func, " ..%s", cpl_frame_get_filename(limage->frame));
4206
4207 /* calculate predicted positions of refcat objects for this wcs */
4208
4209 cpl_size nref = cpl_table_get_nrow(refcat);
4210 const double * ra = cpl_table_get_data_double_const(refcat, "RA");
4211 const double * dec = NULL;
4212 if (cpl_table_has_column(refcat, "DEC")) {
4213 dec = cpl_table_get_data_double_const(refcat, "DEC");
4214 }
4215 ref_world = cpl_matrix_new(nref, 2);
4216 for (cpl_size iobj = 0; iobj < nref; iobj++) {
4217 cpl_matrix_set(ref_world, iobj, 0, ra[iobj]);
4218 cpl_matrix_set(ref_world, iobj, 1, dec[iobj]);
4219 }
4220 wcs = cpl_wcs_new_from_propertylist(limage->plist);
4221 cpl_wcs_convert(wcs, ref_world, &ref_phys, &conv_status,
4222 CPL_WCS_WORLD2PHYS);
4223 enu_check_error_code("failure calculating predicted positions");
4224
4225 /* Store the predicted positions in columns of a duplicate refcat
4226 but with all columns removed except RA, DEC, 'Std index',
4227 Aper_flux_3 */
4228
4229 refcat_copy = cpl_table_duplicate(refcat);
4230 colnames = cpl_table_get_column_names(refcat_copy);
4231 cpl_size ncol = cpl_array_get_size(colnames);
4232 for (cpl_size ic = 0; ic < ncol; ic++) {
4233 const char * colname = cpl_array_get_string(colnames, ic);
4234 if (strcmp(colname, "RA") &&
4235 strcmp(colname, "DEC") &&
4236 strcmp(colname, "Aper_flux_3") &&
4237 strcmp(colname, "Std index")) {
4238 cpl_table_erase_column(refcat_copy, colname);
4239 }
4240 }
4241
4242 /* add xpredict and ypredict columns */
4243
4244 cpl_table_new_column(refcat_copy, "xpredict", CPL_TYPE_DOUBLE);
4245 cpl_table_new_column(refcat_copy, "ypredict", CPL_TYPE_DOUBLE);
4246 for (cpl_size iobj = 0; iobj < nref; iobj++) {
4247 cpl_table_set_double(refcat_copy, "xpredict", iobj,
4248 cpl_matrix_get(ref_phys, iobj, 0));
4249 cpl_table_set_double(refcat_copy, "ypredict", iobj,
4250 cpl_matrix_get(ref_phys, iobj, 1));
4251 }
4252 enu_check_error_code("failure while creating predicted positions");
4253
4254 /* Match detected sources with refcat_copy */
4255
4256 cpl_msg_info(cpl_func, " ..matching sources");
4257 cpl_size nobj = 0;
4258 if (limage->objects && limage->objects->catalogue) {
4259 nobj = cpl_table_get_nrow(limage->objects->catalogue);
4260 }
4261
4262 if (min(nref, nobj) > 0) {
4263
4264 cpl_msg_info(cpl_func, " ..calling enm_try_all_associations");
4265
4266 enm_try_all_associations(limage->objects->catalogue,
4267 refcat_copy,
4268 match_rad,
4269 matched_stds);
4270 enu_check_error_code("enu_correct_wcs failure at "
4271 "try_all_associations");
4272
4273 enm_correct_crpix(wcs_method,
4274 catalogue,
4275 *matched_stds,
4276 limage,
4277 xy_shift);
4278 enu_check_error_code("failure to correct wcs");
4279
4280 } else {
4281 cpl_msg_info(cpl_func, " ..no catalogued objects, cannot correct wcs");
4282 }
4283
4284 cleanup:
4285 cpl_matrix_delete(celestial);
4286 cpl_array_delete(colnames);
4287 cpl_array_delete(conv_status);
4288 cpl_table_delete(refcat_copy);
4289 cpl_matrix_delete(ref_phys);
4290 cpl_matrix_delete(ref_world);
4291 cpl_matrix_delete(xy);
4292 cpl_wcs_delete(wcs);
4293 eris_check_error_code("enu_correct_wcs");
4294 return cpl_error_get_code();
4295}
4296
4297
4298/*----------------------------------------------------------------------------*/
4308/*----------------------------------------------------------------------------*/
4309
4310cpl_error_code enu_modify_CD_matrix(located_image * limage,
4311 const cpl_table * refine_wcs) {
4312
4313 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
4314 cpl_ensure_code(limage, CPL_ERROR_NULL_INPUT);
4315
4316 if (!refine_wcs) return CPL_ERROR_NONE;
4317
4318 const char * camera = cpl_propertylist_get_string(limage->plist,
4319 "ESO INS2 NXCW NAME");
4320 enu_check(camera != NULL,
4321 CPL_ERROR_ILLEGAL_INPUT,
4322 "failed to read NIX camera from ESO.INS2.NXCW.NAME");
4323
4324 cpl_size nrow = cpl_table_get_nrow(refine_wcs);
4325 cpl_boolean match = CPL_FALSE;
4326
4327 double cd1_1 = 0.0;
4328 double cd1_2 = 0.0;
4329 double cd2_1 = 0.0;
4330 double cd2_2 = 0.0;
4331
4332 for (cpl_size row = 0; row < nrow; row++) {
4333 const char * row_cam = cpl_table_get_string(refine_wcs, "camera", row);
4334
4335 if (!strcmp(camera, row_cam)) {
4336 match = CPL_TRUE;
4337
4338 int ignore = 0;
4339 cd1_1 = cpl_table_get_double(refine_wcs, "CD1_1", row, &ignore);
4340 cd1_2 = cpl_table_get_double(refine_wcs, "CD1_2", row, &ignore);
4341 cd2_1 = cpl_table_get_double(refine_wcs, "CD2_1", row, &ignore);
4342 cd2_2 = cpl_table_get_double(refine_wcs, "CD2_2", row, &ignore);
4343 /*
4344 cpl_msg_info(cpl_func,
4345 "camera %s %s cd1_1 %10.8e cd1_2 %10.8e cd2_1 %10.8e cd2_2 %10.8e",
4346 camera, row_cam, cd1_1, cd1_2, cd2_1, cd2_2);
4347 */
4348 cpl_propertylist_update_double(limage->plist, "CD1_1", cd1_1);
4349 cpl_propertylist_update_double(limage->plist, "CD1_2", cd1_2);
4350 cpl_propertylist_update_double(limage->plist, "CD2_1", cd2_1);
4351 cpl_propertylist_update_double(limage->plist, "CD2_2", cd2_2);
4352 }
4353 }
4354
4355 if (!match) {
4356 cpl_error_set_message(cpl_func,
4357 CPL_ERROR_ILLEGAL_INPUT,
4358 "camera name not matched: %s",
4359 camera);
4360 } else {
4361 cd1_1 = cpl_propertylist_get_double(limage->plist, "CD1_1");
4362 cd1_2 = cpl_propertylist_get_double(limage->plist, "CD1_2");
4363 cd2_1 = cpl_propertylist_get_double(limage->plist, "CD2_1");
4364 cd2_2 = cpl_propertylist_get_double(limage->plist, "CD2_2");
4365 cpl_msg_info(cpl_func, "..set CD matrix cd1_1=%10.8e cd1_2=%10.8e "
4366 "cd_2_1=%10.8e cd2_2=%10.8e",
4367 cd1_1, cd1_2, cd2_1, cd2_2);
4368 }
4369
4370 cleanup:
4371 eris_check_error_code("enu_modify_CD_matrix");
4372 return cpl_error_get_code();
4373}
4374
4375
4376/*----------------------------------------------------------------------------*/
4386/*----------------------------------------------------------------------------*/
4387
4388cpl_error_code enu_normalise_confidence(cpl_image * confidence) {
4389
4390 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
4391 cpl_ensure_code(confidence, CPL_ERROR_NULL_INPUT);
4392
4393 const cpl_size nx = cpl_image_get_size_x(confidence);
4394 const cpl_size ny = cpl_image_get_size_y(confidence);
4395 double * data = cpl_image_get_data_double(confidence);
4396 /* Avoid creation + checking of empty bpm */
4397 const cpl_mask * bpm = cpl_image_get_bpm_const(confidence);
4398 cpl_mask * mask = bpm ? cpl_image_get_bpm(confidence) : NULL;
4399 cpl_binary * mask_data = bpm ? cpl_mask_get_data(mask) : NULL;
4400
4401 double sum = 0.0;
4402 int nonzero = 0;
4403
4404 for (cpl_size i = 0; i < nx*ny; i++) {
4405 if (mask_data != NULL && mask_data[i] == CPL_TRUE) {
4406 mask_data[i] = CPL_FALSE;
4407 data[i] = 0.0;
4408 }
4409 if (data[i] < 0.0) data[i] = 0.0;
4410 sum += data[i];
4411 if (data[i] > 0.0) nonzero++;
4412 }
4413
4414 if (sum > 0.0) {
4415 cpl_image_multiply_scalar(confidence, 100.0 * (double)nonzero / sum);
4416 }
4417 eris_check_error_code("enu_normalise_confidence");
4418 return cpl_error_get_code();
4419}
4420
4421
4422/*----------------------------------------------------------------------------*/
4456/*----------------------------------------------------------------------------*/
4457
4458
4459cpl_error_code enu_remove_read_offsets(hdrl_image * himage,
4460 const cpl_propertylist * plist,
4461 cpl_image * confidence,
4462 const int set_confidence) {
4463
4464 cpl_image * himg = hdrl_image_get_image(himage);
4465 cpl_image * eimg = hdrl_image_get_error(himage);
4466 double * hdata = cpl_image_get_data_double(himg);
4467 double * edata = cpl_image_get_data_double(eimg);
4468 cpl_binary* hbpm = cpl_mask_get_data(cpl_image_get_bpm(himg));
4469 cpl_binary* ebpm = cpl_mask_get_data(cpl_image_get_bpm(eimg));
4470 const int mx = cpl_image_get_size_x(himg);
4471 cpl_boolean is_fast_uncorr = CPL_FALSE;
4472 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
4473
4474 /* check that the image data is double */
4475 cpl_ensure_code(hdata != NULL, CPL_ERROR_UNSUPPORTED_MODE);
4476 cpl_ensure_code(edata != NULL, CPL_ERROR_UNSUPPORTED_MODE);
4477 cpl_ensure_code(hbpm != NULL, CPL_ERROR_UNSUPPORTED_MODE);
4478 cpl_ensure_code(ebpm != NULL, CPL_ERROR_UNSUPPORTED_MODE);
4479
4480 cpl_ensure_code(plist, CPL_ERROR_NULL_INPUT);
4481
4482 /* get window information */
4483
4484 cpl_size nx = 0;
4485 cpl_size ny = 0;
4486 int rot = 0;
4487 cpl_size strx = 0;
4488 cpl_size stry = 0;
4489 cpl_size nx_chip = 0;
4490 cpl_size ny_chip = 0;
4491 cpl_boolean windowed = 0;
4493 &ny,
4494 &rot,
4495 &strx,
4496 &stry,
4497 &nx_chip,
4498 &ny_chip,
4499 &windowed,
4500 plist);
4501 enu_check_error_code("failed to read detector window information");
4502
4503 /* determine whether bottom edge of detector is corrupted by
4504 problem with short DITDELAY. Base this on the MJD of the
4505 observation - the fix was applied around 1-Mar-2023 = MJD 60004 */
4506
4507 double mjd = cpl_propertylist_get_double(plist, "MJD-OBS");
4508 enu_check_error_code("failed to read MJD-OBS");
4509 if (mjd <= 60004) {
4510 cpl_msg_info(cpl_func, "PIPE-10417 DITDELAY bug, "
4511 "remove_read_offsets will ignore bottom 4 rows "
4512 "of chip");
4513 }
4514 const char * curr_name = cpl_propertylist_get_string(plist, "ESO DET READ CURNAME");
4515 if (strcmp(curr_name, "FAST_UNCORR") == 0) {
4516 is_fast_uncorr = CPL_TRUE;
4517 }
4518 cpl_size top_width = 4;
4519 cpl_size bottom_width = 4;
4520 cpl_msg_debug(cpl_func,
4521 "..offsets from %d top rows and %d bottom rows of chip",
4522 (int) top_width, (int) bottom_width);
4523
4524 cpl_size nread_chan = nx_chip / 64;
4525
4526 /* Calculate and remove the read offsets */
4527 /* ..loop through the read channels */
4528 cpl_vector* voff = cpl_vector_new(nread_chan);
4529 cpl_size ndata = 0;
4530 double* pvoff = cpl_vector_get_data(voff);
4531 for (cpl_size read_chan = 0; read_chan < nread_chan; read_chan++) {
4532
4533 /* calculate the offsets */
4534
4535 cpl_array * offset_data = cpl_array_new(0, CPL_TYPE_DOUBLE);
4536 ndata = 0;
4537
4538 for (cpl_size x = 64 * read_chan; x < 64 * (read_chan+1); x++) {
4539
4540 /* are we in the x window */
4541 /* window/pixel coords are 1-based, C index 0-based */
4542
4543 if (x+1 >= strx && x+1 < strx+nx) {
4544
4545 for (cpl_size y = 0; y < bottom_width; y++) {
4546
4547 /* are we in the y window */
4548
4549 if (y+1 >= stry && y+1 < stry+ny) {
4550 const int ipos = x-strx+1 + mx * (y-stry+1);
4551
4552 if (!hbpm[ipos]) {
4553 if (mjd > 60004) {
4554 const double pixval = hdata[ipos];
4555 /* bottom channels OK, include them in
4556 offsets */
4557 ndata++;
4558 cpl_array_set_size(offset_data, ndata);
4559 cpl_array_set(offset_data, ndata-1, pixval);
4560 }
4561 /* reject the bottom channels for subsequent use */
4562 hbpm[ipos] = CPL_BINARY_1;
4563 ebpm[ipos] = CPL_BINARY_1;
4564
4565 if (set_confidence && confidence) {
4566 cpl_image_set(confidence,
4567 x-strx+2,
4568 y-stry+2,
4569 0.0);
4570 }
4571 }
4572 }
4573 }
4574
4575 for (cpl_size y = ny_chip-top_width; y < ny_chip; y++) {
4576 if (y+1 >= stry && y+1 < stry+ny) {
4577 const int ipos = x-strx+1 + mx * (y-stry+1);
4578
4579 if (!hbpm[ipos]) {
4580 const double pixval = hdata[ipos];
4581 ndata++;
4582 cpl_array_set_size(offset_data, ndata);
4583 cpl_array_set(offset_data, ndata-1, pixval);
4584 hbpm[ipos] = CPL_BINARY_1;
4585 ebpm[ipos] = CPL_BINARY_1;
4586 if (set_confidence && confidence) {
4587 cpl_image_set(confidence,
4588 x-strx+2,
4589 y-stry+2,
4590 0.0);
4591 }
4592 }
4593 }
4594 }
4595 }
4596 }
4597
4598 /* ..Remove the offset */
4599
4600 hdrl_value offset = {0.0, 0.0};
4601 if (ndata > 0) {
4602 cpl_msg_debug(cpl_func, "read_chan %d", (int)read_chan);
4603 cpl_msg_debug(cpl_func, "ndata %d", (int)ndata);
4604 cpl_msg_debug(cpl_func, "median %f", cpl_array_get_median(offset_data));
4605 cpl_msg_debug(cpl_func, "mean %f", cpl_array_get_mean(offset_data));
4606 cpl_msg_debug(cpl_func, "std %f", cpl_array_get_stdev(offset_data));
4607
4608 /* simple rejection of biggest outliers, there seem to be some
4609 hot pixels even in the unused borders of the chip */
4610
4611 double mean = cpl_array_get_mean(offset_data);
4612 double stdev = cpl_array_get_stdev(offset_data);
4613 int nflagged = 0;
4614 for (cpl_size i = 0; i < cpl_array_get_size(offset_data); i++) {
4615 int invalid = 0;
4616 double datum = cpl_array_get_double(offset_data, i, &invalid);
4617 if (!invalid && fabs(datum - mean) > 5 * stdev) {
4618 cpl_array_set_invalid(offset_data, i);
4619 nflagged++;
4620 }
4621 }
4622
4623 offset.data = cpl_array_get_mean(offset_data);
4624 offset.error = cpl_array_get_stdev(offset_data);
4625 pvoff[read_chan] = offset.data;
4626
4627 cpl_msg_debug(cpl_func, "..removing offset %f (%f) for read "
4628 "channel %d", offset.data, offset.error,
4629 (int) read_chan);
4630
4631 for (cpl_size x = 64 * read_chan; x < 64 * (read_chan+1); x++) {
4632 for (cpl_size y = 0; y < ny_chip; y++) {
4633
4634 if (x+1 >= strx && x+1 < strx+nx &&
4635 y+1 >= stry && y+1 < stry+ny) {
4636 const int ipos = x-strx+1 + mx * (y-stry+1);
4637
4638 if (!hbpm[ipos]) {
4639 hdata[ipos] -= offset.data;
4640 edata[ipos] = hypot(edata[ipos], offset.error);
4641 }
4642 }
4643 }
4644 }
4645 }
4646 cpl_array_delete(offset_data);
4647 }
4648
4649
4650 /* if fast mode add back offset of offsets */
4651 if(is_fast_uncorr && ndata > 0) {
4652 cpl_image_add_scalar(himg,cpl_vector_get_mean(voff));
4653 }
4654
4655 /* reject blanked pixels at left/right edges of detector */
4656
4657 for (cpl_size y = 0; y < ny_chip; y++) {
4658 for (cpl_size x = 0; x < 4; x++) {
4659 /* in window? */
4660 if (x+1 >= strx && x+1 < strx+nx &&
4661 y+1 >= stry && y+1 < stry+ny) {
4662 const int ipos = x-strx+1 + mx * (y-stry+1);
4663
4664 hbpm[ipos] = CPL_BINARY_1;
4665 ebpm[ipos] = CPL_BINARY_1;
4666
4667 if (set_confidence && confidence) {
4668 cpl_image_set(confidence,
4669 x-strx+2,
4670 y-stry+2,
4671 0.0);
4672 }
4673 }
4674 }
4675 }
4676
4677 for (cpl_size y = 0; y < ny_chip; y++) {
4678 for (cpl_size x = nx_chip-4; x < nx_chip; x++) {
4679 /* in window? */
4680 if (x+1 >= strx && x+1 < strx+nx &&
4681 y+1 >= stry && y+1 < stry+ny) {
4682
4683 hdrl_image_reject(himage,
4684 x-strx+2,
4685 y-stry+2);
4686 if (set_confidence && confidence) {
4687 cpl_image_set(confidence,
4688 x-strx+2,
4689 y-stry+2,
4690 0.0);
4691 }
4692 }
4693 }
4694 }
4695
4696 cpl_vector_delete(voff);
4697 /* re-normalise the confidence array after the changes */
4698
4699 if (set_confidence && confidence) {
4700 enu_normalise_confidence(confidence);
4701 }
4702
4703 cleanup:
4704 eris_check_error_code("enu_remove_read_offsets");
4705 return cpl_error_get_code();
4706}
4707
4708
4709/*----------------------------------------------------------------------------*/
4716/*----------------------------------------------------------------------------*/
4717
4718char * enu_repreface(const char * filename,
4719 const char * preface) {
4720
4721 if (cpl_error_get_code() != CPL_ERROR_NONE) return NULL;
4722
4723 char * in_name = cpl_strdup(filename);
4724
4725 /* expect data files to start with either ERIS.20xx or NACO.20xx */
4726 char * pch = strstr(filename, "ERIS.20");
4727 if (!pch) {
4728 pch = strstr(filename, "NACO.20");
4729 }
4730
4731 char * outname = cpl_sprintf("%s.%s", preface, pch);
4732 cpl_free(in_name);
4733
4734 return outname;
4735}
4736
4737
4738/*----------------------------------------------------------------------------*/
4753/*----------------------------------------------------------------------------*/
4754
4755
4756cpl_error_code enu_sky_backgrounds(const char * method,
4757 const char * select_method,
4758 const double timerange,
4759 const located_imagelist * target_list,
4760 const located_imagelist * sky_list,
4761 const cpl_size x_probe,
4762 const cpl_size y_probe,
4763 hdrl_imagelist ** sky_himagelist,
4764 cpl_imagelist ** sky_confidence_list) {
4765
4766 if (cpl_error_get_code() != CPL_ERROR_NONE) return cpl_error_get_code();
4767
4768 cpl_image * contrib = NULL;
4769 hdrl_imagelist * skylist = NULL;
4770 cpl_image * sky_confidence = NULL;
4771 hdrl_image * sky_himage = NULL;
4772 cpl_vector * sky_indeces = NULL;
4773
4774 cpl_msg_debug(cpl_func, "enu_sky_backgrounds entry");
4775
4776 /* parameter validation */
4777
4778 cpl_ensure_code(method, CPL_ERROR_NULL_INPUT);
4779 cpl_ensure_code(select_method, CPL_ERROR_NULL_INPUT);
4780 cpl_ensure_code(target_list, CPL_ERROR_NULL_INPUT);
4781 cpl_ensure_code(sky_list, CPL_ERROR_NULL_INPUT);
4782 cpl_ensure_code(!strcmp(select_method, "bracket") &&
4783 (timerange > 0.0), CPL_ERROR_ILLEGAL_INPUT);
4784
4785 *sky_himagelist = hdrl_imagelist_new();
4786 *sky_confidence_list = cpl_imagelist_new();
4787
4788 /* some variables used for probe pixel debugging */
4789
4790 int debug = CPL_FALSE;
4791 cpl_vector * data = NULL;
4792 cpl_vector * error = NULL;
4793 cpl_vector * reject = NULL;
4794 cpl_vector * confidence = NULL;
4795
4796 cpl_msg_info(cpl_func, "..calculating skys");
4797
4798 /* loop through target images */
4799
4800 cpl_size njitters = target_list->size;
4801 for (cpl_size j = 0; j < njitters; j++) {
4802
4803 /* Get the indices of relevant sky images */
4804
4805 if (strstr(select_method, "bracket") != NULL) {
4806 sky_indeces = enu_bracket_skys(target_list->limages[j], timerange,
4807 sky_list, x_probe > -1);
4808 }
4809 enu_check_error_code("failure in enu_bracket_skys");
4810
4811 cpl_size skysize = cpl_vector_get_size(sky_indeces);
4812 debug = CPL_FALSE;
4813 if (x_probe > 0 && skysize > 0) {
4814 const cpl_size x_size = hdrl_image_get_size_x(
4815 sky_list->limages[0]->himage);
4816 const cpl_size y_size = hdrl_image_get_size_y(
4817 sky_list->limages[0]->himage);
4818 if (x_probe > 0 && x_probe <= x_size &&
4819 y_probe > 0 && y_probe <= y_size) {
4820 debug = CPL_TRUE;
4821 if (skysize > 0) {
4822 data = cpl_vector_new(skysize);
4823 error = cpl_vector_new(skysize);
4824 reject = cpl_vector_new(skysize);
4825 confidence = cpl_vector_new(skysize);
4826 }
4827 }
4828 }
4829
4830 if (strstr(method, "collapse-median") != NULL) {
4831
4832 /* construct an hdrl_imagelist of the jitters to be combined,
4833 accumulate coadd of confidence arrays, apply object_masks
4834 if such defined in the located_images */
4835
4836 skylist = hdrl_imagelist_new();
4837 for (int k = 0; k < (int)skysize; k++) {
4838 int i = (int)cpl_vector_get(sky_indeces, k);
4839 hdrl_image * imcopy = hdrl_image_duplicate(sky_list->
4840 limages[i]->himage);
4841 cpl_image * confcopy = cpl_image_duplicate(sky_list->
4842 limages[i]->confidence);
4843 if (sky_list->limages[i]->object_mask != NULL) {
4844 cpl_mask_or(cpl_image_get_bpm(hdrl_image_get_image(imcopy)),
4845 sky_list->limages[i]->object_mask);
4846 cpl_mask_or(cpl_image_get_bpm(confcopy),
4847 sky_list->limages[i]->object_mask);
4848 cpl_image_fill_rejected(confcopy, 0.0);
4849 cpl_image_accept_all(confcopy);
4850 }
4851
4852 if (debug) {
4853 int rejected = 1;
4854 hdrl_value himval = hdrl_image_get_pixel(imcopy,
4855 x_probe, y_probe, &rejected);
4856 int ignore = 1;
4857 double conf = cpl_image_get(confcopy,
4858 x_probe, y_probe,
4859 &ignore);
4860 cpl_vector_set(data, k, himval.data);
4861 cpl_vector_set(error, k, himval.error);
4862 cpl_vector_set(reject, k, (double)rejected);
4863 cpl_vector_set(confidence, k, conf);
4864 }
4865
4866 hdrl_imagelist_set(skylist, imcopy,
4867 hdrl_imagelist_get_size(skylist));
4868
4869 if (sky_confidence == NULL) {
4870 sky_confidence = confcopy;
4871 } else {
4872 cpl_image_add(sky_confidence, confcopy);
4873 cpl_image_delete(confcopy);
4874 }
4875 }
4876 cpl_msg_debug(cpl_func, "after skylist %s",
4877 cpl_error_get_message());
4878
4879 /* Combine the images to give the result */
4880
4881 hdrl_imagelist_collapse(skylist, HDRL_COLLAPSE_MEDIAN, &sky_himage,
4882 &contrib);
4883 cpl_image_delete(contrib);
4884 contrib = NULL;
4885 cpl_msg_debug(cpl_func, "after collapse %s",
4886 cpl_error_get_message());
4887
4888 /* Re-normalise the confidence array */
4889
4890 enu_normalise_confidence(sky_confidence);
4891
4892 if (debug) {
4893 cpl_msg_info(" ",
4894 ".. enu_sky_backgrounds: probe pixel %d,%d",
4895 (int)x_probe, (int)y_probe);
4896 cpl_msg_info(" ", ".. jitter %d" , (int)j);
4897 cpl_msg_info(" ", "... j# q c d (e)");
4898
4899 for (cpl_size k = 0; k < skysize; k++) {
4900 cpl_msg_info(" ", "... %3d %3d %3d %8.2f(%4.2f)",
4901 (int)cpl_vector_get(sky_indeces, k),
4902 (int)cpl_vector_get(reject, k),
4903 (int)cpl_vector_get(confidence, k),
4904 cpl_vector_get(data, k),
4905 cpl_vector_get(error, k));
4906 }
4907 int rejected = 0;
4908 int ignore = 0;
4909 hdrl_value hval = hdrl_image_get_pixel(sky_himage,
4910 x_probe, y_probe, &rejected);
4911 double cval = cpl_image_get(sky_confidence, x_probe,
4912 y_probe, &ignore);
4913 cpl_msg_info(" ", "... -> %3d %3d %8.2f(%4.2f)",
4914 rejected, (int)cval, hval.data, hval.error);
4915
4916 cpl_vector_delete(data);
4917 cpl_vector_delete(error);
4918 cpl_vector_delete(reject);
4919 cpl_vector_delete(confidence);
4920 }
4921
4922 hdrl_imagelist_delete(skylist); skylist=NULL;
4923 enu_check_error_code("failure in collapse-median");
4924
4925 } else if (strstr(method, "median-median") != NULL) {
4926
4927 /* construct a CPL array of the median of the jitters
4928 selected */
4929
4930 cpl_array * sky_medians = cpl_array_new(0, CPL_TYPE_DOUBLE);
4931
4932 for (int k = 0; k < (int)skysize; k++) {
4933 int i = (int)cpl_vector_get(sky_indeces, k);
4934
4935 /* get a copy of the image with the object mask applied */
4936
4937 hdrl_image * imcopy = hdrl_image_duplicate(
4938 sky_list->limages[i]->himage);
4939 if (sky_list->limages[i]->object_mask != NULL) {
4940 cpl_mask_or(cpl_image_get_bpm(hdrl_image_get_image(imcopy)),
4941 sky_list->limages[i]->object_mask);
4942 }
4943 hdrl_value bkg = hdrl_image_get_median(imcopy);
4944 hdrl_image_delete(imcopy);
4945
4946 cpl_size asize = cpl_array_get_size(sky_medians);
4947 cpl_array_set_size(sky_medians, asize+1);
4948 cpl_array_set_double(sky_medians, asize, bkg.data);
4949
4950 if (debug) {
4951 cpl_vector_set(data, k, bkg.data);
4952 cpl_vector_set(error, k, bkg.error);
4953 cpl_vector_set(confidence, k, 100.0);
4954 cpl_vector_set(reject, k, 0.0);
4955 }
4956 }
4957
4958 /* The result is an image filled with the median of sky_medians
4959 ..the error plane is the stdev of sky_medians */
4960
4961 double sky_med_med = cpl_array_get_median(sky_medians);
4962 double sky_med_stdev = cpl_array_get_stdev(sky_medians);
4963 cpl_size nx = hdrl_image_get_size_x(sky_list->limages[0]->himage);
4964 cpl_size ny = hdrl_image_get_size_y(sky_list->limages[0]->himage);
4965 cpl_image * sky_data = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
4966 cpl_image_fill_window(sky_data, 1, 1, nx, ny, sky_med_med);
4967 cpl_image * sky_error = cpl_image_new(nx, ny, HDRL_TYPE_ERROR);
4968 cpl_image_fill_window(sky_error, 1, 1, nx, ny, sky_med_stdev);
4969 sky_himage = hdrl_image_create(sky_data, sky_error);
4970 cpl_image_delete(sky_data);
4971 cpl_image_delete(sky_error);
4972
4973 sky_confidence = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
4974 cpl_image_fill_window(sky_confidence, 1, 1, nx, ny, 100.0);
4975
4976 cpl_array_delete(sky_medians);
4977
4978 if (debug) {
4979 cpl_msg_info(" ",
4980 ".. enu_sky_backgrounds: median of images");
4981 cpl_msg_info(" ", ".. jitter %d" , (int)j);
4982 cpl_msg_info(" ", "... j# c d (e)");
4983
4984 for (cpl_size k = 0; k < skysize; k++) {
4985 cpl_msg_info(" ", "... %3d %3d %8.2f(%4.2f)",
4986 (int)cpl_vector_get(sky_indeces, k),
4987 (int)cpl_vector_get(confidence, k),
4988 cpl_vector_get(data, k),
4989 cpl_vector_get(error, k));
4990 }
4991 int rejected = 0;
4992 int ignore = 0;
4993 hdrl_value hval = hdrl_image_get_pixel(sky_himage,
4994 1, 1, &rejected);
4995 double cval = cpl_image_get(sky_confidence, 1, 1, &ignore);
4996 cpl_msg_info(" ", "... -> %3d %3d %8.2f(%4.2f)",
4997 rejected, (int)cval, hval.data, hval.error);
4998
4999 cpl_vector_delete(data);
5000 cpl_vector_delete(error);
5001 cpl_vector_delete(confidence);
5002 }
5003 enu_check_error_code("failure in median-median");
5004 }
5005
5006 /* append to lists */
5007
5008 hdrl_imagelist_set(*sky_himagelist, sky_himage,
5009 hdrl_imagelist_get_size(*sky_himagelist));
5010 cpl_imagelist_set(*sky_confidence_list, sky_confidence,
5011 cpl_imagelist_get_size(*sky_confidence_list));
5012 cpl_vector_delete(sky_indeces); sky_indeces = NULL;
5013 }
5014
5015 cleanup:
5016 hdrl_imagelist_delete(skylist);
5017 cpl_vector_delete(sky_indeces);
5018 if (cpl_error_get_code() != CPL_ERROR_NONE) {
5019 hdrl_imagelist_delete(*sky_himagelist);
5020 *sky_himagelist = NULL;
5021 cpl_imagelist_delete(*sky_confidence_list);
5022 *sky_confidence_list = NULL;
5023 }
5024 eris_check_error_code("enu_sky_backgrounds");
5025 return cpl_error_get_code();
5026}
5027
5028
5029/*----------------------------------------------------------------------------*/
5041/*----------------------------------------------------------------------------*/
5042
5043cpl_error_code enu_stack(located_imagelist * limages,
5044 const double stk_lthr, const double stk_hthr,
5045 const char * stk_method, const int stk_fast,
5046 located_image ** result) {
5047
5048 cpl_ensure_code(cpl_error_get_code() == CPL_ERROR_NONE,
5049 cpl_error_get_code());
5050
5051 casu_fits ** indata = NULL;
5052 casu_fits ** inconf = NULL;
5053 casu_fits ** invar = NULL;
5054 casu_fits * out = NULL;
5055 casu_fits * outc = NULL;
5056 casu_fits * outv = NULL;
5057
5058 /* parameter validation */
5059
5060 cpl_ensure_code(limages, CPL_ERROR_NULL_INPUT);
5061 cpl_ensure_code((stk_fast == 0) || (stk_fast == 1),
5062 CPL_ERROR_ILLEGAL_INPUT);
5063
5064 /* parameter translation */
5065
5066 const int casu_stk_method = (!strcmp(stk_method, "nearest") ? 0 : 1);
5067
5068 /* translate located_imagelist to casu_fits components */
5069
5070 encu_limlist_to_casu_fits(limages, &indata, &inconf, &invar);
5071
5072 /* do the stacking */
5073
5074 int njitters = (int) limages->size;
5075 int casu_status = CASU_OK;
5076 casu_imstack(indata, inconf, invar, NULL, (int)njitters, (int)njitters,
5077 stk_lthr, stk_hthr, casu_stk_method, 0, stk_fast, 0,
5078 "ESO DET DIT", &out, &outc, &outv, &casu_status);
5079 *result = enu_located_image_new(hdrl_image_create(out->image, outv->image),
5080 NULL,
5081 cpl_image_duplicate(outc->image),
5082 NULL, NULL,
5083 out->ehu,
5084 NULL, NULL, NULL, NULL, NULL);
5085 freespace(out);
5086 freespace(outc);
5087 freespace(outv);
5088
5089 return cpl_error_get_code();
5090}
5091
5092
5093/*----------------------------------------------------------------------------*/
5106/*----------------------------------------------------------------------------*/
5107
5108cpl_error_code enu_sky_subtract_limlist(const char * method,
5109 const char * select_method,
5110 const double timerange,
5111 const located_imagelist * sky_data,
5112 const cpl_size x_probe,
5113 const cpl_size y_probe,
5114 located_imagelist * target_data) {
5115
5116 cpl_ensure_code(cpl_error_get_code() == CPL_ERROR_NONE,
5117 cpl_error_get_code());
5118 cpl_ensure_code(method, CPL_ERROR_NULL_INPUT);
5119 cpl_ensure_code(select_method, CPL_ERROR_NULL_INPUT);
5120 cpl_ensure_code(target_data, CPL_ERROR_NULL_INPUT);
5121
5122 cpl_imagelist * sky_conf_list = NULL;
5123 hdrl_imagelist * sky_himlist = NULL;
5124
5125 cpl_msg_info(cpl_func,
5126 "enu_sky_subtract called: method=%s, sky_selector=%s, "
5127 "bracket=%6.2f",
5128 method, select_method, timerange);
5129 cpl_size njitters = target_data->size;
5130 cpl_msg_info(cpl_func, "number of jitters to be reduced %d",
5131 (int) njitters);
5132
5133 /* Derive sky backgrounds */
5134
5135 enu_sky_backgrounds(method, select_method, timerange, target_data,
5136 sky_data, x_probe, y_probe, &sky_himlist,
5137 &sky_conf_list);
5138 enu_check_error_code("failure in enu_sky_backgrounds");
5139
5140 /* Subtract the sky backgrounds */
5141
5142 hdrl_value before = {0.0, 0.0};
5143 double bconf = 0.0;
5144 hdrl_value bkg = {0.0, 0.0};
5145 double bkgconf = 0.0;
5146 hdrl_value after = {0.0, 0.0};
5147 double aconf = 0.0;
5148 int brejected = 1;
5149 int bkgrejected = 1;
5150 int arejected = 1;
5151 int ignore = 1;
5152 int header_printed = CPL_FALSE;
5153
5154 for (cpl_size i = 0; i < njitters; i++) {
5155
5156 /* probe pixel debug stuff */
5157
5158 const cpl_size x_size = hdrl_image_get_size_x(
5159 target_data->limages[i]->himage);
5160 const cpl_size y_size = hdrl_image_get_size_y(
5161 target_data->limages[i]->himage);
5162 if (x_probe > 0 && x_probe <= x_size &&
5163 y_probe > 0 && y_probe <= y_size) {
5164 before = hdrl_image_get_pixel(target_data->limages[i]->himage,
5165 x_probe, y_probe, &brejected);
5166 bconf = cpl_image_get(target_data->limages[i]->confidence,
5167 x_probe, y_probe, &ignore);
5168 }
5169
5170 /* this bit does the actual subtraction. */
5171
5172 hdrl_image_sub_image(target_data->limages[i]->himage,
5173 hdrl_imagelist_get_const(sky_himlist, i));
5174 target_data->limages[i]->bkg = hdrl_image_duplicate(
5175 hdrl_imagelist_get(sky_himlist, i));
5176 target_data->limages[i]->bkg_confidence = cpl_image_duplicate(
5177 cpl_imagelist_get(sky_conf_list, i));
5178
5179 /* Confidence array remains that of the target, on the assumption
5180 that the S/N of the 'sky' is much higher */
5181
5182 /* Or could do it this way... */
5183 /* Confidence arrays are combined as if inverse variances */
5184 /* COMMENTED OUT
5185 cpl_image * temp = cpl_image_add_create(
5186 target_data->limages[i]->confidence,
5187 target_data->limages[i]->bkg_confidence);
5188 cpl_image_multiply(target_data->limages[i]->confidence,
5189 target_data->limages[i]->bkg_confidence);
5190 cpl_image_divide(target_data->limages[i]->confidence, temp);
5191 cpl_image_delete(temp);
5192 */
5193
5194 /* normalise the new confidence */
5195
5196 cpl_image_fill_rejected(target_data->limages[i]->confidence, 0.0);
5197 cpl_image_accept_all(target_data->limages[i]->confidence);
5198 enu_normalise_confidence(target_data->limages[i]->confidence);
5199
5200 /* more probe pixel debug stuff */
5201
5202 if (x_probe > 0 && x_probe <= x_size &&
5203 y_probe > 0 && y_probe <= y_size) {
5204 after = hdrl_image_get_pixel(target_data->limages[i]->himage,
5205 x_probe, y_probe, &arejected);
5206 aconf = cpl_image_get(target_data->limages[i]->confidence,
5207 x_probe, y_probe, &ignore);
5208 bkg = hdrl_image_get_pixel(target_data->limages[i]->bkg,
5209 x_probe, y_probe, &bkgrejected);
5210 bkgconf = cpl_image_get(target_data->limages[i]->bkg_confidence,
5211 x_probe, y_probe, &ignore);
5212
5213 if (!header_printed) {
5214 header_printed = CPL_TRUE;
5215 cpl_msg_info(" ", "..Subtracting sky backgrounds: probe pixel %d,%d",
5216 (int)x_probe, (int)y_probe);
5217 cpl_msg_info(" ", " j# before sky after");
5218 cpl_msg_info(" ", " q c d e q c d e q c d e");
5219 }
5220 cpl_msg_info(" ",
5221 "..%3d %d %3.0f %4.2e(%4.2e)) %d %3.0f %4.2e(%4.2e) %d %3.0f %10.2e(%4.2e)",
5222 (int)i,
5223 brejected, bconf, before.data, before.error,
5224 bkgrejected, bkgconf, bkg.data, bkg.error,
5225 arejected, aconf, after.data, after.error);
5226 }
5227 }
5228
5229 cleanup:
5230 cpl_imagelist_delete(sky_conf_list);
5231 hdrl_imagelist_delete(sky_himlist);
5232
5233 return cpl_error_get_code();
5234}
5235
5236
5237/*----------------------------------------------------------------------------*/
5246/*----------------------------------------------------------------------------*/
5247
5248cpl_error_code
5249eris_nix_get_badpix_qc_from_ima(const master_bpm* mbad_pix_map,
5250 cpl_propertylist* qc_list,
5251 const char* prefix)
5252{
5253 cpl_ensure_code(mbad_pix_map != NULL, CPL_ERROR_NULL_INPUT);
5254 cpl_ensure_code(qc_list != NULL, CPL_ERROR_NULL_INPUT);
5255 cpl_ensure_code(prefix != NULL, CPL_ERROR_NULL_INPUT);
5256
5257 int flag_mask = 0;
5258 cpl_mask * bpm_mask = NULL;
5259
5260 flag_mask = ~flag_mask;
5261 bpm_mask = en_master_bpm_get_mask(mbad_pix_map, flag_mask);
5262 int nbad = cpl_mask_count(bpm_mask);
5263 cpl_propertylist_append_int(qc_list, "ESO QC NUMBER BAD PIXELS", nbad);
5264 cpl_size sx = cpl_mask_get_size_x(bpm_mask);
5265 cpl_size sy = cpl_mask_get_size_y(bpm_mask);
5266 double fraction = (double) nbad / (sx * sy);
5267 cpl_propertylist_append_double(qc_list, "ESO QC FRACTION BAD PIXELS",fraction);
5268 return cpl_error_get_code();
5269}
5270
5271
5272/*----------------------------------------------------------------------------*/
5284/*----------------------------------------------------------------------------*/
5285
5286cpl_propertylist*
5287enu_raw_flats_qc(located_imagelist* lamp_on_limlist,
5288 cpl_mask* bp_map_nl_mask,
5289 const cpl_parameterlist* parlist,
5290 const char* context,
5291 const double threshold_pos,
5292 const cpl_boolean verbose,
5293 const cpl_boolean rescale_by_dit){
5294
5295 cpl_ensure(lamp_on_limlist != NULL, CPL_ERROR_NULL_INPUT, NULL);
5296 cpl_ensure(bp_map_nl_mask != NULL, CPL_ERROR_NULL_INPUT, NULL);
5297 cpl_ensure(parlist != NULL, CPL_ERROR_NULL_INPUT, NULL);
5298 cpl_ensure(context != NULL, CPL_ERROR_NULL_INPUT, NULL);
5299
5300
5301 cpl_propertylist* qc;
5302 //located_image* loc_img;
5303 cpl_mask* mask;
5304 double mean = 0;
5305 double median = 0;
5306 double rms = 0;
5307 char* key_name;
5308 char* key_comm;
5309
5310 qc = cpl_propertylist_new();
5311 double threshold_neg = - 4.3e7;
5312 threshold_neg = 300.;
5313 long nthresh_pos = 0;
5314 long nthresh_neg = 0;
5315
5316 const cpl_parameter* param;
5317 char* pname;
5318
5319 /* negative saturation maybe not to be checked as no pixels are sat */
5320 pname = cpl_sprintf("%s%s",context,".saturation_neg");
5321 cpl_msg_warning(cpl_func,"pname: %s",pname);
5322 param = cpl_parameterlist_find_const(parlist,pname);
5323 threshold_neg = cpl_parameter_get_double(param);
5324 cpl_free(pname);
5325 //cpl_msg_info(cpl_func,"threshold_neg: %g",threshold_neg);
5326 //cpl_msg_info(cpl_func,"threshold_pos: %g",threshold_pos);
5327 //char* fname;
5328 cpl_image* ima;
5329 double mean_min = DBL_MAX;
5330 double median_min = DBL_MAX;
5331
5332 double mean_max = -DBL_MIN;
5333 double median_max = -DBL_MIN;
5334 double nthresh_pos_max = 0;
5335 double nthresh_neg_max = 0;
5336 /*
5337 cpl_msg_info(cpl_func,"mean_min: %g",mean_min);
5338 cpl_msg_info(cpl_func,"mean_max: %g",mean_max);
5339 cpl_msg_info(cpl_func,"median_min: %g",median_min);
5340 cpl_msg_info(cpl_func,"median_max: %g",median_max);
5341 */
5342 double dit = 1;
5343 cpl_propertylist* plist = NULL;
5344 for(cpl_size i = 0; i < lamp_on_limlist->size; i++) {
5345 //fname = cpl_sprintf("raw_ima_%lld.fits",i);
5346 mask = hdrl_image_get_mask(lamp_on_limlist->limages[i]->himage);
5347 /*
5348 cpl_image_save(hdrl_image_get_image(lamp_on_limlist->limages[i]->himage),
5349 fname,CPL_TYPE_DOUBLE,NULL,CPL_IO_DEFAULT);
5350 */
5351
5352 cpl_mask_or(mask, bp_map_nl_mask);
5353
5354 hdrl_image_reject_from_mask(lamp_on_limlist->limages[i]->himage, mask);
5355 ima = hdrl_image_get_image(lamp_on_limlist->limages[i]->himage);
5356 plist = lamp_on_limlist->limages[i]->plist;
5357 if(cpl_propertylist_has(plist,"ESO DET SEQ1 DIT")) {
5358 dit = cpl_propertylist_get_double(plist,"ESO DET SEQ1 DIT");
5359 }
5360 nthresh_neg = eris_image_get_threshpix(ima, threshold_neg, CPL_FALSE);
5361 nthresh_pos = eris_image_get_threshpix(ima, threshold_pos, CPL_TRUE);
5362
5363 eris_image_flag_threshpix(&ima, threshold_neg, CPL_FALSE);
5364 mean = cpl_image_get_mean(ima);
5365 median = cpl_image_get_median(ima);
5366 rms = cpl_image_get_stdev(ima);
5367 //cpl_mask_delete(mask);
5368
5369 //nsat = nthresh_neg + nthresh_pos;
5370 //nsat = nthresh_neg;
5371 if(rescale_by_dit) {
5372 mean *= dit;
5373 median *= dit;
5374 rms *= dit;
5375 }
5376 if(verbose) {
5377 key_name = cpl_sprintf("ESO QC FLAT_ON%lld NPOSSAT",i);
5378 key_comm = cpl_sprintf("Number of flat pixels above threshold");
5379 cpl_propertylist_append_int(qc, key_name, nthresh_pos);
5380 cpl_propertylist_set_comment(qc, key_name, key_comm);
5381 cpl_free(key_name);
5382 cpl_free(key_comm);
5383
5384 key_name = cpl_sprintf("ESO QC FLAT_ON%lld NNEGSAT",i);
5385 key_comm = cpl_sprintf("Number of flat pixels below neg threshold");
5386 cpl_propertylist_append_int(qc, key_name, nthresh_neg);
5387 cpl_propertylist_set_comment(qc, key_name, key_comm);
5388 cpl_free(key_name);
5389 cpl_free(key_comm);
5390
5391 key_name = cpl_sprintf("ESO QC FLAT_ON%lld MEAN",i);
5392 key_comm = cpl_sprintf("[ADU] Mean of flat");
5393 cpl_propertylist_append_double(qc, key_name, mean);
5394 cpl_propertylist_set_comment(qc,key_name,key_comm);
5395 cpl_free(key_name);
5396 cpl_free(key_comm);
5397
5398 key_name = cpl_sprintf("ESO QC FLAT_ON%lld MEDIAN",i);
5399 key_comm = cpl_sprintf("[ADU] Median of flat");
5400 cpl_propertylist_append_double(qc, key_name, median);
5401 cpl_propertylist_set_comment(qc,key_name,key_comm);
5402 cpl_free(key_name);
5403 cpl_free(key_comm);
5404
5405 key_name = cpl_sprintf("ESO QC FLAT_ON%lld STDEV",i);
5406 key_comm = cpl_sprintf("[ADU] Stdev of flat");
5407 cpl_propertylist_append_double(qc, key_name, rms);
5408 cpl_propertylist_set_comment(qc,key_name,key_comm);
5409 cpl_free(key_name);
5410 cpl_free(key_comm);
5411 }
5412
5413 if(mean > mean_max) {
5414 mean_max = mean;
5415 }
5416 if(median > median_max) {
5417 median_max = median;
5418 }
5419
5420
5421 if(mean < mean_min) {
5422 mean_min = mean;
5423 }
5424 if(median < median_min) {
5425 median_min = median;
5426 }
5427
5428
5429 if(nthresh_pos > nthresh_pos_max) {
5430 nthresh_pos_max = nthresh_pos;
5431 }
5432 if(nthresh_neg > nthresh_neg_max) {
5433 nthresh_neg_max = nthresh_neg;
5434 }
5435 }
5436 cpl_msg_info(cpl_func,"mean_min: %g",mean_min);
5437 cpl_msg_info(cpl_func,"mean_max: %g",mean_max);
5438 cpl_msg_info(cpl_func,"median_min: %g",median_min);
5439 cpl_msg_info(cpl_func,"median_max: %g",median_max);
5440 cpl_msg_info(cpl_func,"f1: %g",mean_min / mean_max);
5441 cpl_msg_info(cpl_func,"f2: %g",median_min / median_max);
5442
5443 key_name = cpl_sprintf("ESO QC FLAT_ON MEAN MIN");
5444 key_comm = cpl_sprintf("[ADU] Min of Means of flat");
5445 cpl_propertylist_append_double(qc, key_name, mean_min);
5446 cpl_propertylist_set_comment(qc,key_name,key_comm);
5447 cpl_free(key_name);
5448 cpl_free(key_comm);
5449
5450 key_name = cpl_sprintf("ESO QC FLAT_ON MEDIAN MIN");
5451 key_comm = cpl_sprintf("[ADU] Min of Medians of flat");
5452 cpl_propertylist_append_double(qc, key_name, median_min);
5453 cpl_propertylist_set_comment(qc,key_name,key_comm);
5454 cpl_free(key_name);
5455 cpl_free(key_comm);
5456
5457 key_name = cpl_sprintf("ESO QC FLAT_ON MEAN MAX");
5458 key_comm = cpl_sprintf("[ADU] Max of Means of flat");
5459 cpl_propertylist_append_double(qc, key_name, mean_max);
5460 cpl_propertylist_set_comment(qc,key_name,key_comm);
5461 cpl_free(key_name);
5462 cpl_free(key_comm);
5463
5464 key_name = cpl_sprintf("ESO QC FLAT_ON MEDIAN MAX");
5465 key_comm = cpl_sprintf("[ADU] Max of Medians of flat");
5466 cpl_propertylist_append_double(qc, key_name, median_max);
5467 cpl_propertylist_set_comment(qc,key_name,key_comm);
5468 cpl_free(key_name);
5469 cpl_free(key_comm);
5470
5471
5472 key_name = cpl_sprintf("ESO QC FLAT_ON MEAN FRAC");
5473 key_comm = cpl_sprintf("Min/Max of Means of flat");
5474 cpl_propertylist_append_double(qc, key_name, mean_min / mean_max);
5475 cpl_propertylist_set_comment(qc,key_name,key_comm);
5476 cpl_free(key_name);
5477 cpl_free(key_comm);
5478
5479
5480 key_name = cpl_sprintf("ESO QC FLAT_ON MEDIAN FRAC");
5481 key_comm = cpl_sprintf("Min/Max of Medians of flat");
5482 cpl_propertylist_append_double(qc, key_name, median_min / median_max);
5483 cpl_propertylist_set_comment(qc,key_name,key_comm);
5484 cpl_free(key_name);
5485 cpl_free(key_comm);
5486
5487
5488
5489 key_name = cpl_sprintf("ESO QC FLAT_ON NPOSSAT MAX");
5490 key_comm = cpl_sprintf("Max of Number of flat pixels above threshold");
5491 cpl_propertylist_append_int(qc, key_name, nthresh_pos_max);
5492 cpl_propertylist_set_comment(qc, key_name, key_comm);
5493 cpl_free(key_name);
5494 cpl_free(key_comm);
5495
5496 key_name = cpl_sprintf("ESO QC FLAT_ON NNEGSAT MAX");
5497 key_comm = cpl_sprintf("MAX Number of flat pixels below neg threshold");
5498 cpl_propertylist_append_int(qc, key_name, nthresh_neg_max);
5499 cpl_propertylist_set_comment(qc, key_name, key_comm);
5500 cpl_free(key_name);
5501 cpl_free(key_comm);
5502
5503
5504
5505 eris_check_error_code("enu_raw_flats_qc");
5506 return qc;
5507}
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:909
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:423
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.
cpl_error_code eris_check_error_code(const char *func_id)
handle CPL errors
Definition: eris_utils.c:56
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.