CR2RE Pipeline Reference Manual 1.6.2
hdrl_sigclip.c
1/*
2 * This file is part of the HDRL
3 * Copyright (C) 2012,2013 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26-----------------------------------------------------------------------------*/
27
28#include "hdrl_sigclip.h"
29#include "hdrl_utils.h"
30#include "hdrl_collapse.h"
31
32#include <cpl.h>
33#include <string.h>
34#include <math.h>
35
36
37/*-----------------------------------------------------------------------------
38 Static
39 -----------------------------------------------------------------------------*/
40
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);
46
49/*----------------------------------------------------------------------------*/
56/*----------------------------------------------------------------------------*/
57
60/* ---------------------------------------------------------------------------*/
72/* ---------------------------------------------------------------------------*/
73cpl_parameterlist * hdrl_sigclip_parameter_create_parlist(
74 const char *base_context,
75 const char *prefix,
76 const hdrl_parameter *defaults)
77{
78 cpl_ensure(base_context && prefix && defaults,
79 CPL_ERROR_NULL_INPUT, NULL);
80
81 cpl_ensure(hdrl_collapse_parameter_is_sigclip(defaults),
82 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
83
84 cpl_parameterlist *parlist = cpl_parameterlist_new();
85
86 /* --prefix.kappa-low */
87 hdrl_setup_vparameter(parlist, prefix, ".", "",
88 "kappa-low", base_context,
89 "Low kappa factor for kappa-sigma clipping algorithm",
90 CPL_TYPE_DOUBLE,
92
93 /* --prefix.kappa-high */
94 hdrl_setup_vparameter(parlist, prefix, ".", "",
95 "kappa-high", base_context,
96 "High kappa factor for kappa-sigma clipping algorithm",
97 CPL_TYPE_DOUBLE,
99
100 /* --prefix.niter */
101 hdrl_setup_vparameter(parlist, prefix, ".", "",
102 "niter", base_context,
103 "Maximum number of clipping iterations for kappa-sigma clipping",
104 CPL_TYPE_INT,
106
107 if (cpl_error_get_code()) {
108 cpl_parameterlist_delete(parlist);
109 return NULL;
110 }
111
112 return parlist;
113}
114/* ---------------------------------------------------------------------------*/
125/* ---------------------------------------------------------------------------*/
126cpl_parameterlist * hdrl_minmax_parameter_create_parlist(
127 const char *base_context,
128 const char *prefix,
129 const hdrl_parameter *defaults)
130{
131 cpl_ensure(base_context && prefix && defaults,
132 CPL_ERROR_NULL_INPUT, NULL);
133
134 cpl_ensure(hdrl_collapse_parameter_is_minmax(defaults),
135 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
136
137 cpl_parameterlist * parlist = cpl_parameterlist_new();
138
139 /* --prefix.nlow */
140 hdrl_setup_vparameter(parlist, prefix, ".", "",
141 "nlow", base_context,
142 "Low number of pixels to reject for the minmax clipping algorithm",
143 CPL_TYPE_DOUBLE,
145
146 /* --prefix.nhigh */
147 hdrl_setup_vparameter(parlist, prefix, ".", "",
148 "nhigh", base_context,
149 "High number of pixels to reject for the minmax clipping algorithm",
150 CPL_TYPE_DOUBLE,
152
153 if (cpl_error_get_code()) {
154 cpl_parameterlist_delete(parlist);
155 return NULL;
156 }
157
158 return parlist;
159}
160
161/* ---------------------------------------------------------------------------*/
177/* ---------------------------------------------------------------------------*/
178cpl_error_code hdrl_sigclip_parameter_parse_parlist(
179 const cpl_parameterlist * parlist,
180 const char * prefix,
181 double * kappa_low,
182 double * kappa_high,
183 int * niter)
184{
185 cpl_ensure_code(prefix && parlist, CPL_ERROR_NULL_INPUT);
186 char * name;
187
188 if (kappa_low) {
189 name = hdrl_join_string(".", 2, prefix, "sigclip.kappa-low");
190 const cpl_parameter * par = cpl_parameterlist_find_const(parlist, name);
191 *kappa_low = cpl_parameter_get_double(par);
192 cpl_free(name);
193 }
194
195 if (kappa_high) {
196 name = hdrl_join_string(".", 2, prefix, "sigclip.kappa-high");
197 const cpl_parameter * par = cpl_parameterlist_find_const(parlist, name);
198 *kappa_high = cpl_parameter_get_double(par);
199 cpl_free(name);
200 }
201
202 if (niter) {
203 name = hdrl_join_string(".", 2, prefix, "sigclip.niter");
204 const cpl_parameter * par = cpl_parameterlist_find_const(parlist, name);
205 *niter = cpl_parameter_get_int(par);
206 cpl_free(name);
207 }
208
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);
213 }
214
215 return CPL_ERROR_NONE;
216}
217
218/* ---------------------------------------------------------------------------*/
233/* ---------------------------------------------------------------------------*/
234cpl_error_code hdrl_minmax_parameter_parse_parlist(
235 const cpl_parameterlist * parlist,
236 const char * prefix,
237 double * nlow,
238 double * nhigh)
239{
240 cpl_ensure_code(prefix && parlist, CPL_ERROR_NULL_INPUT);
241 char * name;
242
243 if (nlow) {
244 name = hdrl_join_string(".", 2, prefix, "minmax.nlow");
245 const cpl_parameter * par = cpl_parameterlist_find_const(parlist, name);
246 *nlow = cpl_parameter_get_double(par);
247 cpl_free(name);
248 }
249
250 if (nhigh) {
251 name = hdrl_join_string(".", 2, prefix, "minmax.nhigh");
252 const cpl_parameter * par = cpl_parameterlist_find_const(parlist, name);
253 *nhigh = cpl_parameter_get_double(par);
254 cpl_free(name);
255 }
256
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);
261 }
262
263 return CPL_ERROR_NONE;
264}
265
266
267/*----------------------------------------------------------------------------*/
288/*----------------------------------------------------------------------------*/
289cpl_error_code hdrl_minmax_clip_image(
290 const cpl_image * source,
291 const cpl_image * error,
292 const double nlow,
293 const double nhigh,
294 double * mean_mm,
295 double * mean_mm_err,
296 cpl_size * naccepted,
297 double * reject_low,
298 double * reject_high)
299{
300 cpl_vector * vec_source = NULL;
301 cpl_vector * vec_error = NULL;
302
303 /* Check Entries */
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");
314
315 /* compress images to vectors excluding the bad pixels */
316 vec_source = hdrl_image_to_vector(source, NULL);
317 vec_error = hdrl_image_to_vector(error, cpl_image_get_bpm_const(source));
318
319 if (vec_source != NULL && vec_error != NULL) {
320 /* Call here the real clipping function */
321 hdrl_minmax_clip(vec_source, vec_error, nlow, nhigh, CPL_TRUE, mean_mm,
322 mean_mm_err, naccepted, reject_low, reject_high);
323 }
324 /* no good pixels */
325 else {
326 *mean_mm = NAN;
327 *mean_mm_err = NAN;
328 *naccepted = 0;
329 *reject_low = NAN;
330 *reject_high = NAN;
331 }
332
333 cpl_msg_debug(cpl_func, "mean_mm, mean_mm_err, naccepted: %g, %g, %ld",
334 *mean_mm, *mean_mm_err, (long)*naccepted);
335
336 cpl_vector_delete(vec_source);
337 cpl_vector_delete(vec_error);
338 return cpl_error_get_code();
339}
340
341
342/*----------------------------------------------------------------------------*/
365/*----------------------------------------------------------------------------*/
366cpl_error_code hdrl_minmax_clip(
367 cpl_vector * vec,
368 cpl_vector * vec_err,
369 const double nlow,
370 const double nhigh,
371 cpl_boolean inplace,
372 double * mean_mm,
373 double * mean_mm_err,
374 cpl_size * naccepted,
375 double * reject_low,
376 double * reject_high)
377{
378 /* VARIABLES ON THE FUNCTION SCOPE:
379
380 vec_image a deep copy of the input vector vec.
381 mean_mm min-max clip mean (return variable).
382 */
383
384 cpl_vector * vec_image = NULL;
385 cpl_vector * vec_image_err = NULL;
386
387 cpl_size vec_size;
388 cpl_size nlow_int, nhigh_int;
389 cpl_vector * vec_trunc;
390
391 cpl_size trunc_size;
392 double * d, * e;
393
394 /*In the future minmax rejection could also use relative values therefore
395 * we pass a double to the function - nevertheless the code as it is now
396 * expects an integer - thus we need to do the rounding */
397
398 nlow_int = (cpl_size)round(nlow);
399 nhigh_int = (cpl_size)round(nhigh);
400
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");
411
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");
415
416 vec_size = cpl_vector_get_size(vec);
417
418 /* Nothing to do if only one data point */
419 if(vec_size <= (nlow_int+nhigh_int)) {
420 *mean_mm=NAN;
421 *mean_mm_err=NAN;
422 *naccepted=0;
423 return cpl_error_get_code();
424 }
425
426 if (inplace) {
427 vec_image = vec;
428 vec_image_err = vec_err;
429 }
430 else {
431 vec_image = cpl_vector_duplicate(vec);
432 vec_image_err = cpl_vector_duplicate(vec_err);
433 }
434
435 hdrl_sort_double_pairs(vec_image, vec_image_err);
436
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);
441
442 /* COMPUTE THE MIN-MAX CLIP MEAN */
443 *mean_mm = cpl_vector_get_mean(vec_trunc);
444
445 if (naccepted) {
446 *naccepted = trunc_size;
447 }
448
449 if (reject_low) {
450 *reject_low = d[nlow_int];
451 }
452 if (reject_high) {
453 *reject_high = d[vec_size - nhigh_int - 1];
454 }
455
456 if (mean_mm_err) {
457 cpl_vector * vec_trunc_err;
458 /* if multiple equal elements use the one with the smallest error
459 * get the equal range, sort the errors and write the smallest into the
460 * valid array ends */
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));
469 }
470 cpl_vector_delete(e_vec);
471 }
472
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));
481 }
482 cpl_vector_delete(e_vec);
483 }
484
485 vec_trunc_err = cpl_vector_wrap(trunc_size, e + nlow_int);
486 /*Propagate the errors (cpl_vector_power is very slow PIPE-4330) */
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);
491 }
492 /* CLEAN, AND RETURN */
493 cpl_vector_unwrap(vec_trunc);
494 if (!inplace) {
495 cpl_vector_delete(vec_image);
496 cpl_vector_delete(vec_image_err);
497 }
498 return cpl_error_get_code();
499}
500
501
502
503/*----------------------------------------------------------------------------*/
523/*----------------------------------------------------------------------------*/
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,
529 const int iter,
530 double * mean_ks,
531 double * mean_ks_err,
532 cpl_size * naccepted,
533 double * reject_low,
534 double * reject_high)
535{
536 cpl_vector * vec_source = NULL;
537 cpl_vector * vec_error = NULL;
538
539 /* Check Entries */
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");
550
551 /* compress images to vectors excluding the bad pixels */
552 vec_source = hdrl_image_to_vector(source, NULL);
553 vec_error = hdrl_image_to_vector(error, cpl_image_get_bpm_const(source));
554
555 if (vec_source != NULL && vec_error != NULL) {
556 /* Call here the real sigma-clipping function */
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);
560 }
561 /* no good pixels */
562 else {
563 *mean_ks = NAN;
564 *mean_ks_err = NAN;
565 *naccepted = 0;
566 *reject_low = NAN;
567 *reject_high = NAN;
568 }
569
570 cpl_msg_debug(cpl_func, "mean_ks, mean_ks_err, naccepted: %g, %g, %ld",
571 *mean_ks, *mean_ks_err, (long)*naccepted);
572
573 cpl_vector_delete(vec_source);
574 cpl_vector_delete(vec_error);
575 return cpl_error_get_code();
576}
577
578/* ---------------------------------------------------------------------------*/
586/* ---------------------------------------------------------------------------*/
587static long get_upper_bound_d(double * vec, long count, double val)
588{
589 long first = 0;
590 while (count > 0)
591 {
592 long step = count / 2;
593 long it = first + step;
594 if (!(val < vec[it])) {
595 first = it + 1;
596 count -= step + 1;
597 }
598 else
599 count = step;
600 }
601 return first;
602}
603
604/* ---------------------------------------------------------------------------*/
611/* ---------------------------------------------------------------------------*/
612static long get_upper_bound(cpl_vector * vec, double val)
613{
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);
617}
618/* ---------------------------------------------------------------------------*/
626/* ---------------------------------------------------------------------------*/
627static long get_lower_bound_d(double * vec, long count, double val)
628{
629 long first = 0;
630 while (count > 0)
631 {
632 long step = count / 2;
633 long it = first + step;
634 if (vec[it] < val) {
635 first = it + 1;
636 count -= step + 1;
637 }
638 else
639 count = step;
640 }
641 return first;
642}
643
644/* ---------------------------------------------------------------------------*/
651/* ---------------------------------------------------------------------------*/
652static long get_lower_bound(cpl_vector * vec, double val)
653{
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);
657}
658
659/* compute mean and error without needing to wrap a vector, the allocation can
660 * be very expensive for small stacks of images */
661static void get_mean_err(const double * d, const double * e, long count,
662 double * rm, double * re)
663{
664 double m = 0.;
665 for (long i = 0; i < count; i++) {
666 m += (d[i] - m) / (double)(i + 1);
667 }
668 *rm = m;
669
670 if (re) {
671 double se = 0;
672 for (long i = 0; i < count; i++) {
673 se += e[i] * e[i];
674 }
675 *re = sqrt(se) / count;
676 }
677}
678
679/*----------------------------------------------------------------------------*/
736/*----------------------------------------------------------------------------*/
737cpl_error_code hdrl_kappa_sigma_clip(
738 cpl_vector * vec,
739 cpl_vector * vec_err,
740 const double kappa_low,
741 const double kappa_high,
742 const int iter,
743 cpl_boolean inplace,
744 double * mean_ks,
745 double * mean_ks_err,
746 cpl_size * naccepted,
747 double * reject_low,
748 double * reject_high)
749{
750 /* VARIABLES ON THE FUNCTION SCOPE:
751
752 vec_image a deep copy of the input vector vec.
753 mean_ks kappa-sigma clip mean (return variable).
754 mean_ks kappa-sigma clip mean (return variable).
755 */
756
757 cpl_vector * vec_image = NULL;
758 cpl_vector * vec_image_err = NULL;
759
760 cpl_size vec_size;
761 double lower_bound = 0.;
762 double upper_bound = 0.;
763
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");
777
778 if (inplace) {
779 vec_image = vec;
780 vec_image_err = vec_err;
781 }
782 else {
783 vec_image = cpl_vector_duplicate(vec);
784 vec_image_err = cpl_vector_duplicate(vec_err);
785 }
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);
790
791 /* sort the two vectors by the data */
792 hdrl_sort_double_pairs(vec_image, vec_image_err);
793
794 for(int it = 0; it < iter; it++) {
795 double median, sigma;
796 cpl_size lower_index, upper_index;
797
798 /* Nothing to do if only one data point */
799 if(vec_size == 1) {
800 lower_bound = vec_data[0];
801 upper_bound = lower_bound;
802 break;
803 }
804
805 /* STEPS OF KAPPA SIGMA CLIP
806 1. Sort the vector.
807 2. Find mean, and standard deviation (sigma).
808 3. Find lower, and upper bound after kappa-sigma clip.
809 4. Find index which corresponds to lower and upper bound
810 5. Extract the vector within the index bound.
811 */
812
813 /* Use median as a robust estimator of the mean */
814
815 /* standard deviation from Median Absolute Deviation (MAD) as appropriate
816 for a Gaussian distribution */
817
818 /* offset index into original uncut vec_image */
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);
822
823 if(sigma <= 0){
824 sigma=nextafter(0,1.0);
825 }
826 sigma *= CPL_MATH_STD_MAD;
827
828 lower_bound = median - kappa_low * sigma;
829 upper_bound = median + kappa_high * sigma;
830
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);
834
835 /* Stop if no outliers were found */
836 if ((lower_index == 0) && (upper_index == vec_size - 1))
837 break;
838
839 /* truncate vector */
840 vec_data = vec_data + lower_index;
841 vec_data_err = vec_data_err + lower_index;
842 vec_size = upper_index - lower_index + 1;
843 }
844
845 /* COMPUTE THE KAPPA-SIGMA CLIP MEAN */
846 get_mean_err(vec_data, vec_data_err, vec_size, mean_ks, mean_ks_err);
847
848 if (naccepted) *naccepted = vec_size;
849
850 if (reject_low) *reject_low = lower_bound;
851 if (reject_high) *reject_high = upper_bound;
852
853 /* CLEAN, AND RETURN */
854 if (!inplace) {
855 cpl_vector_delete(vec_image);
856 cpl_vector_delete(vec_image_err);
857 }
858 return cpl_error_get_code();
859}
860
861
862/*---------------------------------------------------------------------------*/
871/*---------------------------------------------------------------------------*/
872static cpl_error_code hdrl_sort_double_pairs(cpl_vector *u1, cpl_vector *u2)
873{
874 cpl_bivector * bi_all = NULL;
875
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");
880
881 bi_all = cpl_bivector_wrap_vectors(u1, u2);
882 cpl_bivector_sort(bi_all, bi_all, CPL_SORT_ASCENDING, CPL_SORT_BY_X);
883
884 /* cleaning up */
885 cpl_bivector_unwrap_vectors(bi_all);
886
887 return CPL_ERROR_NONE;
888}
889
890
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
Definition: hdrl_utils.c:812