MOONS Pipeline Reference Manual 0.13.1
moo_drl.c
1/*
2 * This file is part of the MOONS Pipeline
3 * Copyright (C) 2002-2016 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26 -----------------------------------------------------------------------------*/
27#include <math.h>
28#include <string.h>
29#include <cpl.h>
30#include <hdrl.h>
31#include "moo_utils.h"
32#include "moo_dfs.h"
33#include "moo_pfits.h"
34#include "moo_qc.h"
35#include "moo_params.h"
36#include "moo_badpix.h"
37#include "moo_single.h"
38#include "moo_det.h"
39#include "moo_detlist.h"
40#include "moo_cube.h"
41#include "moo_prepare.h"
42#include "moo_drl.h"
43#include <gsl/gsl_poly.h>
44#ifdef _OPENMP
45#include <omp.h>
46#endif
47/*----------------------------------------------------------------------------*/
52/*----------------------------------------------------------------------------*/
53
56/*-----------------------------------------------------------------------------
57 Function codes
58 -----------------------------------------------------------------------------*/
59
60/*----------------------------------------------------------------------------*/
84/*----------------------------------------------------------------------------*/
85cpl_error_code
86moo_correct_bias(moo_det *det,
87 const cpl_frame *masterbias_frame,
88 moo_correct_bias_params *params)
89{
90 cpl_errorstate prestate = cpl_errorstate_get();
91 cpl_ensure_code(det != NULL, CPL_ERROR_NULL_INPUT);
92 cpl_ensure_code(params != NULL, CPL_ERROR_NULL_INPUT);
93 int badpix_level = MOO_BADPIX_GOOD;
94
95 if (masterbias_frame != NULL) {
96 const char *filename = cpl_frame_get_filename(masterbias_frame);
97 const char *tag = cpl_frame_get_tag(masterbias_frame);
98
99 cpl_msg_info(__func__, "Subtracting MASTER_BIAS");
100 cpl_ensure_code(filename != NULL, CPL_ERROR_NULL_INPUT);
101 cpl_ensure_code(strcmp(tag, MOONS_TAG_MASTER_BIAS) == 0,
102 CPL_ERROR_ILLEGAL_INPUT);
103
104 moo_det *mbias = moo_det_create(masterbias_frame);
105 int i;
106 for (i = 1; i <= 2; i++) {
107 moo_single *s1 =
108 moo_det_load_single(det, MOO_TYPE_RI, i, badpix_level);
109 if (s1 != NULL) {
110 cpl_msg_info(__func__, " Correcting RI_%d and ERR_RI_%d", i,
111 i);
112 moo_single *s2 =
113 moo_det_load_single(mbias, MOO_TYPE_RI, i, badpix_level);
114
115 hdrl_image *img1 = moo_single_get_image(s1);
116 hdrl_image *img2 = moo_single_get_image(s2);
117
118 if (strcmp(params->subtract_bias_method,
119 MOO_CORRECT_BIAS_METHOD_MASTER) == 0) {
120 hdrl_image_sub_image(img1, img2);
121 }
122 else {
123 cpl_propertylist *header = moo_single_get_header(s1);
124
125 moo_outputs *outputs = moo_outputs_load(header, s1->type);
126
127 for (int ri = 0; ri < outputs->nb; ri++) {
128 int llx = outputs->outputs[ri].x;
129 int lly = outputs->outputs[ri].y;
130 int urx = outputs->outputs[ri].x +
131 outputs->outputs[ri].nx - 1;
132 int ury = outputs->outputs[ri].y +
133 outputs->outputs[ri].ny - 1;
134
135 hdrl_image *data_im =
136 hdrl_image_extract(s1->image, llx, lly, urx, ury);
137 hdrl_image *bias_im =
138 hdrl_image_extract(s2->image, llx, lly, urx, ury);
139 hdrl_value median = hdrl_image_get_median(bias_im);
140 hdrl_image_sub_scalar(data_im, median);
141 cpl_image *data = hdrl_image_get_image(data_im);
142 cpl_image *err = hdrl_image_get_error(data_im);
143 hdrl_image_insert(s1->image, data, err, llx, lly);
144 hdrl_image_delete(data_im);
145 hdrl_image_delete(bias_im);
146 }
147 moo_outputs_delete(outputs);
148 }
149 cpl_msg_info(__func__, " Updating QUAL_RI_%d", i);
150 cpl_image *qual1 = moo_single_get_qual(s1);
151 cpl_image *qual2 = moo_single_get_qual(s2);
152 cpl_image_or(s1->qual, qual1, qual2);
153 }
154 }
155
156 moo_det_delete(mbias);
157 }
158 // dump error from the state
159 if (!cpl_errorstate_is_equal(prestate)) {
160 cpl_msg_error(__func__, "Error in correct bias");
161 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
162 // Recover from the error(s) (Reset to prestate))
163 cpl_errorstate_set(prestate);
164 }
165 return CPL_ERROR_NONE;
166}
167
168static cpl_error_code
169_moo_correct_dark_using_dit(moo_det *det,
170 moo_det *detoff,
171 moo_det *mnir,
173 int i,
174 int badpix_level)
175{
176 double dit;
177 double ndit;
178
179 cpl_errorstate prev_state = cpl_errorstate_get();
180 moo_single *single = moo_det_get_single(det, type, i);
181 if (single != NULL) {
182 cpl_ensure_code(detoff != NULL, CPL_ERROR_NULL_INPUT);
183 moo_single *off = moo_det_get_single(detoff, type, i);
184
185 if (off != NULL) {
186 moo_det_load_single(det, type, i, badpix_level);
187 moo_det_load_single(detoff, type, i, badpix_level);
188
189 if (mnir != NULL) {
190 moo_single *s = moo_det_get_single(mnir, type, i);
191 if (s != NULL) {
192 moo_det_load_single(mnir, type, i, badpix_level);
193 moo_badpix_merge(single->qual, s->qual);
194 }
195 }
196 moo_try_check(dit = moo_pfits_get_dit(single->header), " ");
197 moo_try_check(ndit = moo_pfits_get_ndit(single->header), " ");
198 double exptime = dit * ndit;
199 moo_try_check(dit = moo_pfits_get_dit(off->header), " ");
200 moo_try_check(ndit = moo_pfits_get_ndit(off->header), " ");
201 double exptimeoff = dit * ndit;
202 moo_try_assure(
203 exptime == exptimeoff, CPL_ERROR_ILLEGAL_INPUT,
204 "Exptime in ON and OFF frames (type=%d) are not equal %f %f",
205 type, exptime, exptimeoff);
206 moo_single_sub(single, off);
207 }
208 else {
209 cpl_msg_error(__func__,
210 "No OFF frame (or MASTER_DARK_NIR) for extname %s",
211 single->extname);
212 }
213 }
214
215moo_try_cleanup:
216 if (!cpl_errorstate_is_equal(prev_state)) {
217 cpl_errorstate_dump(prev_state, CPL_FALSE, cpl_errorstate_dump_one);
218 cpl_errorstate_set(prev_state);
219 }
220 return CPL_ERROR_NONE;
221}
222/*----------------------------------------------------------------------------*/
248/*----------------------------------------------------------------------------*/
249cpl_error_code
250moo_correct_dark(moo_det *det,
251 moo_det *detoff,
252 const cpl_frame *masterDarkVis,
253 const cpl_frame *masterDarkNir)
254{
255 cpl_ensure_code(det != NULL, CPL_ERROR_NULL_INPUT);
256
257 cpl_errorstate prestate = cpl_errorstate_get();
258
259 int i;
260 int badpix_level = MOO_BADPIX_GOOD;
261 moo_det *master_nir = NULL;
262 moo_det *off = NULL;
263
264 if (masterDarkVis != NULL) {
265 const char *filename = cpl_frame_get_filename(masterDarkVis);
266 const char *tag = cpl_frame_get_tag(masterDarkVis);
267 cpl_ensure_code(strcmp(tag, MOONS_TAG_MASTER_DARK_VIS) == 0,
268 CPL_ERROR_ILLEGAL_INPUT);
269 cpl_ensure_code(filename != NULL, CPL_ERROR_NULL_INPUT);
270
271 moo_det *mdarkVis = moo_det_create(masterDarkVis);
272
273 double exptime = moo_pfits_get_exptime(det->primary_header);
274 double exptime2 = moo_pfits_get_exptime(mdarkVis->primary_header);
275 for (i = 1; i <= 2; i++) {
276 moo_single *s1 = moo_det_get_single(det, MOO_TYPE_RI, i);
277 if (s1 != NULL) {
278 cpl_msg_info(__func__,
279 "Subtract DARK on %s using MASTER_DARK_VIS: %s",
281 filename);
282 moo_det_load_single(det, MOO_TYPE_RI, i, badpix_level);
283 moo_det_load_single(mdarkVis, MOO_TYPE_RI, i, badpix_level);
284
285 moo_single *s2 = moo_det_get_single(mdarkVis, MOO_TYPE_RI, i);
286 if (s2 != NULL) {
287 hdrl_image *img2 = moo_single_get_image(s2);
288 hdrl_image_mul_scalar(img2, (hdrl_value){
289 exptime / exptime2, 0.0 });
290 moo_single_sub(s1, s2);
291 }
292 else {
293 cpl_msg_error(__func__, "No MASTER_DARK_VIS for RI_%d", i);
294 }
295 }
296 }
297 moo_det_delete(mdarkVis);
298 }
299 if (detoff != NULL) {
300 off = detoff;
301 cpl_msg_info(__func__, "Subtract DARK using OFF %s", off->filename);
302 if (masterDarkNir != NULL) {
303 cpl_msg_info(__func__, "Subtract DARK using MASTER_DARK_NIR %s",
304 cpl_frame_get_filename(masterDarkNir));
305 master_nir = moo_det_create(masterDarkNir);
306 }
307 }
308 else if (masterDarkNir != NULL) {
309 moo_try_check(master_nir = moo_det_create(masterDarkNir),
310 "Can't create off frame from MASTER_DARK_NIR");
311 cpl_msg_info(__func__, "Subtract DARK using MASTER_DARK_NIR %s",
312 cpl_frame_get_filename(masterDarkNir));
313 off = master_nir;
314 }
315 if (off != NULL) {
316 for (i = 1; i <= 2; i++) {
317 _moo_correct_dark_using_dit(det, off, master_nir, MOO_TYPE_YJ, i,
318 badpix_level);
319 _moo_correct_dark_using_dit(det, off, master_nir, MOO_TYPE_H, i,
320 badpix_level);
321 }
322 }
323 else {
324 cpl_msg_warning(__func__,
325 "No OFF or MASTER_DARK_NIR provided for %s, No DARK "
326 "correction done",
327 det->filename);
328 }
329
330moo_try_cleanup:
331 moo_det_delete(master_nir);
332 // dump error from the state
333 if (!cpl_errorstate_is_equal(prestate)) {
334 cpl_msg_error(__func__, "Error in Correct Dark");
335 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
336 // Recover from the error(s) (Reset to prestate))
337 cpl_errorstate_set(prestate);
338 }
339 return CPL_ERROR_NONE;
340}
341
342static cpl_error_code
343_moo_single_correct_detlin(moo_single *s, cpl_imagelist *cube)
344{
345 cpl_ensure_code(s != NULL, CPL_ERROR_NULL_INPUT);
346 cpl_msg_indent_more();
347 if (cube == NULL) {
348 cpl_msg_warning("moo_correct_detlin",
349 "No linearity correction : coeffs cube is missing");
350 }
351 else if (cpl_imagelist_get_size(cube) == 3) {
352 cpl_image *ima = cpl_imagelist_get(cube, 0);
353 cpl_image *imb = cpl_imagelist_get(cube, 1);
354 cpl_image *imc = cpl_imagelist_get(cube, 2);
355
356 float *pima = cpl_image_get_data_float(ima);
357 float *pimb = cpl_image_get_data_float(imb);
358 float *pimc = cpl_image_get_data_float(imc);
359
360 hdrl_image *himg = moo_single_get_image(s);
361 cpl_image *img = hdrl_image_get_image(himg);
362
363 double *data = cpl_image_get_data_double(img);
364 int nx = cpl_image_get_size_x(img);
365 int ny = cpl_image_get_size_x(img);
366 for (int i = 0; i < nx * ny; i++) {
367 double a = (double)pima[i];
368 double b = (double)pimb[i];
369 double c = (double)pimc[i];
370 double influx = data[i];
371
372 if (isnan(c) || isnan(b) || isnan(a)) {
373 continue;
374 }
375 if (fabs(c) < 1e-5) {
376 double val = data[i];
377 data[i] = val - a;
378 }
379 else if (fabs(b) < 1e-3) {
380 data[i] = 0;
381 }
382 else {
383 // C<1e-5 signal_true = signal-A
384 // B<1e-3 signal_true = 0
385 // C > 0 && B > 0
386 // (A-signal) + signal_true + C/B^2 *signal_true^2. = 0
387 // signal_true = (-B^2 + B^2 * sqrt(1 - 4*C*(A-signal)/B^2)) / (2*C).
388 double x0 = NAN, x1 = NAN;
389 double sol = NAN;
390 double val = data[i];
391 gsl_poly_solve_quadratic(c / (b * b), 1, a - val, &x0, &x1);
392
393 sol = x0;
394 double dist = fabs(x0 - influx);
395 double dist_x1 = fabs(x1 - influx);
396 if (!isnan(x1) && dist > dist_x1) {
397 sol = x1;
398 }
399
400 if (isnan(sol)) {
401 sol = val - a;
402 }
403
404 double val2 = 2 * c / (b * b);
405 double val3 = 1 - 2 * val2 * (a - val);
406 if (val3 < 0.0) {
407 data[i] = val - a;
408 }
409 else {
410 data[i] = (sqrt(val3) - 1) / val2;
411 }
412 // cpl_msg_info("test","test i %d %f %f",i,influx,data[i]);
413 }
414 }
415 }
416 else {
417 cpl_image *ima = cpl_imagelist_get(cube, 0);
418 cpl_image *imb = cpl_imagelist_get(cube, 1);
419 cpl_image *imc = cpl_imagelist_get(cube, 2);
420 cpl_image *imd = cpl_imagelist_get(cube, 3);
421
422 float *pima = cpl_image_get_data_float(ima);
423 float *pimb = cpl_image_get_data_float(imb);
424 float *pimc = cpl_image_get_data_float(imc);
425 float *pimd = cpl_image_get_data_float(imd);
426
427 hdrl_image *himg = moo_single_get_image(s);
428 cpl_image *img = hdrl_image_get_image(himg);
429 double *data = cpl_image_get_data_double(img);
430
431 int nx = cpl_image_get_size_x(img);
432 int ny = cpl_image_get_size_y(img);
433
434 for (int i = 0; i < nx * ny; i++) {
435 double a = (double)pima[i];
436 double b = (double)pimb[i];
437 double c = (double)pimc[i];
438 double d = (double)pimd[i];
439
440 double influx = data[i];
441 if (isnan(d) || isnan(c) || isnan(b) || isnan(a)) {
442 continue;
443 }
444 if (fabs(d) < 1e-5) {
445 double val = data[i];
446 data[i] = val - a;
447 }
448 else if (fabs(c) < 1e-5) {
449 double val = data[i];
450 data[i] = val - a;
451 }
452 else if (fabs(b) < 1e-3) {
453 data[i] = 0;
454 }
455 else {
456 double x0 = NAN, x1 = NAN, x2 = NAN;
457 double sol = NAN;
458 // (A-s) + st + C/B^2*st^2 + D/B^3*st^3 = 0
459 gsl_poly_solve_cubic((c / (b * b)) / (d / (b * b * b)),
460 1 / (d / (b * b * b)),
461 (a - influx) / (d / (b * b * b)), &x0, &x1,
462 &x2);
463 double dist_x1 = fabs(x1 - influx);
464 double dist_x2 = fabs(x2 - influx);
465 sol = x0;
466 double dist = fabs(x0 - influx);
467 if (!isnan(x1) && dist > dist_x1) {
468 dist = dist_x1;
469 sol = x1;
470 }
471 if (!isnan(x2) && dist > dist_x2) {
472 dist = dist_x2;
473 sol = x2;
474 }
475 data[i] = sol;
476 /*{
477 int xt = i % nx+1;
478 int yt = i / nx+1;
479 if(xt==1001 && yt==1001){
480 cpl_msg_info("test","test x=%d y=%d no=%f corr=%f x1=%f x2=%f x3=%f",xt,yt,influx,data[i],
481 x0,x1,x2);
482 }
483 }*/
484 }
485 }
486 }
487 cpl_msg_indent_less();
488 return CPL_ERROR_NONE;
489}
490/*----------------------------------------------------------------------------*/
505/*----------------------------------------------------------------------------*/
506cpl_error_code
507moo_correct_detlin(moo_det *det, const cpl_frame *cube_frame)
508{
509 cpl_ensure_code(det != NULL, CPL_ERROR_NULL_INPUT);
510 int badpix_level = MOO_BADPIX_GOOD;
511
512 if (cube_frame != NULL) {
513 const char *filename = cpl_frame_get_filename(cube_frame);
514 cpl_ensure_code(filename != NULL, CPL_ERROR_ILLEGAL_INPUT);
515
516 cpl_propertylist *primary_header = moo_det_get_primary_header(det);
517 moo_qc_set_is_linearcor(primary_header, CPL_TRUE);
518
519 cpl_msg_info("moo_correct_detlin", "Correct linearity with %s",
520 filename);
521 moo_cube *cube = moo_cube_load(cube_frame);
522 cpl_msg_indent_more();
523 for (int i = 0; i < 2; i++) {
524 for (int j = 0; j <= 3; j++) {
525 moo_single *s1 =
526 moo_det_load_single(det, j, i + 1, badpix_level);
527 if (s1 != NULL) {
528 int idx = j + i * 3;
529 cpl_msg_info(__func__, " Correcting %s", s1->extname);
530 cpl_imagelist *cdata = cube->data[idx];
531 _moo_single_correct_detlin(s1, cdata);
532 }
533 }
534 }
535 cpl_msg_indent_less();
536 moo_cube_delete(cube);
537 }
538 return CPL_ERROR_NONE;
539}
540
541/*----------------------------------------------------------------------------*/
557/*----------------------------------------------------------------------------*/
558cpl_error_code
560 moo_nos_params *params,
561 cpl_imagelist *list,
562 cpl_imagelist *qlist)
563{
564 cpl_ensure_code(single != NULL, CPL_ERROR_NULL_INPUT);
565 cpl_ensure_code(params != NULL, CPL_ERROR_NULL_INPUT);
566 cpl_ensure_code(list != NULL, CPL_ERROR_NULL_INPUT);
567 cpl_ensure_code(qlist != NULL, CPL_ERROR_NULL_INPUT);
568
569 cpl_image *data = NULL;
570 cpl_image *sigma = NULL;
571 cpl_mask *mask = NULL;
572
573 moo_try_check(data = moo_single_get_data(single), " ");
574 moo_try_check(sigma = moo_compute_sigma_map(list, qlist, data), " ");
575
576#if MOO_DEBUG_COMPUTE_NOISE_MAP
577 {
578 char *name = cpl_sprintf("sigma_%s.fits", single->extname);
579 char *qname = cpl_sprintf("mask_sigma_%s.fits", single->extname);
580 cpl_image_save(sigma, name, CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
581 cpl_mask *msigma = cpl_image_get_bpm(sigma);
582 cpl_mask_save(msigma, qname, NULL, CPL_IO_CREATE);
583 cpl_free(name);
584 cpl_free(qname);
585 }
586#endif
587 moo_try_check(mask = moo_kappa_sigma_clipping(sigma, params->clip_niter,
588 params->clip_kappa,
589 params->clip_diff,
590 params->clip_frac),
591 " ");
592
593 moo_try_check(moo_single_apply_mask(single, mask, MOO_BADPIX_NOISY), " ");
594
595moo_try_cleanup:
596 cpl_mask_delete(mask);
597 cpl_image_delete(data);
598 cpl_image_delete(sigma);
599 return cpl_error_get_code();
600}
601/*----------------------------------------------------------------------------*/
627/*----------------------------------------------------------------------------*/
628cpl_error_code
630 moo_detlist *darkList,
631 moo_masklist *cosmiclist,
632 moo_nos_params *params)
633{
634 cpl_ensure_code(det != NULL, CPL_ERROR_NULL_INPUT);
635 cpl_ensure_code(darkList != NULL, CPL_ERROR_NULL_INPUT);
636 cpl_ensure_code(params != NULL, CPL_ERROR_NULL_INPUT);
637
638 int size = moo_detlist_get_size(darkList);
639 cpl_ensure_code(size >= 3, CPL_ERROR_ILLEGAL_INPUT);
640
641 cpl_errorstate prestate = cpl_errorstate_get();
642
645
646 int i;
647
648 cpl_msg_info("moo_compute_noise_map",
649 "Computing the noise map using %d dark files", size);
650 cpl_msg_indent_more();
651 for (i = 1; i <= 2; i++) {
652 for (int extnum = 1; extnum <= 2; extnum++) {
653 moo_detlist_load_single(darkList, extnum, i, badpix_level);
654 cpl_imagelist *list =
655 moo_detlist_get_single_data(darkList, extnum, i);
656 cpl_imagelist *qlist =
657 moo_detlist_get_single_qual(darkList, extnum, i);
658
659 moo_single *single =
660 moo_det_load_single(det, extnum, i, badpix_level);
661
662 if (single != NULL) {
663 if (cosmiclist != NULL) {
664 for (int k = 0; k < size; k++) {
665 moo_mask *mmask = moo_masklist_get(cosmiclist, k);
666
667 cpl_image *qimg = cpl_imagelist_get(qlist, k);
668 cpl_mask *mask = moo_mask_get(mmask, extnum, i);
669 moo_mask_to_badpix(qimg, mask,
671 }
672 }
673 moo_single_compute_noise_map(single, params, list, qlist);
674 }
675 cpl_imagelist_delete(list);
676 cpl_imagelist_unwrap(qlist);
677 moo_detlist_free_single(darkList, extnum, i);
678 }
679 }
680 cpl_msg_indent_less();
681 // dump error from the state
682 if (!cpl_errorstate_is_equal(prestate)) {
683 cpl_msg_error(__func__, "Error in compute noise map");
684 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
685 // Recover from the error(s) (Reset to prestate))
686 cpl_errorstate_set(prestate);
687 }
688
689 return CPL_ERROR_NONE;
690}
691
692/*----------------------------------------------------------------------------*/
710/*----------------------------------------------------------------------------*/
711static int
712_moo_single_compute_hot_map(moo_single *single, moo_hot_params *params)
713{
714 int nb_global_hot = -1;
715 int nb_hot = -1;
716 cpl_ensure(single != NULL, CPL_ERROR_NULL_INPUT, -1);
717
718 cpl_image *data = NULL;
719 cpl_mask *mask = NULL;
720
721 moo_try_check(data = moo_single_get_data(single), " ");
722 int nx = cpl_image_get_size_x(data);
723 int ny = cpl_image_get_size_y(data);
724
725 cpl_mask *data_bpm = cpl_mask_duplicate(cpl_image_get_bpm(data));
726 moo_try_check(mask = moo_kappa_sigma_clipping(data, params->clip_niter,
727 params->clip_kappa,
728 params->clip_diff,
729 params->clip_frac),
730 " ");
731
732 moo_try_check(nb_global_hot = cpl_mask_count(mask), " ");
733 cpl_msg_info("moo_compute_hot_map",
734 "Global hot pixels detection : %d pixels found",
735 nb_global_hot);
736 cpl_mask_delete(cpl_image_get_bpm(data));
737 cpl_image_set_bpm(data, data_bpm);
738
739 int winhsize = params->local_winhsize;
740 if (winhsize != 0) {
741 cpl_msg_info("moo_compute_hot_map",
742 "Local hot pixels detection with winhsize: %d pixels",
743 winhsize);
744#ifdef _OPENMP
745#pragma omp parallel default(none) \
746 shared(nx, ny, data, data_bpm, mask, params, winhsize)
747 {
748#pragma omp for
749#endif
750 for (int j = 1; j <= ny; j++) {
751 for (int i = 1; i <= nx; i++) {
752 int rej;
753 cpl_binary m = cpl_mask_get(mask, i, j);
754 if (m == CPL_BINARY_1) {
755 int llx = i - winhsize;
756 int lly = j - winhsize;
757 int urx = i + winhsize;
758 int ury = j + winhsize;
759 if (llx < 1) {
760 llx = 1;
761 }
762 if (lly < 1) {
763 lly = 1;
764 }
765 if (urx > nx) {
766 urx = nx;
767 }
768 if (ury > ny) {
769 ury = ny;
770 }
771 double flux = cpl_image_get(data, i, j, &rej);
772 cpl_stats *stats = cpl_stats_new_from_image_window(
773 data, CPL_STATS_MEDIAN | CPL_STATS_MEDIAN_DEV, llx,
774 lly, urx, ury);
775 double median = cpl_stats_get_median(stats);
776 double sigma = cpl_stats_get_median_dev(stats);
777
778 cpl_stats_delete(stats);
779
780 if (fabs(flux - median) <=
781 params->local_kappa * sigma) {
782 cpl_mask_set(mask, i, j, CPL_BINARY_0);
783 }
784 }
785 }
786 }
787 }
788#ifdef _OPENMP
789 }
790#endif
791 for (int j = 1; j <= ny; j++) {
792 for (int i = 1; i <= nx; i++) {
793 cpl_binary m = cpl_mask_get(mask, i, j);
794 if (m == CPL_BINARY_1) {
795 cpl_mask_set(data_bpm, i, j, CPL_BINARY_1);
796 }
797 }
798 }
799 moo_try_check(moo_single_apply_mask(single, mask, MOO_BADPIX_HOT), " ");
800 moo_try_check(nb_hot = cpl_mask_count(mask), " ");
801
802 moo_try_check(moo_qc_set_mdark_nhot(single->header, nb_hot), " ");
803
804moo_try_cleanup:
805 cpl_mask_delete(mask);
806 cpl_image_delete(data);
807
808 return nb_hot;
809}
810/*----------------------------------------------------------------------------*/
828/*----------------------------------------------------------------------------*/
829cpl_error_code
830moo_compute_hot_map(moo_det *det, moo_hot_params *params)
831{
832 cpl_ensure_code(det != NULL, CPL_ERROR_NULL_INPUT);
833 cpl_ensure_code(params != NULL, CPL_ERROR_NULL_INPUT);
834
835 cpl_errorstate prestate = cpl_errorstate_get();
838 int i;
839
840 cpl_msg_info(__func__, "Computing the hot map");
841 cpl_msg_indent_more();
842
843 for (i = 1; i <= 2; i++) {
844 for (int extnum = 0; extnum < 3; extnum++) {
845 moo_single *single =
846 moo_det_load_single(det, extnum, i, badpix_level);
847 if (single != NULL) {
848 int nb_hot = 0;
849 moo_try_check(nb_hot =
850 _moo_single_compute_hot_map(single, params),
851 " ");
852 cpl_msg_info(__func__, "Extension %s found %d hot pixels",
853 moo_detector_get_extname(extnum, i), nb_hot);
854 }
855 }
856 }
857
858moo_try_cleanup:
859 cpl_msg_indent_less();
860
861 // dump error from the state
862 if (!cpl_errorstate_is_equal(prestate)) {
863 cpl_msg_error(__func__, "Error in compute hot map");
864 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
865 // Recover from the error(s) (Reset to prestate))
866 cpl_errorstate_set(prestate);
867 }
868
869 return CPL_ERROR_NONE;
870}
#define MOO_BADPIX_NOISY
Definition: moo_badpix.h:39
cpl_error_code moo_mask_to_badpix(cpl_image *badpix, cpl_mask *mask, unsigned int level)
Add the mask of the badpix level to the badpix map.
Definition: moo_badpix.c:105
#define MOO_BADPIX_OUTSIDE_DATA_RANGE
Definition: moo_badpix.h:62
cpl_error_code moo_badpix_merge(cpl_image *badpix1, cpl_image *badpix2)
Merge to bad pixel map.
Definition: moo_badpix.c:146
#define MOO_BADPIX_HOT
Definition: moo_badpix.h:51
#define MOO_BADPIX_COSMIC_UNREMOVED
Definition: moo_badpix.h:42
#define MOO_BADPIX_GOOD
Definition: moo_badpix.h:36
#define MOO_BADPIX_COSMETIC
Definition: moo_badpix.h:57
void moo_cube_delete(moo_cube *self)
Delete a moo_cube.
Definition: moo_cube.c:343
moo_single * moo_det_load_single(moo_det *self, moo_detector_type type, int num, int level)
Load the type part in DET and return it.
Definition: moo_det.c:197
cpl_propertylist * moo_det_get_primary_header(moo_det *self)
Get the PRIMARY HEADER in DET.
Definition: moo_det.c:453
moo_det * moo_det_create(const cpl_frame *frame)
Create a new moo_det from the given DET frame.
Definition: moo_det.c:91
void moo_det_delete(moo_det *self)
Delete a moo_det.
Definition: moo_det.c:472
moo_single * moo_det_get_single(moo_det *self, moo_detector_type type, int num)
Get the type part in DET and return it.
Definition: moo_det.c:359
const char * moo_detector_get_extname(moo_detector_type type, int ntas)
Get the extension name of a detector.
Definition: moo_detector.c:137
enum _moo_detector_type_ moo_detector_type
The type code type.
Definition: moo_detector.h:64
@ MOO_TYPE_YJ
Definition: moo_detector.h:50
@ MOO_TYPE_H
Definition: moo_detector.h:54
@ MOO_TYPE_RI
Definition: moo_detector.h:46
cpl_size moo_detlist_get_size(const moo_detlist *self)
Get the number of DET in the detlist.
Definition: moo_detlist.c:173
cpl_error_code moo_detlist_free_single(const moo_detlist *self, moo_detector_type type, int num)
Free the type part for all DET in the detlist.
Definition: moo_detlist.c:143
cpl_imagelist * moo_detlist_get_single_data(const moo_detlist *self, moo_detector_type type, int num)
Get the type data part for all DET in the detlist.
Definition: moo_detlist.c:279
cpl_imagelist * moo_detlist_get_single_qual(const moo_detlist *self, moo_detector_type type, int num)
Get the type QUAL part for all DET in the detlist.
Definition: moo_detlist.c:320
cpl_error_code moo_detlist_load_single(const moo_detlist *self, moo_detector_type type, int num, int level)
Load the type part for all DET in the detlist.
Definition: moo_detlist.c:107
cpl_mask * moo_mask_get(moo_mask *self, moo_detector_type type, int num)
Get the cpl_mask associated to given type,num.
Definition: moo_mask.c:81
moo_mask * moo_masklist_get(moo_masklist *self, int i)
Get the MASK at the position i in the list.
Definition: moo_masklist.c:121
hdrl_image * moo_single_get_image(moo_single *self)
Get the IMAGE part (DATA,ERR) of single DET.
Definition: moo_single.c:330
cpl_image * moo_single_get_data(moo_single *self)
Get the DATA part of single DET.
Definition: moo_single.c:239
cpl_error_code moo_single_sub(moo_single *a, moo_single *b)
Subtract two single DET.
Definition: moo_single.c:502
cpl_error_code moo_single_apply_mask(moo_single *self, cpl_mask *mask, unsigned int level)
Apply the given mask on the QUAL part.
Definition: moo_single.c:287
cpl_image * moo_single_get_qual(moo_single *self)
Get the QUAL part of single DET.
Definition: moo_single.c:312
cpl_error_code moo_compute_hot_map(moo_det *det, moo_hot_params *params)
Calculates the hot bad pixel mask.
Definition: moo_drl.c:830
cpl_error_code moo_compute_noise_map(moo_det *det, moo_detlist *darkList, moo_masklist *cosmiclist, moo_nos_params *params)
Calculates the noisey bad pixel mask.
Definition: moo_drl.c:629
cpl_error_code moo_single_compute_noise_map(moo_single *single, moo_nos_params *params, cpl_imagelist *list, cpl_imagelist *qlist)
Calculates the noisey bad pixel mask for one extension.
Definition: moo_drl.c:559
cpl_error_code moo_correct_bias(moo_det *det, const cpl_frame *masterbias_frame, moo_correct_bias_params *params)
Subtracts the Master Bias frame from a DET frame.
Definition: moo_drl.c:86
cpl_error_code moo_correct_dark(moo_det *det, moo_det *detoff, const cpl_frame *masterDarkVis, const cpl_frame *masterDarkNir)
Subtracts the master dark frame from a frame after scaling for exposure time (RI)....
Definition: moo_drl.c:250
cpl_error_code moo_correct_detlin(moo_det *det, const cpl_frame *cube_frame)
Apply the detector linearity correction.
Definition: moo_drl.c:507
int moo_pfits_get_ndit(const cpl_propertylist *plist)
find out the ESO DET NDIT value
Definition: moo_pfits.c:382
double moo_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
Definition: moo_pfits.c:362
double moo_pfits_get_exptime(const cpl_propertylist *plist)
find out the EXPTIME value
Definition: moo_pfits.c:1039
cpl_error_code moo_qc_set_mdark_nhot(cpl_propertylist *plist, int val)
Set the QC.MDARK.NHOT value.
Definition: moo_qc.c:424
cpl_error_code moo_qc_set_is_linearcor(cpl_propertylist *plist, cpl_boolean val)
Set the QC.IS.LINEARCOR value.
Definition: moo_qc.c:2381
cpl_mask * moo_kappa_sigma_clipping(cpl_image *sigma_img, int niter, double kappa, double cdiff, double maxfrac)
Compute mask of rejected pixels using kappa sigma algorithm.
Definition: moo_utils.c:163
cpl_image * moo_compute_sigma_map(cpl_imagelist *list, cpl_imagelist *qlist, cpl_image *img)
Compute image of sigma variation.
Definition: moo_utils.c:100