28#include <hdrl_fringe.h>
29#include <hdrl_prototyping.h>
156 const cpl_mask* stat_mask,
const hdrl_parameter* collapse_params,
157 hdrl_image** master, cpl_image** contrib_map,
158 cpl_table ** qctable)
165 cpl_error_ensure(ilist_fringe && collapse_params , CPL_ERROR_NULL_INPUT,
166 goto cleanup,
"NULL input imagelist or parameter");
168 CPL_ERROR_NULL_INPUT,
goto cleanup,
169 "input imagelist is empty");
171 cpl_size nx, ny, nx1, ny1;
176 if (ilist_obj != NULL) {
178 cpl_imagelist_get_size(ilist_obj),
179 CPL_ERROR_INCOMPATIBLE_INPUT,
goto cleanup,
180 "size of fringe and object image list does "
183 nx1 = cpl_image_get_size_x(cpl_imagelist_get_const(ilist_obj, 0));
184 ny1 = cpl_image_get_size_y(cpl_imagelist_get_const(ilist_obj, 0));
185 cpl_error_ensure(nx == nx1, CPL_ERROR_INCOMPATIBLE_INPUT,
goto cleanup,
186 "size of fringe image and object mask does not match");
187 cpl_error_ensure(ny == ny1, CPL_ERROR_INCOMPATIBLE_INPUT,
goto cleanup,
188 "size of fringe image and object mask does not match");
192 if (stat_mask != NULL) {
194 cpl_error_ensure(nx == cpl_mask_get_size_x(stat_mask),
195 CPL_ERROR_INCOMPATIBLE_INPUT,
goto cleanup,
196 "size of fringe image and fringe mask does not match");
197 cpl_error_ensure(ny == cpl_mask_get_size_y(stat_mask),
198 CPL_ERROR_INCOMPATIBLE_INPUT,
goto cleanup,
199 "size of fringe image and fringe mask does not match");
209 double bkg_level = 0.;
210 double fringe_level = 0.;
213 cpl_msg_debug(cpl_func,
"Measure fringe amplitudes");
214 if (qctable != NULL) {
215 *qctable = cpl_table_new(isize);
216 cpl_table_new_column(*qctable,
"Background_level", CPL_TYPE_DOUBLE);
217 cpl_table_new_column(*qctable,
"Fringe_amplitude", CPL_TYPE_DOUBLE);
219 for (cpl_size i = 0; i < isize; i++) {
224 if (ilist_obj != NULL) {
225 const cpl_image * obj = cpl_imagelist_get_const(ilist_obj, i);
226 cpl_mask * obj_mask = cpl_mask_threshold_image_create(obj,
228 cpl_mask_not(obj_mask) ;
229 cpl_mask_or(this_fmsk, obj_mask);
230 cpl_mask_delete(obj_mask) ;
239 if (stat_mask != NULL) {
240 cpl_mask_or(this_fmsk, stat_mask);
242 cpl_errorstate prestate = cpl_errorstate_get();
243 cpl_matrix *cur_amplitudes = hdrl_mime_fringe_amplitudes(
247 if (!cpl_errorstate_is_equal(prestate)) {
248 cpl_msg_warning(cpl_func,
"Background level and fringe amplitude "
249 "could not be determined! Assuming a background"
250 " level of 0 and a fringe amplitude of 1");
254 cpl_errorstate_set(prestate);
257 bkg_level = cpl_matrix_get(cur_amplitudes, 0, 0);
258 fringe_level = cpl_matrix_get(cur_amplitudes, 1, 0);
262 double fringe_amplitude = fringe_level - bkg_level;
263 if (qctable != NULL) {
264 cpl_table_set_double(*qctable,
"Background_level", i, bkg_level);
265 cpl_table_set_double(*qctable,
"Fringe_amplitude", i, fringe_amplitude);
267 cpl_msg_debug(cpl_func,
"img: %04d Bkg: %12.6g Amplitude: %12.6g",
268 (
int)i+1, bkg_level, fringe_amplitude);
270 cpl_msg_debug(cpl_func,
"Rescaling image");
276 cpl_matrix_delete(cur_amplitudes);
277 cpl_mask_delete(this_fmsk);
280 cpl_msg_debug(cpl_func,
"Combining the normalized fringes generating"
281 " the master-fringe");
286 if (cpl_error_get_code() != CPL_ERROR_NONE) {
288 cpl_table_delete(*qctable);
299 return cpl_error_get_code();
342 const cpl_mask * stat_mask,
const hdrl_image * masterfringe,
343 cpl_table ** qctable)
350 cpl_ensure_code(ilist_fringe && masterfringe, CPL_ERROR_NULL_INPUT);
352 CPL_ERROR_NULL_INPUT);
354 cpl_size nx, ny, nx1, ny1;
361 cpl_ensure_code(nx == nx1, CPL_ERROR_INCOMPATIBLE_INPUT );
362 cpl_ensure_code(ny == ny1, CPL_ERROR_INCOMPATIBLE_INPUT );
366 if (ilist_obj != NULL) {
368 cpl_imagelist_get_size(ilist_obj),
369 CPL_ERROR_INCOMPATIBLE_INPUT);
371 nx1 = cpl_image_get_size_x(cpl_imagelist_get_const(ilist_obj, 0));
372 ny1 = cpl_image_get_size_y(cpl_imagelist_get_const(ilist_obj, 0));
373 cpl_ensure_code(nx == nx1, CPL_ERROR_INCOMPATIBLE_INPUT );
374 cpl_ensure_code(ny == ny1, CPL_ERROR_INCOMPATIBLE_INPUT );
378 if (stat_mask != NULL) {
380 cpl_ensure_code(nx == cpl_mask_get_size_x(stat_mask),
381 CPL_ERROR_INCOMPATIBLE_INPUT );
382 cpl_ensure_code(ny == cpl_mask_get_size_y(stat_mask),
383 CPL_ERROR_INCOMPATIBLE_INPUT );
389 double bkg_level = 0.;
390 double fringe_level = 0.;
393 cpl_msg_debug(cpl_func,
"Measure fringe amplitudes");
395 if (qctable != NULL) {
396 *qctable = cpl_table_new(isize);
397 cpl_table_new_column(*qctable,
"Background_level", CPL_TYPE_DOUBLE);
398 cpl_table_new_column(*qctable,
"Fringe_amplitude", CPL_TYPE_DOUBLE);
400 for (cpl_size i = 0; i < isize; i++) {
406 if (stat_mask != NULL) {
407 cpl_mask_or(this_fmsk, stat_mask);
410 if (ilist_obj != NULL) {
411 const cpl_image * obj = cpl_imagelist_get_const(ilist_obj, i);
412 cpl_mask * obj_mask = cpl_mask_threshold_image_create(obj,
414 cpl_mask_not(obj_mask) ;
415 cpl_mask_or(this_fmsk, obj_mask);
416 cpl_mask_delete(obj_mask) ;
419 cpl_errorstate prestate = cpl_errorstate_get();
421 cpl_matrix * cur_amplitudes = hdrl_mime_fringe_amplitudes_ls(
426 if (!cpl_errorstate_is_equal(prestate)) {
427 cpl_msg_warning(cpl_func,
"Background level and fringe amplitude "
428 "could not be determined! Assuming a background"
429 " level of 0 and a fringe amplitude of 0, i.e. "
430 "no correction will be applied to this image");
434 cpl_errorstate_set(prestate);
437 bkg_level = cpl_matrix_get(cur_amplitudes, 0, 0);
438 fringe_level = cpl_matrix_get(cur_amplitudes, 1, 0);
441 double fringe_amplitude = fringe_level - bkg_level;
443 if (qctable != NULL) {
444 cpl_table_set_double(*qctable,
"Background_level", i, bkg_level);
445 cpl_table_set_double(*qctable,
"Fringe_amplitude", i, fringe_amplitude);
447 cpl_msg_debug(cpl_func,
"img: %04d Bkg: %12.6g Amplitude: %12.6g",
448 (
int)i+1, bkg_level, fringe_amplitude);
450 cpl_msg_debug(cpl_func,
"Rescaling masterfringe");
453 cpl_msg_debug(cpl_func,
"Subtract rescaled masterfringe");
457 cpl_matrix_delete(cur_amplitudes);
458 cpl_mask_delete(this_fmsk);
461 if (cpl_error_get_code() != CPL_ERROR_NONE && qctable != NULL) {
462 cpl_table_delete(*qctable);
466 return cpl_error_get_code();
494cpl_matrix *hdrl_mime_fringe_amplitudes(
const cpl_image * img0,
495 const cpl_mask * mask0)
501 cpl_matrix *amplitudes;
504 const double *img_data;
505 const cpl_binary *mask_data;
508 double mean, stdev, bkg_amp, fringe_amp;
509 int nx, ny, n, size, ns;
512 cpl_ensure(img0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
513 cpl_ensure(mask0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
514 cpl_ensure(cpl_image_get_type(img0) == CPL_TYPE_DOUBLE,
515 CPL_ERROR_INVALID_TYPE, NULL);
525 nx = cpl_image_get_size_x(img0);
526 ny = cpl_image_get_size_y(img0);
528 msize = size - cpl_mask_count(mask0);
530 cpl_ensure(msize > 0 , CPL_ERROR_ILLEGAL_INPUT,NULL);
533 mdata = cpl_matrix_new(msize, 1);
534 md = cpl_matrix_get_data(mdata);
536 img_data = cpl_image_get_data_double_const(img0);
537 mask_data = cpl_mask_get_data_const(mask0);
538 for (i = 0; i < size; i++, mask_data++, img_data++)
540 if (*mask_data == CPL_BINARY_0)
542 *md = (double) *img_data;
546 mean = cpl_matrix_get_mean(mdata);
547 stdev = cpl_matrix_get_stdev(mdata);
550 coeffs = hdrl_mime_hermite_functions_sums_create(n, mean, stdev, mdata);
551 cpl_matrix_multiply_scalar(coeffs, 1.0 / msize);
557 hseries = hdrl_mime_hermite_series_create(n, mean, stdev, coeffs, x);
561 params = cpl_vector_new(6);
562 par = cpl_vector_get_data(params);
564 par[0] = 0.62 / (sqrt(CPL_MATH_PI) * stdev);
565 par[1] = mean - 0.4 * stdev;
566 par[2] = 0.58 * stdev;
568 par[3] = 0.57 / (sqrt(CPL_MATH_PI) * stdev);
569 par[4] = mean + 0.3 * stdev;
570 par[5] = 0.61 * stdev;
572 vals = cpl_vector_wrap(ns, cpl_matrix_get_data(hseries));
573 cpl_fit_lvmq(x, NULL, vals, NULL, params, NULL, hdrl_mime_gmix1,
574 hdrl_mime_gmix_derivs1, CPL_FIT_LVMQ_TOLERANCE, CPL_FIT_LVMQ_COUNT,
575 CPL_FIT_LVMQ_MAXITER, NULL, NULL, NULL);
577 bkg_amp = (par[1] > par[4] ? par[4] : par[1]);
578 fringe_amp = (par[1] > par[4] ? par[1] : par[4]);
579 amplitudes = cpl_matrix_new(2, 1);
580 cpl_matrix_set(amplitudes, 0, 0, bkg_amp);
581 cpl_matrix_set(amplitudes, 1, 0, fringe_amp);
584 cpl_matrix_delete(mdata);
585 cpl_matrix_delete(coeffs);
586 cpl_matrix_delete(x);
587 cpl_matrix_delete(hseries);
588 cpl_vector_unwrap(vals);
589 cpl_vector_delete(params);
615cpl_matrix *hdrl_mime_fringe_amplitudes_ls(
const cpl_image * img0,
616 const cpl_mask * mask0,
const cpl_image * fringe0)
622 cpl_matrix *amplitudes;
623 const double *img_data;
624 const cpl_binary *mask_data;
625 const double *fringe_data;
631 cpl_ensure(img0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
632 cpl_ensure(mask0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
633 cpl_ensure(fringe0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
634 cpl_ensure(cpl_image_get_type(img0) == CPL_TYPE_DOUBLE,
635 CPL_ERROR_INVALID_TYPE, NULL);
636 cpl_ensure(cpl_image_get_type(fringe0) == CPL_TYPE_DOUBLE,
637 CPL_ERROR_INVALID_TYPE, NULL);
642 nx = cpl_image_get_size_x(img0);
643 ny = cpl_image_get_size_y(img0);
645 msize = size - cpl_mask_count(mask0);
647 cpl_ensure(msize > 0 , CPL_ERROR_ILLEGAL_INPUT,NULL);
650 mdata = cpl_matrix_new(msize, 1);
651 md = cpl_matrix_get_data(mdata);
653 fdata = cpl_matrix_new(msize, 1);
654 fd = cpl_matrix_get_data(fdata);
656 img_data = cpl_image_get_data_double_const(img0);
657 mask_data = cpl_mask_get_data_const(mask0);
658 fringe_data = cpl_image_get_data_double_const(fringe0);
659 for (i = 0; i < size; i++, img_data++, mask_data++, fringe_data++)
661 if (*mask_data == CPL_BINARY_0)
663 *md = (double) *img_data;
664 *fd = (double) *fringe_data;
671 cols12 = cpl_matrix_new(msize, 2);
672 cpl_matrix_fill(cols12, 1.0);
673 cpl_matrix_copy(cols12, fdata, 0, 0);
677 amplitudes = cpl_matrix_new(2, 1);
678 cpl_matrix_set(amplitudes, 0, 0, cpl_matrix_get(coeffs, 1, 0));
679 cpl_matrix_set(amplitudes, 1, 0, cpl_matrix_get(coeffs, 0, 0) +
680 cpl_matrix_get(coeffs, 1, 0));
683 cpl_matrix_delete(mdata);
684 cpl_matrix_delete(fdata);
685 cpl_matrix_delete(cols12);
686 cpl_matrix_delete(coeffs);
704int hdrl_mime_gmix_derivs1(
const double x[],
const double params[],
707 double a1, m1, sigma1;
708 double a2, m2, sigma2;
721 tmp = (x[0] - m1) / sigma1;
722 result[0] = exp(-0.5 * tmp * tmp);
723 result[1] = a1 * exp(-0.5 * tmp * tmp);
724 result[1] *= tmp / sigma1;
725 result[2] = a1 * exp(-0.5 * tmp * tmp);
726 result[2] *= tmp * tmp / sigma1;
728 tmp = (x[0] - m2) / sigma2;
729 result[3] = exp(-0.5 * tmp * tmp);
730 result[4] = a2 * exp(-0.5 * tmp * tmp);
731 result[4] *= tmp / sigma2;
732 result[5] = a2 * exp(-0.5 * tmp * tmp);
733 result[5] *= tmp * tmp / sigma2;
750int hdrl_mime_gmix1(
const double x[],
const double params[],
double *result)
752 double a1, m1, sigma1;
753 double a2, m2, sigma2;
766 tmp = (x[0] - m1) / sigma1;
767 result[0] = a1 * exp(-0.5 * tmp * tmp);
768 tmp = (x[0] - m2) / sigma2;
769 result[0] += a2 * exp(-0.5 * tmp * tmp);
791cpl_matrix *hdrl_mime_hermite_series_create(
int n,
double center,
792 double scale,
const cpl_matrix * coeffs,
const cpl_matrix * x)
802 if (x == NULL || coeffs == NULL)
804 cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
808 if (n < 1 || scale <= 0.0)
810 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
815 size = cpl_matrix_get_nrow(x) * cpl_matrix_get_ncol(x);
816 mx = cpl_matrix_get_data_const(x);
817 mc = cpl_matrix_get_data_const(coeffs);
820 series = cpl_matrix_new(size, 1);
821 ms = cpl_matrix_get_data(series);
824 rt = 1.0 / sqrt(sqrt(CPL_MATH_PI));
827 for (k = 0; k < size; k++)
829 double xk = (mx[k] - center) / scale;
830 double tmp1 = rt * exp(-0.5 * xk * xk);
831 double tmp2 = rt * sqrt(2.0) * xk * exp(-0.5 * xk * xk);
832 for (i = 2; i < n + 2; i++)
834 double tmp3 = sqrt(2) * xk * tmp2 - sqrt(i - 1) * tmp1;
835 tmp3 = tmp3 / sqrt(i);
837 ms[k] += tmp1 * mc[i - 2];
844 cpl_matrix_multiply_scalar(series, 1 / sqrt(scale));
868cpl_matrix *hdrl_mime_hermite_functions_sums_create(
int n,
double center,
869 double scale,
const cpl_matrix * x)
877 double sqrt_i[n + 2];
878 double rsqrt_i[n + 2];
883 cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
887 if (n < 1 || scale <= 0.0)
889 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
894 size = cpl_matrix_get_nrow(x) * cpl_matrix_get_ncol(x);
895 mx = cpl_matrix_get_data_const(x);
898 sums = cpl_matrix_new(n, 1);
899 ms = cpl_matrix_get_data(sums);
902 rt = 1.0 / sqrt(sqrt(CPL_MATH_PI));
903 for (i = 1; i < n + 2; i++) {
905 rsqrt_i[i] = 1. / sqrt_i[i];
909 for (k = 0; k < size; k++)
911 double xk = (mx[k] - center) / scale;
912 double tmp1 = rt * exp(-0.5 * xk * xk);
913 double tmp2 = rt * sqrt(2.0) * xk * exp(-0.5 * xk * xk);
914 for (i = 2; i < n + 2; i++)
916 tmp3 = sqrt(2) * xk * tmp2 - sqrt_i[i - 1] * tmp1;
917 tmp3 = tmp3 * rsqrt_i[i];
926 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.