CR2RE Pipeline Reference Manual 1.7.0
hdrl_fringe.c
1/*
2 * This file is part of the HDRL
3 * Copyright (C) 2015 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_fringe.h>
29#include <hdrl_prototyping.h>
30#include <math.h>
31
32
33
34
35/*----------------------------------------------------------------------------*/
109/*----------------------------------------------------------------------------*/
110
112
113/*---------------------------------------------------------------------------*/
153/*---------------------------------------------------------------------------*/
154cpl_error_code
155hdrl_fringe_compute(hdrl_imagelist* ilist_fringe, const cpl_imagelist * ilist_obj,
156 const cpl_mask* stat_mask, const hdrl_parameter* collapse_params,
157 hdrl_image** master, cpl_image** contrib_map,
158 cpl_table ** qctable)
159{
160 if (qctable) {
161 *qctable = NULL;
162 }
163 /*Check that ilist_fringe and collapse_params are not pointer to NULL
164 * and that there is at least one image in the hdrl imagelist */
165 cpl_error_ensure(ilist_fringe && collapse_params , CPL_ERROR_NULL_INPUT,
166 goto cleanup, "NULL input imagelist or parameter");
167 cpl_error_ensure(hdrl_imagelist_get_size(ilist_fringe) > 0 ,
168 CPL_ERROR_NULL_INPUT, goto cleanup,
169 "input imagelist is empty");
170
171 cpl_size nx, ny, nx1, ny1;
172 nx = hdrl_image_get_size_x(hdrl_imagelist_get_const(ilist_fringe, 0));
173 ny = hdrl_image_get_size_y(hdrl_imagelist_get_const(ilist_fringe, 0));
174
175 /* If there is a ilist_obj check the size and the dimensions: */
176 if (ilist_obj != NULL) {
177 cpl_error_ensure(hdrl_imagelist_get_size(ilist_fringe) ==
178 cpl_imagelist_get_size(ilist_obj),
179 CPL_ERROR_INCOMPATIBLE_INPUT, goto cleanup,
180 "size of fringe and object image list does "
181 "not match");
182
183 nx1 = cpl_image_get_size_x(cpl_imagelist_get_const(ilist_obj, 0));
184 ny1 = cpl_image_get_size_y(cpl_imagelist_get_const(ilist_obj, 0));
185 cpl_error_ensure(nx == nx1, CPL_ERROR_INCOMPATIBLE_INPUT, goto cleanup,
186 "size of fringe image and object mask does not match");
187 cpl_error_ensure(ny == ny1, CPL_ERROR_INCOMPATIBLE_INPUT, goto cleanup,
188 "size of fringe image and object mask does not match");
189 }
190
191 /* If there is a static mask check the dimensions: */
192 if (stat_mask != NULL) {
193 /* If there is a stat_mask check the dimensions: */
194 cpl_error_ensure(nx == cpl_mask_get_size_x(stat_mask),
195 CPL_ERROR_INCOMPATIBLE_INPUT, goto cleanup,
196 "size of fringe image and fringe mask does not match");
197 cpl_error_ensure(ny == cpl_mask_get_size_y(stat_mask),
198 CPL_ERROR_INCOMPATIBLE_INPUT, goto cleanup,
199 "size of fringe image and fringe mask does not match");
200 }
201
202/* This algorithm combines bpm (ilist_fringe), object list (from ilist_obj)
203 * and static mask (stat_mask) for the fringe computation but uses only
204 * the combined bpm and object list for the collapsing */
205
206/* !! This algorithm directly works on the ilist_fringe object thus it
207 * modifies ilist_fringe !! */
208
209 double bkg_level = 0.;
210 double fringe_level = 0.;
211
212 cpl_size isize = hdrl_imagelist_get_size(ilist_fringe);
213 cpl_msg_debug(cpl_func, "Measure fringe amplitudes");
214 if (qctable != NULL) {
215 *qctable = cpl_table_new(isize);
216 cpl_table_new_column(*qctable, "Background_level", CPL_TYPE_DOUBLE);
217 cpl_table_new_column(*qctable, "Fringe_amplitude", CPL_TYPE_DOUBLE);
218 }
219 for (cpl_size i = 0; i < isize; i++) {
220
221 hdrl_image * this_himg = hdrl_imagelist_get(ilist_fringe, i);
222
223 cpl_mask *this_fmsk = cpl_mask_duplicate(hdrl_image_get_mask(this_himg));
224 if (ilist_obj != NULL) {
225 const cpl_image * obj = cpl_imagelist_get_const(ilist_obj, i);
226 cpl_mask * obj_mask = cpl_mask_threshold_image_create(obj,
227 -0.5, 0.5) ;
228 cpl_mask_not(obj_mask) ;
229 cpl_mask_or(this_fmsk, obj_mask);
230 cpl_mask_delete(obj_mask) ;
231 }
232
233 /* Add the object mask to the bad pixel mask for the collapsing */
234 hdrl_image_reject_from_mask(this_himg, this_fmsk);
235
236 /* Add the static mask to the bad pixel mask and object mask for the
237 * amplitude calculation */
238
239 if (stat_mask != NULL) {
240 cpl_mask_or(this_fmsk, stat_mask);
241 }
242 cpl_errorstate prestate = cpl_errorstate_get();
243 cpl_matrix *cur_amplitudes = hdrl_mime_fringe_amplitudes(
244 hdrl_image_get_image_const(this_himg), this_fmsk);
245
246 /* Handle situation where fit is not converging */
247 if (!cpl_errorstate_is_equal(prestate)) {
248 cpl_msg_warning(cpl_func, "Background level and fringe amplitude "
249 "could not be determined! Assuming a background"
250 " level of 0 and a fringe amplitude of 1");
251 bkg_level = 0.;
252 fringe_level = 1.;
253 /* Reset error code */
254 cpl_errorstate_set(prestate);
255 }
256 else {
257 bkg_level = cpl_matrix_get(cur_amplitudes, 0, 0);
258 fringe_level = cpl_matrix_get(cur_amplitudes, 1, 0);
259 }
260
261
262 double fringe_amplitude = fringe_level - bkg_level;
263 if (qctable != NULL) {
264 cpl_table_set_double(*qctable,"Background_level", i, bkg_level);
265 cpl_table_set_double(*qctable,"Fringe_amplitude", i, fringe_amplitude);
266 }
267 cpl_msg_debug(cpl_func, "img: %04d Bkg: %12.6g Amplitude: %12.6g",
268 (int)i+1, bkg_level, fringe_amplitude);
269
270 cpl_msg_debug(cpl_func, "Rescaling image");
271
272 hdrl_image_sub_scalar(this_himg, (hdrl_value){bkg_level, 0.});
273
274 hdrl_image_div_scalar(this_himg, (hdrl_value){fringe_amplitude, 0.});
275
276 cpl_matrix_delete(cur_amplitudes);
277 cpl_mask_delete(this_fmsk);
278 }
279
280 cpl_msg_debug(cpl_func, "Combining the normalized fringes generating"
281 " the master-fringe");
282 hdrl_imagelist_collapse(ilist_fringe, collapse_params, master,
283 contrib_map);
284
285cleanup:
286 if (cpl_error_get_code() != CPL_ERROR_NONE) {
287 if (qctable) {
288 cpl_table_delete(*qctable);
289 *qctable = NULL;
290 }
291 if (master) {
292 *master = NULL;
293 }
294 if (contrib_map) {
295 *contrib_map = NULL;
296 }
297 }
298
299 return cpl_error_get_code();
300
301}
302
303/*---------------------------------------------------------------------------*/
339/*---------------------------------------------------------------------------*/
340cpl_error_code
341hdrl_fringe_correct(hdrl_imagelist * ilist_fringe, const cpl_imagelist * ilist_obj,
342 const cpl_mask * stat_mask, const hdrl_image * masterfringe,
343 cpl_table ** qctable)
344{
345 if (qctable) {
346 *qctable = NULL;
347 }
348 /*Check that ilist_fringe and masterfringe are not NULL pointers
349 * and that there is at least one image in the hdrl imagelist */
350 cpl_ensure_code(ilist_fringe && masterfringe, CPL_ERROR_NULL_INPUT);
351 cpl_ensure_code(hdrl_imagelist_get_size(ilist_fringe) > 0 ,
352 CPL_ERROR_NULL_INPUT);
353
354 cpl_size nx, ny, nx1, ny1;
355 nx = hdrl_image_get_size_x(hdrl_imagelist_get_const(ilist_fringe, 0));
356 ny = hdrl_image_get_size_y(hdrl_imagelist_get_const(ilist_fringe, 0));
357
358 /*Check the dimension of the masterfringe image*/
359 nx1 = hdrl_image_get_size_x(masterfringe);
360 ny1 = hdrl_image_get_size_y(masterfringe);
361 cpl_ensure_code(nx == nx1, CPL_ERROR_INCOMPATIBLE_INPUT );
362 cpl_ensure_code(ny == ny1, CPL_ERROR_INCOMPATIBLE_INPUT );
363
364
365 /* If there is a ilist_obj check the size and the dimensions: */
366 if (ilist_obj != NULL) {
367 cpl_ensure_code(hdrl_imagelist_get_size(ilist_fringe) ==
368 cpl_imagelist_get_size(ilist_obj),
369 CPL_ERROR_INCOMPATIBLE_INPUT);
370
371 nx1 = cpl_image_get_size_x(cpl_imagelist_get_const(ilist_obj, 0));
372 ny1 = cpl_image_get_size_y(cpl_imagelist_get_const(ilist_obj, 0));
373 cpl_ensure_code(nx == nx1, CPL_ERROR_INCOMPATIBLE_INPUT );
374 cpl_ensure_code(ny == ny1, CPL_ERROR_INCOMPATIBLE_INPUT );
375 }
376
377 /* If there is a static mask check the dimensions: */
378 if (stat_mask != NULL) {
379 /* If there is a stat_mask check the dimensions: */
380 cpl_ensure_code(nx == cpl_mask_get_size_x(stat_mask),
381 CPL_ERROR_INCOMPATIBLE_INPUT );
382 cpl_ensure_code(ny == cpl_mask_get_size_y(stat_mask),
383 CPL_ERROR_INCOMPATIBLE_INPUT );
384 }
385 /* !! This algorithm directly works on the ilist_fringe object thus it
386 * modifies ilist_fringe !! */
387
388 /* Do the actual fringemap correction */
389 double bkg_level = 0.;
390 double fringe_level = 0.;
391
392 cpl_size isize = hdrl_imagelist_get_size(ilist_fringe);
393 cpl_msg_debug(cpl_func, "Measure fringe amplitudes");
394
395 if (qctable != NULL) {
396 *qctable = cpl_table_new(isize);
397 cpl_table_new_column(*qctable, "Background_level", CPL_TYPE_DOUBLE);
398 cpl_table_new_column(*qctable, "Fringe_amplitude", CPL_TYPE_DOUBLE);
399 }
400 for (cpl_size i = 0; i < isize; i++) {
401
402 hdrl_image * this_himg = hdrl_imagelist_get(ilist_fringe, i);
403 hdrl_image * this_masterfringe = hdrl_image_duplicate(masterfringe);
404
405 cpl_mask *this_fmsk = cpl_mask_duplicate(hdrl_image_get_mask(this_himg));
406 if (stat_mask != NULL) {
407 cpl_mask_or(this_fmsk, stat_mask);
408 }
409
410 if (ilist_obj != NULL) {
411 const cpl_image * obj = cpl_imagelist_get_const(ilist_obj, i);
412 cpl_mask * obj_mask = cpl_mask_threshold_image_create(obj,
413 -0.5, 0.5) ;
414 cpl_mask_not(obj_mask) ;
415 cpl_mask_or(this_fmsk, obj_mask);
416 cpl_mask_delete(obj_mask) ;
417 }
418
419 cpl_errorstate prestate = cpl_errorstate_get();
420
421 cpl_matrix * cur_amplitudes = hdrl_mime_fringe_amplitudes_ls(
422 hdrl_image_get_image_const(this_himg), this_fmsk,
423 hdrl_image_get_image_const(this_masterfringe));
424
425 /* Handle situation where fit is not converging */
426 if (!cpl_errorstate_is_equal(prestate)) {
427 cpl_msg_warning(cpl_func, "Background level and fringe amplitude "
428 "could not be determined! Assuming a background"
429 " level of 0 and a fringe amplitude of 0, i.e. "
430 "no correction will be applied to this image");
431 bkg_level = 0.;
432 fringe_level = 0.;
433 /* Reset error code */
434 cpl_errorstate_set(prestate);
435 }
436 else {
437 bkg_level = cpl_matrix_get(cur_amplitudes, 0, 0);
438 fringe_level = cpl_matrix_get(cur_amplitudes, 1, 0);
439 }
440
441 double fringe_amplitude = fringe_level - bkg_level;
442
443 if (qctable != NULL) {
444 cpl_table_set_double(*qctable,"Background_level", i, bkg_level);
445 cpl_table_set_double(*qctable,"Fringe_amplitude", i, fringe_amplitude);
446 }
447 cpl_msg_debug(cpl_func, "img: %04d Bkg: %12.6g Amplitude: %12.6g",
448 (int)i+1, bkg_level, fringe_amplitude);
449
450 cpl_msg_debug(cpl_func, "Rescaling masterfringe");
451 hdrl_image_mul_scalar(this_masterfringe, (hdrl_value){fringe_amplitude, 0.});
452
453 cpl_msg_debug(cpl_func, "Subtract rescaled masterfringe");
454 hdrl_image_sub_image(this_himg, this_masterfringe);
455
456 hdrl_image_delete(this_masterfringe);
457 cpl_matrix_delete(cur_amplitudes);
458 cpl_mask_delete(this_fmsk);
459 }
460
461 if (cpl_error_get_code() != CPL_ERROR_NONE && qctable != NULL) {
462 cpl_table_delete(*qctable);
463 *qctable = NULL;
464 }
465
466 return cpl_error_get_code();
467
468}
469
471/*---------------------------------------------------------------------------*/
493/*---------------------------------------------------------------------------*/
494cpl_matrix *hdrl_mime_fringe_amplitudes(const cpl_image * img0,
495 const cpl_mask * mask0)
496{
497 cpl_matrix *mdata;
498 cpl_matrix *coeffs;
499 cpl_matrix *x;
500 cpl_matrix *hseries;
501 cpl_matrix *amplitudes;
502 cpl_vector *vals;
503 cpl_vector *params;
504 const double *img_data;
505 const cpl_binary *mask_data;
506 double *md;
507 double *par;
508 double mean, stdev, bkg_amp, fringe_amp;
509 int nx, ny, n, size, ns;
510 int msize, i;
511
512 cpl_ensure(img0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
513 cpl_ensure(mask0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
514 cpl_ensure(cpl_image_get_type(img0) == CPL_TYPE_DOUBLE,
515 CPL_ERROR_INVALID_TYPE, NULL);
516
517/* setting parameters
518 n number of the Hermite functions
519 */
520 n = 20;
521
522/* getting image parameters and stats
523 nx, ny dimensions of images
524 */
525 nx = cpl_image_get_size_x(img0);
526 ny = cpl_image_get_size_y(img0);
527 size = nx * ny;
528 msize = size - cpl_mask_count(mask0);
529 /* check that at least some region have been flagged */
530 cpl_ensure(msize > 0 , CPL_ERROR_ILLEGAL_INPUT,NULL);
531
532/* creating masked image */
533 mdata = cpl_matrix_new(msize, 1);
534 md = cpl_matrix_get_data(mdata);
535
536 img_data = cpl_image_get_data_double_const(img0);
537 mask_data = cpl_mask_get_data_const(mask0);
538 for (i = 0; i < size; i++, mask_data++, img_data++)
539 {
540 if (*mask_data == CPL_BINARY_0)
541 {
542 *md = (double) *img_data;
543 md++;
544 }
545 }
546 mean = cpl_matrix_get_mean(mdata);
547 stdev = cpl_matrix_get_stdev(mdata);
548
549/* computing the Hermite coefficients */
550 coeffs = hdrl_mime_hermite_functions_sums_create(n, mean, stdev, mdata);
551 cpl_matrix_multiply_scalar(coeffs, 1.0 / msize);
552
553/* reconstructing the density function as the Hermite series */
554 ns = 1000;
555 x = hdrl_mime_matrix_linspace_create(ns, mean - 4.0 * stdev,
556 mean + 4.0 * stdev);
557 hseries = hdrl_mime_hermite_series_create(n, mean, stdev, coeffs, x);
558
559/* computing the parameters of the Gaussian mixture */
560
561 params = cpl_vector_new(6);
562 par = cpl_vector_get_data(params);
563
564 par[0] = 0.62 / (sqrt(CPL_MATH_PI) * stdev);
565 par[1] = mean - 0.4 * stdev;
566 par[2] = 0.58 * stdev;
567
568 par[3] = 0.57 / (sqrt(CPL_MATH_PI) * stdev);
569 par[4] = mean + 0.3 * stdev;
570 par[5] = 0.61 * stdev;
571
572 vals = cpl_vector_wrap(ns, cpl_matrix_get_data(hseries));
573 cpl_fit_lvmq(x, NULL, vals, NULL, params, NULL, hdrl_mime_gmix1,
574 hdrl_mime_gmix_derivs1, CPL_FIT_LVMQ_TOLERANCE, CPL_FIT_LVMQ_COUNT,
575 CPL_FIT_LVMQ_MAXITER, NULL, NULL, NULL);
576
577 bkg_amp = (par[1] > par[4] ? par[4] : par[1]);
578 fringe_amp = (par[1] > par[4] ? par[1] : par[4]);
579 amplitudes = cpl_matrix_new(2, 1);
580 cpl_matrix_set(amplitudes, 0, 0, bkg_amp);
581 cpl_matrix_set(amplitudes, 1, 0, fringe_amp);
582
583/* cleaning up */
584 cpl_matrix_delete(mdata);
585 cpl_matrix_delete(coeffs);
586 cpl_matrix_delete(x);
587 cpl_matrix_delete(hseries);
588 cpl_vector_unwrap(vals);
589 cpl_vector_delete(params);
590
591 return amplitudes;
592}
593
594
595/*---------------------------------------------------------------------------*/
614/*---------------------------------------------------------------------------*/
615cpl_matrix *hdrl_mime_fringe_amplitudes_ls(const cpl_image * img0,
616 const cpl_mask * mask0, const cpl_image * fringe0)
617{
618 cpl_matrix *mdata;
619 cpl_matrix *fdata;
620 cpl_matrix *cols12;
621 cpl_matrix *coeffs;
622 cpl_matrix *amplitudes;
623 const double *img_data;
624 const cpl_binary *mask_data;
625 const double *fringe_data;
626 double *md;
627 double *fd;
628 int nx, ny, size;
629 int msize, i;
630
631 cpl_ensure(img0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
632 cpl_ensure(mask0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
633 cpl_ensure(fringe0 != NULL, CPL_ERROR_NULL_INPUT, NULL);
634 cpl_ensure(cpl_image_get_type(img0) == CPL_TYPE_DOUBLE,
635 CPL_ERROR_INVALID_TYPE, NULL);
636 cpl_ensure(cpl_image_get_type(fringe0) == CPL_TYPE_DOUBLE,
637 CPL_ERROR_INVALID_TYPE, NULL);
638
639/* getting image parameters and stats
640 nx, ny dimensions of images
641 */
642 nx = cpl_image_get_size_x(img0);
643 ny = cpl_image_get_size_y(img0);
644 size = nx * ny;
645 msize = size - cpl_mask_count(mask0);
646 /* check that at least some region have been flagged */
647 cpl_ensure(msize > 0 , CPL_ERROR_ILLEGAL_INPUT,NULL);
648
649/* creating masked image and masked fringe */
650 mdata = cpl_matrix_new(msize, 1);
651 md = cpl_matrix_get_data(mdata);
652
653 fdata = cpl_matrix_new(msize, 1);
654 fd = cpl_matrix_get_data(fdata);
655
656 img_data = cpl_image_get_data_double_const(img0);
657 mask_data = cpl_mask_get_data_const(mask0);
658 fringe_data = cpl_image_get_data_double_const(fringe0);
659 for (i = 0; i < size; i++, img_data++, mask_data++, fringe_data++)
660 {
661 if (*mask_data == CPL_BINARY_0)
662 {
663 *md = (double) *img_data;
664 *fd = (double) *fringe_data;
665 md++;
666 fd++;
667 }
668 }
669
670/* computing the least squares coefficients */
671 cols12 = cpl_matrix_new(msize, 2);
672 cpl_matrix_fill(cols12, 1.0);
673 cpl_matrix_copy(cols12, fdata, 0, 0);
674 coeffs = hdrl_mime_linalg_solve_tikhonov(cols12, mdata, 1.0e-10);
675
676/* computing the amplitudes */
677 amplitudes = cpl_matrix_new(2, 1);
678 cpl_matrix_set(amplitudes, 0, 0, cpl_matrix_get(coeffs, 1, 0));
679 cpl_matrix_set(amplitudes, 1, 0, cpl_matrix_get(coeffs, 0, 0) +
680 cpl_matrix_get(coeffs, 1, 0));
681
682/* cleaning up */
683 cpl_matrix_delete(mdata);
684 cpl_matrix_delete(fdata);
685 cpl_matrix_delete(cols12);
686 cpl_matrix_delete(coeffs);
687
688 return amplitudes;
689}
690
691
692/*---------------------------------------------------------------------------*/
703/*---------------------------------------------------------------------------*/
704int hdrl_mime_gmix_derivs1(const double x[], const double params[],
705 double result[])
706{
707 double a1, m1, sigma1;
708 double a2, m2, sigma2;
709 double tmp;
710
711/* initializing */
712 a1 = params[0];
713 m1 = params[1];
714 sigma1 = params[2];
715
716 a2 = params[3];
717 m2 = params[4];
718 sigma2 = params[5];
719
720/* evaluating */
721 tmp = (x[0] - m1) / sigma1;
722 result[0] = exp(-0.5 * tmp * tmp);
723 result[1] = a1 * exp(-0.5 * tmp * tmp);
724 result[1] *= tmp / sigma1;
725 result[2] = a1 * exp(-0.5 * tmp * tmp);
726 result[2] *= tmp * tmp / sigma1;
727
728 tmp = (x[0] - m2) / sigma2;
729 result[3] = exp(-0.5 * tmp * tmp);
730 result[4] = a2 * exp(-0.5 * tmp * tmp);
731 result[4] *= tmp / sigma2;
732 result[5] = a2 * exp(-0.5 * tmp * tmp);
733 result[5] *= tmp * tmp / sigma2;
734
735 return 0;
736}
737
738/*---------------------------------------------------------------------------*/
749/*---------------------------------------------------------------------------*/
750int hdrl_mime_gmix1(const double x[], const double params[], double *result)
751{
752 double a1, m1, sigma1;
753 double a2, m2, sigma2;
754 double tmp;
755
756/* initializing */
757 a1 = params[0];
758 m1 = params[1];
759 sigma1 = params[2];
760
761 a2 = params[3];
762 m2 = params[4];
763 sigma2 = params[5];
764
765/* evaluating */
766 tmp = (x[0] - m1) / sigma1;
767 result[0] = a1 * exp(-0.5 * tmp * tmp);
768 tmp = (x[0] - m2) / sigma2;
769 result[0] += a2 * exp(-0.5 * tmp * tmp);
770
771 return 0;
772}
773
774/*---------------------------------------------------------------------------*/
790/*---------------------------------------------------------------------------*/
791cpl_matrix *hdrl_mime_hermite_series_create(int n, double center,
792 double scale, const cpl_matrix * coeffs, const cpl_matrix * x)
793{
794 cpl_matrix *series;
795 double *ms;
796 const double *mc;
797 const double *mx;
798 double rt;
799 int i, k, size;
800
801/* testing input */
802 if (x == NULL || coeffs == NULL)
803 {
804 cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
805 return NULL;
806 }
807
808 if (n < 1 || scale <= 0.0)
809 {
810 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
811 return NULL;
812 }
813
814/* The specific dimensions of the matrix x are not used, only its size. */
815 size = cpl_matrix_get_nrow(x) * cpl_matrix_get_ncol(x);
816 mx = cpl_matrix_get_data_const(x);
817 mc = cpl_matrix_get_data_const(coeffs);
818
819/* allocating memory */
820 series = cpl_matrix_new(size, 1);
821 ms = cpl_matrix_get_data(series);
822
823/* computing the normalization constant */
824 rt = 1.0 / sqrt(sqrt(CPL_MATH_PI));
825
826/* evaluating the Hermite functions at the samples */
827 for (k = 0; k < size; k++)
828 {
829 double xk = (mx[k] - center) / scale;
830 double tmp1 = rt * exp(-0.5 * xk * xk);
831 double tmp2 = rt * sqrt(2.0) * xk * exp(-0.5 * xk * xk);
832 for (i = 2; i < n + 2; i++)
833 {
834 double tmp3 = sqrt(2) * xk * tmp2 - sqrt(i - 1) * tmp1;
835 tmp3 = tmp3 / sqrt(i);
836
837 ms[k] += tmp1 * mc[i - 2];
838 tmp1 = tmp2;
839 tmp2 = tmp3;
840 }
841 }
842
843/* normalizing */
844 cpl_matrix_multiply_scalar(series, 1 / sqrt(scale));
845
846 return series;
847}
848
849
850
851/*---------------------------------------------------------------------------*/
867/*---------------------------------------------------------------------------*/
868cpl_matrix *hdrl_mime_hermite_functions_sums_create(int n, double center,
869 double scale, const cpl_matrix * x)
870{
871 cpl_matrix *sums;
872 double *ms;
873 const double *mx;
874 double rt;
875 int i, k, size;
876 double tmp3;
877 double sqrt_i[n + 2];
878 double rsqrt_i[n + 2];
879
880/* testing input */
881 if (x == NULL)
882 {
883 cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
884 return NULL;
885 }
886
887 if (n < 1 || scale <= 0.0)
888 {
889 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
890 return NULL;
891 }
892
893/* The specific dimensions of the matrix x are not used, only its size. */
894 size = cpl_matrix_get_nrow(x) * cpl_matrix_get_ncol(x);
895 mx = cpl_matrix_get_data_const(x);
896
897/* allocating memory */
898 sums = cpl_matrix_new(n, 1);
899 ms = cpl_matrix_get_data(sums);
900
901/* computing the normalization constant */
902 rt = 1.0 / sqrt(sqrt(CPL_MATH_PI));
903 for (i = 1; i < n + 2; i++) {
904 sqrt_i[i] = sqrt(i);
905 rsqrt_i[i] = 1. / sqrt_i[i];
906 }
907
908/* evaluating the Hermite functions at the samples */
909 for (k = 0; k < size; k++)
910 {
911 double xk = (mx[k] - center) / scale;
912 double tmp1 = rt * exp(-0.5 * xk * xk);
913 double tmp2 = rt * sqrt(2.0) * xk * exp(-0.5 * xk * xk);
914 for (i = 2; i < n + 2; i++)
915 {
916 tmp3 = sqrt(2) * xk * tmp2 - sqrt_i[i - 1] * tmp1;
917 tmp3 = tmp3 * rsqrt_i[i];
918
919 ms[i - 2] += tmp1;
920 tmp1 = tmp2;
921 tmp2 = tmp3;
922 }
923 }
924
925/* normalizing */
926 cpl_matrix_multiply_scalar(sums, 1 / sqrt(scale));
927
928 return sums;
929}
931
932
cpl_error_code hdrl_fringe_correct(hdrl_imagelist *ilist_fringe, const cpl_imagelist *ilist_obj, const cpl_mask *stat_mask, const hdrl_image *masterfringe, cpl_table **qctable)
Scales and subtracts the master fringe from the images.
cpl_error_code hdrl_fringe_compute(hdrl_imagelist *ilist_fringe, const cpl_imagelist *ilist_obj, const cpl_mask *stat_mask, const hdrl_parameter *collapse_params, hdrl_image **master, cpl_image **contrib_map, cpl_table **qctable)
Calculates the master fringe and contribution map based on the.
cpl_error_code hdrl_image_sub_image(hdrl_image *self, const hdrl_image *other)
Subtract two images, store the result in the first image.
cpl_error_code hdrl_image_reject_from_mask(hdrl_image *self, const cpl_mask *map)
set bpm of hdrl_image
Definition hdrl_image.c:407
cpl_error_code hdrl_image_div_scalar(hdrl_image *self, hdrl_value value)
Elementwise division of an image with a scalar.
cpl_error_code hdrl_image_mul_scalar(hdrl_image *self, hdrl_value value)
Elementwise multiplication of an image with a scalar.
hdrl_image * hdrl_image_duplicate(const hdrl_image *himg)
copy hdrl_image
Definition hdrl_image.c:391
cpl_mask * hdrl_image_get_mask(hdrl_image *himg)
get cpl bad pixel mask from image
Definition hdrl_image.c:157
cpl_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
Definition hdrl_image.c:540
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_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
cpl_error_code hdrl_image_sub_scalar(hdrl_image *self, hdrl_value value)
Elementwise subtraction of a scalar from an image.
const hdrl_image * hdrl_imagelist_get_const(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
cpl_error_code hdrl_imagelist_collapse(const hdrl_imagelist *himlist, const hdrl_parameter *param, hdrl_image **out, cpl_image **contrib)
collapsing of image list
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
cpl_matrix * hdrl_mime_linalg_solve_tikhonov(const cpl_matrix *mat, const cpl_matrix *rhs, double alpha)
Solve an overdetermined linear system in the least-squares sense.
cpl_matrix * hdrl_mime_matrix_linspace_create(int n, double a, double b)
Create equally spaced nodes.