28#include "hdrl_types.h"
29#include "hdrl_image.h"
30#include "hdrl_imagelist.h"
31#include "hdrl_utils.h"
53#if CPL_VERSION_CODE > CPL_VERSION(6, 6, 255)
54static cpl_matrix * matrix_product_normal_create(
const cpl_matrix * self)
56 const size_t m = cpl_matrix_get_nrow(self);
57 cpl_matrix * product = cpl_matrix_wrap((cpl_size)m, (cpl_size)m,
58 cpl_malloc(m * m *
sizeof(
double)));
60 if (cpl_matrix_product_normal(product, self)) {
61 cpl_matrix_delete(product);
68cpl_matrix * cpl_matrix_product_normal_create(
const cpl_matrix * self);
69cpl_error_code cpl_matrix_product_transpose(cpl_matrix * self,
70 const cpl_matrix * ma,
71 const cpl_matrix * mb);
72static cpl_matrix * matrix_product_normal_create(
const cpl_matrix * self)
75 return cpl_matrix_product_normal_create(self);
96static hdrl_ls_fit_result * hdrl_ls_fit_result_create(
void)
98 return cpl_calloc(1,
sizeof(hdrl_ls_fit_result));
107static void hdrl_ls_fit_result_delete(hdrl_ls_fit_result * r)
111 cpl_matrix_delete(r->design);
112 cpl_matrix_delete(r->coef);
113 cpl_matrix_delete(r->cov);
124static cpl_vector * hdrl_ls_fit_result_get_fitted_values(
125 const hdrl_ls_fit_result * r)
127 cpl_matrix * fvalues = cpl_matrix_product_create(r->design, r->coef);
128 cpl_vector * res = cpl_vector_wrap(cpl_matrix_get_nrow(fvalues),
129 cpl_matrix_get_data(fvalues));
130 cpl_matrix_unwrap(fvalues);
142static cpl_vector * hdrl_ls_fit_result_get_residuals(
143 const hdrl_ls_fit_result * r,
144 const cpl_vector * data)
146 cpl_vector * fval = hdrl_ls_fit_result_get_fitted_values(r);
147 cpl_vector * res = cpl_vector_duplicate(data);
148 cpl_vector_subtract(res, fval);
149 cpl_vector_delete(fval);
166static double hdrl_ls_fit_result_get_chi2(
167 const hdrl_ls_fit_result * r,
168 const cpl_vector * data,
171 cpl_vector * fval = hdrl_ls_fit_result_get_residuals(r, data);
173 cpl_vector_divide(fval, errors);
174 cpl_vector_multiply(fval, fval);
175 double mswd = cpl_vector_get_sum(fval);
177 cpl_vector_delete(fval);
188static cpl_size hdrl_ls_fit_result_get_residual_dof(
const hdrl_ls_fit_result * r)
190 return cpl_matrix_get_nrow(r->design) - cpl_matrix_get_ncol(r->design);
204static cpl_matrix * vander1d(
205 const cpl_vector * sample,
207 void (*func)(
double,
double *,
size_t))
209 const size_t nr = cpl_vector_get_size(sample);
210 const size_t nc = degree + 1;
211 cpl_matrix * V = cpl_matrix_new(nr, nc);
212 double * v = cpl_matrix_get_data(V);
213 const double * d = cpl_vector_get_data_const(sample);
214 for (
size_t i = 0; i < nr; i++) {
215 func(d[i], &v[i*nc], nc);
221static void polynomial(
double x,
double * p,
size_t ncoefs)
224 for (
size_t i = 1; i < ncoefs; i++) {
238static cpl_matrix * polyvander1d(
239 const cpl_vector * sample,
242 return vander1d(sample, degree, &polynomial);
256static hdrl_ls_fit_result * fit(
257 const cpl_matrix * design,
258 const cpl_vector * values,
259 const cpl_vector * errors)
261 hdrl_ls_fit_result * r = hdrl_ls_fit_result_create();
262 r->design = cpl_matrix_duplicate(design);
264 assert(cpl_matrix_get_nrow(design) == cpl_vector_get_size(errors));
266 cpl_vector * vrhs = cpl_vector_duplicate(errors);
267 cpl_vector_power(vrhs, -1);
268 cpl_matrix * wdesign = cpl_matrix_duplicate(design);
269 for (
size_t i = 0; i < (size_t)cpl_vector_get_size(errors); i++) {
270 double w = cpl_vector_get(vrhs, i);
271 for (
size_t j = 0; j < (size_t)cpl_matrix_get_ncol(wdesign); j++) {
272 cpl_matrix_set(wdesign, i, j,
273 cpl_matrix_get(wdesign, i, j) * w);
277 cpl_vector_multiply(vrhs, values);
278 cpl_matrix * rhs = cpl_matrix_wrap(cpl_vector_get_size(vrhs), 1,
279 cpl_vector_get_data(vrhs));
284 cpl_matrix * At = cpl_matrix_transpose_create(wdesign);
285 cpl_matrix * AtA = matrix_product_normal_create(At);
288 cpl_matrix_decomp_chol(AtA);
290 cpl_matrix_solve_chol(AtA, At);
292 r->coef = cpl_matrix_product_create(At, rhs);
294 r->cov = cpl_matrix_new(cpl_matrix_get_ncol(At),
295 cpl_matrix_get_ncol(At));
296 cpl_matrix_product_transpose(r->cov, At, At);
298 cpl_matrix_delete(At);
299 cpl_matrix_delete(AtA);
302 cpl_matrix_unwrap(rhs);
303 cpl_vector_delete(vrhs);
304 cpl_matrix_delete(wdesign);
307 cpl_vector * vrhs = cpl_vector_duplicate(values);
308 cpl_matrix * rhs = cpl_matrix_wrap(cpl_vector_get_size(vrhs), 1,
309 cpl_vector_get_data(vrhs));
310 r->coef = cpl_matrix_solve_normal(design, rhs);
311 cpl_matrix_unwrap(rhs);
312 cpl_vector_delete(vrhs);
331static hdrl_ls_fit_result * polyfit1d(
332 const cpl_vector * sample,
333 const cpl_vector * values,
334 const cpl_vector * errors,
337 cpl_matrix * design = polyvander1d(sample, degree);
338 hdrl_ls_fit_result * r = fit(design, values, errors);
339 cpl_matrix_delete(design);
368 const cpl_vector * samplepos,
370 hdrl_imagelist ** coef,
374 cpl_ensure_code(degree >= 0, CPL_ERROR_INCOMPATIBLE_INPUT);
375 cpl_ensure_code(list && samplepos && coef, CPL_ERROR_NULL_INPUT);
377 cpl_ensure_code(cpl_vector_get_size(samplepos) ==
379 CPL_ERROR_INCOMPATIBLE_INPUT);
380 cpl_ensure_code(cpl_vector_get_size(samplepos) ==
382 CPL_ERROR_INCOMPATIBLE_INPUT);
384 CPL_ERROR_INCOMPATIBLE_INPUT);
386 CPL_ERROR_INCOMPATIBLE_INPUT);
389 size_t noz = degree + 1;
396 *chi2 = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
397 cpl_image_get_bpm(*chi2);
400 *dof = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
401 cpl_image_get_bpm(*dof);
403 for (
size_t z = 0; z < noz; z++) {
408 cpl_imagelist * datal, *errorl;
409 if (hdrl_imagelist_to_cplwrap(list, &datal, &errorl)) {
412 HDRL_OMP(omp parallel shared(coef, chi2, dof))
414 hdrl_vector_cache * cache =
415 hdrl_vector_cache_new(cpl_imagelist_get_size(datal), nx * 2);
417 cpl_vector * nsamppos = cpl_vector_duplicate(samplepos);
419 for (intptr_t y = 0; y < ny; y++) {
420 cpl_vector * datav[nx];
421 cpl_vector * errsv[nx];
422 hdrl_imagelist_to_vector_row(datal, y + 1, datav, cache);
423 hdrl_imagelist_to_vector_row(errorl, y + 1, errsv, cache);
424 for (intptr_t x = 0; x < nx; x++) {
426 cpl_vector * data = datav[x];
427 cpl_vector * errs = errsv[x];
428 if (data == NULL || (
size_t)cpl_vector_get_size(data) < noz) {
429 for (
size_t z = 0; z < noz; z++) {
432 (hdrl_value){NAN, NAN});
436 cpl_image_set(*chi2, x + 1, y + 1, NAN);
437 cpl_image_reject(*chi2, x + 1, y + 1);
440 int n = data ? cpl_vector_get_size(data) - noz : -noz;
441 cpl_image_set(*dof, x + 1, y + 1, n);
442 cpl_image_reject(*dof, x + 1, y + 1);
444 hdrl_cplvector_delete_to_cache(cache, data);
445 hdrl_cplvector_delete_to_cache(cache, errs);
449 hdrl_ls_fit_result * r;
452 if (cpl_vector_get_size(data) != cpl_vector_get_size(samplepos)) {
454 cpl_vector_set_size(nsamppos, cpl_vector_get_size(data));
459 cpl_vector_set(nsamppos, j++, cpl_vector_get(samplepos, i));
462 r = polyfit1d(nsamppos, data, errs, degree);
465 r = polyfit1d(samplepos, data, errs, degree);
469 for (
size_t z = 0; z < noz; z++) {
472 (hdrl_value){cpl_matrix_get(r->coef, z, 0),
473 sqrt(cpl_matrix_get(r->cov, z, z))});
476 cpl_image_set(*chi2, x + 1, y + 1,
477 hdrl_ls_fit_result_get_chi2(r, data, errs));
480 cpl_image_set(*dof, x + 1, y + 1,
481 hdrl_ls_fit_result_get_residual_dof(r));
483 hdrl_ls_fit_result_delete(r);
484 hdrl_cplvector_delete_to_cache(cache, data);
485 hdrl_cplvector_delete_to_cache(cache, errs);
488 hdrl_vector_cache_delete(cache);
489 cpl_vector_delete(nsamppos);
492 cpl_imagelist_unwrap(datal);
493 cpl_imagelist_unwrap(errorl);
495 return cpl_error_get_code();
500 cpl_image_delete(*chi2);
504 cpl_image_delete(*dof);
507 return cpl_error_get_code();
541 const cpl_imagelist * samplepos,
543 hdrl_imagelist ** coef,
547 cpl_ensure_code(degree >= 0, CPL_ERROR_INCOMPATIBLE_INPUT);
548 cpl_ensure_code(list && samplepos && coef, CPL_ERROR_NULL_INPUT);
549 cpl_ensure_code(cpl_imagelist_get_size(samplepos) ==
551 CPL_ERROR_INCOMPATIBLE_INPUT);
552 cpl_ensure_code(cpl_imagelist_get_size(samplepos) ==
554 CPL_ERROR_INCOMPATIBLE_INPUT);
556 CPL_ERROR_INCOMPATIBLE_INPUT);
558 CPL_ERROR_INCOMPATIBLE_INPUT);
560 cpl_image_get_size_x(cpl_imagelist_get_const(samplepos, 0)),
561 CPL_ERROR_INCOMPATIBLE_INPUT);
563 cpl_image_get_size_y(cpl_imagelist_get_const(samplepos, 0)),
564 CPL_ERROR_INCOMPATIBLE_INPUT);
567 size_t noz = degree + 1;
574 *chi2 = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
575 cpl_image_get_bpm(*chi2);
578 *dof = cpl_image_new(nx, ny, HDRL_TYPE_DATA);
579 cpl_image_get_bpm(*dof);
581 for (
size_t z = 0; z < noz; z++) {
586 cpl_imagelist * datal, *errorl;
587 if (hdrl_imagelist_to_cplwrap(list, &datal, &errorl)) {
590 HDRL_OMP(omp parallel shared(coef, chi2, dof))
592 hdrl_vector_cache * cache =
593 hdrl_vector_cache_new(cpl_imagelist_get_size(datal), nx * 3);
595 for (intptr_t y = 0; y < ny; y++) {
596 cpl_vector * datav[nx];
597 cpl_vector * errsv[nx];
598 cpl_vector * samplev[nx];
599 hdrl_imagelist_to_vector_row(datal, y + 1, datav, cache);
600 hdrl_imagelist_to_vector_row(errorl, y + 1, errsv, cache);
601 hdrl_imagelist_to_vector_row(samplepos, y + 1, samplev, cache);
602 for (intptr_t x = 0; x < nx; x++) {
603 cpl_vector * data = datav[x];
604 cpl_vector * errs = errsv[x];
605 cpl_vector * samp = samplev[x];
607 if (data == NULL || samp == NULL ||
608 (
size_t)cpl_vector_get_size(data) < noz ||
609 (
size_t)cpl_vector_get_size(samp) < noz) {
610 for (
size_t z = 0; z < noz; z++) {
613 (hdrl_value){NAN, NAN});
617 cpl_image_set(*chi2, x + 1, y + 1, NAN);
618 cpl_image_reject(*chi2, x + 1, y + 1);
621 int n = data ? cpl_vector_get_size(data) - noz : -noz;
622 cpl_image_set(*dof, x + 1, y + 1, n);
623 cpl_image_reject(*dof, x + 1, y + 1);
625 hdrl_cplvector_delete_to_cache(cache, data);
626 hdrl_cplvector_delete_to_cache(cache, errs);
627 hdrl_cplvector_delete_to_cache(cache, samp);
638 const cpl_image * img = cpl_imagelist_get_const(samplepos, i);
641 cpl_image_is_rejected(img, x + 1, y + 1))
645 cpl_vector_set(data, j, val.data);
646 cpl_vector_set(errs, j, val.error);
647 cpl_vector_set(samp, j, cpl_image_get(img, x + 1, y + 1, &dump));
650 cpl_vector_set_size(data, j);
651 cpl_vector_set_size(errs, j);
652 cpl_vector_set_size(samp, j);
655 hdrl_ls_fit_result * r = polyfit1d(samp, data, errs, degree);
657 for (
size_t z = 0; z < noz; z++) {
660 (hdrl_value){cpl_matrix_get(r->coef, z, 0),
661 sqrt(cpl_matrix_get(r->cov, z, z))});
664 cpl_image_set(*chi2, x + 1, y + 1,
665 hdrl_ls_fit_result_get_chi2(r, data, errs));
668 cpl_image_set(*dof, x + 1, y + 1,
669 hdrl_ls_fit_result_get_residual_dof(r));
671 hdrl_ls_fit_result_delete(r);
672 hdrl_cplvector_delete_to_cache(cache, data);
673 hdrl_cplvector_delete_to_cache(cache, errs);
674 hdrl_cplvector_delete_to_cache(cache, samp);
677 hdrl_vector_cache_delete(cache);
680 cpl_imagelist_unwrap(datal);
681 cpl_imagelist_unwrap(errorl);
683 return cpl_error_get_code();
688 cpl_image_delete(*chi2);
692 cpl_image_delete(*dof);
695 return cpl_error_get_code();
cpl_error_code hdrl_fit_polynomial_imagelist2(const hdrl_imagelist *list, const cpl_imagelist *samplepos, const int degree, hdrl_imagelist **coef, cpl_image **chi2, cpl_image **dof)
weighted least squares polynomial fit of each pixel of a imagelist
cpl_error_code hdrl_fit_polynomial_imagelist(const hdrl_imagelist *list, const cpl_vector *samplepos, const int degree, hdrl_imagelist **coef, cpl_image **chi2, cpl_image **dof)
weighted least squares polynomial fit of each pixel of a imagelist
hdrl_value hdrl_image_get_pixel(const hdrl_image *self, cpl_size xpos, cpl_size ypos, int *pis_rejected)
get pixel values of hdrl_image
int hdrl_image_is_rejected(hdrl_image *self, cpl_size xpos, cpl_size ypos)
return if pixel is marked bad
cpl_error_code hdrl_image_set_pixel(hdrl_image *self, cpl_size xpos, cpl_size ypos, hdrl_value value)
set pixel values of hdrl_image
cpl_mask * hdrl_image_get_mask(hdrl_image *himg)
get cpl bad pixel mask from image
cpl_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
cpl_size hdrl_image_get_size_x(const hdrl_image *self)
return size of X dimension of image
cpl_error_code hdrl_image_reject(hdrl_image *self, cpl_size xpos, cpl_size ypos)
mark pixel as bad
hdrl_image * hdrl_image_new(cpl_size nx, cpl_size ny)
create new zero filled hdrl image
cpl_error_code hdrl_imagelist_set(hdrl_imagelist *himlist, hdrl_image *himg, cpl_size pos)
Insert an image into an imagelist.
cpl_size hdrl_imagelist_get_size_y(const hdrl_imagelist *himlist)
Get number of rows of images in the imagelist.
void hdrl_imagelist_delete(hdrl_imagelist *himlist)
Free all memory used by a hdrl_imagelist object including the images.
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.
hdrl_imagelist * hdrl_imagelist_new(void)
Create an empty imagelist.
cpl_size hdrl_imagelist_get_size_x(const hdrl_imagelist *himlist)
Get number of colums of images in the imagelist.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.