CR2RE Pipeline Reference Manual 1.6.10
hdrl_overscan.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_overscan.h"
29#include "hdrl_overscan_defs.h"
30#include "hdrl_sigclip.h"
31#include "hdrl_utils.h"
32#include "hdrl_collapse.h"
33
34#include <cpl.h>
35#include <math.h>
36#include <string.h>
37
38/*-----------------------------------------------------------------------------
39 Static
40 -----------------------------------------------------------------------------*/
41
42static hdrl_overscan_compute_result * hdrl_overscan_compute_result_create(
43 void);
44static cpl_error_code hdrl_overscan_compute_result_verify(
45 const hdrl_overscan_compute_result *);
46static hdrl_overscan_correct_result * hdrl_overscan_correct_result_create(
47 void);
48static cpl_error_code hdrl_overscan_compute_chi_square(const cpl_image *,
49 const cpl_image *, const double, double *, double *);
50static cpl_error_code hdrl_overscan_reduce_image_to_scalar(
51 hdrl_collapse_imagelist_to_vector_t *, cpl_image *, cpl_image *,
52 double *, double *, cpl_size *, void **) ;
53static void hdrl_overscan_parameter_destroy(void * param);
54
55/*----------------------------------------------------------------------------*/
56/* INCLUDED FROM doc/Func_Overscan.tex */
110/*----------------------------------------------------------------------------*/
111
114/*-----------------------------------------------------------------------------
115 Overscan Parameters Definition
116 -----------------------------------------------------------------------------*/
117typedef struct {
118 HDRL_PARAMETER_HEAD;
119 hdrl_direction correction_direction;
120 double ccd_ron;
121 int box_hsize;
122 hdrl_parameter * collapse;
123 hdrl_parameter * rect_region;
124} hdrl_overscan_parameter;
125
126/* Parameter type */
127static hdrl_parameter_typeobj hdrl_overscan_parameter_type = {
128 HDRL_PARAMETER_OVERSCAN, /* type */
129 (hdrl_alloc *)&cpl_malloc, /* fp_alloc */
130 (hdrl_free *)&cpl_free, /* fp_free */
131 (hdrl_free *)&hdrl_overscan_parameter_destroy, /* fp_destroy */
132 sizeof(hdrl_overscan_parameter), /* obj_size */
133};
134
135/* ---------------------------------------------------------------------------*/
149/* ---------------------------------------------------------------------------*/
151 hdrl_direction correction_direction,
152 double ccd_ron,
153 int box_hsize,
154 hdrl_parameter * collapse,
155 hdrl_parameter * rect_region)
156{
157 hdrl_overscan_parameter * p = (hdrl_overscan_parameter *)
158 hdrl_parameter_new(&hdrl_overscan_parameter_type);
159 p->correction_direction = correction_direction ;
160 p->ccd_ron = ccd_ron ;
161 p->box_hsize = box_hsize ;
162 p->collapse = collapse ;
163 p->rect_region = rect_region ;
164 return (hdrl_parameter *)p;
165}
166
167/*----------------------------------------------------------------------------*/
175/*----------------------------------------------------------------------------*/
177 const hdrl_parameter * param,
178 cpl_size nx,
179 cpl_size ny)
180{
181 const hdrl_overscan_parameter * param_loc =
182 (const hdrl_overscan_parameter *)param ;
183
184 cpl_error_ensure(param != NULL, CPL_ERROR_NULL_INPUT,
185 return CPL_ERROR_NULL_INPUT, "NULL Input Parameters");
186 cpl_error_ensure(hdrl_overscan_parameter_check(param),
187 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
188 "Expected Overscan parameter") ;
189
190 cpl_error_ensure(param_loc->ccd_ron >= 0, CPL_ERROR_ILLEGAL_INPUT,
191 return CPL_ERROR_ILLEGAL_INPUT,
192 "CCD read out noise (%g) must be >= 0", param_loc->ccd_ron);
193 cpl_error_ensure(param_loc->box_hsize >= 0 ||
194 param_loc->box_hsize == HDRL_OVERSCAN_FULL_BOX,
195 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
196 "half box size (%d) must be >= 0 or -1",
197 param_loc->box_hsize);
198 cpl_error_ensure(param_loc->correction_direction == HDRL_X_AXIS ||
199 param_loc->correction_direction == HDRL_Y_AXIS,
200 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
201 "correction_direction must be HDRL_X_AXIS or HDRL_Y_AXIS");
202
203 if (hdrl_collapse_parameter_is_sigclip(param_loc->collapse)) {
204 cpl_error_ensure(
205 hdrl_collapse_sigclip_parameter_verify(param_loc->collapse)
206 == CPL_ERROR_NONE, CPL_ERROR_ILLEGAL_INPUT,
207 return CPL_ERROR_ILLEGAL_INPUT,
208 "Illegal Collapse Sigclip parameters");
209 }
210 if (hdrl_collapse_parameter_is_minmax(param_loc->collapse)) {
211 cpl_error_ensure(
212 hdrl_collapse_minmax_parameter_verify(param_loc->collapse)
213 == CPL_ERROR_NONE, CPL_ERROR_ILLEGAL_INPUT,
214 return CPL_ERROR_ILLEGAL_INPUT,
215 "Illegal Collapse Minmax parameters");
216 }
217 if (hdrl_collapse_parameter_is_mode(param_loc->collapse)) {
218 cpl_error_ensure(
219 hdrl_collapse_mode_parameter_verify(param_loc->collapse)
220 == CPL_ERROR_NONE, CPL_ERROR_ILLEGAL_INPUT,
221 return CPL_ERROR_ILLEGAL_INPUT,
222 "Illegal Collapse Mode parameters");
223 }
224 cpl_error_ensure(
225 hdrl_rect_region_parameter_verify(param_loc->rect_region, -1, -1)
226 == CPL_ERROR_NONE, CPL_ERROR_ILLEGAL_INPUT,
227 return CPL_ERROR_ILLEGAL_INPUT,
228 "Illegal Rect Region parameters");
229
230 cpl_error_ensure(hdrl_collapse_parameter_is_mean(param_loc->collapse) ||
231 hdrl_collapse_parameter_is_weighted_mean(param_loc->collapse) ||
232 hdrl_collapse_parameter_is_median(param_loc->collapse) ||
233 hdrl_collapse_parameter_is_sigclip(param_loc->collapse) ||
234 hdrl_collapse_parameter_is_minmax(param_loc->collapse) ||
235 hdrl_collapse_parameter_is_mode(param_loc->collapse),
236 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
237 "Only supported methods are MEAN, WEIGHTED_MEAN, MEDIAN, SIGCLIP,"
238 " MINMAX and MODE");
239
240 /* The region must be contained in the image */
241 if (nx > 0) {
242 cpl_size region_llx = hdrl_rect_region_get_llx(param_loc->rect_region);
243 cpl_size region_urx = hdrl_rect_region_get_urx(param_loc->rect_region);
244 cpl_error_ensure(
245 region_llx>=1 && region_urx <= nx,
246 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
247 "Region (%d) exceeds source (%d) size in the X dir.",
248 (int)region_urx, (int)nx);
249 }
250 if (ny > 0) {
251 cpl_size region_lly = hdrl_rect_region_get_lly(param_loc->rect_region);
252 cpl_size region_ury = hdrl_rect_region_get_ury(param_loc->rect_region);
253 cpl_error_ensure(
254 region_lly>=1 && region_ury <= ny,
255 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
256 "Region (%d) exceeds source (%d) size in the Y dir.",
257 (int)region_ury, (int)ny);
258 }
259 return CPL_ERROR_NONE;
260}
261
262/*----------------------------------------------------------------------------*/
268/*----------------------------------------------------------------------------*/
269cpl_boolean hdrl_overscan_parameter_check(const hdrl_parameter * self)
270{
271 return hdrl_parameter_check_type(self, &hdrl_overscan_parameter_type);
272}
273
274/*----------------------------------------------------------------------------*/
280/*----------------------------------------------------------------------------*/
282 const hdrl_parameter * p)
283{
284 cpl_ensure(p, CPL_ERROR_NULL_INPUT, HDRL_UNDEFINED_AXIS);
285 return ((const hdrl_overscan_parameter *)p)->correction_direction;
286}
287/*----------------------------------------------------------------------------*/
293/*----------------------------------------------------------------------------*/
295 const hdrl_parameter * p)
296{
297 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1.0) ;
298 return ((const hdrl_overscan_parameter *)p)->ccd_ron ;
299}
300/*----------------------------------------------------------------------------*/
306/*----------------------------------------------------------------------------*/
308 const hdrl_parameter * p)
309{
310 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1.0) ;
311 return ((const hdrl_overscan_parameter *)p)->box_hsize ;
312}
313/*----------------------------------------------------------------------------*/
319/*----------------------------------------------------------------------------*/
321 const hdrl_parameter * p)
322{
323 cpl_ensure(p, CPL_ERROR_NULL_INPUT, NULL) ;
324 return ((const hdrl_overscan_parameter *)p)->collapse;
325}
326/*----------------------------------------------------------------------------*/
332/*----------------------------------------------------------------------------*/
334 const hdrl_parameter * p)
335{
336 cpl_ensure(p, CPL_ERROR_NULL_INPUT, NULL) ;
337 return ((const hdrl_overscan_parameter *)p)->rect_region;
338}
339
340/* ---------------------------------------------------------------------------*/
366/* ---------------------------------------------------------------------------*/
368 const char *base_context,
369 const char *prefix,
370 const char *corr_dir_def,
371 int box_hsize_def,
372 double ccd_ron_def,
373 hdrl_parameter *rect_region_def,
374 const char *method_def,
375 hdrl_parameter *sigclip_def,
376 hdrl_parameter *minmax_def,
377 hdrl_parameter *mode_def)
378{
379 cpl_ensure(prefix && base_context && rect_region_def && sigclip_def
380 && minmax_def && mode_def, CPL_ERROR_NULL_INPUT, NULL);
381
382 cpl_ensure(hdrl_rect_region_parameter_check(rect_region_def)
386 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
387
388 char * name ;
389 cpl_parameterlist * parlist = cpl_parameterlist_new();
390 cpl_parameter * par ;
391 char * context =
392 hdrl_join_string(".", 2, base_context, prefix);
393
394 /* --prefix.correction_direction */
395 name = hdrl_join_string(".", 2, context, "correction-direction");
396 par = cpl_parameter_new_enum(name, CPL_TYPE_STRING, "Correction Direction",
397 context, corr_dir_def, 2, "alongX", "alongY");
398 cpl_free(name);
399 name = hdrl_join_string(".", 2, prefix, "correction-direction");
400 cpl_parameter_set_alias(par, CPL_PARAMETER_MODE_CLI, name);
401 cpl_parameter_disable(par, CPL_PARAMETER_MODE_ENV);
402 cpl_free(name);
403 cpl_parameterlist_append(parlist, par);
404
405 /* --prefix.box-hsize */
406 hdrl_setup_vparameter(parlist, prefix, ".", "", "box-hsize", base_context,
407 "Half size of running box in pixel, -1 for full overscan region",
408 CPL_TYPE_INT, box_hsize_def) ;
409
410 /* --prefix.ccd-ron */
411 hdrl_setup_vparameter(parlist, prefix, ".", "", "ccd-ron", base_context,
412 "Readout noise in ADU", CPL_TYPE_DOUBLE, ccd_ron_def) ;
413
414 /* Create Overscan Computation Region parameters */
415 /* --prefix.overscan.calc-xxx */
416 cpl_parameterlist * os_comp_reg = hdrl_rect_region_parameter_create_parlist(
417 base_context, prefix, "calc-", rect_region_def);
418 for (cpl_parameter * p = cpl_parameterlist_get_first(os_comp_reg) ;
419 p != NULL; p = cpl_parameterlist_get_next(os_comp_reg))
420 cpl_parameterlist_append(parlist,cpl_parameter_duplicate(p));
421 cpl_parameterlist_delete(os_comp_reg);
422
423 /* Overscan Collapsing related parameters */
424 /* --prefix.collapse.xxx */
425 name = hdrl_join_string(".", 2, prefix, "collapse");
426 cpl_parameterlist * pcollapse = hdrl_collapse_parameter_create_parlist(
427 base_context, name, method_def, sigclip_def, minmax_def, mode_def) ;
428 cpl_free(name);
429 for (cpl_parameter * p = cpl_parameterlist_get_first(pcollapse) ;
430 p != NULL; p = cpl_parameterlist_get_next(pcollapse))
431 cpl_parameterlist_append(parlist,cpl_parameter_duplicate(p));
432 cpl_parameterlist_delete(pcollapse);
433
434 cpl_free(context);
435
436 if (cpl_error_get_code()) {
437 cpl_parameterlist_delete(parlist);
438 return NULL;
439 }
440
441 return parlist;
442}
443
444/* ---------------------------------------------------------------------------*/
472/* ---------------------------------------------------------------------------*/
474 const cpl_parameterlist * parlist,
475 const char * prefix)
476{
477 cpl_ensure(prefix && parlist, CPL_ERROR_NULL_INPUT, NULL);
478 hdrl_direction corr_dir_param = HDRL_UNDEFINED_AXIS ;
479 int box_hsize = 0 ;
480 double ccd_ron = 0. ;
481 hdrl_parameter * os_collapse_params = NULL;
482 hdrl_parameter * os_region_params = NULL;
483 char * name ;
484
485 /* --correction-direction */
486 name = hdrl_join_string(".", 2, prefix, "correction-direction");
487 const cpl_parameter *par = cpl_parameterlist_find_const(parlist, name);
488 const char *correction_direction = cpl_parameter_get_string(par);
489 if (correction_direction == NULL) {
490 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
491 "Parameter %s not found", name);
492 cpl_free(name);
493 return NULL;
494 }
495 if(!strcmp(correction_direction, "alongX")) {
496 corr_dir_param = HDRL_X_AXIS;
497 } else if(!strcmp(correction_direction, "alongY")) {
498 corr_dir_param = HDRL_Y_AXIS;
499 }
500 cpl_free(name) ;
501
502 /* --box-hsize */
503 name = hdrl_join_string(".", 2, prefix, "box-hsize");
504 par=cpl_parameterlist_find_const(parlist, name);
505 box_hsize = cpl_parameter_get_int(par);
506 cpl_free(name) ;
507
508 /* --ccd-ron */
509 name = hdrl_join_string(".", 2, prefix, "ccd-ron");
510 par=cpl_parameterlist_find_const(parlist, name);
511 ccd_ron = cpl_parameter_get_double(par);
512 cpl_free(name) ;
513
514 if (cpl_error_get_code()) {
515 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
516 "Error while parsing parameterlist "
517 "with prefix %s", prefix);
518 return NULL;
519 }
520
521 /* --calc-* */
522 os_region_params = hdrl_rect_region_parameter_parse_parlist(parlist,
523 prefix, "calc-");
524
525 /* --collapse.* */
526 name = hdrl_join_string(".", 2, prefix, "collapse");
527 os_collapse_params = hdrl_collapse_parameter_parse_parlist(parlist, name) ;
528 cpl_free(name) ;
529
530 if (cpl_error_get_code()) {
531 hdrl_parameter_destroy(os_region_params);
532 hdrl_parameter_destroy(os_collapse_params);
533 return NULL;
534 }
535 else {
536 return hdrl_overscan_parameter_create(corr_dir_param, ccd_ron,
537 box_hsize, os_collapse_params,
538 os_region_params);
539 }
540}
541
542/* ---------------------------------------------------------------------------*/
554/* ---------------------------------------------------------------------------*/
555static cpl_error_code
556get_reduction(const hdrl_parameter * cpse,
557 const cpl_image * overscan_sub_ima,
558 hdrl_collapse_imagelist_to_vector_t ** reduce)
559{
561 *reduce = hdrl_collapse_imagelist_to_vector_mean();
563 *reduce = hdrl_collapse_imagelist_to_vector_weighted_mean();
564 } else if (hdrl_collapse_parameter_is_median(cpse)) {
565 *reduce = hdrl_collapse_imagelist_to_vector_median();
566 } else if (hdrl_collapse_parameter_is_sigclip(cpse)) {
567 double kappa =
568 sqrt(log(CX_MAX(hdrl_get_image_good_npix(overscan_sub_ima), 1)));
569 double kappa_low = hdrl_collapse_sigclip_parameter_get_kappa_low(cpse);
570 double kappa_high =
573 if (kappa_low <= 0) kappa_low = kappa;
574 if (kappa_high <= 0) kappa_high = kappa;
575 *reduce = hdrl_collapse_imagelist_to_vector_sigclip(kappa_low,
576 kappa_high, niter);
577 } else if (hdrl_collapse_parameter_is_minmax(cpse)) {
578 double nlow = hdrl_collapse_minmax_parameter_get_nlow(cpse);
579 double nhigh = hdrl_collapse_minmax_parameter_get_nhigh(cpse);
580 if (nlow <= 0) nlow = 0;
581 if (nhigh <= 0) nhigh = 0;
582 *reduce = hdrl_collapse_imagelist_to_vector_minmax(nlow, nhigh);
583
584 } else if (hdrl_collapse_parameter_is_mode(cpse)) {
585 double histo_min = hdrl_collapse_mode_parameter_get_histo_min(cpse);
586 double histo_max = hdrl_collapse_mode_parameter_get_histo_max(cpse);
587 double bin_size = hdrl_collapse_mode_parameter_get_bin_size(cpse);
588 hdrl_mode_type method = hdrl_collapse_mode_parameter_get_method(cpse);
589 cpl_size error_niter = hdrl_collapse_mode_parameter_get_error_niter(cpse);
590 *reduce = hdrl_collapse_imagelist_to_vector_mode(histo_min, histo_max,
591 bin_size, method,
592 error_niter);
593 }
594
595 return cpl_error_get_code();
596}
597
598/*----------------------------------------------------------------------------*/
685/*----------------------------------------------------------------------------*/
686hdrl_overscan_compute_result * hdrl_overscan_compute(
687 const cpl_image * source,
688 const hdrl_parameter * params)
689{
690 cpl_image * correction_img = NULL;
691 cpl_image * correction_err_img = NULL;
692 cpl_image * contribution_img = NULL;
693 cpl_image * chi2_img = NULL;
694 cpl_image * red_chi2_img = NULL;
695 cpl_image * reject_low = NULL;
696 cpl_image * reject_high = NULL;
697 cpl_size llx = 0;
698 cpl_size lly = 0;
699 cpl_size urx = 0;
700 cpl_size ury = 0;
701 cpl_image * overscan_ima = NULL;
702
703 /*TODO add minmax description to the doxygen */
704
705 /* Check Entries */
706 cpl_error_ensure(source != NULL, CPL_ERROR_NULL_INPUT,
707 return NULL, "NULL input image");
708 cpl_error_ensure(params != NULL, CPL_ERROR_NULL_INPUT,
709 return NULL, "NULL input parameters");
710
711 int d1 = sizeof(hdrl_sigclip_vector_output);
712 int d2 = sizeof(hdrl_minmax_vector_output );
713 cpl_error_ensure(d1 == d2, CPL_ERROR_INVALID_TYPE, return NULL,
714 "Invalid check type between hdrl_sigclip_vector_output and hdrl_minmax_vector_output");
715
717 params,
718 cpl_image_get_size_x(source),
719 cpl_image_get_size_y(source)) != CPL_ERROR_NONE)
720 return NULL;
721
722 /* Local Usage Parameters */
723 const hdrl_overscan_parameter * p_loc =
724 (const hdrl_overscan_parameter *)params ;
725 const hdrl_parameter * cpse = p_loc->collapse ;
726 const hdrl_parameter * rr = p_loc->rect_region ;
727
728 /* Extract Overscan region */
729 overscan_ima = cpl_image_extract(source,
734
735 /* Handle Orientation */
736 if(p_loc->correction_direction == HDRL_Y_AXIS) {
737 /* rotate the image 90 degree counter-clockwise */
738 cpl_image_turn(overscan_ima, -1);
739 }
740
741 /* Redefine the boundaries to extracted image */
742 llx = 1;
743 lly = 1;
744 urx = cpl_image_get_size_x(overscan_ima);
745 ury = cpl_image_get_size_y(overscan_ima);
746
747 /* Create output images */
748 correction_img = cpl_image_new(1, ury, HDRL_TYPE_DATA);
749 correction_err_img = cpl_image_new(1, ury, HDRL_TYPE_ERROR);
750 contribution_img = cpl_image_new(1, ury, CPL_TYPE_INT);
751 chi2_img = cpl_image_new(1, ury, CPL_TYPE_DOUBLE);
752 red_chi2_img = cpl_image_new(1, ury, CPL_TYPE_DOUBLE);
753
756 reject_low = cpl_image_new(1, ury, CPL_TYPE_DOUBLE);
757 reject_high = cpl_image_new(1, ury, CPL_TYPE_DOUBLE);
758 }
759
760 /* Loop along Y direction */
761 /* only 1 iteration if hbox == HDRL_OVERSCAN_FULL_BOX */
762HDRL_OMP(omp parallel for)
763 for (long ipixel = 1;
764 ipixel <= (p_loc->box_hsize == HDRL_OVERSCAN_FULL_BOX ? 1 : ury);
765 ipixel++) {
766 cpl_size contribution;
767 double corr, error, chi2, red_chi2;
768 const int box_hsize = p_loc->box_hsize;
769 const double ccd_ron = p_loc->ccd_ron;
770 cpl_size upperlimit;
771 cpl_size lowerlimit;
772 cpl_image * overscan_sub_ima, * ccd_ron_ima;
773 /* Switch on the different methods */
774 hdrl_collapse_imagelist_to_vector_t * reduce = NULL;
775 void * collapse_eout = NULL;
776
777 /* define proper extraction limits */
778 if (box_hsize == HDRL_OVERSCAN_FULL_BOX) {
779 /* take full region as box */
780 lowerlimit = lly;
781 upperlimit = ury;
782 }
783 else if (ipixel + box_hsize > ury) {
784 /* Shrink the window if you are approaching the image boundaries */
785 upperlimit = CX_MIN(ipixel + box_hsize, ury);
786 lowerlimit = 2 * ipixel - upperlimit;
787 }
788 else {
789 /* Shrink the window if you are approaching the image boundaries */
790 lowerlimit = CX_MAX(ipixel - box_hsize, 1);
791 upperlimit = 2 * ipixel - lowerlimit;
792 }
793
794 /* Extract the current running sub-window */
795 overscan_sub_ima = cpl_image_extract(overscan_ima, llx, lowerlimit,
796 urx, upperlimit);
797
798 /* Fill an image with the ccd_ron constant */
799 ccd_ron_ima = cpl_image_duplicate(overscan_sub_ima);
800 cpl_image_multiply_scalar(ccd_ron_ima, 0.0);
801 cpl_image_add_scalar(ccd_ron_ima, ccd_ron);
802
803 get_reduction(cpse, overscan_sub_ima, &reduce);
804
805 /* Compute the over-scan correction, error, and contribution */
806 hdrl_overscan_reduce_image_to_scalar(reduce, overscan_sub_ima,
807 ccd_ron_ima, &corr, &error, &contribution, &collapse_eout);
808
809 /* handle additional sigclip and minmax output */
810 if (collapse_eout && (hdrl_collapse_parameter_is_sigclip(cpse) ||
812
813 hdrl_sigclip_vector_output * eout = collapse_eout;
814
815 double low = cpl_vector_get(eout->reject_low, 0);
816 double high = cpl_vector_get(eout->reject_high, 0);
817
818 cpl_image_set(reject_low, 1, ipixel, low);
819 cpl_image_set(reject_high, 1, ipixel, high);
820
821 cpl_vector_delete(eout->reject_low);
822 cpl_vector_delete(eout->reject_high);
823 }
824
825 hdrl_collapse_imagelist_to_vector_unwrap_eout(reduce, collapse_eout);
826
827 /* Compute the chi2 - Independent of the method */
828 if (contribution == 0) {
829 chi2 = NAN;
830 red_chi2 = NAN;
831 } else if (p_loc->box_hsize == HDRL_OVERSCAN_FULL_BOX) {
832 hdrl_overscan_compute_chi_square(overscan_sub_ima,
833 ccd_ron_ima, corr, &chi2, &red_chi2);
834 } else {
835 /*Calculate the chi2 only in the central slice of the image
836 * TODO very inefficient - restructure */
837 cpl_size nx = cpl_image_get_size_x(overscan_sub_ima);
838 cpl_size ny = cpl_image_get_size_y(overscan_sub_ima);
839
840 cpl_image * overscan_sub_ima_slice =
841 cpl_image_extract(overscan_sub_ima, 1, (cpl_size)((ny+1)/2),
842 nx, (cpl_size)((ny+1)/2));
843 cpl_image * ccd_ron_ima_slice =
844 cpl_image_extract(ccd_ron_ima, 1, (cpl_size)((ny+1)/2), nx,
845 (cpl_size)((ny+1)/2));
846
847 hdrl_overscan_compute_chi_square(overscan_sub_ima_slice,
848 ccd_ron_ima_slice, corr, &chi2, &red_chi2);
849
850 cpl_image_delete(overscan_sub_ima_slice);
851 cpl_image_delete(ccd_ron_ima_slice);
852 }
853
854 /* Fill the result images with the current result */
855 cpl_image_set(correction_img, 1, ipixel, corr);
856 cpl_image_set(correction_err_img, 1, ipixel, error);
857 cpl_image_set(contribution_img, 1, ipixel, contribution);
858 cpl_image_set(chi2_img, 1, ipixel, chi2);
859 cpl_image_set(red_chi2_img, 1, ipixel, red_chi2);
860
861 cpl_image_delete(overscan_sub_ima);
862 cpl_image_delete(ccd_ron_ima);
863
864 hdrl_collapse_imagelist_to_vector_delete(reduce);
865 }
866
867 /* broadcast the full box result to the full result row/col */
868 if (p_loc->box_hsize == HDRL_OVERSCAN_FULL_BOX) {
869 int rej;
870 const double ccd_ron = p_loc->ccd_ron;
871 const double correction_value =
872 cpl_image_get(correction_img, 1, 1, &rej);
873 const double correction_err_value =
874 cpl_image_get(correction_err_img, 1, 1, &rej);
875 const cpl_size contribution_value =
876 cpl_image_get(contribution_img, 1, 1, &rej);
877 cpl_size loopmax = cpl_image_get_size_y(correction_img);
878HDRL_OMP(omp parallel for private(rej))
879 for (cpl_size i = 1; i <= loopmax; i++) {
880 double chi2, red_chi2;
881 cpl_image * overscan_sub_ima, * ccd_ron_ima;
882
883 if (i < loopmax) {
884 /*Here we broadcast*/
885 cpl_image_set(correction_img, 1, i + 1, correction_value);
886 cpl_image_set(correction_err_img, 1, i + 1,
887 correction_err_value);
888 cpl_image_set(contribution_img, 1, i + 1,contribution_value);
891 cpl_image_set(reject_low, 1, i + 1,
892 cpl_image_get(reject_low, 1, 1, &rej));
893 cpl_image_set(reject_high, 1, i + 1,
894 cpl_image_get(reject_high, 1, 1, &rej));
895 }
896 }
897 /* Here we do additional chi2 calculation */
898
899 /* Extract the current running sub-window */
900 overscan_sub_ima = cpl_image_extract(overscan_ima, llx, i, urx, i);
901
902 /* Fill an image with the ccd_ron constant */
903 ccd_ron_ima = cpl_image_duplicate(overscan_sub_ima);
904 cpl_image_multiply_scalar(ccd_ron_ima, 0.0);
905 cpl_image_add_scalar(ccd_ron_ima, ccd_ron);
906
907 hdrl_overscan_compute_chi_square(overscan_sub_ima,
908 ccd_ron_ima, correction_value,
909 &chi2, &red_chi2);
910
911 cpl_image_set(chi2_img, 1, i, chi2);
912 cpl_image_set(red_chi2_img, 1, i, red_chi2);
913 cpl_image_delete(overscan_sub_ima);
914 cpl_image_delete(ccd_ron_ima);
915 }
916 }
917
918 cpl_image_delete(overscan_ima);
919 /* flag bad pixels */
920 cpl_image_reject_value(correction_img, CPL_VALUE_NAN);
921 cpl_image_reject_value(correction_err_img, CPL_VALUE_NAN);
922 cpl_image_reject_value(chi2_img, CPL_VALUE_NAN);
923 cpl_image_reject_value(red_chi2_img, CPL_VALUE_NAN);
926 cpl_image_reject_value(reject_low, CPL_VALUE_NAN);
927 cpl_image_reject_value(reject_high, CPL_VALUE_NAN);
928 }
929
930 /* Handle Orientation */
931 if(p_loc->correction_direction == HDRL_Y_AXIS) {
932 cpl_image_turn(correction_img, +1);
933 cpl_image_turn(correction_err_img, +1);
934 cpl_image_turn(contribution_img, +1);
935 cpl_image_turn(chi2_img, +1);
936 cpl_image_turn(red_chi2_img, +1);
939 cpl_image_turn(reject_low, +1);
940 cpl_image_turn(reject_high, +1);
941 }
942 }
943
944 /* Create the Overscan resulting structure */
945 {
946 hdrl_overscan_compute_result * result =
947 hdrl_overscan_compute_result_create();
948 hdrl_image * res = hdrl_image_create(correction_img,
949 correction_err_img);
950 cpl_image_delete(correction_img);
951 cpl_image_delete(correction_err_img);
952 result->correction_direction = p_loc->correction_direction;
953 result->correction = res;
954 result->contribution = contribution_img;
955 result->chi2 = chi2_img;
956 result->red_chi2 = red_chi2_img;
957 result->sigclip_reject_low = reject_low;
958 result->sigclip_reject_high = reject_high;
959 return result;
960 }
961}
962
963/*----------------------------------------------------------------------------*/
969/*----------------------------------------------------------------------------*/
971 const hdrl_overscan_compute_result * res)
972{
973 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
974 return res->correction;
975}
976
977/*----------------------------------------------------------------------------*/
983/*----------------------------------------------------------------------------*/
985 hdrl_overscan_compute_result * res)
986{
987 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
988 hdrl_image * r = res->correction;
989 res->correction = NULL;
990 return r;
991}
992
993/*----------------------------------------------------------------------------*/
999/*----------------------------------------------------------------------------*/
1001 const hdrl_overscan_compute_result * res)
1002{
1003 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1004 return res->contribution;
1005}
1006
1007/*----------------------------------------------------------------------------*/
1013/*----------------------------------------------------------------------------*/
1015 hdrl_overscan_compute_result * res)
1016{
1017 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1018 cpl_image * r = res->contribution;
1019 res->contribution = NULL;
1020 return r;
1021}
1022
1023/*----------------------------------------------------------------------------*/
1029/*----------------------------------------------------------------------------*/
1031 const hdrl_overscan_compute_result * res)
1032{
1033 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1034 return res->chi2;
1035}
1036
1037/*----------------------------------------------------------------------------*/
1043/*----------------------------------------------------------------------------*/
1045 hdrl_overscan_compute_result * res)
1046{
1047 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1048 cpl_image * r = res->chi2;
1049 res->chi2 = NULL;
1050 return r;
1051}
1052
1053/*----------------------------------------------------------------------------*/
1059/*----------------------------------------------------------------------------*/
1061 const hdrl_overscan_compute_result * res)
1062{
1063 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1064 return res->red_chi2;
1065}
1066
1067/*----------------------------------------------------------------------------*/
1073/*----------------------------------------------------------------------------*/
1075 hdrl_overscan_compute_result * res)
1076{
1077 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1078 cpl_image * r = res->red_chi2;
1079 res->red_chi2 = NULL;
1080 return r;
1081}
1082
1083/*----------------------------------------------------------------------------*/
1089/*----------------------------------------------------------------------------*/
1091 const hdrl_overscan_compute_result * res)
1092{
1093 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1094 if (!res->sigclip_reject_low) {
1095 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
1096 "rejection parameters are only "
1097 "available if collapse mode of overscan is set "
1098 "to sigclip or minmax");
1099 }
1100 return res->sigclip_reject_low;
1101}
1102
1103/*----------------------------------------------------------------------------*/
1109/*----------------------------------------------------------------------------*/
1111 hdrl_overscan_compute_result * res)
1112{
1113 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1114 cpl_image * r = res->sigclip_reject_low;
1115 if (!res->sigclip_reject_low) {
1116 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
1117 "rejection parameters are only "
1118 "available if collapse mode of overscan is set "
1119 "to sigclip or minmax");
1120 }
1121 res->sigclip_reject_low = NULL;
1122 return r;
1123}
1124
1125/*----------------------------------------------------------------------------*/
1131/*----------------------------------------------------------------------------*/
1133 const hdrl_overscan_compute_result * res)
1134{
1135 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1136 if (!res->sigclip_reject_high) {
1137 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
1138 "rejection parameters are only "
1139 "available if collapse mode of overscan is set "
1140 "to sigclip or minmax");
1141 }
1142 return res->sigclip_reject_high;
1143}
1144
1145/*----------------------------------------------------------------------------*/
1151/*----------------------------------------------------------------------------*/
1153 hdrl_overscan_compute_result * res)
1154{
1155 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1156 cpl_image * r = res->sigclip_reject_high;
1157 res->sigclip_reject_high = NULL;
1158 return r;
1159}
1160
1161
1162/*----------------------------------------------------------------------------*/
1168/*----------------------------------------------------------------------------*/
1170 const hdrl_overscan_compute_result * res)
1171{
1173}
1174
1175/*----------------------------------------------------------------------------*/
1181/*----------------------------------------------------------------------------*/
1183 hdrl_overscan_compute_result * res)
1184{
1186}
1187
1188/*----------------------------------------------------------------------------*/
1194/*----------------------------------------------------------------------------*/
1196 const hdrl_overscan_compute_result * res)
1197{
1199}
1200
1201/*----------------------------------------------------------------------------*/
1207/*----------------------------------------------------------------------------*/
1209 hdrl_overscan_compute_result * res)
1210{
1212}
1213
1214
1215
1216/*----------------------------------------------------------------------------*/
1221/*----------------------------------------------------------------------------*/
1223 hdrl_overscan_compute_result * result)
1224{
1225 if (result == NULL) return;
1226 hdrl_image_delete(result->correction);
1227 cpl_image_delete(result->contribution);
1228 cpl_image_delete(result->chi2);
1229 cpl_image_delete(result->red_chi2);
1230 cpl_image_delete(result->sigclip_reject_low);
1231 cpl_image_delete(result->sigclip_reject_high);
1232 cpl_free(result);
1233 return;
1234}
1235
1236/*----------------------------------------------------------------------------*/
1285/*----------------------------------------------------------------------------*/
1286hdrl_overscan_correct_result * hdrl_overscan_correct(
1287 const hdrl_image * source,
1288 const hdrl_parameter * region,
1289 const hdrl_overscan_compute_result * os_computation)
1290{
1291 cpl_size llx = 0, lly = 0, urx = 0, ury = 0;
1292 /* local pointers to source image and its error */
1293 cpl_image * source_loc = NULL;
1294 cpl_image * source_error_loc = NULL;
1295 long xsize_overscan = 0;
1296 long ysize_overscan = 0;
1297 size_t nx;
1298 cpl_mask * orig_mask = NULL;
1299 hdrl_image * hoverscan;
1300 /* value to use in mask for pixels rejected by algorithm */
1301 hdrl_bitmask_t reject_code = 1;
1302
1303 /* Check Entries */
1304 cpl_error_ensure(source != NULL, CPL_ERROR_NULL_INPUT,
1305 return NULL, "NULL input source image");
1306 cpl_error_ensure(os_computation != NULL, CPL_ERROR_NULL_INPUT,
1307 return NULL, "NULL overscan computation result");
1308
1309 cpl_error_ensure(hdrl_int_is_power_of_two(reject_code),
1310 CPL_ERROR_ILLEGAL_INPUT, return NULL,
1311 "reject_code must be a power of two");
1312
1313 if (hdrl_overscan_compute_result_verify(os_computation) != CPL_ERROR_NONE)
1314 return NULL;
1315
1316 hoverscan = os_computation->correction;
1317
1318 /* Initialise Region parameters */
1319 if (region != NULL) {
1321 hdrl_image_get_size_x(source),
1322 hdrl_image_get_size_y(source)) != CPL_ERROR_NONE)
1323 return NULL;
1324 llx = hdrl_rect_region_get_llx(region);
1325 lly = hdrl_rect_region_get_lly(region);
1326 urx = hdrl_rect_region_get_urx(region);
1327 ury = hdrl_rect_region_get_ury(region);
1328 } else {
1329 llx = lly = 1;
1330 urx = hdrl_image_get_size_x(source);
1331 ury = hdrl_image_get_size_y(source);
1332 }
1333
1334 source_loc =
1335 cpl_image_cast(hdrl_image_get_image_const(source), HDRL_TYPE_DATA);
1336 source_error_loc =
1337 cpl_image_cast(hdrl_image_get_error_const(source), HDRL_TYPE_ERROR);
1338 nx = cpl_image_get_size_x(source_loc);
1339
1340 xsize_overscan = hdrl_image_get_size_x(hoverscan);
1341 ysize_overscan = hdrl_image_get_size_y(hoverscan);
1342
1343 /* Check if the overscan image has an appropriate size */
1344 if (os_computation->correction_direction == HDRL_X_AXIS &&
1345 ury-lly+1 != ysize_overscan) {
1346 cpl_image_delete(source_loc);
1347 cpl_image_delete(source_error_loc);
1348 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
1349 "Correction region Y size does not match overscan Y size");
1350 return NULL;
1351 }
1352 if (os_computation->correction_direction == HDRL_Y_AXIS &&
1353 urx-llx+1 != xsize_overscan) {
1354 cpl_image_delete(source_loc);
1355 cpl_image_delete(source_error_loc);
1356 cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
1357 "Correction region X size does not match overscan X size");
1358 return NULL;
1359 }
1360
1361 if (xsize_overscan != 1 && ysize_overscan != 1) {
1362 cpl_image_delete(source_loc);
1363 cpl_image_delete(source_error_loc);
1364 cpl_error_set(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT);
1365 return NULL;
1366 }
1367
1368 /* store original mask to later separate it from newly created bpms */
1369 orig_mask = hdrl_copy_image_mask(source_loc);
1370
1371 {
1372 hdrl_data_t * psource_loc = cpl_image_get_data(source_loc);
1373 hdrl_error_t * psource_err_loc = cpl_image_get_data(source_error_loc);
1374 const cpl_mask * bpm = hdrl_image_get_mask_const(hoverscan);
1375 /* os image is one dimensional, so just get the data */
1376 const cpl_binary * rej = bpm ? cpl_mask_get_data_const(bpm) : NULL;
1377 const hdrl_data_t * pos_val = hdrl_get_image_data_const(
1378 hdrl_image_get_image_const(hoverscan));
1379 const hdrl_error_t * pos_e = hdrl_get_image_error_const(
1380 hdrl_image_get_error_const(hoverscan));
1381 /* make sure we have a bpm before the parallel loop */
1382 cpl_image_get_bpm(source_loc);
1383
1384 /* corrects extracted image for over-scan value, compute associated
1385 * error, flag bad pixels */
1386HDRL_OMP(omp parallel for)
1387 for (long j = lly - 1; j < ury; j++) {
1388 for (long i = llx - 1; i < urx; i++) {
1389 const size_t idx =
1390 os_computation->correction_direction == HDRL_X_AXIS ?
1391 j-lly+1 : i-llx+1;
1392 double ima_e = psource_err_loc[j * nx + i];
1393
1394 if (rej && rej[idx]) {
1395 /* set to zero as per requirements */
1396 cpl_image_reject(source_loc, i + 1, j + 1);
1397 psource_loc[j * nx + i] = 0;
1398 psource_err_loc[j * nx + i] = 0;
1399 } else {
1400 psource_loc[j * nx + i] -= pos_val[idx];
1401 psource_err_loc[j * nx + i] =
1402 sqrt(pos_e[idx] * pos_e[idx] + ima_e * ima_e);
1403 }
1404 }
1405 }
1406 }
1407
1408 {
1409 hdrl_overscan_correct_result * res;
1410 cpl_mask * new_mask = hdrl_copy_image_mask(source_loc);
1411 cpl_image * badmask = cpl_image_new(cpl_image_get_size_x(source_loc),
1412 cpl_image_get_size_y(source_loc),
1413 CPL_TYPE_INT);
1414 /* get the new bad pixels */
1415 cpl_mask_xor(new_mask, orig_mask);
1416 /* fill them with the code */
1417 cpl_image_reject_from_mask(badmask, new_mask);
1418 cpl_image_fill_rejected(badmask, reject_code);
1419
1420 cpl_mask_delete(new_mask);
1421 cpl_mask_delete(orig_mask);
1422
1423 /* Create, fill and return the returned structure */
1424 res = hdrl_overscan_correct_result_create();
1425 res->corrected = hdrl_image_wrap(source_loc, source_error_loc, NULL,
1426 CPL_TRUE);
1427 res->badmask = badmask;
1428 return res;
1429 }
1430}
1431
1432/*----------------------------------------------------------------------------*/
1437/*----------------------------------------------------------------------------*/
1439 hdrl_overscan_correct_result * result)
1440{
1441 if (result == NULL) return;
1442 hdrl_image_delete(result->corrected);
1443 cpl_image_delete(result->badmask);
1444 cpl_free(result);
1445 return;
1446}
1447
1448/*----------------------------------------------------------------------------*/
1454/*----------------------------------------------------------------------------*/
1456 const hdrl_overscan_correct_result * res)
1457{
1458 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1459 return res->corrected;
1460}
1461
1462/*----------------------------------------------------------------------------*/
1468/*----------------------------------------------------------------------------*/
1470 hdrl_overscan_correct_result * res)
1471{
1472 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1473 hdrl_image * r = res->corrected;
1474 res->corrected = NULL;
1475 return r;
1476}
1477
1478/*----------------------------------------------------------------------------*/
1484/*----------------------------------------------------------------------------*/
1486 const hdrl_overscan_correct_result * res)
1487{
1488 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1489 return res->badmask;
1490}
1491
1492/*----------------------------------------------------------------------------*/
1498/*----------------------------------------------------------------------------*/
1500 hdrl_overscan_correct_result * res)
1501{
1502 cpl_ensure(res, CPL_ERROR_NULL_INPUT, NULL);
1503 cpl_image * r = res->badmask;
1504 res->badmask = NULL;
1505 return r;
1506}
1507
1510/*----------------------------------------------------------------------------*/
1515/*----------------------------------------------------------------------------*/
1516static void hdrl_overscan_parameter_destroy(void * param)
1517{
1518 hdrl_overscan_parameter * p = (hdrl_overscan_parameter *)param ;
1519 hdrl_parameter_destroy(p->collapse) ;
1520 hdrl_parameter_destroy(p->rect_region) ;
1521 hdrl_parameter_delete((hdrl_parameter*)param) ;
1522 return ;
1523}
1524
1525/*----------------------------------------------------------------------------*/
1532/*----------------------------------------------------------------------------*/
1533static hdrl_overscan_compute_result * hdrl_overscan_compute_result_create(
1534 void)
1535{
1536 hdrl_overscan_compute_result * self =
1537 cpl_malloc(sizeof(hdrl_overscan_compute_result));
1538
1539 self->correction_direction = HDRL_UNDEFINED_AXIS;
1540 self->correction = NULL;
1541 self->contribution = NULL;
1542 self->chi2 = NULL;
1543 self->red_chi2 = NULL;
1544 self->sigclip_reject_low = NULL;
1545 self->sigclip_reject_high = NULL;
1546 return self;
1547}
1548
1549
1550/*----------------------------------------------------------------------------*/
1556/*----------------------------------------------------------------------------*/
1557static cpl_error_code hdrl_overscan_compute_result_verify(
1558 const hdrl_overscan_compute_result * result)
1559{
1560 cpl_error_ensure(result != NULL, CPL_ERROR_NULL_INPUT,
1561 return CPL_ERROR_NULL_INPUT,
1562 "NULL input overscan result structure");
1563 cpl_error_ensure(result->correction_direction == HDRL_X_AXIS ||
1564 result->correction_direction == HDRL_Y_AXIS,
1565 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
1566 "The specified collapse direction is unknown");
1567
1568 if (result->correction_direction == HDRL_X_AXIS) {
1569 cpl_error_ensure(hdrl_image_get_size_x(result->correction) == 1,
1570 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
1571 "The Correction image X size should be 1");
1572 cpl_error_ensure(cpl_image_get_size_x(result->contribution) == 1,
1573 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
1574 "The Contribution image X size should be 1");
1575 cpl_error_ensure(cpl_image_get_size_x(result->chi2) == 1,
1576 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
1577 "The Chi Square image X size should be 1");
1578 cpl_error_ensure(cpl_image_get_size_x(result->red_chi2) == 1,
1579 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
1580 "The reduced Chi Square image X size should be 1");
1581 if (result->sigclip_reject_low != NULL) {
1582 cpl_error_ensure(cpl_image_get_size_x(result->sigclip_reject_low)
1583 == 1,
1584 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
1585 "The SIGCLIP low rejection image X size should be 1");
1586
1587 }
1588 if (result->sigclip_reject_high != NULL) {
1589 cpl_error_ensure(cpl_image_get_size_x(result->sigclip_reject_high)
1590 == 1,
1591 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
1592 "The SIGCLIP high rejection image X size should be 1");
1593 }
1594 }
1595 else if (result->correction_direction == HDRL_Y_AXIS) {
1596 cpl_error_ensure(hdrl_image_get_size_y(result->correction) == 1,
1597 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
1598 "The Correction image Y size should be 1");
1599 cpl_error_ensure(cpl_image_get_size_y(result->contribution) == 1,
1600 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
1601 "The Contribution image Y size should be 1");
1602 cpl_error_ensure(cpl_image_get_size_y(result->chi2) == 1,
1603 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
1604 "The Chi Square image Y size should be 1");
1605 cpl_error_ensure(cpl_image_get_size_y(result->red_chi2) == 1,
1606 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
1607 "The reduced Chi Square image Y size should be 1");
1608 if (result->sigclip_reject_low != NULL) {
1609 cpl_error_ensure(cpl_image_get_size_y(result->sigclip_reject_low)
1610 == 1,
1611 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
1612 "The SIGCLIP low rejection image Y size should be 1");
1613
1614 }
1615 if (result->sigclip_reject_high != NULL) {
1616 cpl_error_ensure(cpl_image_get_size_y(result->sigclip_reject_high)
1617 == 1,
1618 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
1619 "The SIGCLIP high rejection image Y size should be 1");
1620 }
1621 }
1622 else return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1623 "correction_direction must be HDRL_X_AXIS or HDRL_Y_AXIS");
1624 return CPL_ERROR_NONE;
1625}
1626
1627/*----------------------------------------------------------------------------*/
1634/*----------------------------------------------------------------------------*/
1635static hdrl_overscan_correct_result * hdrl_overscan_correct_result_create(
1636 void)
1637{
1638 hdrl_overscan_correct_result * self = cpl_malloc(sizeof(*self));
1639 self->corrected = NULL;
1640 self->badmask = NULL;
1641 return self;
1642}
1643
1644/*----------------------------------------------------------------------------*/
1654/* ---------------------------------------------------------------------------*/
1655static cpl_error_code hdrl_overscan_compute_chi_square(
1656 const cpl_image * data,
1657 const cpl_image * error,
1658 const double expect,
1659 double * chi2,
1660 double * red_chi2)
1661{
1662 cpl_image * s;
1663 cpl_size nrej, nerej;
1664 cpl_image * e = NULL;
1665 cpl_size nepix = 0;
1666 cpl_size npix = 0;
1667
1668 nrej = cpl_image_count_rejected(data);
1669 npix = cpl_image_get_size_x(data) * cpl_image_get_size_y(data);
1670
1671 if (nrej == npix) {
1672 *chi2 = NAN;
1673 *red_chi2 = NAN;
1674 return CPL_ERROR_NONE;
1675 }
1676
1677 e = cpl_image_duplicate(error);
1678 nepix = cpl_image_get_size_x(e) * cpl_image_get_size_y(e);
1679
1680 /*TODO handle pre-existing Zero's marked as bad */
1681 /* check if error image contains zeros */
1682 cpl_image_accept_all(e);
1683 cpl_image_reject_value(e, CPL_VALUE_ZERO);
1684 nerej = cpl_image_count_rejected(e);
1685 /* all errors zero allowed */
1686 if (nerej == nepix) {
1687 cpl_image_delete(e);
1688 *chi2 = NAN;
1689 *red_chi2 = NAN;
1690 return CPL_ERROR_NONE;
1691 }
1692 /* partial zero errors make no sense */
1693 else if (nerej != 0) {
1694 cpl_image_delete(e);
1695 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1696 "Error image can't contain zeros");
1697 *chi2 = NAN;
1698 *red_chi2 = NAN;
1699 return CPL_ERROR_ILLEGAL_INPUT;
1700 }
1701
1702 s = cpl_image_duplicate(data);
1703 /* computes chi squared defined as:
1704 * \Sum_i[ (x_i - expect)^2 / sigma_i^2 ] */
1705 cpl_image_subtract_scalar(s, expect);
1706 cpl_image_divide(s, e);
1707 *chi2 = cpl_image_get_sqflux(s); /* = squared sum */
1708 *red_chi2 = *chi2 / npix; /* reduced chi2 */
1709 cpl_image_delete(s);
1710 cpl_image_delete(e);
1711 return CPL_ERROR_NONE;
1712}
1713
1714/*----------------------------------------------------------------------------*/
1729/* ---------------------------------------------------------------------------*/
1730static cpl_error_code hdrl_overscan_reduce_image_to_scalar(
1731 hdrl_collapse_imagelist_to_vector_t * red,
1732 cpl_image * data,
1733 cpl_image * data_error,
1734 double * result,
1735 double * error,
1736 cpl_size * contribution,
1737 void ** eout)
1738{
1739 cpl_imagelist * ld = cpl_imagelist_new();
1740 cpl_imagelist * le = cpl_imagelist_new();
1741 cpl_vector * od = NULL, * oe = NULL;
1742 cpl_array * oc = NULL;
1743 cpl_error_code fail;
1744 cpl_imagelist_set(ld, data, 0);
1745 cpl_imagelist_set(le, data_error, 0);
1746
1747
1748 fail = hdrl_collapse_imagelist_to_vector_call(red, ld, le, &od, &oe, &oc,
1749 eout);
1750 cpl_imagelist_unwrap(ld);
1751 cpl_imagelist_unwrap(le);
1752
1753 if (fail == CPL_ERROR_NONE) {
1754 *result = cpl_vector_get(od, 0);
1755 *error = cpl_vector_get(oe, 0);
1756 *contribution = cpl_array_get_int(oc, 0, NULL);
1757 }
1758 else {
1759 *result = NAN;
1760 *error = NAN;
1761 *contribution = 0;
1762 }
1763
1764 cpl_vector_delete(od);
1765 cpl_vector_delete(oe);
1766 cpl_array_delete(oc);
1767
1768 return fail;
1769}
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
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
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_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
cpl_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
Definition: hdrl_image.c:540
const cpl_mask * hdrl_image_get_mask_const(const hdrl_image *himg)
get cpl bad pixel mask from image
Definition: hdrl_image.c:175
cpl_size hdrl_image_get_size_x(const hdrl_image *self)
return size of X dimension of image
Definition: hdrl_image.c:525
const cpl_image * hdrl_image_get_error_const(const hdrl_image *himg)
get error as cpl image
Definition: hdrl_image.c:144
hdrl_image * hdrl_image_create(const cpl_image *image, const cpl_image *error)
create a new hdrl_image from to existing images by copying them
Definition: hdrl_image.c:295
const cpl_image * hdrl_image_get_image_const(const hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:118
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
Definition: hdrl_image.c:379
void hdrl_overscan_compute_result_delete(hdrl_overscan_compute_result *result)
Deletes the Overscan Computation Result Structure.
cpl_image * hdrl_overscan_correct_result_get_badmask(const hdrl_overscan_correct_result *res)
Access the bad pixels mask in the Overscan Correction result object.
cpl_image * hdrl_overscan_compute_result_unset_red_chi2(hdrl_overscan_compute_result *res)
Unset the reduced CHI2 in the Overscan Computation result object.
cpl_image * hdrl_overscan_correct_result_unset_badmask(hdrl_overscan_correct_result *res)
Unset the bad pixels mask in the Overscan Correction result object.
cpl_image * hdrl_overscan_compute_result_get_minmax_reject_high(const hdrl_overscan_compute_result *res)
Access the high threshold in the Overscan Computation result object.
cpl_boolean hdrl_overscan_parameter_check(const hdrl_parameter *self)
Check that the parameter is an Overscan parameter.
hdrl_image * hdrl_overscan_correct_result_unset_corrected(hdrl_overscan_correct_result *res)
Unset the corrected image in the Overscan Correction result object.
cpl_image * hdrl_overscan_compute_result_get_red_chi2(const hdrl_overscan_compute_result *res)
Access the reduced CHI2 in the Overscan Computation result object.
cpl_image * hdrl_overscan_compute_result_get_sigclip_reject_low(const hdrl_overscan_compute_result *res)
Access the low threshold in the Overscan Computation result object.
cpl_image * hdrl_overscan_compute_result_get_chi2(const hdrl_overscan_compute_result *res)
Access the CHI2 in the Overscan Computation result object.
hdrl_overscan_compute_result * hdrl_overscan_compute(const cpl_image *source, const hdrl_parameter *params)
Overscan correction computation.
cpl_image * hdrl_overscan_compute_result_unset_chi2(hdrl_overscan_compute_result *res)
Unset the CHI2 in the Overscan Computation result object.
cpl_image * hdrl_overscan_compute_result_unset_minmax_reject_high(hdrl_overscan_compute_result *res)
Unset the high threshold in the Overscan Computation result object.
cpl_image * hdrl_overscan_compute_result_unset_contribution(hdrl_overscan_compute_result *res)
Unset the contribution in the Overscan Computation result object.
cpl_image * hdrl_overscan_compute_result_get_minmax_reject_low(const hdrl_overscan_compute_result *res)
Access the low threshold in the Overscan Computation result object.
hdrl_image * hdrl_overscan_compute_result_unset_correction(hdrl_overscan_compute_result *res)
Unset the correction in the Overscan Computation result object.
hdrl_image * hdrl_overscan_correct_result_get_corrected(const hdrl_overscan_correct_result *res)
Access the corrected image in the Overscan Correction result object.
hdrl_parameter * hdrl_overscan_parameter_get_rect_region(const hdrl_parameter *p)
Access the Overscan Region parameters in the Overscan Parameter.
hdrl_parameter * hdrl_overscan_parameter_get_collapse(const hdrl_parameter *p)
Access the collapse method parameters in the Overscan Parameter.
hdrl_parameter * hdrl_overscan_parameter_create(hdrl_direction correction_direction, double ccd_ron, int box_hsize, hdrl_parameter *collapse, hdrl_parameter *rect_region)
Creates Overscan Parameters object.
hdrl_image * hdrl_overscan_compute_result_get_correction(const hdrl_overscan_compute_result *res)
Access the correction in the Overscan Computation result object.
double hdrl_overscan_parameter_get_ccd_ron(const hdrl_parameter *p)
Access the CCD read out noise in the Overscan Parameter.
hdrl_direction hdrl_overscan_parameter_get_correction_direction(const hdrl_parameter *p)
Access the Correction Direction in the Overscan Parameter.
hdrl_overscan_correct_result * hdrl_overscan_correct(const hdrl_image *source, const hdrl_parameter *region, const hdrl_overscan_compute_result *os_computation)
Overscan correction.
hdrl_parameter * hdrl_overscan_parameter_parse_parlist(const cpl_parameterlist *parlist, const char *prefix)
Parse parameterlist to create input parameters for the Overscan method.
cpl_image * hdrl_overscan_compute_result_get_contribution(const hdrl_overscan_compute_result *res)
Access the contribution in the Overscan Computation result object.
int hdrl_overscan_parameter_get_box_hsize(const hdrl_parameter *p)
Access the Box Half Size in the Overscan Parameter.
cpl_image * hdrl_overscan_compute_result_unset_minmax_reject_low(hdrl_overscan_compute_result *res)
Unset the low threshold in the Overscan Computation result object.
cpl_image * hdrl_overscan_compute_result_get_sigclip_reject_high(const hdrl_overscan_compute_result *res)
Access the high threshold in the Overscan Computation result object.
void hdrl_overscan_correct_result_delete(hdrl_overscan_correct_result *result)
Delete the Overscan Correction Result Structure.
cpl_image * hdrl_overscan_compute_result_unset_sigclip_reject_low(hdrl_overscan_compute_result *res)
Unset the low threshold in the Overscan Computation result object.
cpl_image * hdrl_overscan_compute_result_unset_sigclip_reject_high(hdrl_overscan_compute_result *res)
Unset the high threshold in the Overscan Computation result object.
cpl_parameterlist * hdrl_overscan_parameter_create_parlist(const char *base_context, const char *prefix, const char *corr_dir_def, int box_hsize_def, double ccd_ron_def, hdrl_parameter *rect_region_def, const char *method_def, hdrl_parameter *sigclip_def, hdrl_parameter *minmax_def, hdrl_parameter *mode_def)
Create parameter list for the Overscan computation.
cpl_error_code hdrl_overscan_parameter_verify(const hdrl_parameter *param, cpl_size nx, cpl_size ny)
Verify basic correctness of the Overscan parameters.
void hdrl_parameter_destroy(hdrl_parameter *obj)
deep delete of a parameter
void hdrl_parameter_delete(hdrl_parameter *obj)
shallow delete of a parameter
cpl_error_code hdrl_rect_region_parameter_verify(const hdrl_parameter *param, const cpl_size max_x, const cpl_size max_y)
Verify basic correctness of the parameters.
Definition: hdrl_utils.c:560
cpl_parameterlist * hdrl_rect_region_parameter_create_parlist(const char *base_context, const char *prefix, const char *name_prefix, const hdrl_parameter *defaults)
Create parameter list for hdrl_rect_region.
Definition: hdrl_utils.c:615
cpl_size hdrl_rect_region_get_llx(const hdrl_parameter *p)
get lower left x coordinate of rectangual region
Definition: hdrl_utils.c:518
cpl_size hdrl_rect_region_get_urx(const hdrl_parameter *p)
get upper right x coordinate of rectangular region
Definition: hdrl_utils.c:536
cpl_size hdrl_rect_region_get_lly(const hdrl_parameter *p)
get lower left y coordinate of rectangual region
Definition: hdrl_utils.c:527
char * hdrl_join_string(const char *sep_, int n,...)
join strings together
Definition: hdrl_utils.c:812
cpl_size hdrl_rect_region_get_ury(const hdrl_parameter *p)
get upper right y coordinate of rectangual region
Definition: hdrl_utils.c:545
hdrl_parameter * hdrl_rect_region_parameter_parse_parlist(const cpl_parameterlist *parlist, const char *base_context, const char *name_prefix)
parse parameterlist for rectangle parameters
Definition: hdrl_utils.c:674
cpl_boolean hdrl_rect_region_parameter_check(const hdrl_parameter *self)
Check that the parameter is hdrl_rect_region parameter.
Definition: hdrl_utils.c:506