35#include "moo_params.h"
36#include "moo_badpix.h"
37#include "moo_single.h"
39#include "moo_detlist.h"
41#include "moo_prepare.h"
43#include <gsl/gsl_poly.h>
87 const cpl_frame *masterbias_frame,
88 moo_correct_bias_params *params)
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);
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);
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);
106 for (i = 1; i <= 2; i++) {
110 cpl_msg_info(__func__,
" Correcting RI_%d and ERR_RI_%d", i,
118 if (strcmp(params->subtract_bias_method,
119 MOO_CORRECT_BIAS_METHOD_MASTER) == 0) {
120 hdrl_image_sub_image(img1, img2);
123 cpl_propertylist *header = moo_single_get_header(s1);
125 moo_outputs *outputs = moo_outputs_load(header, s1->type);
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;
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);
147 moo_outputs_delete(outputs);
149 cpl_msg_info(__func__,
" Updating QUAL_RI_%d", i);
152 cpl_image_or(s1->qual, qual1, qual2);
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);
163 cpl_errorstate_set(prestate);
165 return CPL_ERROR_NONE;
169_moo_correct_dark_using_dit(moo_det *det,
179 cpl_errorstate prev_state = cpl_errorstate_get();
181 if (single != NULL) {
182 cpl_ensure_code(detoff != NULL, CPL_ERROR_NULL_INPUT);
198 double exptime = dit * ndit;
201 double exptimeoff = dit * ndit;
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);
209 cpl_msg_error(__func__,
210 "No OFF frame (or MASTER_DARK_NIR) for extname %s",
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);
220 return CPL_ERROR_NONE;
252 const cpl_frame *masterDarkVis,
253 const cpl_frame *masterDarkNir)
255 cpl_ensure_code(det != NULL, CPL_ERROR_NULL_INPUT);
257 cpl_errorstate prestate = cpl_errorstate_get();
261 moo_det *master_nir = NULL;
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);
275 for (i = 1; i <= 2; i++) {
278 cpl_msg_info(__func__,
279 "Subtract DARK on %s using MASTER_DARK_VIS: %s",
288 hdrl_image_mul_scalar(img2, (hdrl_value){
289 exptime / exptime2, 0.0 });
293 cpl_msg_error(__func__,
"No MASTER_DARK_VIS for RI_%d", i);
299 if (detoff != NULL) {
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));
308 else if (masterDarkNir != NULL) {
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));
316 for (i = 1; i <= 2; i++) {
317 _moo_correct_dark_using_dit(det, off, master_nir,
MOO_TYPE_YJ, i,
319 _moo_correct_dark_using_dit(det, off, master_nir,
MOO_TYPE_H, i,
324 cpl_msg_warning(__func__,
325 "No OFF or MASTER_DARK_NIR provided for %s, No DARK "
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);
337 cpl_errorstate_set(prestate);
339 return CPL_ERROR_NONE;
343_moo_single_correct_detlin(moo_single *s, cpl_imagelist *cube)
345 cpl_ensure_code(s != NULL, CPL_ERROR_NULL_INPUT);
346 cpl_msg_indent_more();
348 cpl_msg_warning(
"moo_correct_detlin",
349 "No linearity correction : coeffs cube is missing");
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);
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);
361 cpl_image *img = hdrl_image_get_image(himg);
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];
372 if (isnan(c) || isnan(b) || isnan(a)) {
375 if (fabs(c) < 1e-5) {
376 double val = data[i];
379 else if (fabs(b) < 1e-3) {
388 double x0 = NAN, x1 = NAN;
390 double val = data[i];
391 gsl_poly_solve_quadratic(c / (b * b), 1, a - val, &x0, &x1);
394 double dist = fabs(x0 - influx);
395 double dist_x1 = fabs(x1 - influx);
396 if (!isnan(x1) && dist > dist_x1) {
404 double val2 = 2 * c / (b * b);
405 double val3 = 1 - 2 * val2 * (a - val);
410 data[i] = (sqrt(val3) - 1) / val2;
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);
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);
428 cpl_image *img = hdrl_image_get_image(himg);
429 double *data = cpl_image_get_data_double(img);
431 int nx = cpl_image_get_size_x(img);
432 int ny = cpl_image_get_size_y(img);
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];
440 double influx = data[i];
441 if (isnan(d) || isnan(c) || isnan(b) || isnan(a)) {
444 if (fabs(d) < 1e-5) {
445 double val = data[i];
448 else if (fabs(c) < 1e-5) {
449 double val = data[i];
452 else if (fabs(b) < 1e-3) {
456 double x0 = NAN, x1 = NAN, x2 = NAN;
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,
463 double dist_x1 = fabs(x1 - influx);
464 double dist_x2 = fabs(x2 - influx);
466 double dist = fabs(x0 - influx);
467 if (!isnan(x1) && dist > dist_x1) {
471 if (!isnan(x2) && dist > dist_x2) {
487 cpl_msg_indent_less();
488 return CPL_ERROR_NONE;
509 cpl_ensure_code(det != NULL, CPL_ERROR_NULL_INPUT);
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);
519 cpl_msg_info(
"moo_correct_detlin",
"Correct linearity with %s",
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++) {
529 cpl_msg_info(__func__,
" Correcting %s", s1->extname);
530 cpl_imagelist *cdata = cube->data[idx];
531 _moo_single_correct_detlin(s1, cdata);
535 cpl_msg_indent_less();
538 return CPL_ERROR_NONE;
560 moo_nos_params *params,
562 cpl_imagelist *qlist)
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);
569 cpl_image *data = NULL;
570 cpl_image *sigma = NULL;
571 cpl_mask *mask = NULL;
576#if MOO_DEBUG_COMPUTE_NOISE_MAP
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);
596 cpl_mask_delete(mask);
597 cpl_image_delete(data);
598 cpl_image_delete(sigma);
599 return cpl_error_get_code();
630 moo_detlist *darkList,
631 moo_masklist *cosmiclist,
632 moo_nos_params *params)
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);
639 cpl_ensure_code(size >= 3, CPL_ERROR_ILLEGAL_INPUT);
641 cpl_errorstate prestate = cpl_errorstate_get();
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++) {
654 cpl_imagelist *list =
656 cpl_imagelist *qlist =
662 if (single != NULL) {
663 if (cosmiclist != NULL) {
664 for (
int k = 0; k < size; k++) {
667 cpl_image *qimg = cpl_imagelist_get(qlist, k);
675 cpl_imagelist_delete(list);
676 cpl_imagelist_unwrap(qlist);
680 cpl_msg_indent_less();
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);
686 cpl_errorstate_set(prestate);
689 return CPL_ERROR_NONE;
712_moo_single_compute_hot_map(moo_single *single, moo_hot_params *params)
714 int nb_global_hot = -1;
716 cpl_ensure(single != NULL, CPL_ERROR_NULL_INPUT, -1);
718 cpl_image *data = NULL;
719 cpl_mask *mask = NULL;
722 int nx = cpl_image_get_size_x(data);
723 int ny = cpl_image_get_size_y(data);
725 cpl_mask *data_bpm = cpl_mask_duplicate(cpl_image_get_bpm(data));
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",
736 cpl_mask_delete(cpl_image_get_bpm(data));
737 cpl_image_set_bpm(data, data_bpm);
739 int winhsize = params->local_winhsize;
741 cpl_msg_info(
"moo_compute_hot_map",
742 "Local hot pixels detection with winhsize: %d pixels",
745#pragma omp parallel default(none) \
746 shared(nx, ny, data, data_bpm, mask, params, winhsize)
750 for (
int j = 1; j <= ny; j++) {
751 for (
int i = 1; i <= nx; i++) {
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;
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,
775 double median = cpl_stats_get_median(stats);
776 double sigma = cpl_stats_get_median_dev(stats);
778 cpl_stats_delete(stats);
780 if (fabs(flux - median) <=
781 params->local_kappa * sigma) {
782 cpl_mask_set(mask, i, j, CPL_BINARY_0);
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);
800 moo_try_check(nb_hot = cpl_mask_count(mask),
" ");
805 cpl_mask_delete(mask);
806 cpl_image_delete(data);
832 cpl_ensure_code(det != NULL, CPL_ERROR_NULL_INPUT);
833 cpl_ensure_code(params != NULL, CPL_ERROR_NULL_INPUT);
835 cpl_errorstate prestate = cpl_errorstate_get();
840 cpl_msg_info(__func__,
"Computing the hot map");
841 cpl_msg_indent_more();
843 for (i = 1; i <= 2; i++) {
844 for (
int extnum = 0; extnum < 3; extnum++) {
847 if (single != NULL) {
849 moo_try_check(nb_hot =
850 _moo_single_compute_hot_map(single, params),
852 cpl_msg_info(__func__,
"Extension %s found %d hot pixels",
859 cpl_msg_indent_less();
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);
866 cpl_errorstate_set(prestate);
869 return CPL_ERROR_NONE;
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.
#define MOO_BADPIX_OUTSIDE_DATA_RANGE
cpl_error_code moo_badpix_merge(cpl_image *badpix1, cpl_image *badpix2)
Merge to bad pixel map.
#define MOO_BADPIX_COSMIC_UNREMOVED
#define MOO_BADPIX_COSMETIC
void moo_cube_delete(moo_cube *self)
Delete a moo_cube.
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.
cpl_propertylist * moo_det_get_primary_header(moo_det *self)
Get the PRIMARY HEADER in DET.
moo_det * moo_det_create(const cpl_frame *frame)
Create a new moo_det from the given DET frame.
void moo_det_delete(moo_det *self)
Delete a moo_det.
moo_single * moo_det_get_single(moo_det *self, moo_detector_type type, int num)
Get the type part in DET and return it.
const char * moo_detector_get_extname(moo_detector_type type, int ntas)
Get the extension name of a detector.
enum _moo_detector_type_ moo_detector_type
The type code type.
cpl_size moo_detlist_get_size(const moo_detlist *self)
Get the number of DET in the detlist.
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.
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.
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.
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.
cpl_mask * moo_mask_get(moo_mask *self, moo_detector_type type, int num)
Get the cpl_mask associated to given type,num.
moo_mask * moo_masklist_get(moo_masklist *self, int i)
Get the MASK at the position i in the list.
hdrl_image * moo_single_get_image(moo_single *self)
Get the IMAGE part (DATA,ERR) of single DET.
cpl_image * moo_single_get_data(moo_single *self)
Get the DATA part of single DET.
cpl_error_code moo_single_sub(moo_single *a, moo_single *b)
Subtract two single DET.
cpl_error_code moo_single_apply_mask(moo_single *self, cpl_mask *mask, unsigned int level)
Apply the given mask on the QUAL part.
cpl_image * moo_single_get_qual(moo_single *self)
Get the QUAL part of single DET.
cpl_error_code moo_compute_hot_map(moo_det *det, moo_hot_params *params)
Calculates the hot bad pixel mask.
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.
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.
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.
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)....
cpl_error_code moo_correct_detlin(moo_det *det, const cpl_frame *cube_frame)
Apply the detector linearity correction.
int moo_pfits_get_ndit(const cpl_propertylist *plist)
find out the ESO DET NDIT value
double moo_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
double moo_pfits_get_exptime(const cpl_propertylist *plist)
find out the EXPTIME value
cpl_error_code moo_qc_set_mdark_nhot(cpl_propertylist *plist, int val)
Set the QC.MDARK.NHOT value.
cpl_error_code moo_qc_set_is_linearcor(cpl_propertylist *plist, cpl_boolean val)
Set the QC.IS.LINEARCOR value.
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.
cpl_image * moo_compute_sigma_map(cpl_imagelist *list, cpl_imagelist *qlist, cpl_image *img)
Compute image of sigma variation.