33#include <hdrl_fringe.h>
34#include <hdrl_prototyping.h>
161 const cpl_mask* stat_mask,
const hdrl_parameter* collapse_params,
162 hdrl_image** master, cpl_image** contrib_map,
163 cpl_table ** qctable)
170 cpl_error_ensure(ilist_fringe && collapse_params , CPL_ERROR_NULL_INPUT,
171 goto cleanup,
"NULL input imagelist or parameter");
173 CPL_ERROR_NULL_INPUT,
goto cleanup,
174 "input imagelist is empty");
176 cpl_size nx, ny, nx1, ny1;
181 if (ilist_obj != NULL) {
183 cpl_imagelist_get_size(ilist_obj),
184 CPL_ERROR_INCOMPATIBLE_INPUT,
goto cleanup,
185 "size of fringe and object image list does "
188 nx1 = cpl_image_get_size_x(cpl_imagelist_get_const(ilist_obj, 0));
189 ny1 = cpl_image_get_size_y(cpl_imagelist_get_const(ilist_obj, 0));
190 cpl_error_ensure(nx == nx1, CPL_ERROR_INCOMPATIBLE_INPUT,
goto cleanup,
191 "size of fringe image and object mask does not match");
192 cpl_error_ensure(ny == ny1, CPL_ERROR_INCOMPATIBLE_INPUT,
goto cleanup,
193 "size of fringe image and object mask does not match");
197 if (stat_mask != NULL) {
199 cpl_error_ensure(nx == cpl_mask_get_size_x(stat_mask),
200 CPL_ERROR_INCOMPATIBLE_INPUT,
goto cleanup,
201 "size of fringe image and fringe mask does not match");
202 cpl_error_ensure(ny == cpl_mask_get_size_y(stat_mask),
203 CPL_ERROR_INCOMPATIBLE_INPUT,
goto cleanup,
204 "size of fringe image and fringe mask does not match");
214 double bkg_level = 0.;
215 double fringe_level = 0.;
218 cpl_msg_debug(cpl_func,
"Measure fringe amplitudes");
219 if (qctable != NULL) {
220 *qctable = cpl_table_new(isize);
221 cpl_table_new_column(*qctable,
"Background_level", CPL_TYPE_DOUBLE);
222 cpl_table_new_column(*qctable,
"Fringe_amplitude", CPL_TYPE_DOUBLE);
224 for (cpl_size i = 0; i < isize; i++) {
229 if (ilist_obj != NULL) {
230 const cpl_image * obj = cpl_imagelist_get_const(ilist_obj, i);
231 cpl_mask * obj_mask = cpl_mask_threshold_image_create(obj,
233 cpl_mask_not(obj_mask) ;
234 cpl_mask_or(this_fmsk, obj_mask);
235 cpl_mask_delete(obj_mask) ;
244 if (stat_mask != NULL) {
245 cpl_mask_or(this_fmsk, stat_mask);
247 cpl_errorstate prestate = cpl_errorstate_get();
248 cpl_matrix *cur_amplitudes = hdrl_mime_fringe_amplitudes(
252 if (!cpl_errorstate_is_equal(prestate)) {
253 cpl_msg_warning(cpl_func,
"Background level and fringe amplitude "
254 "could not be determined! Assuming a background"
255 " level of 0 and a fringe amplitude of 1");
259 cpl_errorstate_set(prestate);
262 bkg_level = cpl_matrix_get(cur_amplitudes, 0, 0);
263 fringe_level = cpl_matrix_get(cur_amplitudes, 1, 0);
267 double fringe_amplitude = fringe_level - bkg_level;
268 if (qctable != NULL) {
269 cpl_table_set_double(*qctable,
"Background_level", i, bkg_level);
270 cpl_table_set_double(*qctable,
"Fringe_amplitude", i, fringe_amplitude);
272 cpl_msg_info(cpl_func,
"img: %04d Bkg: %12.6g Amplitude: %12.6g",
273 (
int)i+1, bkg_level, fringe_amplitude);
275 cpl_msg_debug(cpl_func,
"Rescaling image");
281 cpl_matrix_delete(cur_amplitudes);
282 cpl_mask_delete(this_fmsk);
285 cpl_msg_debug(cpl_func,
"Combining the normalized fringes generating"
286 " the master-fringe");
291 if (cpl_error_get_code() != CPL_ERROR_NONE) {
293 cpl_table_delete(*qctable);
304 return cpl_error_get_code();
347 const cpl_mask * stat_mask,
const hdrl_image * masterfringe,
348 cpl_table ** qctable)
355 cpl_ensure_code(ilist_fringe && masterfringe, CPL_ERROR_NULL_INPUT);
357 CPL_ERROR_NULL_INPUT);
359 cpl_size nx, ny, nx1, ny1;
366 cpl_ensure_code(nx == nx1, CPL_ERROR_INCOMPATIBLE_INPUT );
367 cpl_ensure_code(ny == ny1, CPL_ERROR_INCOMPATIBLE_INPUT );
371 if (ilist_obj != NULL) {
373 cpl_imagelist_get_size(ilist_obj),
374 CPL_ERROR_INCOMPATIBLE_INPUT);
376 nx1 = cpl_image_get_size_x(cpl_imagelist_get_const(ilist_obj, 0));
377 ny1 = cpl_image_get_size_y(cpl_imagelist_get_const(ilist_obj, 0));
378 cpl_ensure_code(nx == nx1, CPL_ERROR_INCOMPATIBLE_INPUT );
379 cpl_ensure_code(ny == ny1, CPL_ERROR_INCOMPATIBLE_INPUT );
383 if (stat_mask != NULL) {
385 cpl_ensure_code(nx == cpl_mask_get_size_x(stat_mask),
386 CPL_ERROR_INCOMPATIBLE_INPUT );
387 cpl_ensure_code(ny == cpl_mask_get_size_y(stat_mask),
388 CPL_ERROR_INCOMPATIBLE_INPUT );
394 double bkg_level = 0.;
395 double fringe_level = 0.;
398 cpl_msg_debug(cpl_func,
"Measure fringe amplitudes");
400 if (qctable != NULL) {
401 *qctable = cpl_table_new(isize);
402 cpl_table_new_column(*qctable,
"Background_level", CPL_TYPE_DOUBLE);
403 cpl_table_new_column(*qctable,
"Fringe_amplitude", CPL_TYPE_DOUBLE);
405 for (cpl_size i = 0; i < isize; i++) {
411 if (stat_mask != NULL) {
412 cpl_mask_or(this_fmsk, stat_mask);
415 if (ilist_obj != NULL) {
416 const cpl_image * obj = cpl_imagelist_get_const(ilist_obj, i);
417 cpl_mask * obj_mask = cpl_mask_threshold_image_create(obj,
419 cpl_mask_not(obj_mask) ;
420 cpl_mask_or(this_fmsk, obj_mask);
421 cpl_mask_delete(obj_mask) ;
424 cpl_errorstate prestate = cpl_errorstate_get();
426 cpl_matrix * cur_amplitudes = hdrl_mime_fringe_amplitudes_ls(
431 if (!cpl_errorstate_is_equal(prestate)) {
432 cpl_msg_warning(cpl_func,
"Background level and fringe amplitude "
433 "could not be determined! Assuming a background"
434 " level of 0 and a fringe amplitude of 0, i.e. "
435 "no correction will be applied to this image");
439 cpl_errorstate_set(prestate);
442 bkg_level = cpl_matrix_get(cur_amplitudes, 0, 0);
443 fringe_level = cpl_matrix_get(cur_amplitudes, 1, 0);
446 double fringe_amplitude = fringe_level - bkg_level;
448 if (qctable != NULL) {
449 cpl_table_set_double(*qctable,
"Background_level", i, bkg_level);
450 cpl_table_set_double(*qctable,
"Fringe_amplitude", i, fringe_amplitude);
452 cpl_msg_info(cpl_func,
"img: %04d Bkg: %12.6g Amplitude: %12.6g",
453 (
int)i+1, bkg_level, fringe_amplitude);
455 cpl_msg_debug(cpl_func,
"Rescaling masterfringe");
458 cpl_msg_debug(cpl_func,
"Subtract rescaled masterfringe");
462 cpl_matrix_delete(cur_amplitudes);
463 cpl_mask_delete(this_fmsk);
466 if (cpl_error_get_code() != CPL_ERROR_NONE && qctable != NULL) {
467 cpl_table_delete(*qctable);
471 return cpl_error_get_code();
499cpl_matrix *hdrl_mime_fringe_amplitudes(
const cpl_image * img0,
500 const cpl_mask * mask0)
506 cpl_matrix *amplitudes;
509 const double *img_data;
510 const cpl_binary *mask_data;
513 double mean, stdev, bkg_amp, fringe_amp;
514 int nx, ny, n, size, ns;
517 cpl_ensure(img0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
518 cpl_ensure(mask0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
519 cpl_ensure(cpl_image_get_type(img0) == CPL_TYPE_DOUBLE,
520 CPL_ERROR_INVALID_TYPE, NULL);
530 nx = cpl_image_get_size_x(img0);
531 ny = cpl_image_get_size_y(img0);
533 msize = size - cpl_mask_count(mask0);
535 cpl_ensure(msize > 0 , CPL_ERROR_ILLEGAL_INPUT,NULL);
538 mdata = cpl_matrix_new(msize, 1);
539 md = cpl_matrix_get_data(mdata);
541 img_data = cpl_image_get_data_double_const(img0);
542 mask_data = cpl_mask_get_data_const(mask0);
543 for (i = 0; i < size; i++, mask_data++, img_data++)
545 if (*mask_data == CPL_BINARY_0)
547 *md = (double) *img_data;
551 mean = cpl_matrix_get_mean(mdata);
552 stdev = cpl_matrix_get_stdev(mdata);
555 coeffs = hdrl_mime_hermite_functions_sums_create(n, mean, stdev, mdata);
556 cpl_matrix_multiply_scalar(coeffs, 1.0 / msize);
562 hseries = hdrl_mime_hermite_series_create(n, mean, stdev, coeffs, x);
566 params = cpl_vector_new(6);
567 par = cpl_vector_get_data(params);
569 par[0] = 0.62 / (sqrt(CPL_MATH_PI) * stdev);
570 par[1] = mean - 0.4 * stdev;
571 par[2] = 0.58 * stdev;
573 par[3] = 0.57 / (sqrt(CPL_MATH_PI) * stdev);
574 par[4] = mean + 0.3 * stdev;
575 par[5] = 0.61 * stdev;
577 vals = cpl_vector_wrap(ns, cpl_matrix_get_data(hseries));
578 cpl_fit_lvmq(x, NULL, vals, NULL, params, NULL, hdrl_mime_gmix1,
579 hdrl_mime_gmix_derivs1, CPL_FIT_LVMQ_TOLERANCE, CPL_FIT_LVMQ_COUNT,
580 CPL_FIT_LVMQ_MAXITER, NULL, NULL, NULL);
582 bkg_amp = (par[1] > par[4] ? par[4] : par[1]);
583 fringe_amp = (par[1] > par[4] ? par[1] : par[4]);
584 amplitudes = cpl_matrix_new(2, 1);
585 cpl_matrix_set(amplitudes, 0, 0, bkg_amp);
586 cpl_matrix_set(amplitudes, 1, 0, fringe_amp);
589 cpl_matrix_delete(mdata);
590 cpl_matrix_delete(coeffs);
591 cpl_matrix_delete(x);
592 cpl_matrix_delete(hseries);
593 cpl_vector_unwrap(vals);
594 cpl_vector_delete(params);
620cpl_matrix *hdrl_mime_fringe_amplitudes_ls(
const cpl_image * img0,
621 const cpl_mask * mask0,
const cpl_image * fringe0)
627 cpl_matrix *amplitudes;
628 const double *img_data;
629 const cpl_binary *mask_data;
630 const double *fringe_data;
636 cpl_ensure(img0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
637 cpl_ensure(mask0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
638 cpl_ensure(fringe0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
639 cpl_ensure(cpl_image_get_type(img0) == CPL_TYPE_DOUBLE,
640 CPL_ERROR_INVALID_TYPE, NULL);
641 cpl_ensure(cpl_image_get_type(fringe0) == CPL_TYPE_DOUBLE,
642 CPL_ERROR_INVALID_TYPE, NULL);
647 nx = cpl_image_get_size_x(img0);
648 ny = cpl_image_get_size_y(img0);
650 msize = size - cpl_mask_count(mask0);
652 cpl_ensure(msize > 0 , CPL_ERROR_ILLEGAL_INPUT,NULL);
655 mdata = cpl_matrix_new(msize, 1);
656 md = cpl_matrix_get_data(mdata);
658 fdata = cpl_matrix_new(msize, 1);
659 fd = cpl_matrix_get_data(fdata);
661 img_data = cpl_image_get_data_double_const(img0);
662 mask_data = cpl_mask_get_data_const(mask0);
663 fringe_data = cpl_image_get_data_double_const(fringe0);
664 for (i = 0; i < size; i++, img_data++, mask_data++, fringe_data++)
666 if (*mask_data == CPL_BINARY_0)
668 *md = (double) *img_data;
669 *fd = (double) *fringe_data;
676 cols12 = cpl_matrix_new(msize, 2);
677 cpl_matrix_fill(cols12, 1.0);
678 cpl_matrix_copy(cols12, fdata, 0, 0);
682 amplitudes = cpl_matrix_new(2, 1);
683 cpl_matrix_set(amplitudes, 0, 0, cpl_matrix_get(coeffs, 1, 0));
684 cpl_matrix_set(amplitudes, 1, 0, cpl_matrix_get(coeffs, 0, 0) +
685 cpl_matrix_get(coeffs, 1, 0));
688 cpl_matrix_delete(mdata);
689 cpl_matrix_delete(fdata);
690 cpl_matrix_delete(cols12);
691 cpl_matrix_delete(coeffs);
709int hdrl_mime_gmix_derivs1(
const double x[],
const double params[],
712 double a1, m1, sigma1;
713 double a2, m2, sigma2;
726 tmp = (x[0] - m1) / sigma1;
727 result[0] = exp(-0.5 * tmp * tmp);
728 result[1] = a1 * exp(-0.5 * tmp * tmp);
729 result[1] *= tmp / sigma1;
730 result[2] = a1 * exp(-0.5 * tmp * tmp);
731 result[2] *= tmp * tmp / sigma1;
733 tmp = (x[0] - m2) / sigma2;
734 result[3] = exp(-0.5 * tmp * tmp);
735 result[4] = a2 * exp(-0.5 * tmp * tmp);
736 result[4] *= tmp / sigma2;
737 result[5] = a2 * exp(-0.5 * tmp * tmp);
738 result[5] *= tmp * tmp / sigma2;
755int hdrl_mime_gmix1(
const double x[],
const double params[],
double *result)
757 double a1, m1, sigma1;
758 double a2, m2, sigma2;
771 tmp = (x[0] - m1) / sigma1;
772 result[0] = a1 * exp(-0.5 * tmp * tmp);
773 tmp = (x[0] - m2) / sigma2;
774 result[0] += a2 * exp(-0.5 * tmp * tmp);
796cpl_matrix *hdrl_mime_hermite_series_create(
int n,
double center,
797 double scale,
const cpl_matrix * coeffs,
const cpl_matrix * x)
807 if (x == NULL || coeffs == NULL)
809 cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
813 if (n < 1 || scale <= 0.0)
815 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
820 size = cpl_matrix_get_nrow(x) * cpl_matrix_get_ncol(x);
821 mx = cpl_matrix_get_data_const(x);
822 mc = cpl_matrix_get_data_const(coeffs);
825 series = cpl_matrix_new(size, 1);
826 ms = cpl_matrix_get_data(series);
829 rt = 1.0 / sqrt(sqrt(CPL_MATH_PI));
832 for (k = 0; k < size; k++)
834 double xk = (mx[k] - center) / scale;
835 double tmp1 = rt * exp(-0.5 * xk * xk);
836 double tmp2 = rt * sqrt(2.0) * xk * exp(-0.5 * xk * xk);
837 for (i = 2; i < n + 2; i++)
839 double tmp3 = sqrt(2) * xk * tmp2 - sqrt(i - 1) * tmp1;
840 tmp3 = tmp3 / sqrt(i);
842 ms[k] += tmp1 * mc[i - 2];
849 cpl_matrix_multiply_scalar(series, 1 / sqrt(scale));
873cpl_matrix *hdrl_mime_hermite_functions_sums_create(
int n,
double center,
874 double scale,
const cpl_matrix * x)
882 double sqrt_i[n + 2];
883 double rsqrt_i[n + 2];
888 cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
892 if (n < 1 || scale <= 0.0)
894 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
899 size = cpl_matrix_get_nrow(x) * cpl_matrix_get_ncol(x);
900 mx = cpl_matrix_get_data_const(x);
903 sums = cpl_matrix_new(n, 1);
904 ms = cpl_matrix_get_data(sums);
907 rt = 1.0 / sqrt(sqrt(CPL_MATH_PI));
908 for (i = 1; i < n + 2; i++) {
910 rsqrt_i[i] = 1. / sqrt_i[i];
914 for (k = 0; k < size; k++)
916 double xk = (mx[k] - center) / scale;
917 double tmp1 = rt * exp(-0.5 * xk * xk);
918 double tmp2 = rt * sqrt(2.0) * xk * exp(-0.5 * xk * xk);
919 for (i = 2; i < n + 2; i++)
921 tmp3 = sqrt(2) * xk * tmp2 - sqrt_i[i - 1] * tmp1;
922 tmp3 = tmp3 * rsqrt_i[i];
931 cpl_matrix_multiply_scalar(sums, 1 / sqrt(scale));
cpl_error_code hdrl_fringe_correct(hdrl_imagelist *ilist_fringe, const cpl_imagelist *ilist_obj, const cpl_mask *stat_mask, const hdrl_image *masterfringe, cpl_table **qctable)
Scales and subtracts the master fringe from the images.
cpl_error_code hdrl_fringe_compute(hdrl_imagelist *ilist_fringe, const cpl_imagelist *ilist_obj, const cpl_mask *stat_mask, const hdrl_parameter *collapse_params, hdrl_image **master, cpl_image **contrib_map, cpl_table **qctable)
Calculates the master fringe and contribution map based on the.
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
cpl_error_code hdrl_image_div_scalar(hdrl_image *self, hdrl_value value)
Elementwise division of an image with a scalar.
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_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_image_const(const hdrl_image *himg)
get data as cpl image
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
cpl_error_code hdrl_image_sub_scalar(hdrl_image *self, hdrl_value value)
Elementwise subtraction of a scalar from an image.
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_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
cpl_matrix * hdrl_mime_linalg_solve_tikhonov(const cpl_matrix *mat, const cpl_matrix *rhs, double alpha)
Solve an overdetermined linear system in the least-squares sense.
cpl_matrix * hdrl_mime_matrix_linspace_create(int n, double a, double b)
Create equally spaced nodes.