30 #include <cxmessages.h>
31 #include <cxstrutils.h>
34 #include <cpl_propertylist.h>
35 #include <cpl_matrix.h>
36 #include <cpl_image.h>
42 #include "gichebyshev.h"
55 struct GiSLightSetup {
64 typedef struct GiSLightSetup GiSLightSetup;
67 inline static GiSLightSetup*
68 _giraffe_slightsetup_new(cxint nslices)
71 GiSLightSetup*
self = cx_calloc(1,
sizeof *
self);
74 self->slices = cpl_matrix_new(nslices, 3);
83 _giraffe_slightsetup_delete(GiSLightSetup*
self)
88 if (self->slices != NULL) {
89 cpl_matrix_delete(self->slices);
103 _giraffe_compute_isregion(cpl_matrix* xis, cpl_matrix* yis, cpl_matrix* zis,
104 const cpl_image* image,
const cpl_image* locy,
105 const cpl_image* locw,
const GiSLightSetup* setup)
108 cxint nx = cpl_image_get_size_y(image);
109 cxint ny = cpl_image_get_size_x(image);
114 cxint ismax = ny * nx;
117 cx_assert(xis != NULL);
118 cx_assert(yis != NULL);
119 cx_assert(zis != NULL);
121 cx_assert(setup->slices != NULL);
124 if (nx != cpl_image_get_size_y(locy) ||
125 nx != cpl_image_get_size_y(locw)) {
129 if (setup->istrim == FALSE) {
131 cxint nregions = cpl_image_get_size_x(locy) - 1;
136 for (xs = 0; xs < cpl_matrix_get_nrow(setup->slices); xs++) {
138 cxint xstart = CX_MAX(cpl_matrix_get(setup->slices, xs, 0), oxend);
139 cxint xend = CX_MIN(cpl_matrix_get(setup->slices, xs, 1), nx - 1);
140 cxint xstep = CX_MAX(cpl_matrix_get(setup->slices, xs, 2), 1);
143 for (x = oxend; x < xstart; x += setup->xstep) {
146 cxint lx = x * cpl_image_get_size_x(locy);
150 const cxdouble* _locy = cpl_image_get_data_const(locy);
151 const cxdouble* _locw = cpl_image_get_data_const(locw);
152 const cxdouble* _image = cpl_image_get_data_const(image);
155 if (_locw[lx] <= 0. || _locw[lx + nregions] <= 0.) {
159 ylower = (cxint)floor(_locy[lx] -
160 (_locw[lx] + setup->ewidth));
161 yupper = (cxint)ceil(_locy[lx + nregions] +
162 (_locw[lx + nregions] + setup->ewidth));
164 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
165 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
172 if (ylower > setup->iswidth) {
176 for (k = 0; k <= ylower; k += setup->ystep) {
177 cpl_matrix_set(xis, iscount, 0, x);
178 cpl_matrix_set(yis, iscount, 0, k);
179 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
190 if (ny - yupper > setup->iswidth) {
194 for (k = yupper; k < kmax; k += setup->ystep) {
195 cpl_matrix_set(xis, iscount, 0, x);
196 cpl_matrix_set(yis, iscount, 0, k);
197 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
205 for (x = xstart; x <= xend; x +=xstep) {
208 cxint lx = x * cpl_image_get_size_x(locy);
212 const cxdouble* _locy = cpl_image_get_data_const(locy);
213 const cxdouble* _locw = cpl_image_get_data_const(locw);
214 const cxdouble* _image = cpl_image_get_data_const(image);
217 if (_locw[lx] <= 0. || _locw[lx + nregions] <= 0.) {
221 ylower = (cxint)floor(_locy[lx] -
222 (_locw[lx] + setup->ewidth));
223 yupper = (cxint)ceil(_locy[lx + nregions] +
224 (_locw[lx + nregions] + setup->ewidth));
226 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
227 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
234 if (ylower > setup->iswidth) {
238 for (k = 0; k <= ylower; k += setup->ystep) {
239 cpl_matrix_set(xis, iscount, 0, x);
240 cpl_matrix_set(yis, iscount, 0, k);
241 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
252 if (ny - yupper > setup->iswidth) {
256 for (k = yupper; k < kmax; k += setup->ystep) {
257 cpl_matrix_set(xis, iscount, 0, x);
258 cpl_matrix_set(yis, iscount, 0, k);
259 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
271 for (x = oxend; x < nx; x += setup->xstep) {
274 cxint lx = x * cpl_image_get_size_x(locy);
278 const cxdouble* _locy = cpl_image_get_data_const(locy);
279 const cxdouble* _locw = cpl_image_get_data_const(locw);
280 const cxdouble* _image = cpl_image_get_data_const(image);
283 if (_locw[lx] <= 0. || _locw[lx + nregions] <= 0.) {
287 ylower = (cxint)floor(_locy[lx] -
288 (_locw[lx] + setup->ewidth));
289 yupper = (cxint)ceil(_locy[lx + nregions] +
290 (_locw[lx + nregions] + setup->ewidth));
292 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
293 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
300 if (ylower > setup->iswidth) {
304 for (k = 0; k <= ylower; k += setup->ystep) {
305 cpl_matrix_set(xis, iscount, 0, x);
306 cpl_matrix_set(yis, iscount, 0, k);
307 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
318 if (ny - yupper > setup->iswidth) {
322 for (k = yupper; k < kmax; k += setup->ystep) {
323 cpl_matrix_set(xis, iscount, 0, x);
324 cpl_matrix_set(yis, iscount, 0, k);
325 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
335 nsmax = cpl_image_get_size_x(locy) - 1;
336 for (ns = 0; ns < nsmax; ns++) {
338 cxint nregions = ns + 1;
344 for (xs = 0; xs < cpl_matrix_get_nrow(setup->slices); xs++) {
346 cxint xstart = CX_MAX(cpl_matrix_get(setup->slices, xs, 0), oxend);
347 cxint xend = CX_MIN(cpl_matrix_get(setup->slices, xs, 1), nx - 1);
350 for (x = oxend; x < xstart; x += setup->xstep) {
354 cxint lx = x * cpl_image_get_size_x(locy);
358 const cxdouble* _locy = cpl_image_get_data_const(locy);
359 const cxdouble* _locw = cpl_image_get_data_const(locw);
360 const cxdouble* _image = cpl_image_get_data_const(image);
363 if (_locw[lx + ns] <= 0.) {
367 while (_locw[lx + nregions] <= 0. &&
368 _locy[lx + nregions] <= 0.) {
374 ylower = (cxint)floor(_locy[lx + nregions] -
375 (_locw[lx + nregions] + setup->ewidth));
379 yupper = (cxint)ceil(_locy[lx + ns] +
380 (_locw[lx + ns] + setup->ewidth));
382 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
383 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
385 if (ylower - yupper <= setup->iswidth) {
389 for (k = yupper; k <= ylower && iscount < ismax;
391 cpl_matrix_set(xis, iscount, 0, x);
392 cpl_matrix_set(yis, iscount, 0, k);
393 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
399 for (x = xstart; x <= xend; x += setup->xstep) {
403 cxint lx = x * cpl_image_get_size_x(locy);
407 const cxdouble* _locy = cpl_image_get_data_const(locy);
408 const cxdouble* _locw = cpl_image_get_data_const(locw);
409 const cxdouble* _image = cpl_image_get_data_const(image);
412 if (_locw[lx + ns] <= 0.) {
416 while (_locw[lx + nregions] <= 0. &&
417 _locy[lx + nregions] <= 0.) {
423 ylower = (cxint)floor(_locy[lx + nregions] -
424 (_locw[lx + nregions] + setup->ewidth));
428 yupper = (cxint)ceil(_locy[lx + ns] +
429 (_locw[lx + ns] + setup->ewidth));
431 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
432 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
434 if (ylower - yupper <= setup->iswidth) {
438 for (k = yupper; k <= ylower && iscount < ismax;
440 cpl_matrix_set(xis, iscount, 0, x);
441 cpl_matrix_set(yis, iscount, 0, k);
442 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
452 for (x = oxend; x < nx; x += setup->xstep) {
456 cxint lx = x * cpl_image_get_size_x(locy);
460 const cxdouble* _locy = cpl_image_get_data_const(locy);
461 const cxdouble* _locw = cpl_image_get_data_const(locw);
462 const cxdouble* _image = cpl_image_get_data_const(image);
465 if (_locw[lx + ns] <= 0.) {
469 while (_locw[lx + nregions] <= 0. &&
470 _locy[lx + nregions] <= 0.) {
476 ylower = (cxint)floor(_locy[lx + nregions] -
477 (_locw[lx + nregions] + setup->ewidth));
481 yupper = (cxint)ceil(_locy[lx + ns] +
482 (_locw[lx + ns] + setup->ewidth));
484 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
485 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
487 if (ylower - yupper <= setup->iswidth) {
491 for (k = yupper; k <= ylower && iscount < ismax;
493 cpl_matrix_set(xis, iscount, 0, x);
494 cpl_matrix_set(yis, iscount, 0, k);
495 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
509 _giraffe_compute_isregion_bpm(cpl_matrix* xis, cpl_matrix* yis,
510 cpl_matrix* zis,
const cpl_image* image,
511 const cpl_image* locy,
const cpl_image* locw,
512 const cpl_image* bpixel,
513 const GiSLightSetup* setup)
516 cxint nx = cpl_image_get_size_y(image);
517 cxint ny = cpl_image_get_size_x(image);
522 cxint ismax = ny * nx;
525 cx_assert(xis != NULL);
526 cx_assert(yis != NULL);
527 cx_assert(zis != NULL);
529 cx_assert(setup->slices != NULL);
532 if (nx != cpl_image_get_size_y(locy) ||
533 nx != cpl_image_get_size_y(locw)) {
537 if (nx != cpl_image_get_size_y(bpixel) ||
538 nx != cpl_image_get_size_y(bpixel)) {
542 if (setup->istrim == FALSE) {
544 cxint nregions = cpl_image_get_size_x(locy) - 1;
550 for (xs = 0; xs < cpl_matrix_get_nrow(setup->slices); xs++) {
552 cxint xstart = CX_MAX(cpl_matrix_get(setup->slices, xs, 0), oxend);
553 cxint xend = CX_MIN(cpl_matrix_get(setup->slices, xs, 1), nx - 1);
554 cxint xstep = CX_MAX(cpl_matrix_get(setup->slices, xs, 2), 1);
557 for (x = oxend; x < xstart; x += setup->xstep) {
560 cxint lx = x * cpl_image_get_size_x(locy);
564 const cxdouble* _locy = cpl_image_get_data_const(locy);
565 const cxdouble* _locw = cpl_image_get_data_const(locw);
566 const cxdouble* _image = cpl_image_get_data_const(image);
569 if (_locw[lx] <= 0. || _locw[lx + nregions] <= 0.) {
573 ylower = (cxint)floor(_locy[lx] -
574 (_locw[lx] + setup->ewidth));
575 yupper = (cxint)ceil(_locy[lx + nregions] +
576 (_locw[lx + nregions] + setup->ewidth));
578 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
579 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
586 if (ylower > setup->iswidth) {
590 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
593 for (k = 0; k <= ylower; k += setup->ystep) {
595 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
599 cpl_matrix_set(xis, iscount, 0, x);
600 cpl_matrix_set(yis, iscount, 0, k);
601 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
612 if (ny - yupper > setup->iswidth) {
616 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
619 for (k = yupper; k < kmax; k += setup->ystep) {
621 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
625 cpl_matrix_set(xis, iscount, 0, x);
626 cpl_matrix_set(yis, iscount, 0, k);
627 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
635 for (x = xstart; x <= xend; x +=xstep) {
638 cxint lx = x * cpl_image_get_size_x(locy);
642 const cxdouble* _locy = cpl_image_get_data_const(locy);
643 const cxdouble* _locw = cpl_image_get_data_const(locw);
644 const cxdouble* _image = cpl_image_get_data_const(image);
647 if (_locw[lx] <= 0. || _locw[lx + nregions] <= 0.) {
651 ylower = (cxint)floor(_locy[lx] -
652 (_locw[lx] + setup->ewidth));
653 yupper = (cxint)ceil(_locy[lx + nregions] +
654 (_locw[lx + nregions] + setup->ewidth));
656 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
657 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
664 if (ylower > setup->iswidth) {
668 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
671 for (k = 0; k <= ylower; k += setup->ystep) {
673 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
677 cpl_matrix_set(xis, iscount, 0, x);
678 cpl_matrix_set(yis, iscount, 0, k);
679 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
690 if (ny - yupper > setup->iswidth) {
694 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
697 for (k = yupper; k < kmax; k += setup->ystep) {
699 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
703 cpl_matrix_set(xis, iscount, 0, x);
704 cpl_matrix_set(yis, iscount, 0, k);
705 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
717 for (x = oxend; x < nx; x += setup->xstep) {
720 cxint lx = x * cpl_image_get_size_x(locy);
724 const cxdouble* _locy = cpl_image_get_data_const(locy);
725 const cxdouble* _locw = cpl_image_get_data_const(locw);
726 const cxdouble* _image = cpl_image_get_data_const(image);
729 if (_locw[lx] <= 0. || _locw[lx + nregions] <= 0.) {
733 ylower = (cxint)floor(_locy[lx] -
734 (_locw[lx] + setup->ewidth));
735 yupper = (cxint)ceil(_locy[lx + nregions] +
736 (_locw[lx + nregions] + setup->ewidth));
738 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
739 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
746 if (ylower > setup->iswidth) {
750 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
753 for (k = 0; k <= ylower; k += setup->ystep) {
755 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
759 cpl_matrix_set(xis, iscount, 0, x);
760 cpl_matrix_set(yis, iscount, 0, k);
761 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
772 if (ny - yupper > setup->iswidth) {
776 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
779 for (k = yupper; k < kmax; k += setup->ystep) {
781 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
785 cpl_matrix_set(xis, iscount, 0, x);
786 cpl_matrix_set(yis, iscount, 0, k);
787 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
797 nsmax = cpl_image_get_size_x(locy) - 1;
798 for (ns = 0; ns < nsmax; ns++) {
800 cxint nregions = ns + 1;
806 for (xs = 0; xs < cpl_matrix_get_nrow(setup->slices); xs++) {
808 cxint xstart = CX_MAX(cpl_matrix_get(setup->slices, xs, 0), oxend);
809 cxint xend = CX_MIN(cpl_matrix_get(setup->slices, xs, 1), nx - 1);
812 for (x = oxend; x < xstart; x += setup->xstep) {
815 cxint lx = x * cpl_image_get_size_x(locy);
819 const cxdouble* _locy = cpl_image_get_data_const(locy);
820 const cxdouble* _locw = cpl_image_get_data_const(locw);
821 const cxdouble* _image = cpl_image_get_data_const(image);
824 if (_locw[lx + ns] <= 0.) {
828 while (_locw[lx + nregions] <= 0. &&
829 _locy[lx + nregions] <= 0.) {
835 ylower = (cxint)floor(_locy[lx + nregions] -
836 (_locw[lx + nregions] + setup->ewidth));
840 yupper = (cxint)ceil(_locy[lx + ns] +
841 (_locw[lx + ns] + setup->ewidth));
843 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
844 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
846 if (ylower - yupper > setup->iswidth) {
850 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
853 for (k = yupper; k <= ylower && iscount < ismax;
856 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
860 cpl_matrix_set(xis, iscount, 0, x);
861 cpl_matrix_set(yis, iscount, 0, k);
862 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
870 for (x = xstart; x <= xend; x += setup->xstep) {
873 cxint lx = x * cpl_image_get_size_x(locy);
877 const cxdouble* _locy = cpl_image_get_data_const(locy);
878 const cxdouble* _locw = cpl_image_get_data_const(locw);
879 const cxdouble* _image = cpl_image_get_data_const(image);
882 if (_locw[lx + ns] <= 0.) {
886 while (_locw[lx + nregions] <= 0. &&
887 _locy[lx + nregions] <= 0.) {
893 ylower = (cxint)floor(_locy[lx + nregions] -
894 (_locw[lx + nregions] + setup->ewidth));
898 yupper = (cxint)ceil(_locy[lx + ns] +
899 (_locw[lx + ns] + setup->ewidth));
901 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
902 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
904 if (ylower - yupper > setup->iswidth) {
908 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
910 for (k = yupper; k <= ylower && iscount < ismax;
913 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
917 cpl_matrix_set(xis, iscount, 0, x);
918 cpl_matrix_set(yis, iscount, 0, k);
919 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
932 for (x = oxend; x < nx; x += setup->xstep) {
935 cxint lx = x * cpl_image_get_size_x(locy);
939 const cxdouble* _locy = cpl_image_get_data_const(locy);
940 const cxdouble* _locw = cpl_image_get_data_const(locw);
941 const cxdouble* _image = cpl_image_get_data_const(image);
944 if (_locw[lx + ns] <= 0.) {
948 while (_locw[lx + nregions] <= 0. &&
949 _locy[lx + nregions] <= 0.) {
955 ylower = (cxint)floor(_locy[lx + nregions] -
956 (_locw[lx + nregions] + setup->ewidth));
960 yupper = (cxint)ceil(_locy[lx + ns] +
961 (_locw[lx + ns] + setup->ewidth));
963 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
964 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
966 if (ylower - yupper > setup->iswidth) {
970 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
973 for (k = yupper; k <= ylower && iscount < ismax;
976 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
980 cpl_matrix_set(xis, iscount, 0, x);
981 cpl_matrix_set(yis, iscount, 0, k);
982 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
997 _giraffe_slight_fit_polynom(
const cpl_image* image,
const cpl_image* locy,
998 const cpl_image* locw,
const cpl_image* bpixel,
999 cxint xorder, cxint yorder, cxint *iscount,
1000 const GiSLightSetup* setup)
1005 cxint nx = cpl_image_get_size_y(image);
1006 cxint ny = cpl_image_get_size_x(image);
1008 cpl_image* slfit = NULL;
1010 cpl_matrix* xis = cpl_matrix_new(nx * ny, 1);
1011 cpl_matrix* yis = cpl_matrix_new(nx * ny, 1);
1012 cpl_matrix* zis = cpl_matrix_new(1, nx * ny);
1017 if (bpixel != NULL) {
1018 *iscount = _giraffe_compute_isregion_bpm(xis, yis, zis, image, locy,
1019 locw, bpixel, setup);
1022 *iscount = _giraffe_compute_isregion(xis, yis, zis, image, locy,
1026 if (*iscount <= 0 || *iscount >= nx * ny) {
1028 cpl_matrix_delete(xis);
1031 cpl_matrix_delete(yis);
1034 cpl_matrix_delete(zis);
1044 cpl_matrix* base = NULL;
1045 cpl_matrix* coeff = NULL;
1046 cpl_matrix* chebyshev = NULL;
1048 GiChebyshev2D* fit = NULL;
1050 cpl_matrix_set_size(xis, *iscount, 1);
1051 cpl_matrix_set_size(yis, *iscount, 1);
1052 cpl_matrix_set_size(zis, 1, *iscount);
1058 cpl_image* tmp = cpl_image_new(ny, nx, CPL_TYPE_DOUBLE);
1059 cxdouble* _tmp = cpl_image_get_data(tmp);
1061 for (i = 0; i < *iscount; i++) {
1062 cxint k = cpl_matrix_get(xis, i, 0) * cpl_image_get_size_x(tmp) +
1063 cpl_matrix_get(yis, i, 0);
1064 _tmp[k] = cpl_matrix_get(zis, 0, i);
1067 cpl_image_save(tmp,
"idiot.fits", CPL_BPP_IEEE_FLOAT, NULL,
1069 cpl_image_delete(tmp);
1074 base = giraffe_chebyshev_base2d(0., 0., nx, ny, xorder + 1,
1075 yorder + 1, xis, yis);
1079 if (coeff == NULL) {
1080 cpl_matrix_delete(base);
1083 cpl_matrix_delete(xis);
1086 cpl_matrix_delete(yis);
1089 cpl_matrix_delete(zis);
1095 cpl_matrix_delete(base);
1098 cpl_matrix_delete(xis);
1101 cpl_matrix_delete(yis);
1104 cpl_matrix_delete(zis);
1112 chebyshev = cpl_matrix_wrap(xorder + 1, yorder + 1,
1113 cpl_matrix_get_data(coeff));
1115 fit = giraffe_chebyshev2d_new(xorder, yorder);
1116 status = giraffe_chebyshev2d_set(fit, 0., nx, 0., ny, chebyshev);
1120 giraffe_chebyshev2d_delete(fit);
1123 cpl_matrix_unwrap(chebyshev);
1126 cpl_matrix_delete(coeff);
1133 cpl_matrix_unwrap(chebyshev);
1136 cpl_matrix_delete(coeff);
1139 slfit = cpl_image_new(ny, nx, CPL_TYPE_DOUBLE);
1141 if (slfit == NULL) {
1142 giraffe_chebyshev2d_delete(fit);
1149 for (i = 0; i < nx; i++) {
1151 cxdouble* _slfit = cpl_image_get_data(slfit);
1153 for (j = 0; j < ny; j++) {
1154 cxint k = i * ny + j;
1155 cxdouble value = giraffe_chebyshev2d_eval(fit, i, j);
1157 _slfit[k] = value > 0. ? value : 0.;
1162 giraffe_chebyshev2d_delete(fit);
1198 const GiLocalization* localization,
1199 const GiImage* bpixel, GiImage* phff,
1200 const GiSLightConfig* config)
1203 const cxchar *
const fctid =
"giraffe_adjust_scattered_light";
1206 if (image == NULL) {
1210 if (localization == NULL) {
1214 if (localization->locy == NULL || localization->locw == NULL) {
1218 if (config == NULL) {
1229 cpl_msg_warning(fctid,
"Photometric flat field correction is not "
1230 "implemented! Ignoring photometric flat field.");
1234 if (strncmp(config->model,
"polynom", 7) != 0) {
1235 cpl_msg_error(fctid,
"Scattered light model `%s' is not supported!",
1243 cx_string* s = NULL;
1248 const cpl_image* _bpixel = NULL;
1250 cpl_propertylist* properties = NULL;
1252 cpl_image* slfit = NULL;
1254 GiSLightSetup* setup = _giraffe_slightsetup_new(1);
1257 setup->xstep = config->xstep;
1258 setup->ystep = config->ystep;
1259 setup->ewidth = config->ewidth;
1260 setup->iswidth = config->iswidth;
1261 setup->istrim = config->istrim;
1263 cpl_matrix_set(setup->slices, 0, 0, 0);
1264 cpl_matrix_set(setup->slices, 0, 1, cpl_image_get_size_y(_image));
1265 cpl_matrix_set(setup->slices, 0, 2, config->xstep);
1268 if (bpixel != NULL) {
1272 slfit = _giraffe_slight_fit_polynom(_image, _locy, _locw, _bpixel,
1276 if (slfit == NULL) {
1277 cpl_msg_error(fctid,
"Fitting scattered light model failed!");
1279 _giraffe_slightsetup_delete(setup);
1285 _giraffe_slightsetup_delete(setup);
1290 cpl_image_delete(slfit);
1297 cpl_propertylist_update_string(properties, GIALIAS_SLMNAME,
1299 cpl_propertylist_set_comment(properties, GIALIAS_SLMNAME,
1300 "Scattered light model type.");
1303 s = cx_string_new();
1305 if (strncmp(config->model,
"polynom", 7) == 0) {
1307 cx_string_sprintf(s,
"%d:%d", config->xorder[0],
1310 cpl_propertylist_update_string(properties, GIALIAS_SLMORDER,
1312 cpl_propertylist_set_comment(properties, GIALIAS_SLMORDER,
1313 "Scattered light polynom order "
1317 else if (strncmp(config->model,
"polyfrac", 8) == 0) {
1319 cx_string_sprintf(s,
"%d:%d/%d:%d", config->xorder[0],
1320 config->yorder[0], config->xorder[1],
1323 cpl_propertylist_update_string(properties, GIALIAS_SLMORDER,
1325 cpl_propertylist_set_comment(properties, GIALIAS_SLMORDER,
1326 "Scattered light polynom fraction "
1327 "order Xn:Yn/Xd:Xd.");
1332 cx_string_sprintf(s,
"%d:%d", config->xstep, config->ystep);
1334 cpl_propertylist_update_string(properties, GIALIAS_SLMSTEPS,
1336 cpl_propertylist_set_comment(properties, GIALIAS_SLMSTEPS,
1337 "Scattered light X, Y sampling step.");
1339 cx_string_delete(s);
1343 cpl_propertylist_update_double(properties, GIALIAS_SLMEWIDTH,
1345 cpl_propertylist_set_comment(properties, GIALIAS_SLMEWIDTH,
1346 "Extra pixels added to spectrum "
1349 cpl_propertylist_update_int(properties, GIALIAS_SLMIWIDTH,
1351 cpl_propertylist_set_comment(properties, GIALIAS_SLMIWIDTH,
1352 "Minimum required inter-spectrum "
1355 cpl_propertylist_update_bool(properties, GIALIAS_SLMTRIM,
1357 cpl_propertylist_set_comment(properties, GIALIAS_SLMTRIM,
1358 "Removal of first and last "
1359 "inter-spectrum region.");
1384 cpl_parameter* p = NULL;
1386 GiSLightConfig* config = NULL;
1393 config = cx_calloc(1,
sizeof *config);
1395 p = cpl_parameterlist_find(list,
"giraffe.slight.model.name");
1396 config->model = cx_strdup(cpl_parameter_get_string(p));
1398 if (strncmp(config->model,
"polynom", 7) != 0 &&
1399 strncmp(config->model,
"polyfrac", 8) != 0) {
1404 p = cpl_parameterlist_find(list,
"giraffe.slight.model.order");
1405 s = cpl_parameter_get_default_string(p);
1407 if (sscanf(s,
"%d,%d", &config->xorder[0], &config->yorder[0]) != 2) {
1412 config->xorder[1] = 0;
1413 config->yorder[1] = 0;
1415 s = cpl_parameter_get_string(p);
1423 cxchar** values = cx_strsplit(s,
",", 5);
1425 if (values == NULL) {
1433 config->xorder[0] = strtol(values[0], &last, 10);
1435 if (*last !=
'\0') {
1436 cx_strfreev(values);
1442 if (values[1] != NULL) {
1444 config->yorder[0] = strtol(values[1], &last, 10);
1446 if (*last !=
'\0') {
1447 cx_strfreev(values);
1455 if (strncmp(config->model,
"polyfrac", 8) == 0) {
1457 if (values[2] != NULL) {
1459 config->xorder[1] = strtol(values[2], &last, 10);
1461 if (*last !=
'\0') {
1462 cx_strfreev(values);
1470 if (values[3] != NULL) {
1472 config->yorder[1] = strtol(values[3], &last, 10);
1474 if (*last !=
'\0') {
1475 cx_strfreev(values);
1485 cx_strfreev(values);
1493 p = cpl_parameterlist_find(list,
"giraffe.slight.xstep");
1494 config->xstep = cpl_parameter_get_int(p);
1496 p = cpl_parameterlist_find(list,
"giraffe.slight.ystep");
1497 config->ystep = cpl_parameter_get_int(p);
1499 p = cpl_parameterlist_find(list,
"giraffe.slight.xslice");
1500 s = cpl_parameter_get_default_string(p);
1508 if (strncmp(s,
"none", 4) != 0) {
1513 s = cpl_parameter_get_string(p);
1521 cxchar** slices = cx_strsplit(s,
",", -1);
1523 if (slices == NULL) {
1528 cx_strfreev(slices);
1535 p = cpl_parameterlist_find(list,
"giraffe.slight.ewidth");
1536 config->ewidth = cpl_parameter_get_double(p);
1538 p = cpl_parameterlist_find(list,
"giraffe.slight.iswidth");
1539 config->iswidth = cpl_parameter_get_int(p);
1541 p = cpl_parameterlist_find(list,
"giraffe.slight.istrim");
1542 config->istrim = cpl_parameter_get_bool(p);
1544 p = cpl_parameterlist_find(list,
"giraffe.slight.phffcorrection");
1545 config->phffcor = cpl_parameter_get_bool(p);
1547 p = cpl_parameterlist_find(list,
"giraffe.slight.remove");
1548 config->remove = cpl_parameter_get_bool(p);
1572 if (config != NULL) {
1574 if (config->model != NULL) {
1575 cx_free((cxchar*)config->model);
1576 config->model = NULL;
1611 p = cpl_parameter_new_enum(
"giraffe.slight.model.name",
1613 "Name of the scattered light model to use.",
1615 "polynom", 2,
"polynom",
"polyfrac");
1616 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-model");
1617 cpl_parameterlist_append(list, p);
1620 p = cpl_parameter_new_value(
"giraffe.slight.model.order",
1622 "Scattered light model fit X and Y order.",
1625 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-order");
1626 cpl_parameterlist_append(list, p);
1629 p = cpl_parameter_new_value(
"giraffe.slight.xstep",
1631 "Interspectrum region sampling step along "
1632 "the dispersion direction.",
1635 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-xstep");
1636 cpl_parameterlist_append(list, p);
1639 p = cpl_parameter_new_value(
"giraffe.slight.ystep",
1641 "Interspectrum region sampling step along "
1642 "the spatial direction.",
1645 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-ystep");
1646 cpl_parameterlist_append(list, p);
1649 p = cpl_parameter_new_value(
"giraffe.slight.xslice",
1651 "Interspectrum region sampling step along "
1652 "the dispersion direction for a specific "
1653 "region. This overrides 'xstep' for the "
1657 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-xslice");
1658 cpl_parameterlist_append(list, p);
1661 p = cpl_parameter_new_value(
"giraffe.slight.ewidth",
1663 "Extra width [pixels] added to both sides "
1664 "of a spectrum trace.",
1667 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-ewidth");
1668 cpl_parameterlist_append(list, p);
1671 p = cpl_parameter_new_value(
"giraffe.slight.iswidth",
1673 "Minimum width [pixels] required for "
1674 "interspectrum regions.",
1677 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-iswidth");
1678 cpl_parameterlist_append(list, p);
1681 p = cpl_parameter_new_value(
"giraffe.slight.istrim",
1683 "Turn off using the first and last "
1684 "interspectrum region.",
1687 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-istrim");
1688 cpl_parameterlist_append(list, p);
1691 p = cpl_parameter_new_value(
"giraffe.slight.phffcorrection",
1693 "Use photometric flat field correction.",
1696 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-phff");
1697 cpl_parameterlist_append(list, p);
1700 p = cpl_parameter_new_value(
"giraffe.slight.remove",
1702 "Remove scattered light from the input "
1706 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-remove");
1707 cpl_parameterlist_append(list, p);
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
cxint giraffe_image_set(GiImage *self, cpl_image *image)
Sets the image data.
cxint giraffe_image_set_properties(GiImage *self, cpl_propertylist *properties)
Attaches a property list to an image.
cpl_matrix * giraffe_matrix_leastsq(const cpl_matrix *mA, const cpl_matrix *mB)
Computes the solution of an equation using a pseudo-inverse.
void giraffe_slight_config_add(cpl_parameterlist *list)
Adds parameters for the scattered light computation.
GiSLightConfig * giraffe_slight_config_create(cpl_parameterlist *list)
Creates a setup structure for the scattered light computation.
cxint giraffe_adjust_scattered_light(GiImage *result, const GiImage *image, const GiLocalization *localization, const GiImage *bpixel, GiImage *phff, const GiSLightConfig *config)
Compute a scattered light model for a given image.
void giraffe_slight_config_destroy(GiSLightConfig *config)
Destroys a scattered light setup structure.