CR2RE Pipeline Reference Manual 1.6.8
hdrl_collapse.c
1/*
2 * This file is part of the HDRL
3 * Copyright (C) 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_collapse.h"
29#include "hdrl_parameter.h"
30#include "hdrl_parameter_defs.h"
31#include "hdrl_sigclip.h"
32#include "hdrl_mode.h"
33#include "hdrl_utils.h"
34#include "hdrl_types.h"
35#include <cpl.h>
36
37#include <string.h>
38#include <math.h>
39/*-----------------------------------------------------------------------------
40 Types
41-----------------------------------------------------------------------------*/
42
43/* function performing imglist -> image reduction */
44typedef cpl_error_code (hdrl_collapse_imagelist_to_image_f)(
45 const cpl_imagelist * data,
46 const cpl_imagelist * errors,
47 cpl_image ** out,
48 cpl_image ** err,
49 cpl_image ** contrib,
50 void * parameters,
51 void * extra_out);
52
53struct hdrl_collapse_imagelist_to_image_s {
54 /* function performing imglist -> image reduction */
55 hdrl_collapse_imagelist_to_image_f * func;
56 /* create extra out storage */
57 void * (*create_eout)(const cpl_image *);
58 /* move extra out storage */
59 cpl_error_code (*move_eout)(void *, void *, const cpl_size);
60 /* unwrap extra out storage */
61 hdrl_free * unwrap_eout;
62 /* delete extra out storage */
63 void (*delete_eout)(void *);
64 /* parameters the reduction function requires */
65 hdrl_parameter * parameters;
66};
67
68/* function performing imglist -> image reduction */
69typedef cpl_error_code (hdrl_collapse_imagelist_to_vector_f)(
70 const cpl_imagelist * data,
71 const cpl_imagelist * errors,
72 cpl_vector ** out,
73 cpl_vector ** err,
74 cpl_array ** contrib,
75 void * parameters,
76 void * extra_out);
77
78struct hdrl_collapse_imagelist_to_vector_s {
79 /* function performing imglist -> vector reduction */
80 hdrl_collapse_imagelist_to_vector_f * func;
81 /* create extra out storage */
82 void * (*create_eout)(cpl_size);
83 /* move extra out storage */
84 cpl_error_code (*move_eout)(void *, void *, const cpl_size);
85 /* unwrap extra out storage */
86 hdrl_free * unwrap_eout;
87 /* delete extra out storage */
88 void (*delete_eout)(void *);
89 /* parameters the reduction function requires */
90 hdrl_parameter * parameters;
91};
92
93static cpl_error_code
94hdrl_collapse_mean(const cpl_imagelist * data,
95 const cpl_imagelist * errors,
96 cpl_image ** out, cpl_image ** err,
97 cpl_image ** contrib, void *, void *);
98static cpl_error_code
99hdrl_collapse_median(const cpl_imagelist * data,
100 const cpl_imagelist * errors,
101 cpl_image ** out, cpl_image ** err,
102 cpl_image ** contrib, void *, void *);
103static cpl_error_code
104hdrl_collapse_sigclip(const cpl_imagelist * data,
105 const cpl_imagelist * errors,
106 cpl_image ** out, cpl_image ** err,
107 cpl_image ** contrib,
108 void * parameters, void * extra_out);
109
110static cpl_error_code
111hdrl_collapse_minmax(const cpl_imagelist * data,
112 const cpl_imagelist * errors,
113 cpl_image ** out, cpl_image ** err,
114 cpl_image ** contrib,
115 void * parameters, void * extra_out);
116static cpl_error_code
117hdrl_collapse_mode(const cpl_imagelist * data,
118 const cpl_imagelist * errors,
119 cpl_image ** out, cpl_image ** err,
120 cpl_image ** contrib, void *, void *);
121
122static cpl_error_code
123hdrl_collapse_weighted_mean(const cpl_imagelist * data_,
124 const cpl_imagelist * errors_,
125 cpl_image ** out, cpl_image ** err,
126 cpl_image ** contrib, void *, void *);
127
128/*-----------------------------------------------------------------------------
129 Static
130 -----------------------------------------------------------------------------*/
131
132/*----------------------------------------------------------------------------*/
139/*----------------------------------------------------------------------------*/
140
146/*-----------------------------------------------------------------------------
147 Collapse Parameters
148 -----------------------------------------------------------------------------*/
149static void hdrl_nop_free(void * HDRL_UNUSED(x))
150{
151 return;
152}
153
154static void * hdrl_mean_alloc(size_t n);
155static void * hdrl_median_alloc(size_t n);
156static void * hdrl_weighted_mean_alloc(size_t n);
157
158/* Mean COLLAPSE */
159typedef hdrl_parameter_empty hdrl_collapse_mean_parameter;
160static hdrl_parameter_typeobj hdrl_collapse_mean_parameter_type = {
161 HDRL_PARAMETER_COLLAPSE_MEAN, /* type */
162 (hdrl_alloc *)&hdrl_mean_alloc, /* fp_alloc */
163 (hdrl_free *)&hdrl_nop_free, /* fp_free */
164 NULL, /* fp_destroy */
165 sizeof(hdrl_collapse_mean_parameter), /* obj_size */
166};
167
168HDRL_PARAMETER_SINGLETON(HDRL_COLLAPSE_MEAN,
169 hdrl_collapse_mean_parameter_type,
170 hdrl_mean_alloc);
171
172/* Median COLLAPSE */
173typedef hdrl_parameter_empty hdrl_collapse_median_parameter;
174static hdrl_parameter_typeobj hdrl_collapse_median_parameter_type = {
175 HDRL_PARAMETER_COLLAPSE_MEDIAN, /* type */
176 (hdrl_alloc *)&hdrl_median_alloc, /* fp_alloc */
177 (hdrl_free *)&hdrl_nop_free, /* fp_free */
178 NULL, /* fp_destroy */
179 sizeof(hdrl_collapse_median_parameter), /* obj_size */
180};
181
182HDRL_PARAMETER_SINGLETON(HDRL_COLLAPSE_MEDIAN,
183 hdrl_collapse_median_parameter_type,
184 hdrl_median_alloc);
185
186/* Weighted Mean COLLAPSE */
187typedef hdrl_parameter_empty hdrl_collapse_weighted_mean_parameter;
188static hdrl_parameter_typeobj hdrl_collapse_weighted_mean_parameter_type = {
189 HDRL_PARAMETER_COLLAPSE_WEIGHTED_MEAN, /* type */
190 (hdrl_alloc *)&hdrl_weighted_mean_alloc, /* fp_alloc */
191 (hdrl_free *)&hdrl_nop_free, /* fp_free */
192 NULL, /* fp_destroy */
193 sizeof(hdrl_collapse_weighted_mean_parameter), /* obj_size */
194};
195
196HDRL_PARAMETER_SINGLETON(HDRL_COLLAPSE_WEIGHTED_MEAN,
197 hdrl_collapse_weighted_mean_parameter_type,
198 hdrl_weighted_mean_alloc);
199
200/* Sigma-Clipping COLLAPSE */
201typedef struct {
202 HDRL_PARAMETER_HEAD;
203 double kappa_low;
204 double kappa_high;
205 int niter;
206} hdrl_collapse_sigclip_parameter;
207static hdrl_parameter_typeobj hdrl_collapse_sigclip_parameter_type = {
208 HDRL_PARAMETER_COLLAPSE_SIGCLIP, /* type */
209 (hdrl_alloc *)&cpl_malloc, /* fp_alloc */
210 (hdrl_free *)&cpl_free, /* fp_free */
211 NULL, /* fp_destroy */
212 sizeof(hdrl_collapse_sigclip_parameter), /* obj_size */
213};
214
215
216/* Minmax-Clipping COLLAPSE */
217typedef struct {
218 HDRL_PARAMETER_HEAD;
219 double nlow;
220 double nhigh;
221} hdrl_collapse_minmax_parameter;
222static hdrl_parameter_typeobj hdrl_collapse_minmax_parameter_type = {
223 HDRL_PARAMETER_COLLAPSE_MINMAX, /* type */
224 (hdrl_alloc *)&cpl_malloc, /* fp_alloc */
225 (hdrl_free *)&cpl_free, /* fp_free */
226 NULL, /* fp_destroy */
227 sizeof(hdrl_collapse_minmax_parameter), /* obj_size */
228};
229
230/* Mode COLLAPSE */
231typedef struct {
232 HDRL_PARAMETER_HEAD;
233 double histo_min;
234 double histo_max;
235 double bin_size;
236 hdrl_mode_type method;
237 cpl_size error_niter;
238} hdrl_collapse_mode_parameter;
239static hdrl_parameter_typeobj hdrl_collapse_mode_parameter_type = {
240 HDRL_PARAMETER_COLLAPSE_MODE, /* type */
241 (hdrl_alloc *)&cpl_malloc, /* fp_alloc */
242 (hdrl_free *)&cpl_free, /* fp_free */
243 NULL, /* fp_destroy */
244 sizeof(hdrl_collapse_mode_parameter), /* obj_size */
245};
246
249/* ---------------------------------------------------------------------------*/
254/* ---------------------------------------------------------------------------*/
256{
257 hdrl_parameter_empty * p = (hdrl_parameter_empty *)
258 hdrl_parameter_new(&hdrl_collapse_mean_parameter_type);
259 return (hdrl_parameter *)p;
260}
261
262/* ---------------------------------------------------------------------------*/
267/* ---------------------------------------------------------------------------*/
268cpl_boolean hdrl_collapse_parameter_is_mean(const hdrl_parameter * self)
269{
270 return hdrl_parameter_check_type(self, &hdrl_collapse_mean_parameter_type);
271}
272
273/* ---------------------------------------------------------------------------*/
278/* ---------------------------------------------------------------------------*/
280{
281 hdrl_parameter_empty * p = (hdrl_parameter_empty *)
282 hdrl_parameter_new(&hdrl_collapse_median_parameter_type);
283 return (hdrl_parameter *)p;
284}
285
286/* ---------------------------------------------------------------------------*/
291/* ---------------------------------------------------------------------------*/
292cpl_boolean hdrl_collapse_parameter_is_median(const hdrl_parameter * self)
293{
294 return hdrl_parameter_check_type(self, &hdrl_collapse_median_parameter_type);
295}
296
297/* ---------------------------------------------------------------------------*/
302/* ---------------------------------------------------------------------------*/
304{
305 hdrl_parameter_empty * p = (hdrl_parameter_empty *)
306 hdrl_parameter_new(&hdrl_collapse_weighted_mean_parameter_type);
307 return (hdrl_parameter *)p;
308}
309
310/* ---------------------------------------------------------------------------*/
315/* ---------------------------------------------------------------------------*/
317 const hdrl_parameter * self)
318{
319 return hdrl_parameter_check_type(self,
320 &hdrl_collapse_weighted_mean_parameter_type);
321}
322
323/* ---------------------------------------------------------------------------*/
331/* ---------------------------------------------------------------------------*/
332hdrl_parameter *
333hdrl_collapse_sigclip_parameter_create(double kappa_low, double kappa_high, int niter)
334{
335 hdrl_collapse_sigclip_parameter * p = (hdrl_collapse_sigclip_parameter *)
336 hdrl_parameter_new(&hdrl_collapse_sigclip_parameter_type);
337 p->kappa_low = kappa_low;
338 p->kappa_high = kappa_high;
339 p->niter = niter;
340
341 if (hdrl_collapse_sigclip_parameter_verify((hdrl_parameter*)p) !=
342 CPL_ERROR_NONE) {
343 hdrl_parameter_delete((hdrl_parameter*)p);
344 return NULL;
345 }
346 return (hdrl_parameter *)p;
347}
348
349/* ---------------------------------------------------------------------------*/
354/* ---------------------------------------------------------------------------*/
355cpl_boolean hdrl_collapse_parameter_is_sigclip(const hdrl_parameter * self)
356{
357 return hdrl_parameter_check_type(self,
358 &hdrl_collapse_sigclip_parameter_type);
359}
360
363/*----------------------------------------------------------------------------*/
370/*----------------------------------------------------------------------------*/
371cpl_error_code hdrl_collapse_sigclip_parameter_verify(
372 const hdrl_parameter * param)
373{
374 cpl_error_ensure(param != NULL, CPL_ERROR_NULL_INPUT,
375 return CPL_ERROR_NULL_INPUT,
376 "NULL Collapse Sigclip Parameters");
377
378 cpl_error_ensure(hdrl_collapse_parameter_is_sigclip(param),
379 CPL_ERROR_INCOMPATIBLE_INPUT, return
380 CPL_ERROR_INCOMPATIBLE_INPUT,
381 "Not a Sigclip parameter");
382
383 const hdrl_collapse_sigclip_parameter * param_loc =
384 (const hdrl_collapse_sigclip_parameter *)param ;
385
386 cpl_error_ensure(param_loc->niter > 0, CPL_ERROR_ILLEGAL_INPUT,
387 return CPL_ERROR_ILLEGAL_INPUT,
388 "sigma-clipping iter (%d) value must be > 0",
389 param_loc->niter);
390
391 return CPL_ERROR_NONE ;
392}
393
396/* ---------------------------------------------------------------------------*/
402/* ---------------------------------------------------------------------------*/
404{
405 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
407 CPL_ERROR_INCOMPATIBLE_INPUT, -1);
408
409 return ((const hdrl_collapse_sigclip_parameter *)p)->kappa_high;
410}
411
412/* ---------------------------------------------------------------------------*/
418/* ---------------------------------------------------------------------------*/
419double hdrl_collapse_sigclip_parameter_get_kappa_low(const hdrl_parameter * p)
420{
421 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
423 CPL_ERROR_INCOMPATIBLE_INPUT, -1);
424
425 return ((const hdrl_collapse_sigclip_parameter *)p)->kappa_low;
426}
427
428/* ---------------------------------------------------------------------------*/
434/* ---------------------------------------------------------------------------*/
435int hdrl_collapse_sigclip_parameter_get_niter(const hdrl_parameter * p)
436{
437 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
439 CPL_ERROR_INCOMPATIBLE_INPUT, -1);
440
441 return ((const hdrl_collapse_sigclip_parameter *)p)->niter;
442}
443
444/* ---------------------------------------------------------------------------*/
452/* ---------------------------------------------------------------------------*/
453hdrl_parameter *
455{
456 hdrl_collapse_minmax_parameter * p = (hdrl_collapse_minmax_parameter *)
457 hdrl_parameter_new(&hdrl_collapse_minmax_parameter_type);
458 p->nlow = nlow;
459 p->nhigh = nhigh;
460
461 if (hdrl_collapse_minmax_parameter_verify((hdrl_parameter*)p) !=
462 CPL_ERROR_NONE) {
463 hdrl_parameter_delete((hdrl_parameter*)p);
464 return NULL;
465 }
466 return (hdrl_parameter *)p;
467}
468
469/* ---------------------------------------------------------------------------*/
474/* ---------------------------------------------------------------------------*/
475cpl_boolean hdrl_collapse_parameter_is_minmax(const hdrl_parameter * self)
476{
477 return hdrl_parameter_check_type(self,
478 &hdrl_collapse_minmax_parameter_type);
479}
480
483/*----------------------------------------------------------------------------*/
490/*----------------------------------------------------------------------------*/
491cpl_error_code hdrl_collapse_minmax_parameter_verify(
492 const hdrl_parameter * param)
493{
494
495 cpl_error_ensure(param != NULL, CPL_ERROR_NULL_INPUT,
496 return CPL_ERROR_NULL_INPUT,
497 "NULL Collapse Minmax Parameters");
498
499 cpl_error_ensure(hdrl_collapse_parameter_is_minmax(param),
500 CPL_ERROR_INCOMPATIBLE_INPUT, return
501 CPL_ERROR_INCOMPATIBLE_INPUT,
502 "Not a minmax parameter");
503
504 const hdrl_collapse_minmax_parameter * param_loc =
505 (const hdrl_collapse_minmax_parameter *)param ;
506
507 cpl_error_ensure(param_loc->nlow >= 0, CPL_ERROR_ILLEGAL_INPUT,
508 return CPL_ERROR_ILLEGAL_INPUT,
509 "nlow value (%g) must be >= 0",
510 param_loc->nlow);
511
512 cpl_error_ensure(param_loc->nhigh >= 0, CPL_ERROR_ILLEGAL_INPUT,
513 return CPL_ERROR_ILLEGAL_INPUT,
514 "nhigh value (%g) must be >= 0",
515 param_loc->nlow);
516
517 return CPL_ERROR_NONE ;
518}
519
522/* ---------------------------------------------------------------------------*/
528/* ---------------------------------------------------------------------------*/
529double hdrl_collapse_minmax_parameter_get_nhigh(const hdrl_parameter * p)
530{
531 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
533 CPL_ERROR_INCOMPATIBLE_INPUT, -1);
534
535 return ((const hdrl_collapse_minmax_parameter *)p)->nhigh;
536}
537
538/* ---------------------------------------------------------------------------*/
544/* ---------------------------------------------------------------------------*/
545double hdrl_collapse_minmax_parameter_get_nlow(const hdrl_parameter * p)
546{
547 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
549 CPL_ERROR_INCOMPATIBLE_INPUT, -1);
550
551 return ((const hdrl_collapse_minmax_parameter *)p)->nlow;
552}
553
554/* ---------------------------------------------------------------------------*/
565/* ---------------------------------------------------------------------------*/
566hdrl_parameter *
568 double histo_max,
569 double bin_size,
570 hdrl_mode_type mode_method,
571 cpl_size error_niter)
572{
573 hdrl_collapse_mode_parameter * p = (hdrl_collapse_mode_parameter *)
574 hdrl_parameter_new(&hdrl_collapse_mode_parameter_type);
575 p->histo_min = histo_min;
576 p->histo_max = histo_max;
577 p->bin_size = bin_size;
578 p->method = mode_method;
579 p->error_niter = error_niter;
580 if (hdrl_collapse_mode_parameter_verify((hdrl_parameter*)p) !=
581 CPL_ERROR_NONE) {
582 hdrl_parameter_delete((hdrl_parameter*)p);
583 return NULL;
584 }
585 return (hdrl_parameter *)p;
586}
587
588/* ---------------------------------------------------------------------------*/
593/* ---------------------------------------------------------------------------*/
594cpl_boolean hdrl_collapse_parameter_is_mode(const hdrl_parameter * self)
595{
596 return hdrl_parameter_check_type(self,
597 &hdrl_collapse_mode_parameter_type);
598}
599
602/*----------------------------------------------------------------------------*/
609/*----------------------------------------------------------------------------*/
610cpl_error_code hdrl_collapse_mode_parameter_verify(
611 const hdrl_parameter * param)
612{
613
614 cpl_error_ensure(param != NULL, CPL_ERROR_NULL_INPUT,
615 return CPL_ERROR_NULL_INPUT,
616 "NULL Collapse Mode Parameters");
617
618 cpl_error_ensure(hdrl_collapse_parameter_is_mode(param),
619 CPL_ERROR_INCOMPATIBLE_INPUT, return
620 CPL_ERROR_INCOMPATIBLE_INPUT,
621 "Not a mode parameter");
622
623 const hdrl_collapse_mode_parameter * param_loc =
624 (const hdrl_collapse_mode_parameter *)param ;
625
626
627 cpl_error_ensure(param_loc->bin_size >= 0, CPL_ERROR_ILLEGAL_INPUT,
628 return CPL_ERROR_ILLEGAL_INPUT,
629 "bin_size value (%g) must be >= 0",
630 param_loc->bin_size);
631
632 cpl_error_ensure(param_loc->error_niter >= 0, CPL_ERROR_ILLEGAL_INPUT,
633 return CPL_ERROR_ILLEGAL_INPUT,
634 "error_niter value (%lld) must be >= 0",
635 param_loc->error_niter);
636
637 cpl_error_ensure(param_loc->method == HDRL_MODE_MEDIAN ||
638 param_loc->method == HDRL_MODE_FIT ||
639 param_loc->method == HDRL_MODE_WEIGHTED ,
640 CPL_ERROR_ILLEGAL_INPUT,
641 return CPL_ERROR_ILLEGAL_INPUT,
642 "Please check the computation method of the mode. It has to be "
643 "%d, or %d, or %d", HDRL_MODE_MEDIAN, HDRL_MODE_WEIGHTED,
644 HDRL_MODE_FIT);
645
646 return CPL_ERROR_NONE ;
647}
648
651/* ---------------------------------------------------------------------------*/
657/* ---------------------------------------------------------------------------*/
658double hdrl_collapse_mode_parameter_get_histo_min(const hdrl_parameter * p)
659{
660 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
662 CPL_ERROR_INCOMPATIBLE_INPUT, -1);
663
664 return ((const hdrl_collapse_mode_parameter *)p)->histo_min;
665}
666
667/* ---------------------------------------------------------------------------*/
673/* ---------------------------------------------------------------------------*/
674double hdrl_collapse_mode_parameter_get_histo_max(const hdrl_parameter * p)
675{
676 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
678 CPL_ERROR_INCOMPATIBLE_INPUT, -1);
679
680 return ((const hdrl_collapse_mode_parameter *)p)->histo_max;
681}
682
683/* ---------------------------------------------------------------------------*/
689/* ---------------------------------------------------------------------------*/
690double hdrl_collapse_mode_parameter_get_bin_size(const hdrl_parameter * p)
691{
692 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
694 CPL_ERROR_INCOMPATIBLE_INPUT, -1);
695
696 return ((const hdrl_collapse_mode_parameter *)p)->bin_size;
697}
698
699/* ---------------------------------------------------------------------------*/
705/* ---------------------------------------------------------------------------*/
706hdrl_mode_type hdrl_collapse_mode_parameter_get_method(const hdrl_parameter * p)
707{
708 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
710 CPL_ERROR_INCOMPATIBLE_INPUT, -1);
711
712 return ((const hdrl_collapse_mode_parameter *)p)->method;
713}
714
715/* ---------------------------------------------------------------------------*/
721/* ---------------------------------------------------------------------------*/
722cpl_size hdrl_collapse_mode_parameter_get_error_niter(const hdrl_parameter * p)
723{
724 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1);
726 CPL_ERROR_INCOMPATIBLE_INPUT, -1);
727
728 return ((const hdrl_collapse_mode_parameter *)p)->error_niter;
729}
730
731
732/* ---------------------------------------------------------------------------*/
747/* ---------------------------------------------------------------------------*/
749 const char *base_context,
750 const char *prefix,
751 const char *method_def,
752 hdrl_parameter *sigclip_def,
753 hdrl_parameter *minmax_def,
754 hdrl_parameter *mode_def)
755{
756 cpl_ensure(base_context && prefix, CPL_ERROR_NULL_INPUT, NULL);
757
758 cpl_ensure(hdrl_collapse_parameter_is_sigclip(sigclip_def)
759 && hdrl_collapse_parameter_is_minmax( minmax_def )
760 && hdrl_collapse_parameter_is_mode( mode_def ),
761 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
762
763 char *name;
764 cpl_parameterlist *parlist = cpl_parameterlist_new();
765 cpl_parameter *p;
766 char *context = hdrl_join_string(".", 2, base_context, prefix);
767
768 /* --prefix.method */
769 name = hdrl_join_string(".", 2, context, "method");
770 p = cpl_parameter_new_enum(name, CPL_TYPE_STRING,
771 "Method used for collapsing the data", context,
772 method_def, 6, "MEAN", "WEIGHTED_MEAN", "MEDIAN", "SIGCLIP",
773 "MINMAX", "MODE");
774 cpl_free(name) ;
775 name = hdrl_join_string(".", 2, prefix, "method");
776 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
777 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
778 cpl_free(name) ;
779 cpl_parameterlist_append(parlist, p);
780
781 /* --prefix.sigclip.xxx */
782 name = hdrl_join_string(".", 2, prefix, "sigclip");
783 cpl_parameterlist * psigclip = hdrl_sigclip_parameter_create_parlist(
784 base_context, name, sigclip_def);
785 cpl_free(name) ;
786
787 for (cpl_parameter * par = cpl_parameterlist_get_first(psigclip);
788 par != NULL;
789 par = cpl_parameterlist_get_next(psigclip)) {
790 cpl_parameterlist_append(parlist, cpl_parameter_duplicate(par));
791 }
792 cpl_parameterlist_delete(psigclip);
793
794 /* --prefix.minmax.xxx */
795 name = hdrl_join_string(".", 2, prefix, "minmax");
796 cpl_parameterlist * pminmax = hdrl_minmax_parameter_create_parlist(
797 base_context, name, minmax_def);
798 cpl_free(name) ;
799
800
801 for (cpl_parameter * par = cpl_parameterlist_get_first(pminmax);
802 par != NULL;
803 par = cpl_parameterlist_get_next(pminmax)) {
804 cpl_parameterlist_append(parlist, cpl_parameter_duplicate(par));
805 }
806 cpl_parameterlist_delete(pminmax);
807
808
809 /* --prefix.mode.xxx */
810 name = hdrl_join_string(".", 2, prefix, "mode");
811 cpl_parameterlist * pmode = hdrl_mode_parameter_create_parlist(
812 base_context, name, mode_def);
813 cpl_free(name) ;
814
815
816 for (cpl_parameter * par = cpl_parameterlist_get_first(pmode);
817 par != NULL;
818 par = cpl_parameterlist_get_next(pmode)) {
819 cpl_parameterlist_append(parlist, cpl_parameter_duplicate(par));
820 }
821 cpl_parameterlist_delete(pmode);
822
823 cpl_free(context);
824
825 if (cpl_error_get_code()) {
826 cpl_parameterlist_delete(parlist);
827 return NULL;
828 }
829
830 return parlist;
831}
832
833/* ---------------------------------------------------------------------------*/
844/* ---------------------------------------------------------------------------*/
846 const cpl_parameterlist * parlist,
847 const char * prefix)
848{
849 cpl_ensure(prefix && parlist, CPL_ERROR_NULL_INPUT, NULL);
850 hdrl_parameter * p = NULL;
851
852 /* Get the Method parameter */
853 char * name = hdrl_join_string(".", 2, prefix, "method");
854 const cpl_parameter * par = cpl_parameterlist_find_const(parlist, name);
855 const char * value = cpl_parameter_get_string(par);
856 if (value == NULL) {
857 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
858 "Parameter %s not found", name);
859 cpl_free(name);
860 return NULL;
861 }
862
863 /* Switch on the methods */
864 if(!strcmp(value, "MEDIAN")) {
866 } else if (!strcmp(value, "WEIGHTED_MEAN")) {
868 } else if (!strcmp(value, "MEAN")) {
870 } else if (!strcmp(value, "SIGCLIP")) {
871 double kappa_low, kappa_high;
872 int niter;
873 hdrl_sigclip_parameter_parse_parlist(parlist, prefix, &kappa_low,
874 &kappa_high, &niter);
875 p = hdrl_collapse_sigclip_parameter_create(kappa_low,kappa_high,niter);
876 } else if (!strcmp(value, "MINMAX")) {
877 double nlow, nhigh;
878 hdrl_minmax_parameter_parse_parlist(parlist, prefix, &nlow,
879 &nhigh);
881
882 } else if (!strcmp(value, "MODE")) {
883 double histo_min, histo_max, bin_size;
884 cpl_size error_niter;
885 hdrl_mode_type method;
886 hdrl_mode_parameter_parse_parlist(parlist, prefix, &histo_min,
887 &histo_max,
888 &bin_size,
889 &method,
890 &error_niter);
891 p = hdrl_collapse_mode_parameter_create(histo_min, histo_max, bin_size,
892 method, error_niter);
893 } else {
894 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
895 "%s not a valid method for %s", value, name);
896 cpl_free(name);
897 return NULL;
898 }
899 cpl_free(name);
900 return p;
901}
902
905/* ---------------------------------------------------------------------------*/
918/* ---------------------------------------------------------------------------*/
919static cpl_imagelist *
920wrap_synced_errlist(const cpl_imagelist * data, const cpl_imagelist * errors)
921{
922 cpl_imagelist * nerrors = cpl_imagelist_new();
923 for (size_t i = 0; i < (size_t)cpl_imagelist_get_size(errors); i++) {
924 const cpl_image * img = cpl_imagelist_get_const(data, i);
925 const cpl_image * err = cpl_imagelist_get_const(errors, i);
926
927 CPL_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
928
929 cpl_image * nerr = cpl_image_wrap(cpl_image_get_size_x(err),
930 cpl_image_get_size_y(err),
931 cpl_image_get_type(err),
932 (void*)cpl_image_get_data_const(err));
933 cpl_mask_delete(hcpl_image_set_bpm(nerr,
934 (cpl_mask*)cpl_image_get_bpm_const(img)));
935
936 CPL_DIAG_PRAGMA_POP;
937
938 cpl_imagelist_set(nerrors, nerr, i);
939 }
940 return nerrors;
941}
942
943/* ---------------------------------------------------------------------------*/
949/* ---------------------------------------------------------------------------*/
950static void
951unwrap_synced_errlist(cpl_imagelist * nerrors)
952{
953 for (size_t i = 0; i < (size_t)cpl_imagelist_get_size(nerrors); i++) {
954
955 CPL_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
956
957 cpl_image * err = (cpl_image*)cpl_imagelist_get_const(nerrors, i);
958
959 CPL_DIAG_PRAGMA_POP;
960
961 cpl_image_unset_bpm(err);
962 cpl_image_unwrap(err);
963 }
964 cpl_imagelist_unwrap(nerrors);
965}
966
967/* ---------------------------------------------------------------------------*/
979/* ---------------------------------------------------------------------------*/
980static cpl_image * imagelist_sqsum(
981 const cpl_imagelist * data,
982 cpl_image ** pcontrib)
983{
984 cpl_image * contrib = cpl_image_new_from_accepted(data);
985 cpl_image * res = NULL;
986
987 for (cpl_size i = 0; i < cpl_imagelist_get_size(data); i++) {
988 const cpl_image * img = cpl_imagelist_get_const(data, i);
989 cpl_image * sqerr = cpl_image_multiply_create(img, img);
990 if (cpl_image_get_bpm_const(sqerr)) {
991 cpl_image_fill_rejected(sqerr, 0.0);
992 cpl_image_accept_all(sqerr);
993 }
994
995 if (i == 0) {
996 res = sqerr;
997 } else {
998 cpl_image_add(res, sqerr);
999 cpl_image_delete(sqerr);
1000 }
1001 }
1002 cpl_mask * allbad = cpl_mask_threshold_image_create(contrib, 0, 0);
1003 cpl_image_reject_from_mask(res, allbad);
1004 cpl_mask_delete(allbad);
1005
1006 if (pcontrib)
1007 *pcontrib = contrib;
1008 else
1009 cpl_image_delete(contrib);
1010
1011 return res;
1012}
1013
1014/* ---------------------------------------------------------------------------*/
1041/* ---------------------------------------------------------------------------*/
1042static cpl_error_code
1043hdrl_collapse_mean(const cpl_imagelist * data,
1044 const cpl_imagelist * errors,
1045 cpl_image ** out, cpl_image ** err,
1046 cpl_image ** contrib,
1047 void * HDRL_UNUSED(parameters),
1048 void * HDRL_UNUSED(extra_out))
1049{
1050 /* (\Sum_i^n x_i) / n */
1051 /* \sqrt(\Sum_i^n x_i^2) / n */
1052 cpl_errorstate prestate = cpl_errorstate_get();
1053 *out = cpl_imagelist_collapse_create(data);
1054 /* ignore division by 0 on all pixels zero error */
1055 if (*out == NULL) {
1056 cpl_errorstate_set(prestate);
1057 *out = cpl_image_duplicate(cpl_imagelist_get_const(data, 0));
1058 cpl_image_accept_all(*out);
1059 cpl_mask_not(cpl_image_get_bpm(*out));
1060 *err = cpl_image_duplicate(cpl_imagelist_get_const(errors, 0));
1061 cpl_image_accept_all(*err);
1062 cpl_mask_not(cpl_image_get_bpm(*err));
1063 *contrib = cpl_image_new(cpl_image_get_size_x(*err),
1064 cpl_image_get_size_y(*err), CPL_TYPE_INT);
1065 cpl_image_fill_rejected(*out, NAN);
1066 cpl_image_fill_rejected(*err, NAN);
1067 }
1068 else {
1069 *err = imagelist_sqsum(errors, contrib);
1070 cpl_image_power(*err, 0.5);
1071 cpl_image_divide(*err, *contrib);
1072 cpl_image_fill_rejected(*out, NAN);
1073 cpl_image_fill_rejected(*err, NAN);
1074 }
1075
1076 return cpl_error_get_code();
1077}
1078
1079/* ---------------------------------------------------------------------------*/
1105/* ---------------------------------------------------------------------------*/
1106static cpl_error_code
1107hdrl_collapse_weighted_mean(const cpl_imagelist * data_,
1108 const cpl_imagelist * errors_,
1109 cpl_image ** out, cpl_image ** err,
1110 cpl_image ** contrib,
1111 void * HDRL_UNUSED(parameters),
1112 void * HDRL_UNUSED(extra_out))
1113{
1114 /* (\Sum_i^n w_i * x_i) / (\Sum_i^n w_i) */
1115 /* 1 / \sqrt(\Sum_i^n w_i^2) */
1116 cpl_errorstate prestate = cpl_errorstate_get();
1117 cpl_imagelist * data = cpl_imagelist_duplicate(data_);
1118 cpl_imagelist * errors = cpl_imagelist_new();
1119 cpl_image * tmperr;
1120 cpl_imagelist_cast(errors, errors_,
1121 cpl_image_get_type(cpl_imagelist_get(data, 0)));
1122 cpl_imagelist_power(errors, -2);
1123 cpl_imagelist_multiply(data, errors);
1124 *contrib = cpl_image_new_from_accepted(data);
1125 *out = cpl_imagelist_collapse_create(data);
1126 if (*out == NULL) {
1127 cpl_errorstate_set(prestate);
1128 *out = cpl_image_duplicate(cpl_imagelist_get_const(data, 0));
1129 cpl_image_accept_all(*out);
1130 cpl_mask_not(cpl_image_get_bpm(*out));
1131 *err = cpl_image_duplicate(cpl_imagelist_get_const(errors, 0));
1132 cpl_image_accept_all(*err);
1133 cpl_mask_not(cpl_image_get_bpm(*err));
1134 cpl_image_fill_rejected(*out, NAN);
1135 cpl_image_fill_rejected(*err, NAN);
1136 cpl_imagelist_delete(errors);
1137 cpl_imagelist_delete(data);
1138 return cpl_error_get_code();
1139 }
1140 cpl_imagelist_delete(data);
1141 tmperr = cpl_imagelist_collapse_create(errors);
1142 cpl_imagelist_delete(errors);
1143 cpl_image_multiply(*out, *contrib);
1144 cpl_image_multiply(tmperr, *contrib);
1145 cpl_image_divide(*out, tmperr);
1146 cpl_image_power(tmperr, -0.5);
1147 if (cpl_image_get_type(cpl_imagelist_get_const(errors_, 0)) ==
1148 cpl_image_get_type(cpl_imagelist_get_const(data_, 0))) {
1149 *err = tmperr;
1150 }
1151 else {
1152 *err = cpl_image_cast(tmperr,
1153 cpl_image_get_type(cpl_imagelist_get_const(errors_, 0)));
1154 cpl_image_delete(tmperr);
1155 }
1156
1157 cpl_image_fill_rejected(*out, NAN);
1158 cpl_image_fill_rejected(*err, NAN);
1159
1160 return cpl_error_get_code();
1161}
1162
1163/* ---------------------------------------------------------------------------*/
1181/* ---------------------------------------------------------------------------*/
1182static cpl_error_code
1183hdrl_collapse_median(const cpl_imagelist * data,
1184 const cpl_imagelist * errors,
1185 cpl_image ** out, cpl_image ** err,
1186 cpl_image ** contrib,
1187 void * HDRL_UNUSED(parameters),
1188 void * HDRL_UNUSED(extra_out))
1189{
1190 cpl_errorstate prestate = cpl_errorstate_get();
1191 /* same as mean with scaling by \sqrt(\pi / 2) */
1192 *out = cpl_imagelist_collapse_median_create(data);
1193 *err = imagelist_sqsum(errors, contrib);
1194 cpl_image_power(*err, 0.5);
1195 cpl_image_divide(*err, *contrib);
1196 if (cpl_error_get_code() == CPL_ERROR_DIVISION_BY_ZERO) {
1197 cpl_errorstate_set(prestate);
1198 cpl_image_accept_all(*out);
1199 cpl_mask_not(cpl_image_get_bpm(*out));
1200 cpl_image_accept_all(*err);
1201 cpl_mask_not(cpl_image_get_bpm(*err));
1202 cpl_image_fill_rejected(*out, NAN);
1203 cpl_image_fill_rejected(*err, NAN);
1204 return cpl_error_get_code();
1205 }
1206 /* scale error so it estimates stdev of normal distribution */
1207 cpl_image_multiply_scalar(*err, sqrt(CPL_MATH_PI_2));
1208 /* revert scaling for contrib <= 2 as median == mean in this case */
1209 cpl_image * tmp = cpl_image_cast(*contrib, CPL_TYPE_DOUBLE);
1210 cpl_image_threshold(tmp, 2.1, 2.1, 1. / sqrt(CPL_MATH_PI_2), 1.);
1211 cpl_image_multiply(*err, tmp);
1212 cpl_image_delete(tmp);
1213 cpl_image_fill_rejected(*out, NAN);
1214 cpl_image_fill_rejected(*err, NAN);
1215
1216 return cpl_error_get_code();
1217}
1218
1219/* ---------------------------------------------------------------------------*/
1237/* ---------------------------------------------------------------------------*/
1238static cpl_error_code
1239hdrl_collapse_sigclip(const cpl_imagelist * data,
1240 const cpl_imagelist * errors,
1241 cpl_image ** out, cpl_image ** err,
1242 cpl_image ** contrib,
1243 void * parameters, void * extra_out)
1244{
1245 /* same as mean but working on the not-clipped values only */
1246 hdrl_collapse_sigclip_parameter * par = parameters;
1247 hdrl_sigclip_image_output * eout =
1248 (hdrl_sigclip_image_output *)extra_out;
1249 cpl_ensure_code(par, CPL_ERROR_NULL_INPUT);
1250 const cpl_image * img = cpl_imagelist_get_const(data, 0);
1251 size_t nx = cpl_image_get_size_x(img);
1252 size_t ny = cpl_image_get_size_y(img);
1253 *out = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
1254 *err = cpl_image_new(nx, ny, HDRL_TYPE_ERROR);
1255 *contrib = cpl_image_new(nx, ny, CPL_TYPE_INT);
1256 hdrl_vector_cache * cache =
1257 hdrl_vector_cache_new(cpl_imagelist_get_size(data), nx * 2);
1258
1259 /* sigmaclip along imagelist axis */
1260 for (size_t y = 1; y < ny + 1; y++) {
1261 cpl_vector * vdv[nx];
1262 cpl_vector * vev[nx];
1263 hdrl_imagelist_to_vector_row(data, y, vdv, cache);
1264 hdrl_imagelist_to_vector_row(errors, y, vev, cache);
1265 for (size_t x = 1; x < nx + 1; x++) {
1266 cpl_vector * vd = vdv[x - 1];
1267 cpl_vector * ve = vev[x - 1];
1268 if (vd && ve) {
1269 double m, e, rej_low, rej_high;
1270 cpl_size naccepted;
1271 hdrl_kappa_sigma_clip(vd, ve,
1272 par->kappa_low, par->kappa_high,
1273 par->niter, CPL_TRUE,
1274 &m, &e, &naccepted,
1275 &rej_low, &rej_high);
1276 cpl_image_set(*out, x, y, m);
1277 cpl_image_set(*err, x, y, e);
1278 cpl_image_set(*contrib, x, y, naccepted);
1279 if (eout) {
1280 cpl_image_set(eout->reject_low, x, y, rej_low);
1281 cpl_image_set(eout->reject_high, x, y, rej_high);
1282 }
1283 }
1284 else {
1285 cpl_image_set(*out, x, y, NAN);
1286 cpl_image_set(*err, x, y, NAN);
1287 cpl_image_reject(*out, x, y);
1288 cpl_image_reject(*err, x, y);
1289 cpl_image_set(*contrib, x, y, 0);
1290 if (eout) {
1291 cpl_image_set(eout->reject_low, x, y, 0.);
1292 cpl_image_set(eout->reject_high, x, y, 0.);
1293 }
1294 }
1295 hdrl_cplvector_delete_to_cache(cache, vd);
1296 hdrl_cplvector_delete_to_cache(cache, ve);
1297 }
1298 }
1299 hdrl_vector_cache_delete(cache);
1300
1301 return cpl_error_get_code();
1302}
1303
1304
1305
1306
1307/* ---------------------------------------------------------------------------*/
1325/* ---------------------------------------------------------------------------*/
1326static cpl_error_code
1327hdrl_collapse_minmax(const cpl_imagelist * data,
1328 const cpl_imagelist * errors,
1329 cpl_image ** out, cpl_image ** err,
1330 cpl_image ** contrib,
1331 void * parameters, void * extra_out)
1332{
1333 /* same as mean but working on the not-clipped values only */
1334 hdrl_collapse_minmax_parameter * par = parameters;
1335 cpl_ensure_code(par, CPL_ERROR_NULL_INPUT);
1336 hdrl_minmax_image_output * eout =
1337 (hdrl_minmax_image_output *)extra_out;
1338 const cpl_image * img = cpl_imagelist_get_const(data, 0);
1339 size_t nx = cpl_image_get_size_x(img);
1340 size_t ny = cpl_image_get_size_y(img);
1341 *out = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
1342 *err = cpl_image_new(nx, ny, HDRL_TYPE_ERROR);
1343 *contrib = cpl_image_new(nx, ny, CPL_TYPE_INT);
1344 hdrl_vector_cache * cache =
1345 hdrl_vector_cache_new(cpl_imagelist_get_size(data), nx * 2);
1346
1347 /* minmaxclip along imagelist axis */
1348 for (size_t y = 1; y < ny + 1; y++) {
1349 cpl_vector * vdv[nx];
1350 cpl_vector * vev[nx];
1351 hdrl_imagelist_to_vector_row(data, y, vdv, cache);
1352 hdrl_imagelist_to_vector_row(errors, y, vev, cache);
1353 for (size_t x = 1; x < nx + 1; x++) {
1354 cpl_vector * vd = vdv[x - 1];
1355 cpl_vector * ve = vev[x - 1];
1356 if (vd && ve) {
1357 double m, e, rej_low, rej_high;
1358 cpl_size naccepted;
1359 hdrl_minmax_clip(vd, ve,
1360 par->nlow, par->nhigh, CPL_TRUE,
1361 &m, &e, &naccepted,
1362 &rej_low, &rej_high);
1363 cpl_image_set(*out, x, y, m);
1364 cpl_image_set(*err, x, y, e);
1365 cpl_image_set(*contrib, x, y, naccepted);
1366 if (eout) {
1367 cpl_image_set(eout->reject_low, x, y, rej_low);
1368 cpl_image_set(eout->reject_high, x, y, rej_high);
1369 }
1370 }
1371 else {
1372 cpl_image_set(*out, x, y, NAN);
1373 cpl_image_set(*err, x, y, NAN);
1374 cpl_image_reject(*out, x, y);
1375 cpl_image_reject(*err, x, y);
1376 cpl_image_set(*contrib, x, y, 0);
1377 if (eout) {
1378 cpl_image_set(eout->reject_low, x, y, 0.);
1379 cpl_image_set(eout->reject_high, x, y, 0.);
1380 }
1381 }
1382 hdrl_cplvector_delete_to_cache(cache, vd);
1383 hdrl_cplvector_delete_to_cache(cache, ve);
1384 }
1385 }
1386 hdrl_vector_cache_delete(cache);
1387
1388 return cpl_error_get_code();
1389}
1390
1391
1392
1393/* ---------------------------------------------------------------------------*/
1410/* ---------------------------------------------------------------------------*/
1411static cpl_error_code
1412hdrl_collapse_mode(const cpl_imagelist * data,
1413 const cpl_imagelist * errors,
1414 cpl_image ** out,
1415 cpl_image ** err,
1416 cpl_image ** contrib,
1417 void * parameters,
1418 void * HDRL_UNUSED(extra_out))
1419{
1420
1421 hdrl_collapse_mode_parameter * par = parameters;
1422 cpl_ensure_code(par, CPL_ERROR_NULL_INPUT);
1423 const cpl_image * img = cpl_imagelist_get_const(data, 0);
1424 size_t nx = cpl_image_get_size_x(img);
1425 size_t ny = cpl_image_get_size_y(img);
1426 *out = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
1427 *err = cpl_image_new(nx, ny, HDRL_TYPE_ERROR);
1428 *contrib = cpl_image_new(nx, ny, CPL_TYPE_INT);
1429 hdrl_vector_cache * cache =
1430 hdrl_vector_cache_new(cpl_imagelist_get_size(data), nx * 2);
1431
1432 /* mode along imagelist axis */
1433 for (size_t y = 1; y < ny + 1; y++) {
1434 cpl_vector * vdv[nx];
1435 cpl_vector * vev[nx];
1436 hdrl_imagelist_to_vector_row(data, y, vdv, cache);
1437 hdrl_imagelist_to_vector_row(errors, y, vev, cache);
1438 for (size_t x = 1; x < nx + 1; x++) {
1439 cpl_vector * vd = vdv[x - 1];
1440 cpl_vector * ve = vev[x - 1];
1441 cpl_errorstate prestate = cpl_errorstate_get();
1442 if (vd && ve) {
1443 double m, e;
1444 cpl_size naccepted;
1445 cpl_errorstate prestate1 = cpl_errorstate_get();
1446 if (hdrl_mode_clip(vd,
1447 par->histo_min,
1448 par->histo_max,
1449 par->bin_size,
1450 par->method,
1451 par->error_niter,
1452 &m, &e, &naccepted) == CPL_ERROR_NONE) {
1453 cpl_image_set(*out, x, y, m);
1454 cpl_image_set(*err, x, y, e);
1455 cpl_image_set(*contrib, x, y, naccepted);
1456 } else {
1457 cpl_image_set(*out, x, y, NAN);
1458 cpl_image_set(*err, x, y, NAN);
1459 cpl_image_reject(*out, x, y);
1460 cpl_image_reject(*err, x, y);
1461 cpl_image_set(*contrib, x, y, 0);
1462 cpl_errorstate_set(prestate1);
1463 }
1464 }
1465 else {
1466 cpl_image_set(*out, x, y, NAN);
1467 cpl_image_set(*err, x, y, NAN);
1468 cpl_image_reject(*out, x, y);
1469 cpl_image_reject(*err, x, y);
1470 cpl_image_set(*contrib, x, y, 0);
1471 cpl_errorstate_set(prestate);
1472 }
1473 hdrl_cplvector_delete_to_cache(cache, vd);
1474 hdrl_cplvector_delete_to_cache(cache, ve);
1475 }
1476 }
1477 hdrl_vector_cache_delete(cache);
1478
1479 return cpl_error_get_code();}
1480
1481
1482static void *
1483hdrl_nop_create_eout_vec(cpl_size HDRL_UNUSED(size))
1484{
1485 return NULL;
1486}
1487
1488static void *
1489hdrl_nop_create_eout_img(const cpl_image * HDRL_UNUSED(img))
1490{
1491 return NULL;
1492}
1493
1494static cpl_error_code
1495hdrl_nop_move_eout(void * HDRL_UNUSED(dst_),
1496 void * HDRL_UNUSED(src_), const cpl_size HDRL_UNUSED(y))
1497{
1498 return CPL_ERROR_NONE;
1499}
1500
1501static void
1502hdrl_nop_unwrap_eout(void * HDRL_UNUSED(dst))
1503{
1504 return;
1505}
1506
1507/* ---------------------------------------------------------------------------*/
1512/* ---------------------------------------------------------------------------*/
1513hdrl_collapse_imagelist_to_image_t *
1514 hdrl_collapse_imagelist_to_image_mean(void)
1515{
1516 hdrl_collapse_imagelist_to_image_t * s = cpl_calloc(1, sizeof(*s));
1517 s->func = &hdrl_collapse_mean;
1518 s->create_eout = &hdrl_nop_create_eout_img;
1519 s->move_eout = &hdrl_nop_move_eout;
1520 s->unwrap_eout = &hdrl_nop_unwrap_eout;
1521 s->delete_eout = &hdrl_nop_unwrap_eout;
1522 return s;
1523}
1524
1525/* ---------------------------------------------------------------------------*/
1530/* ---------------------------------------------------------------------------*/
1531hdrl_collapse_imagelist_to_image_t *
1532 hdrl_collapse_imagelist_to_image_weighted_mean(void)
1533{
1534 hdrl_collapse_imagelist_to_image_t * s = cpl_calloc(1, sizeof(*s));
1535 s->func = &hdrl_collapse_weighted_mean;
1536 s->create_eout = &hdrl_nop_create_eout_img;
1537 s->move_eout = &hdrl_nop_move_eout;
1538 s->unwrap_eout = &hdrl_nop_unwrap_eout;
1539 s->delete_eout = &hdrl_nop_unwrap_eout;
1540 return s;
1541}
1542
1543/* ---------------------------------------------------------------------------*/
1548/* ---------------------------------------------------------------------------*/
1549hdrl_collapse_imagelist_to_image_t *
1550 hdrl_collapse_imagelist_to_image_median(void)
1551{
1552 hdrl_collapse_imagelist_to_image_t * s = cpl_calloc(1, sizeof(*s));
1553 s->func = &hdrl_collapse_median;
1554 s->create_eout = &hdrl_nop_create_eout_img;
1555 s->move_eout = &hdrl_nop_move_eout;
1556 s->unwrap_eout = &hdrl_nop_unwrap_eout;
1557 s->delete_eout = &hdrl_nop_unwrap_eout;
1558 return s;
1559}
1560
1561static void *
1562hdrl_sigclip_create_eout_img(const cpl_image * img)
1563{
1564 cpl_ensure(img, CPL_ERROR_NULL_INPUT, NULL);
1565 hdrl_sigclip_image_output * eout = cpl_calloc(sizeof(*eout), 1);
1566 eout->reject_low = cpl_image_new(cpl_image_get_size_x(img),
1567 cpl_image_get_size_y(img),
1568 cpl_image_get_type(img));
1569 eout->reject_high = cpl_image_new(cpl_image_get_size_x(img),
1570 cpl_image_get_size_y(img),
1571 cpl_image_get_type(img));
1572 /* add masks for thread safety on move */
1573 cpl_image_get_bpm(eout->reject_low);
1574 cpl_image_get_bpm(eout->reject_high);
1575 return eout;
1576}
1577
1578static void
1579hdrl_sigclip_delete_eout_img(void * eout_)
1580{
1581 if (eout_ == NULL) {
1582 return;
1583 }
1584 hdrl_sigclip_image_output * eout = (hdrl_sigclip_image_output*)eout_;
1585 cpl_image_delete(eout->reject_low);
1586 cpl_image_delete(eout->reject_high);
1587 cpl_free(eout);
1588}
1589
1590static cpl_error_code
1591hdrl_sigclip_move_eout_img(void * dst_, void * src_, const cpl_size y)
1592{
1593 hdrl_sigclip_image_output * dst = dst_;
1594 hdrl_sigclip_image_output * src = src_;
1595 cpl_ensure_code(dst, CPL_ERROR_NULL_INPUT);
1596 cpl_ensure_code(src, CPL_ERROR_NULL_INPUT);
1597 cpl_ensure_code(y > 0, CPL_ERROR_ACCESS_OUT_OF_RANGE);
1598 cpl_ensure_code(y <= cpl_image_get_size_y(dst->reject_low),
1599 CPL_ERROR_ACCESS_OUT_OF_RANGE);
1600
1601 cpl_image_copy(dst->reject_low, src->reject_low, 1, y);
1602 cpl_image_copy(dst->reject_high, src->reject_high, 1, y);
1603 cpl_image_delete(src->reject_low);
1604 cpl_image_delete(src->reject_high);
1605 cpl_free(src);
1606 return cpl_error_get_code();
1607}
1608
1609
1610/* ---------------------------------------------------------------------------*/
1623/* ---------------------------------------------------------------------------*/
1624hdrl_collapse_imagelist_to_image_t *
1625hdrl_collapse_imagelist_to_image_sigclip(double kappa_low,
1626 double kappa_high,
1627 int niter)
1628{
1629 hdrl_collapse_imagelist_to_image_t * s = cpl_calloc(1, sizeof(*s));
1630 hdrl_parameter * sp =
1631 hdrl_collapse_sigclip_parameter_create(kappa_low, kappa_high, niter);
1632 s->func = &hdrl_collapse_sigclip;
1633 s->create_eout = &hdrl_sigclip_create_eout_img;
1634 s->move_eout = &hdrl_sigclip_move_eout_img;
1635 s->unwrap_eout = &cpl_free;
1636 s->delete_eout = &hdrl_sigclip_delete_eout_img;
1637 s->parameters = sp;
1638 return s;
1639}
1640
1641/* ---------------------------------------------------------------------------*/
1653/* ---------------------------------------------------------------------------*/
1654hdrl_collapse_imagelist_to_image_t *
1655hdrl_collapse_imagelist_to_image_minmax(double nlow,
1656 double nhigh)
1657{
1658 hdrl_collapse_imagelist_to_image_t * s = cpl_calloc(1, sizeof(*s));
1659 hdrl_parameter * sp =
1661 s->func = &hdrl_collapse_minmax;
1662 s->create_eout = &hdrl_sigclip_create_eout_img;
1663 s->move_eout = &hdrl_sigclip_move_eout_img;
1664 s->unwrap_eout = &cpl_free;
1665 s->delete_eout = &hdrl_sigclip_delete_eout_img;
1666 s->parameters = sp;
1667 return s;
1668}
1669/* ---------------------------------------------------------------------------*/
1684/* ---------------------------------------------------------------------------*/
1685hdrl_collapse_imagelist_to_image_t *
1686hdrl_collapse_imagelist_to_image_mode( double histo_min,
1687 double histo_max,
1688 double bin_size,
1689 hdrl_mode_type method,
1690 cpl_size error_niter)
1691{
1692 hdrl_collapse_imagelist_to_image_t * s = cpl_calloc(1, sizeof(*s));
1693 hdrl_parameter * sp =
1694 hdrl_collapse_mode_parameter_create(histo_min, histo_max, bin_size,
1695 method, error_niter);
1696 s->func = &hdrl_collapse_mode;
1697 s->create_eout = &hdrl_nop_create_eout_img;
1698 s->move_eout = &hdrl_nop_move_eout;
1699 s->unwrap_eout = &hdrl_nop_unwrap_eout;
1700 s->delete_eout = &hdrl_nop_unwrap_eout;
1701 s->parameters = sp;
1702 return s;
1703}
1704
1705/* ---------------------------------------------------------------------------*/
1719/* ---------------------------------------------------------------------------*/
1720cpl_error_code
1721hdrl_collapse_imagelist_to_image_call(hdrl_collapse_imagelist_to_image_t * f,
1722 const cpl_imagelist * data,
1723 const cpl_imagelist * errors,
1724 cpl_image ** out,
1725 cpl_image ** err,
1726 cpl_image ** contrib,
1727 void ** eout)
1728{
1729 cpl_ensure_code(f, CPL_ERROR_NULL_INPUT);
1730 cpl_ensure_code(data, CPL_ERROR_NULL_INPUT);
1731 cpl_ensure_code(errors, CPL_ERROR_NULL_INPUT);
1732 cpl_ensure_code(out, CPL_ERROR_NULL_INPUT);
1733 cpl_ensure_code(err, CPL_ERROR_NULL_INPUT);
1734 cpl_ensure_code(contrib, CPL_ERROR_NULL_INPUT);
1735 cpl_ensure_code(cpl_imagelist_get_size(data) ==
1736 cpl_imagelist_get_size(errors),
1737 CPL_ERROR_INCOMPATIBLE_INPUT);
1738 if (eout) {
1739 *eout = f->create_eout(cpl_imagelist_get_const(data, 0));
1740 }
1741
1742 cpl_imagelist * nerrors = wrap_synced_errlist(data, errors);
1743 if (nerrors == NULL) {
1744 return cpl_error_get_code();
1745 }
1746
1747 cpl_error_code errcode = f->func(data, nerrors, out, err, contrib,
1748 f->parameters, eout ? *eout : NULL);
1749
1750 unwrap_synced_errlist(nerrors);
1751
1752 return errcode;
1753}
1754
1755/* ---------------------------------------------------------------------------*/
1766/* ---------------------------------------------------------------------------*/
1767void *
1768hdrl_collapse_imagelist_to_image_create_eout(
1769 hdrl_collapse_imagelist_to_image_t * f,
1770 const cpl_image * data)
1771{
1772 cpl_ensure(f, CPL_ERROR_NULL_INPUT, NULL);
1773 cpl_ensure(data, CPL_ERROR_NULL_INPUT, NULL);
1774
1775 return f->create_eout(data);
1776}
1777
1778/* ---------------------------------------------------------------------------*/
1787/* ---------------------------------------------------------------------------*/
1788void
1789hdrl_collapse_imagelist_to_image_unwrap_eout(
1790 hdrl_collapse_imagelist_to_image_t * f,
1791 void * eout)
1792{
1793 if (f != NULL) {
1794 f->unwrap_eout(eout);
1795 }
1796}
1797
1798/* ---------------------------------------------------------------------------*/
1807/* ---------------------------------------------------------------------------*/
1808void
1809hdrl_collapse_imagelist_to_image_delete_eout(
1810 hdrl_collapse_imagelist_to_image_t * f,
1811 void * eout)
1812{
1813 if (f != NULL) {
1814 f->delete_eout(eout);
1815 }
1816}
1817
1818/* ---------------------------------------------------------------------------*/
1831/* ---------------------------------------------------------------------------*/
1832cpl_error_code
1833hdrl_collapse_imagelist_to_image_move_eout(
1834 hdrl_collapse_imagelist_to_image_t * f,
1835 void * dst,
1836 void * src,
1837 cpl_size y)
1838{
1839 cpl_ensure_code(f, CPL_ERROR_NULL_INPUT);
1840
1841 return f->move_eout(dst, src, y);
1842}
1843
1844/* ---------------------------------------------------------------------------*/
1850/* ---------------------------------------------------------------------------*/
1851void hdrl_collapse_imagelist_to_image_delete(hdrl_collapse_imagelist_to_image_t * p)
1852{
1853 if (p) {
1854 hdrl_parameter_delete(p->parameters);
1855 }
1856 cpl_free(p);
1857}
1858
1859/* ---------------------------------------------------------------------------*/
1870/* ---------------------------------------------------------------------------*/
1871void * hdrl_collapse_imagelist_to_vector_create_eout(
1872 hdrl_collapse_imagelist_to_vector_t * f,
1873 const cpl_size size)
1874{
1875 cpl_ensure(f, CPL_ERROR_NULL_INPUT, NULL);
1876 cpl_ensure(size > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1877
1878 return f->create_eout(size);
1879}
1880
1881/* ---------------------------------------------------------------------------*/
1890/* ---------------------------------------------------------------------------*/
1891void
1892hdrl_collapse_imagelist_to_vector_unwrap_eout(
1893 hdrl_collapse_imagelist_to_vector_t * f,
1894 void * eout)
1895{
1896 if (f != NULL) {
1897 f->unwrap_eout(eout);
1898 }
1899}
1900
1901/* ---------------------------------------------------------------------------*/
1910/* ---------------------------------------------------------------------------*/
1911void hdrl_collapse_imagelist_to_vector_delete_eout(
1912 hdrl_collapse_imagelist_to_vector_t * f,
1913 void * eout)
1914{
1915 if (f != NULL) {
1916 f->delete_eout(eout);
1917 }
1918}
1919
1920/* ---------------------------------------------------------------------------*/
1933/* ---------------------------------------------------------------------------*/
1934cpl_error_code hdrl_collapse_imagelist_to_vector_move_eout(
1935 hdrl_collapse_imagelist_to_vector_t * f,
1936 void * dst,
1937 void * src,
1938 cpl_size y)
1939{
1940 cpl_ensure_code(f, CPL_ERROR_NULL_INPUT);
1941
1942 return f->move_eout(dst, src, y);
1943}
1944
1945/* ---------------------------------------------------------------------------*/
1967/* ---------------------------------------------------------------------------*/
1968static cpl_error_code
1969reduce_imagelist_to_vector_mean(const cpl_imagelist * data,
1970 const cpl_imagelist * errors,
1971 cpl_vector ** out, cpl_vector ** err,
1972 cpl_array ** contrib,
1973 void * HDRL_UNUSED(parameters),
1974 void * HDRL_UNUSED(extra_out))
1975{
1976 size_t nz = cpl_imagelist_get_size(data);
1977 *out = cpl_vector_new(nz);
1978 *err = cpl_vector_new(nz);
1979 *contrib = cpl_array_new(nz, CPL_TYPE_INT);
1980
1981 for (size_t i = 0; i < nz; i++) {
1982 const cpl_image * img = cpl_imagelist_get_const(data, i);
1983 const cpl_image * ierr = cpl_imagelist_get_const(errors, i);
1984 size_t naccepted = hdrl_get_image_good_npix(img);
1985
1986 if (naccepted != 0) {
1987 double error = sqrt(cpl_image_get_sqflux(ierr)) / naccepted;
1988
1989 cpl_vector_set(*out, i, cpl_image_get_mean(img));
1990 cpl_vector_set(*err, i, error);
1991 }
1992 else {
1993 cpl_vector_set(*out, i, NAN);
1994 cpl_vector_set(*err, i, NAN);
1995 }
1996 cpl_array_set_int(*contrib, i, naccepted);
1997 }
1998
1999 return cpl_error_get_code();
2000}
2001
2002/* ---------------------------------------------------------------------------*/
2007/* ---------------------------------------------------------------------------*/
2008hdrl_collapse_imagelist_to_vector_t *
2009 hdrl_collapse_imagelist_to_vector_mean(void)
2010{
2011 hdrl_collapse_imagelist_to_vector_t * s = cpl_calloc(1, sizeof(*s));
2012 s->create_eout = &hdrl_nop_create_eout_vec;
2013 s->move_eout = &hdrl_nop_move_eout;
2014 s->unwrap_eout = &hdrl_nop_unwrap_eout;
2015 s->delete_eout = &hdrl_nop_unwrap_eout;
2016 s->func = &reduce_imagelist_to_vector_mean;
2017 return s;
2018}
2019
2020/* ---------------------------------------------------------------------------*/
2046/* ---------------------------------------------------------------------------*/
2047static cpl_error_code
2048reduce_imagelist_to_vector_weighted_mean(const cpl_imagelist * data,
2049 const cpl_imagelist * errors,
2050 cpl_vector ** out, cpl_vector ** err,
2051 cpl_array ** contrib,
2052 void * HDRL_UNUSED(parameters),
2053 void * HDRL_UNUSED(extra_out))
2054{
2055 size_t nz = cpl_imagelist_get_size(data);
2056 *out = cpl_vector_new(nz);
2057 *err = cpl_vector_new(nz);
2058 *contrib = cpl_array_new(nz, CPL_TYPE_INT);
2059
2060 for (size_t i = 0; i < nz; i++) {
2061 cpl_image * img =
2062 cpl_image_duplicate(cpl_imagelist_get_const(data, i));
2063 cpl_image * ierr =
2064 cpl_image_duplicate(cpl_imagelist_get_const(errors, i));
2065 size_t naccepted = hdrl_get_image_good_npix(img);
2066
2067 if (naccepted != 0) {
2068 /* (\Sum_i^n w_i * x_i) / (\Sum_i^n w_i) */
2069 /* 1 / \sqrt(\Sum_i^n w_i^2) */
2070 cpl_image_power(ierr, -2);
2071 /* ierr = weights now */
2072 cpl_image_multiply(img, ierr);
2073 double sum_v = cpl_image_get_mean(img) * naccepted;
2074 double sum_w = cpl_image_get_mean(ierr) * naccepted;
2075 double wmean = sum_v / sum_w;
2076 double error = 1. / sqrt(sum_w);
2077
2078 cpl_vector_set(*out, i, wmean);
2079 cpl_vector_set(*err, i, error);
2080 }
2081 else {
2082 cpl_vector_set(*out, i, NAN);
2083 cpl_vector_set(*err, i, NAN);
2084 }
2085 cpl_array_set_int(*contrib, i, naccepted);
2086 cpl_image_delete(img);
2087 cpl_image_delete(ierr);
2088 }
2089
2090 return cpl_error_get_code();
2091}
2092
2093/* ---------------------------------------------------------------------------*/
2098/* ---------------------------------------------------------------------------*/
2099hdrl_collapse_imagelist_to_vector_t *
2100 hdrl_collapse_imagelist_to_vector_weighted_mean(void)
2101{
2102 hdrl_collapse_imagelist_to_vector_t * s = cpl_calloc(1, sizeof(*s));
2103 s->create_eout = &hdrl_nop_create_eout_vec;
2104 s->move_eout = &hdrl_nop_move_eout;
2105 s->unwrap_eout = &hdrl_nop_unwrap_eout;
2106 s->delete_eout = &hdrl_nop_unwrap_eout;
2107 s->func = &reduce_imagelist_to_vector_weighted_mean;
2108 return s;
2109}
2110
2111/* ---------------------------------------------------------------------------*/
2134/* ---------------------------------------------------------------------------*/
2135static cpl_error_code
2136reduce_imagelist_to_vector_median(const cpl_imagelist * data,
2137 const cpl_imagelist * errors,
2138 cpl_vector ** out, cpl_vector ** err,
2139 cpl_array ** contrib,
2140 void * HDRL_UNUSED(parameters),
2141 void * HDRL_UNUSED(extra_out))
2142{
2143 size_t nz = cpl_imagelist_get_size(data);
2144 *out = cpl_vector_new(nz);
2145 *err = cpl_vector_new(nz);
2146 *contrib = cpl_array_new(nz, CPL_TYPE_INT);
2147
2148 for (size_t i = 0; i < nz; i++) {
2149 const cpl_image * img = cpl_imagelist_get_const(data, i);
2150 const cpl_image * ierr = cpl_imagelist_get_const(errors, i);
2151 size_t naccepted = hdrl_get_image_good_npix(img);
2152
2153 if (naccepted != 0) {
2154 double error = sqrt(cpl_image_get_sqflux(ierr)) / naccepted;
2155 /* sqrt(statistical efficiency on normal data)*/
2156 if (naccepted > 2) {
2157 error *= sqrt(CPL_MATH_PI_2);
2158 }
2159
2160 cpl_vector_set(*out, i, cpl_image_get_median(img));
2161 cpl_vector_set(*err, i, error);
2162 }
2163 else {
2164 cpl_vector_set(*out, i, NAN);
2165 cpl_vector_set(*err, i, NAN);
2166 }
2167 cpl_array_set_int(*contrib, i, naccepted);
2168 }
2169
2170 return cpl_error_get_code();
2171}
2172
2173/* ---------------------------------------------------------------------------*/
2178/* ---------------------------------------------------------------------------*/
2179hdrl_collapse_imagelist_to_vector_t *
2180 hdrl_collapse_imagelist_to_vector_median(void)
2181{
2182 hdrl_collapse_imagelist_to_vector_t * s = cpl_calloc(1, sizeof(*s));
2183 s->create_eout = &hdrl_nop_create_eout_vec;
2184 s->move_eout = &hdrl_nop_move_eout;
2185 s->unwrap_eout = &hdrl_nop_unwrap_eout;
2186 s->delete_eout = &hdrl_nop_unwrap_eout;
2187 s->func = &reduce_imagelist_to_vector_median;
2188 return s;
2189}
2190
2191static void *
2192hdrl_sigclip_create_eout_vec(cpl_size size)
2193{
2194 hdrl_sigclip_vector_output * eout = cpl_calloc(sizeof(*eout), 1);
2195 eout->reject_low = cpl_vector_new(size);
2196 eout->reject_high = cpl_vector_new(size);
2197 return eout;
2198}
2199
2200static void
2201hdrl_sigclip_delete_eout_vec(void * eout_)
2202{
2203 if (eout_ == NULL) {
2204 return;
2205 }
2206 hdrl_sigclip_vector_output * eout = (hdrl_sigclip_vector_output*)eout_;
2207 cpl_vector_delete(eout->reject_low);
2208 cpl_vector_delete(eout->reject_high);
2209 cpl_free(eout);
2210}
2211
2212static cpl_error_code
2213hdrl_sigclip_move_eout_vec(void * dst_, void * src_, const cpl_size y)
2214{
2215 hdrl_sigclip_vector_output * dst = dst_;
2216 hdrl_sigclip_vector_output * src = src_;
2217 cpl_ensure_code(dst, CPL_ERROR_NULL_INPUT);
2218 cpl_ensure_code(src, CPL_ERROR_NULL_INPUT);
2219 cpl_ensure_code(y >= 0, CPL_ERROR_ACCESS_OUT_OF_RANGE);
2220 cpl_ensure_code(y < cpl_vector_get_size(dst->reject_low),
2221 CPL_ERROR_ACCESS_OUT_OF_RANGE);
2222
2223 double * ddst = cpl_vector_get_data(dst->reject_low);
2224 double * dsrc = cpl_vector_get_data(src->reject_low);
2225 memcpy(ddst + y, dsrc, cpl_vector_get_size(src->reject_low));
2226 ddst = cpl_vector_get_data(dst->reject_high);
2227 dsrc = cpl_vector_get_data(src->reject_high);
2228 memcpy(ddst + y, dsrc, cpl_vector_get_size(src->reject_high));
2229 cpl_vector_delete(src->reject_low);
2230 cpl_vector_delete(src->reject_high);
2231 cpl_free(src);
2232 return cpl_error_get_code();
2233}
2234
2235/* ---------------------------------------------------------------------------*/
2252/* ---------------------------------------------------------------------------*/
2253static cpl_error_code
2254reduce_imagelist_to_vector_sigclip(const cpl_imagelist * data,
2255 const cpl_imagelist * errors,
2256 cpl_vector ** out, cpl_vector ** err,
2257 cpl_array ** contrib, void * parameters,
2258 void * extra_out)
2259{
2260 hdrl_collapse_sigclip_parameter * par = parameters;
2261 hdrl_minmax_vector_output * eout =
2262 (hdrl_minmax_vector_output *)extra_out;
2263
2264 cpl_size nz = cpl_imagelist_get_size(data);
2265 *out = cpl_vector_new(nz);
2266 *err = cpl_vector_new(nz);
2267 *contrib = cpl_array_new(nz, CPL_TYPE_INT);
2268
2269 /* sigmaclip on each image of the imagelist */
2270 for (cpl_size z = 0; z < nz ; z++) {
2271 double corr, error, low, high;
2272 cpl_size contribution;
2273 if (hdrl_kappa_sigma_clip_image(cpl_imagelist_get_const(data, z),
2274 cpl_imagelist_get_const(errors, z),
2275 par->kappa_low,
2276 par->kappa_high,
2277 par->niter,
2278 &corr,
2279 &error,
2280 &contribution,
2281 &low,
2282 &high) != CPL_ERROR_NONE) {
2283 break;
2284 }
2285 cpl_vector_set(*out, z, corr);
2286 cpl_vector_set(*err, z, error);
2287 cpl_array_set_int(*contrib, z, contribution);
2288
2289 if (eout) {
2290 cpl_vector_set(eout->reject_low, z, low);
2291 cpl_vector_set(eout->reject_high, z, high);
2292 }
2293 }
2294
2295 return cpl_error_get_code();
2296}
2297
2298/* ---------------------------------------------------------------------------*/
2312/* ---------------------------------------------------------------------------*/
2313hdrl_collapse_imagelist_to_vector_t *
2314hdrl_collapse_imagelist_to_vector_sigclip(double kappa_low, double kappa_high,
2315 int niter)
2316{
2317 hdrl_collapse_imagelist_to_vector_t * s = cpl_calloc(1, sizeof(*s));
2318 hdrl_parameter * sp =
2319 hdrl_collapse_sigclip_parameter_create(kappa_low, kappa_high, niter);
2320 s->func = &reduce_imagelist_to_vector_sigclip;
2321 s->create_eout = &hdrl_sigclip_create_eout_vec;
2322 s->move_eout = &hdrl_sigclip_move_eout_vec;
2323 s->unwrap_eout = &cpl_free;
2324 s->delete_eout = &hdrl_sigclip_delete_eout_vec;
2325 s->parameters = sp;
2326 return s;
2327}
2328
2329/* ---------------------------------------------------------------------------*/
2345/* ---------------------------------------------------------------------------*/
2346static cpl_error_code
2347reduce_imagelist_to_vector_minmax(const cpl_imagelist * data,
2348 const cpl_imagelist * errors,
2349 cpl_vector ** out, cpl_vector ** err,
2350 cpl_array ** contrib, void * parameters,
2351 void * extra_out)
2352{
2353 hdrl_collapse_minmax_parameter * par = parameters;
2354 hdrl_sigclip_vector_output * eout =
2355 (hdrl_sigclip_vector_output *)extra_out;
2356 cpl_size nz = cpl_imagelist_get_size(data);
2357 *out = cpl_vector_new(nz);
2358 *err = cpl_vector_new(nz);
2359 *contrib = cpl_array_new(nz, CPL_TYPE_INT);
2360
2361 /* minmax on each image of the imagelist */
2362 for (cpl_size z = 0; z < nz ; z++) {
2363 double corr, error, low, high;
2364 cpl_size contribution;
2365 if (hdrl_minmax_clip_image(cpl_imagelist_get_const(data, z),
2366 cpl_imagelist_get_const(errors, z),
2367 par->nlow,
2368 par->nhigh,
2369 &corr,
2370 &error,
2371 &contribution,
2372 &low, &high) != CPL_ERROR_NONE) {
2373 break;
2374 }
2375 cpl_vector_set(*out, z, corr);
2376 cpl_vector_set(*err, z, error);
2377 cpl_array_set_int(*contrib, z, contribution);
2378
2379 if (eout) {
2380 cpl_vector_set(eout->reject_low, z, low);
2381 cpl_vector_set(eout->reject_high, z, high);
2382 }
2383 }
2384
2385 return cpl_error_get_code();
2386}
2387
2388/* ---------------------------------------------------------------------------*/
2399/* ---------------------------------------------------------------------------*/
2400hdrl_collapse_imagelist_to_vector_t *
2401hdrl_collapse_imagelist_to_vector_minmax(double nlow, double nhigh)
2402{
2403 hdrl_collapse_imagelist_to_vector_t * s = cpl_calloc(1, sizeof(*s));
2404 hdrl_parameter * sp =
2406 s->func = &reduce_imagelist_to_vector_minmax;
2407 s->create_eout = &hdrl_sigclip_create_eout_vec;
2408 s->move_eout = &hdrl_sigclip_move_eout_vec;
2409 s->unwrap_eout = &cpl_free;
2410 s->delete_eout = &hdrl_sigclip_delete_eout_vec;
2411 s->parameters = sp;
2412 return s;
2413}
2414
2415/* ---------------------------------------------------------------------------*/
2436/* ---------------------------------------------------------------------------*/
2437static cpl_error_code
2438reduce_imagelist_to_vector_mode(const cpl_imagelist * data,
2439 const cpl_imagelist * HDRL_UNUSED(errors),
2440 cpl_vector ** out, cpl_vector ** err,
2441 cpl_array ** contrib, void * parameters,
2442 void * HDRL_UNUSED(extra_out))
2443{
2444
2445 hdrl_collapse_mode_parameter * par = parameters;
2446 cpl_size nz = cpl_imagelist_get_size(data);
2447 *out = cpl_vector_new(nz);
2448 *err = cpl_vector_new(nz);
2449 *contrib = cpl_array_new(nz, CPL_TYPE_INT);
2450
2451 /* mode on each image of the imagelist */
2452 for (cpl_size z = 0; z < nz ; z++) {
2453 double corr, error;
2454 cpl_size contribution;
2455 if (hdrl_mode_clip_image(cpl_imagelist_get_const(data, z),
2456 par->histo_min,
2457 par->histo_max,
2458 par->bin_size,
2459 par->method,
2460 par->error_niter,
2461 &corr,
2462 &error,
2463 &contribution) != CPL_ERROR_NONE) {
2464 break;
2465 }
2466 cpl_vector_set(*out, z, corr);
2467 cpl_vector_set(*err, z, error);
2468 cpl_array_set_int(*contrib, z, contribution);
2469
2470 }
2471
2472 return cpl_error_get_code();
2473}
2474
2475/* ---------------------------------------------------------------------------*/
2480/* ---------------------------------------------------------------------------*/
2481hdrl_collapse_imagelist_to_vector_t *
2482 hdrl_collapse_imagelist_to_vector_mode(double histo_min, double histo_max,
2483 double bin_size, hdrl_mode_type method,
2484 cpl_size error_niter)
2485{
2486
2487 hdrl_collapse_imagelist_to_vector_t * s = cpl_calloc(1, sizeof(*s));
2488 hdrl_parameter * sp =
2489 hdrl_collapse_mode_parameter_create(histo_min, histo_max, bin_size, method, error_niter);
2490
2491 s->func = &reduce_imagelist_to_vector_mode;
2492 s->create_eout = &hdrl_nop_create_eout_vec;
2493 s->move_eout = &hdrl_nop_move_eout;
2494 s->unwrap_eout = &hdrl_nop_unwrap_eout;
2495 s->delete_eout = &hdrl_nop_unwrap_eout;
2496 s->parameters = sp;
2497 return s;
2498}
2499
2500/* ---------------------------------------------------------------------------*/
2514/* ---------------------------------------------------------------------------*/
2515cpl_error_code
2516hdrl_collapse_imagelist_to_vector_call(hdrl_collapse_imagelist_to_vector_t * f,
2517 const cpl_imagelist * data,
2518 const cpl_imagelist * errors,
2519 cpl_vector ** out,
2520 cpl_vector ** err,
2521 cpl_array ** contrib,
2522 void ** eout)
2523{
2524 cpl_ensure_code(f, CPL_ERROR_NULL_INPUT);
2525 cpl_ensure_code(data, CPL_ERROR_NULL_INPUT);
2526 cpl_ensure_code(errors, CPL_ERROR_NULL_INPUT);
2527 cpl_ensure_code(out, CPL_ERROR_NULL_INPUT);
2528 cpl_ensure_code(err, CPL_ERROR_NULL_INPUT);
2529 cpl_ensure_code(contrib, CPL_ERROR_NULL_INPUT);
2530 if (eout) {
2531 *eout = f->create_eout(cpl_imagelist_get_size(data));
2532 }
2533
2534 cpl_imagelist * nerrors = wrap_synced_errlist(data, errors);
2535 if (nerrors == NULL) {
2536 return cpl_error_get_code();
2537 }
2538
2539 cpl_error_code errcode = f->func(data, errors, out, err, contrib,
2540 f->parameters, eout ? *eout : NULL);
2541
2542 unwrap_synced_errlist(nerrors);
2543
2544 return errcode;
2545}
2546
2547/* ---------------------------------------------------------------------------*/
2553/* ---------------------------------------------------------------------------*/
2554void
2555hdrl_collapse_imagelist_to_vector_delete(hdrl_collapse_imagelist_to_vector_t * p)
2556{
2557 if (p) {
2558 cpl_free(p->parameters);
2559 }
2560 cpl_free(p);
2561}
2562
double hdrl_collapse_mode_parameter_get_bin_size(const hdrl_parameter *p)
get size of the histogram bins
double hdrl_collapse_mode_parameter_get_histo_min(const hdrl_parameter *p)
get min value
cpl_boolean hdrl_collapse_parameter_is_weighted_mean(const hdrl_parameter *self)
check if parameter is a weighted mean parameter
double hdrl_collapse_sigclip_parameter_get_kappa_low(const hdrl_parameter *p)
get low kappa
hdrl_parameter * hdrl_collapse_mean_parameter_create(void)
create a parameter object for mean
hdrl_parameter * hdrl_collapse_sigclip_parameter_create(double kappa_low, double kappa_high, int niter)
create a parameter object for sigclipped mean
hdrl_parameter * hdrl_collapse_weighted_mean_parameter_create(void)
create a parameter object for weighted mean
cpl_boolean hdrl_collapse_parameter_is_mean(const hdrl_parameter *self)
check if parameter is a mean parameter
cpl_boolean hdrl_collapse_parameter_is_median(const hdrl_parameter *self)
check if parameter is a median parameter
double hdrl_collapse_mode_parameter_get_histo_max(const hdrl_parameter *p)
get high value
int hdrl_collapse_sigclip_parameter_get_niter(const hdrl_parameter *p)
get maximum number of clipping iterations
cpl_size hdrl_collapse_mode_parameter_get_error_niter(const hdrl_parameter *p)
get the error type of the mode
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_mode(const hdrl_parameter *self)
check if parameter is a mode 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
hdrl_parameter * hdrl_collapse_median_parameter_create(void)
create a parameter object for median
hdrl_parameter * hdrl_collapse_mode_parameter_create(double histo_min, double histo_max, double bin_size, hdrl_mode_type mode_method, cpl_size error_niter)
create a parameter object for the mode
cpl_parameterlist * hdrl_collapse_parameter_create_parlist(const char *base_context, const char *prefix, const char *method_def, hdrl_parameter *sigclip_def, hdrl_parameter *minmax_def, hdrl_parameter *mode_def)
Create parameters for the collapse.
hdrl_mode_type hdrl_collapse_mode_parameter_get_method(const hdrl_parameter *p)
get the mode determination method
hdrl_parameter * hdrl_collapse_minmax_parameter_create(double nlow, double nhigh)
create a parameter object for min-max rejected mean
hdrl_parameter * hdrl_collapse_parameter_parse_parlist(const cpl_parameterlist *parlist, const char *prefix)
parse parameterlist for imagelist reduction method
double hdrl_collapse_minmax_parameter_get_nhigh(const hdrl_parameter *p)
get high value
void hdrl_parameter_delete(hdrl_parameter *obj)
shallow delete of a parameter
char * hdrl_join_string(const char *sep_, int n,...)
join strings together
Definition: hdrl_utils.c:812