28#include "hdrl_sigclip.h"
29#include "hdrl_utils.h"
30#include "hdrl_collapse.h"
41static cpl_error_code hdrl_sort_double_pairs(cpl_vector *, cpl_vector *) ;
42static long get_lower_bound_d(
double * vec,
long count,
double val);
43static long get_upper_bound_d(
double * vec,
long count,
double val);
44static long get_lower_bound(cpl_vector * vec,
double val);
45static long get_upper_bound(cpl_vector * vec,
double val);
73cpl_parameterlist * hdrl_sigclip_parameter_create_parlist(
74 const char *base_context,
76 const hdrl_parameter *defaults)
78 cpl_ensure(base_context && prefix && defaults,
79 CPL_ERROR_NULL_INPUT, NULL);
82 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
84 cpl_parameterlist *parlist = cpl_parameterlist_new();
87 hdrl_setup_vparameter(parlist, prefix,
".",
"",
88 "kappa-low", base_context,
89 "Low kappa factor for kappa-sigma clipping algorithm",
94 hdrl_setup_vparameter(parlist, prefix,
".",
"",
95 "kappa-high", base_context,
96 "High kappa factor for kappa-sigma clipping algorithm",
101 hdrl_setup_vparameter(parlist, prefix,
".",
"",
102 "niter", base_context,
103 "Maximum number of clipping iterations for kappa-sigma clipping",
107 if (cpl_error_get_code()) {
108 cpl_parameterlist_delete(parlist);
126cpl_parameterlist * hdrl_minmax_parameter_create_parlist(
127 const char *base_context,
129 const hdrl_parameter *defaults)
131 cpl_ensure(base_context && prefix && defaults,
132 CPL_ERROR_NULL_INPUT, NULL);
135 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
137 cpl_parameterlist * parlist = cpl_parameterlist_new();
140 hdrl_setup_vparameter(parlist, prefix,
".",
"",
141 "nlow", base_context,
142 "Low number of pixels to reject for the minmax clipping algorithm",
147 hdrl_setup_vparameter(parlist, prefix,
".",
"",
148 "nhigh", base_context,
149 "High number of pixels to reject for the minmax clipping algorithm",
153 if (cpl_error_get_code()) {
154 cpl_parameterlist_delete(parlist);
178cpl_error_code hdrl_sigclip_parameter_parse_parlist(
179 const cpl_parameterlist * parlist,
185 cpl_ensure_code(prefix && parlist, CPL_ERROR_NULL_INPUT);
190 const cpl_parameter * par = cpl_parameterlist_find_const(parlist, name);
191 *kappa_low = cpl_parameter_get_double(par);
197 const cpl_parameter * par = cpl_parameterlist_find_const(parlist, name);
198 *kappa_high = cpl_parameter_get_double(par);
204 const cpl_parameter * par = cpl_parameterlist_find_const(parlist, name);
205 *niter = cpl_parameter_get_int(par);
209 if (cpl_error_get_code()) {
210 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
211 "Error while parsing parameterlist "
212 "with prefix %s", prefix);
215 return CPL_ERROR_NONE;
234cpl_error_code hdrl_minmax_parameter_parse_parlist(
235 const cpl_parameterlist * parlist,
240 cpl_ensure_code(prefix && parlist, CPL_ERROR_NULL_INPUT);
245 const cpl_parameter * par = cpl_parameterlist_find_const(parlist, name);
246 *nlow = cpl_parameter_get_double(par);
252 const cpl_parameter * par = cpl_parameterlist_find_const(parlist, name);
253 *nhigh = cpl_parameter_get_double(par);
257 if (cpl_error_get_code()) {
258 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
259 "Error while parsing parameterlist "
260 "with prefix %s", prefix);
263 return CPL_ERROR_NONE;
289cpl_error_code hdrl_minmax_clip_image(
290 const cpl_image * source,
291 const cpl_image * error,
295 double * mean_mm_err,
296 cpl_size * naccepted,
298 double * reject_high)
300 cpl_vector * vec_source = NULL;
301 cpl_vector * vec_error = NULL;
304 cpl_error_ensure(source != NULL, CPL_ERROR_NULL_INPUT,
305 return CPL_ERROR_NULL_INPUT,
"Null input source image!");
306 cpl_error_ensure(error != NULL, CPL_ERROR_NULL_INPUT,
307 return CPL_ERROR_NULL_INPUT,
"Null input error image!");
308 cpl_error_ensure(cpl_image_get_size_x(source)==cpl_image_get_size_x(error),
309 CPL_ERROR_INCOMPATIBLE_INPUT,
return CPL_ERROR_INCOMPATIBLE_INPUT,
310 "source and error image musty have same X size");
311 cpl_error_ensure(cpl_image_get_size_y(source)==cpl_image_get_size_y(error),
312 CPL_ERROR_INCOMPATIBLE_INPUT,
return CPL_ERROR_INCOMPATIBLE_INPUT,
313 "source and error image musty have same Y size");
316 vec_source = hdrl_image_to_vector(source, NULL);
317 vec_error = hdrl_image_to_vector(error, cpl_image_get_bpm_const(source));
319 if (vec_source != NULL && vec_error != NULL) {
321 hdrl_minmax_clip(vec_source, vec_error, nlow, nhigh, CPL_TRUE, mean_mm,
322 mean_mm_err, naccepted, reject_low, reject_high);
333 cpl_msg_debug(cpl_func,
"mean_mm, mean_mm_err, naccepted: %g, %g, %ld",
334 *mean_mm, *mean_mm_err, (
long)*naccepted);
336 cpl_vector_delete(vec_source);
337 cpl_vector_delete(vec_error);
338 return cpl_error_get_code();
366cpl_error_code hdrl_minmax_clip(
368 cpl_vector * vec_err,
373 double * mean_mm_err,
374 cpl_size * naccepted,
376 double * reject_high)
384 cpl_vector * vec_image = NULL;
385 cpl_vector * vec_image_err = NULL;
388 cpl_size nlow_int, nhigh_int;
389 cpl_vector * vec_trunc;
398 nlow_int = (cpl_size)round(nlow);
399 nhigh_int = (cpl_size)round(nhigh);
401 cpl_error_ensure(vec != NULL, CPL_ERROR_NULL_INPUT,
402 return CPL_ERROR_NULL_INPUT,
"Null input vector data");
403 cpl_error_ensure(vec_err != NULL, CPL_ERROR_NULL_INPUT,
404 return CPL_ERROR_NULL_INPUT,
"Null input vector errors");
405 cpl_error_ensure(cpl_vector_get_size(vec) == cpl_vector_get_size(vec_err),
406 CPL_ERROR_INCOMPATIBLE_INPUT,
407 return CPL_ERROR_INCOMPATIBLE_INPUT,
408 "input data and error vectors must have same sizes");
409 cpl_error_ensure(mean_mm != NULL, CPL_ERROR_NULL_INPUT,
410 return CPL_ERROR_NULL_INPUT,
"Null input mean storage");
412 cpl_error_ensure(nlow_int >=0 && nhigh_int>=0, CPL_ERROR_INCOMPATIBLE_INPUT,
413 return CPL_ERROR_INCOMPATIBLE_INPUT,
"nlow and nhigh must "
414 "be strictly positive");
416 vec_size = cpl_vector_get_size(vec);
419 if(vec_size <= (nlow_int+nhigh_int)) {
423 return cpl_error_get_code();
428 vec_image_err = vec_err;
431 vec_image = cpl_vector_duplicate(vec);
432 vec_image_err = cpl_vector_duplicate(vec_err);
435 hdrl_sort_double_pairs(vec_image, vec_image_err);
437 trunc_size = (vec_size - nhigh_int) - nlow_int;
438 d = cpl_vector_get_data(vec_image);
439 e = cpl_vector_get_data(vec_image_err);
440 vec_trunc = cpl_vector_wrap(trunc_size, d + nlow_int);
443 *mean_mm = cpl_vector_get_mean(vec_trunc);
446 *naccepted = trunc_size;
450 *reject_low = d[nlow_int];
453 *reject_high = d[vec_size - nhigh_int - 1];
457 cpl_vector * vec_trunc_err;
461 intptr_t l = get_lower_bound(vec_image, d[nlow_int]);
462 intptr_t h = get_upper_bound(vec_image, d[nlow_int]);
463 if (h - l > 1 && h - l != vec_size) {
464 cpl_vector * e_vec = cpl_vector_extract(vec_image_err, l, h - 1, 1);
465 cpl_vector_sort(e_vec, CPL_SORT_ASCENDING);
466 for (intptr_t i = nlow_int; i < h; i++) {
467 cpl_vector_set(vec_image_err, i,
468 cpl_vector_get(e_vec, i - nlow_int));
470 cpl_vector_delete(e_vec);
473 l = get_lower_bound(vec_image, d[vec_size - nhigh_int - 1]);
474 h = get_upper_bound(vec_image, d[vec_size - nhigh_int - 1]);
475 if (h - l > 1 && h - l != vec_size) {
476 cpl_vector * e_vec = cpl_vector_extract(vec_image_err, l, h - 1, 1);
477 cpl_vector_sort(e_vec, CPL_SORT_ASCENDING);
478 for (intptr_t i = l; i < vec_size - nhigh; i++) {
479 cpl_vector_set(vec_image_err, i,
480 cpl_vector_get(e_vec, i - l));
482 cpl_vector_delete(e_vec);
485 vec_trunc_err = cpl_vector_wrap(trunc_size, e + nlow_int);
487 cpl_vector_multiply(vec_trunc_err, vec_trunc_err);
488 *mean_mm_err = sqrt(cpl_vector_get_mean(vec_trunc_err) /
489 cpl_vector_get_size(vec_trunc_err));
490 cpl_vector_unwrap(vec_trunc_err);
493 cpl_vector_unwrap(vec_trunc);
495 cpl_vector_delete(vec_image);
496 cpl_vector_delete(vec_image_err);
498 return cpl_error_get_code();
524cpl_error_code hdrl_kappa_sigma_clip_image(
525 const cpl_image * source,
526 const cpl_image * error,
527 const double kappa_low,
528 const double kappa_high,
531 double * mean_ks_err,
532 cpl_size * naccepted,
534 double * reject_high)
536 cpl_vector * vec_source = NULL;
537 cpl_vector * vec_error = NULL;
540 cpl_error_ensure(source != NULL, CPL_ERROR_NULL_INPUT,
541 return CPL_ERROR_NULL_INPUT,
"Null input source image!");
542 cpl_error_ensure(error != NULL, CPL_ERROR_NULL_INPUT,
543 return CPL_ERROR_NULL_INPUT,
"Null input error image!");
544 cpl_error_ensure(cpl_image_get_size_x(source)==cpl_image_get_size_x(error),
545 CPL_ERROR_INCOMPATIBLE_INPUT,
return CPL_ERROR_INCOMPATIBLE_INPUT,
546 "source and error image musty have same X size");
547 cpl_error_ensure(cpl_image_get_size_y(source)==cpl_image_get_size_y(error),
548 CPL_ERROR_INCOMPATIBLE_INPUT,
return CPL_ERROR_INCOMPATIBLE_INPUT,
549 "source and error image musty have same Y size");
552 vec_source = hdrl_image_to_vector(source, NULL);
553 vec_error = hdrl_image_to_vector(error, cpl_image_get_bpm_const(source));
555 if (vec_source != NULL && vec_error != NULL) {
557 hdrl_kappa_sigma_clip(vec_source, vec_error, kappa_low, kappa_high,
558 iter, CPL_TRUE, mean_ks, mean_ks_err, naccepted,
559 reject_low, reject_high);
570 cpl_msg_debug(cpl_func,
"mean_ks, mean_ks_err, naccepted: %g, %g, %ld",
571 *mean_ks, *mean_ks_err, (
long)*naccepted);
573 cpl_vector_delete(vec_source);
574 cpl_vector_delete(vec_error);
575 return cpl_error_get_code();
587static long get_upper_bound_d(
double * vec,
long count,
double val)
592 long step = count / 2;
593 long it = first + step;
594 if (!(val < vec[it])) {
612static long get_upper_bound(cpl_vector * vec,
double val)
614 double * d = cpl_vector_get_data(vec);
615 long count = cpl_vector_get_size(vec);
616 return get_upper_bound_d(d, count, val);
627static long get_lower_bound_d(
double * vec,
long count,
double val)
632 long step = count / 2;
633 long it = first + step;
652static long get_lower_bound(cpl_vector * vec,
double val)
654 double * d = cpl_vector_get_data(vec);
655 long count = cpl_vector_get_size(vec);
656 return get_lower_bound_d(d, count, val);
661static void get_mean_err(
const double * d,
const double * e,
long count,
662 double * rm,
double * re)
665 for (
long i = 0; i < count; i++) {
666 m += (d[i] - m) / (
double)(i + 1);
672 for (
long i = 0; i < count; i++) {
675 *re = sqrt(se) / count;
737cpl_error_code hdrl_kappa_sigma_clip(
739 cpl_vector * vec_err,
740 const double kappa_low,
741 const double kappa_high,
745 double * mean_ks_err,
746 cpl_size * naccepted,
748 double * reject_high)
757 cpl_vector * vec_image = NULL;
758 cpl_vector * vec_image_err = NULL;
761 double lower_bound = 0.;
762 double upper_bound = 0.;
764 cpl_error_ensure(vec != NULL, CPL_ERROR_NULL_INPUT,
765 return CPL_ERROR_NULL_INPUT,
"Null input vector data");
766 cpl_error_ensure(vec_err != NULL, CPL_ERROR_NULL_INPUT,
767 return CPL_ERROR_NULL_INPUT,
"Null input vector errors");
768 cpl_error_ensure(cpl_vector_get_size(vec) == cpl_vector_get_size(vec_err),
769 CPL_ERROR_INCOMPATIBLE_INPUT,
770 return CPL_ERROR_INCOMPATIBLE_INPUT,
771 "input data and error vectors must have same sizes");
772 cpl_error_ensure(mean_ks != NULL, CPL_ERROR_NULL_INPUT,
773 return CPL_ERROR_NULL_INPUT,
"Null input mean storage");
774 cpl_error_ensure(iter > 0, CPL_ERROR_ILLEGAL_INPUT,
775 return CPL_ERROR_ILLEGAL_INPUT,
776 "iter must be larger than 0");
780 vec_image_err = vec_err;
783 vec_image = cpl_vector_duplicate(vec);
784 vec_image_err = cpl_vector_duplicate(vec_err);
786 double * vec_data = cpl_vector_get_data(vec_image);
787 double * vec_data_orig = vec_data;
788 double * vec_data_err = cpl_vector_get_data(vec_image_err);
789 vec_size = cpl_vector_get_size(vec_image);
792 hdrl_sort_double_pairs(vec_image, vec_image_err);
794 for(
int it = 0; it < iter; it++) {
795 double median, sigma;
796 cpl_size lower_index, upper_index;
800 lower_bound = vec_data[0];
801 upper_bound = lower_bound;
819 cpl_size orig_offset = (cpl_size)(vec_data - vec_data_orig) + 1;
820 median = hcpl_vector_get_mad_window(vec_image, orig_offset,
821 orig_offset + vec_size - 1, &sigma);
824 sigma=nextafter(0,1.0);
826 sigma *= CPL_MATH_STD_MAD;
828 lower_bound = median - kappa_low * sigma;
829 upper_bound = median + kappa_high * sigma;
831 lower_index = get_lower_bound_d(vec_data, vec_size, lower_bound);
832 upper_index = get_upper_bound_d(vec_data, vec_size, upper_bound);
833 upper_index = CX_MAX(upper_index - 1, 0);
836 if ((lower_index == 0) && (upper_index == vec_size - 1))
840 vec_data = vec_data + lower_index;
841 vec_data_err = vec_data_err + lower_index;
842 vec_size = upper_index - lower_index + 1;
846 get_mean_err(vec_data, vec_data_err, vec_size, mean_ks, mean_ks_err);
848 if (naccepted) *naccepted = vec_size;
850 if (reject_low) *reject_low = lower_bound;
851 if (reject_high) *reject_high = upper_bound;
855 cpl_vector_delete(vec_image);
856 cpl_vector_delete(vec_image_err);
858 return cpl_error_get_code();
872static cpl_error_code hdrl_sort_double_pairs(cpl_vector *u1, cpl_vector *u2)
874 cpl_bivector * bi_all = NULL;
876 cpl_error_ensure(u1 != NULL, CPL_ERROR_NULL_INPUT,
877 return CPL_ERROR_NULL_INPUT,
"NULL pointer to 1st array");
878 cpl_error_ensure(u2 != NULL, CPL_ERROR_NULL_INPUT,
879 return CPL_ERROR_NULL_INPUT,
"NULL pointer to 2nd array");
881 bi_all = cpl_bivector_wrap_vectors(u1, u2);
882 cpl_bivector_sort(bi_all, bi_all, CPL_SORT_ASCENDING, CPL_SORT_BY_X);
885 cpl_bivector_unwrap_vectors(bi_all);
887 return CPL_ERROR_NONE;
double hdrl_collapse_sigclip_parameter_get_kappa_low(const hdrl_parameter *p)
get low kappa
int hdrl_collapse_sigclip_parameter_get_niter(const hdrl_parameter *p)
get maximum number of clipping iterations
cpl_boolean hdrl_collapse_parameter_is_minmax(const hdrl_parameter *self)
check if parameter is a minmax mean parameter
cpl_boolean hdrl_collapse_parameter_is_sigclip(const hdrl_parameter *self)
check if parameter is a sigclip mean parameter
double hdrl_collapse_sigclip_parameter_get_kappa_high(const hdrl_parameter *p)
get high kappa
double hdrl_collapse_minmax_parameter_get_nlow(const hdrl_parameter *p)
get low value
double hdrl_collapse_minmax_parameter_get_nhigh(const hdrl_parameter *p)
get high value
char * hdrl_join_string(const char *sep_, int n,...)
join strings together