31#include "cr2res_calib.h"
32#include "cr2res_bpm.h"
33#include "cr2res_pfits.h"
35#include "cr2res_detlin.h"
36#include "cr2res_utils.h"
45 const hdrl_image * flat, cpl_size degree);
76 const hdrl_imagelist * in,
79 int subtract_nolight_rows,
80 int subtract_interorder_column,
82 const cpl_frame * flat,
83 const cpl_frame * dark,
84 const cpl_frame * bpm,
85 const cpl_frame * detlin,
86 const cpl_vector * dits,
87 const cpl_vector * ndits,
88 const cpl_vector * ndsamples)
90 hdrl_imagelist * out ;
97 if (in == NULL)
return NULL ;
109 const hdrl_image *cur_ima;
110 hdrl_image *cur_ima_calib;
113 if (dits != NULL) dit = cpl_vector_get(dits, i) ;
114 if (ndits != NULL) ndit = (int)cpl_vector_get(ndits, i) ;
115 if (ndsamples != NULL) ndsamp = (int)cpl_vector_get(ndsamples, i) ;
118 cpl_msg_info(__func__,
119 "Apply calibrations for image #%"CPL_SIZE_FORMAT, i+1) ;
120 cpl_msg_indent_more() ;
122 subtract_nolight_rows, subtract_interorder_column,
123 cosmics_corr, flat, dark, bpm,
124 detlin, dit, ndit, ndsamp)) == NULL) {
125 cpl_msg_error(__func__,
"Failed to Calibrate the Data") ;
127 cpl_msg_indent_less() ;
133 cpl_msg_indent_less() ;
159 const hdrl_image * in,
162 int subtract_nolight_rows,
163 int subtract_interorder_column,
165 const cpl_frame * flat,
166 const cpl_frame * dark,
167 const cpl_frame * bpm,
168 const cpl_frame * detlin,
175 hdrl_imagelist * calib_list ;
178 if (in == NULL)
return NULL ;
179 if (chip < 1 || chip > CR2RES_NB_DETECTORS)
return NULL ;
186 cpl_msg_info(__func__,
"Correct the bad pixels") ;
188 cpl_frame_get_filename(bpm), chip, clean_bad) != 0) {
189 cpl_msg_error(__func__,
"Cannot clean the bad pixels");
196 if (detlin != NULL) {
197 cpl_msg_info(__func__,
"Correct for the Non-Linearity") ;
199 cpl_frame_get_filename(detlin), chip)) == NULL) {
200 cpl_msg_error(__func__,
"Cannot load the detlin") ;
208 cpl_msg_error(__func__,
"Cannot correct for the Non-Linearity") ;
214 cpl_msg_info(__func__,
"Add shot-noise") ;
216 cpl_msg_error(__func__,
"Cannot add shot-noise") ;
225 cpl_propertylist *plist;
227 cpl_msg_info(__func__,
"Correct for the dark") ;
232 cpl_msg_error(__func__,
"Cannot load the dark") ;
236 if (detlin != NULL) {
237 cpl_msg_indent_more() ;
238 cpl_msg_info(__func__,
"Correct DARK for Non-Linearity") ;
243 cpl_msg_error(__func__,
"Cannot correct DARK for Non-Linearity");
244 cpl_msg_indent_less() ;
247 cpl_msg_indent_less() ;
251 plist = cpl_propertylist_load(cpl_frame_get_filename(dark), 0);
253 cpl_propertylist_delete(plist) ;
255 hdrl_value hdrl_dit_corr = {dit/dark_dit, 0.0};
260 cpl_msg_error(__func__,
"Cannot apply the dark") ;
267 if (detlin != NULL) {
272 if (subtract_nolight_rows) {
275 cpl_msg_info(__func__,
"Subtract median of bottom rows");
277 img_tmp = cpl_image_collapse_median_create(
279 CR2RES_DETECTOR_SIZE-CR2RES_NB_BPM_VIGN_BOTTOM);
280 calib =
hdrl_image_new(CR2RES_DETECTOR_SIZE,CR2RES_DETECTOR_SIZE);
281 for (i=1; i<=CR2RES_DETECTOR_SIZE; i++) {
286 cpl_image_delete(img_tmp);
290 if (subtract_interorder_column) {
292 cpl_msg_info(__func__,
293 "Skip subtracting fit to inter-order pixels (no flat-field)");
295 cpl_msg_info(__func__,
"Subtract fit to inter-order pixels");
297 cpl_frame_get_filename(flat), chip)) == NULL) {
298 cpl_msg_error(__func__,
"Cannot load the flat field") ;
303 cpl_msg_error(__func__,
"Could not subtract inter-order fit");
311 cpl_msg_info(__func__,
"Correct for the flat field") ;
314 cpl_frame_get_filename(flat), chip)) == NULL) {
315 cpl_msg_error(__func__,
"Cannot load the flat field") ;
322 cpl_msg_error(__func__,
"Cannot apply the flat field") ;
333 cpl_msg_info(__func__,
"Apply the cosmics corrections") ;
336 cpl_msg_warning(__func__,
"invalid cospar");
339 cpl_mask_delete(cosmask);
355static double cr2res_utr_shot_factor(
int ndsamples)
358 if (ndsamples < 2)
return 1.0 ;
359 n = (double)ndsamples ;
360 return 6.0 * (n * n + 1.0) / (5.0 * n * (n + 1.0)) ;
381 double gain, alpha, read_noise, min_rn ;
382 const double min_dit = 1.427 ;
383 const double lim_dit = 50.0 ;
384 const double lim_rn = 6.0 ;
386 if (in == NULL)
return -1 ;
389 cpl_msg_error(__func__,
"Broken input image") ;
393 cpl_msg_error(__func__,
"Invalid NDIT: %d", ndit) ;
397 if (chip == 1) gain = CR2RES_GAIN_CHIP1 ;
398 else if (chip == 2) gain = CR2RES_GAIN_CHIP2 ;
399 else if (chip == 3) gain = CR2RES_GAIN_CHIP3 ;
401 cpl_msg_error(__func__,
"Unknown detector") ;
406 min_rn = (chip == 1) ? 11.0 : 12.0 ;
407 if (dit <= min_dit) read_noise = min_rn ;
408 else if (dit >= lim_dit) read_noise = lim_rn ;
409 else read_noise = min_rn + (lim_rn-min_rn)*(dit-min_dit)/(lim_dit-min_dit);
411 alpha = cr2res_utr_shot_factor(ndsamples) ;
413 cpl_msg_debug(__func__,
"chip:%d, gain:%g, ndit:%d, ndsamples:%d, "
414 "alpha:%g, read_noise:%g", chip, gain, ndit, ndsamples, alpha,
418 cpl_msg_error(__func__,
"Cannot duplicate the input image") ;
421 cpl_image_threshold(var, 0.0, DBL_MAX, 0.0, DBL_MAX) ;
422 cpl_image_multiply_scalar(var, alpha / (gain * ndit)) ;
423 cpl_image_add_scalar(var, read_noise * read_noise / (gain * gain * ndit)) ;
426 cpl_image_accept_all(var) ;
428 if (cpl_image_power(error, 2.0) != CPL_ERROR_NONE ||
429 cpl_image_add(error, var) != CPL_ERROR_NONE ||
430 cpl_image_power(error, 0.5) != CPL_ERROR_NONE) {
431 cpl_msg_error(__func__,
"Cannot combine the errors") ;
432 cpl_image_delete(var) ;
435 cpl_image_delete(var) ;
453 const hdrl_image * flat, cpl_size degree)
457 const cpl_image * flat_img;
458 cpl_polynomial * poly;
460 cpl_size ncolumns, nrow;
464 double value, median, mad;
467 if (in == NULL || flat == NULL)
return -1;
474 ncolumns = cpl_image_get_size_x(img);
475 nrow = cpl_image_get_size_y(img);
478 for (i = CR2RES_NB_BPM_EDGEPIX + 1; i < ncolumns - CR2RES_NB_BPM_EDGEPIX;
484 px = cpl_matrix_new(1, nrow);
485 py = cpl_vector_new(nrow);
487 for ( j = CR2RES_NB_BPM_VIGN_BOTTOM + 5; j < nrow -20 ; j++)
491 if (cpl_image_is_rejected(flat_img, i, j)
492 && !cpl_image_is_rejected(img, i, j) &&
493 isnan(cpl_image_get(img, i, j, &badpix)) == 0){
494 cpl_matrix_set(px, 0, npixel, j);
495 cpl_vector_set(py, npixel, cpl_image_get(img, i, j, &badpix));
499 cpl_msg_debug(__func__,
"Column %lld has %lld pixels for background",
503 cpl_matrix_delete(px);
504 cpl_vector_delete(py);
507 cpl_matrix_set_size(px, 1, npixel);
508 cpl_vector_set_size(py, npixel);
512 for (j=0;j<npixel;j++){
514 if ((cpl_vector_get(py,j) > median*2) || (cpl_vector_get(py,j) < 0.0) )
515 cpl_vector_set(py,j,median);
518 tmp = cpl_vector_filter_lowpass_create(py,CPL_LOWPASS_LINEAR,100);
519 cpl_vector_delete(py);
521 if (cpl_msg_get_level() == CPL_MSG_DEBUG){
522 tmp = cpl_vector_wrap(npixel, cpl_matrix_get_data(px));
523 cpl_vector_save(tmp,
"debug_background.fits",
524 CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
525 cpl_vector_save(py,
"debug_background.fits",
526 CPL_TYPE_DOUBLE, NULL, CPL_IO_EXTEND);
527 cpl_vector_unwrap(tmp);
531 poly = cpl_polynomial_new(1);
532 if (cpl_polynomial_fit(poly, px, NULL, py, NULL, CPL_FALSE, NULL,
536 cpl_msg_warning(__func__,
537 "Could not fit the background of column %"CPL_SIZE_FORMAT, i);
539 cpl_matrix_delete(px);
540 cpl_vector_delete(py);
541 cpl_polynomial_delete(poly);
546 for ( j = 1; j < nrow + 1; j++)
548 value = cpl_image_get(img, i, j, &badpix);
550 if (badpix)
continue;
551 value -= cpl_polynomial_eval_1d(poly, j, NULL);
552 cpl_image_set(img, i, j, value);
556 cpl_matrix_delete(px);
557 cpl_vector_delete(py);
558 cpl_polynomial_delete(poly);
562 cpl_msg_warning(__func__,
563 "%d columns could not be background-subtracted from inter-order gaps",
580 const cpl_image * var)
583 cpl_image_power(err, 2.0) ;
584 cpl_image_add(err, var) ;
585 cpl_image_threshold(err, 0.0, DBL_MAX, 0.0, DBL_MAX) ;
586 cpl_image_power(err, 0.5) ;
598 cpl_image * relerr2 ;
600 if (mflat == NULL)
return NULL ;
603 if (relerr2 == NULL)
return NULL ;
604 cpl_image_power(relerr2, 2.0) ;
620 const cpl_image * relerr2,
623 cpl_image * term = cpl_image_power_create(
625 cpl_image_multiply(term, relerr2) ;
626 cpl_image_multiply_scalar(term, sign) ;
628 cpl_image_delete(term) ;
646 hdrl_imagelist * list,
647 const cpl_frame * master_dark_frame,
649 const hdrl_image * mflat,
650 const cpl_vector * dits,
654 cpl_propertylist * plist ;
659 if (list == NULL || master_dark_frame == NULL || dits == NULL)
return -1 ;
663 cpl_frame_get_filename(master_dark_frame), chip)) == NULL)
665 plist = cpl_propertylist_load(cpl_frame_get_filename(master_dark_frame),0);
667 cpl_propertylist_delete(plist) ;
668 if (cpl_error_get_code() || dark_dit == 0.0) {
676 cpl_image * flat2 = cpl_image_power_create(
678 cpl_image_divide(var, flat2) ;
679 cpl_image_delete(flat2) ;
682 cpl_image_fill_rejected(var, 0.0) ;
683 cpl_image_accept_all(var) ;
686 double scale = cpl_vector_get(dits, i) / dark_dit ;
687 cpl_image * term = cpl_image_multiply_scalar_create(var,
688 sign * scale * scale) ;
690 cpl_image_delete(term) ;
692 cpl_image_delete(var) ;
int cr2res_bpm_set_and_correct_image(cpl_image *in, const char *bpm, int chip, int correct)
Set the BPM and optionally apply the correction to an image.
cpl_image * cr2res_calib_flat_relerr2(const hdrl_image *mflat)
Squared relative error of a master flat, (sigma_F/F)^2.
hdrl_image * cr2res_calib_image(const hdrl_image *in, int chip, int clean_bad, int subtract_nolight_rows, int subtract_interorder_column, int cosmics_corr, const cpl_frame *flat, const cpl_frame *dark, const cpl_frame *bpm, const cpl_frame *detlin, double dit, int ndit, int ndsamples)
The images calibration routine for a given chip.
hdrl_imagelist * cr2res_calib_imagelist(const hdrl_imagelist *in, int chip, int clean_bad, int subtract_nolight_rows, int subtract_interorder_column, int cosmics_corr, const cpl_frame *flat, const cpl_frame *dark, const cpl_frame *bpm, const cpl_frame *detlin, const cpl_vector *dits, const cpl_vector *ndits, const cpl_vector *ndsamples)
The images calibration routine for a given chip on a list.
int cr2res_calib_dark_var(hdrl_imagelist *list, const cpl_frame *master_dark_frame, int chip, const hdrl_image *mflat, const cpl_vector *dits, double sign)
Add or remove the master dark variance of cr2res_calib_image()
int cr2res_calib_subtract_interorder_column(hdrl_image *in, const hdrl_image *flat, cpl_size degree)
Remove background column by column.
void cr2res_calib_add_var(hdrl_image *ima, const cpl_image *var)
Add a variance image to the error of an HDRL image.
int cr2res_add_shotnoise(hdrl_image *in, double dit, int ndit, int ndsamples, int chip)
Add shot- and read-noise to errors in HDRL-image.
void cr2res_calib_flat_var(hdrl_image *ima, const cpl_image *relerr2, double sign)
Add or remove the flat-field variance term of an image.
int cr2res_detlin_correct(hdrl_image *in, const hdrl_imagelist *detlin)
Apply the detector linearity correction.
hdrl_imagelist * cr2res_io_load_DETLIN_COEFFS(const char *filename, int detector)
Load the detlin coefficients.
hdrl_image * cr2res_io_load_MASTER_DARK(const char *filename, int detector)
Load an image from a MASTER_DARK.
hdrl_image * cr2res_io_load_MASTER_FLAT(const char *filename, int detector)
Load an hdrl image from a MASTER_FLAT.
double cr2res_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
double cr2res_vector_get_mad(cpl_vector *invec, double *mad)
Get MAD from a vector.
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_div_image(hdrl_image *self, const hdrl_image *other)
Divide two images, store the result in the first image.
cpl_error_code hdrl_image_mul_scalar(hdrl_image *self, hdrl_value value)
Elementwise multiplication of an image with a scalar.
hdrl_image * hdrl_image_duplicate(const hdrl_image *himg)
copy hdrl_image
cpl_mask * hdrl_image_get_mask(hdrl_image *himg)
get cpl bad pixel mask from image
cpl_image * hdrl_image_get_error(hdrl_image *himg)
get error as cpl image
cpl_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
cpl_size hdrl_image_get_size_x(const hdrl_image *self)
return size of X dimension of image
const cpl_image * hdrl_image_get_error_const(const hdrl_image *himg)
get error as cpl image
cpl_error_code hdrl_image_insert(hdrl_image *self, const cpl_image *image, const cpl_image *error, cpl_size xpos, cpl_size ypos)
Copy cpl images into an hdrl image.
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
const cpl_image * hdrl_image_get_image_const(const hdrl_image *himg)
get data as cpl image
hdrl_image * hdrl_image_new(cpl_size nx, cpl_size ny)
create new zero filled hdrl image
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
cpl_error_code hdrl_imagelist_set(hdrl_imagelist *himlist, hdrl_image *himg, cpl_size pos)
Insert an image into an imagelist.
void hdrl_imagelist_delete(hdrl_imagelist *himlist)
Free all memory used by a hdrl_imagelist object including the images.
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
hdrl_imagelist * hdrl_imagelist_new(void)
Create an empty imagelist.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
cpl_mask * hdrl_lacosmic_edgedetect(const hdrl_image *ima_in, const hdrl_parameter *params)
Detect bad-pixels / cosmic-rays on a single image.
cpl_error_code hdrl_lacosmic_parameter_verify(const hdrl_parameter *param)
Verify basic correctness of the LaCosmic parameters.
hdrl_parameter * hdrl_lacosmic_parameter_create(double sigma_lim, double f_lim, int max_iter)
Creates LaCosmic parameters object.
void hdrl_parameter_delete(hdrl_parameter *obj)
shallow delete of a parameter