38 #include <cxmessages.h>
39 #include <cxstrutils.h>
42 #include <cpl_propertylist.h>
43 #include <cpl_matrix.h>
44 #include <cpl_image.h>
50 #include "gichebyshev.h"
63 struct GiSLightSetup {
72 typedef struct GiSLightSetup GiSLightSetup;
75 inline static GiSLightSetup*
76 _giraffe_slightsetup_new(cxint nslices)
79 GiSLightSetup*
self = cx_calloc(1,
sizeof *
self);
82 self->slices = cpl_matrix_new(nslices, 3);
91 _giraffe_slightsetup_delete(GiSLightSetup*
self)
96 if (self->slices != NULL) {
97 cpl_matrix_delete(self->slices);
111 _giraffe_compute_isregion(cpl_matrix* xis, cpl_matrix* yis, cpl_matrix* zis,
112 const cpl_image* image,
const cpl_image* locy,
113 const cpl_image* locw,
const GiSLightSetup* setup)
116 cxint nx = cpl_image_get_size_y(image);
117 cxint ny = cpl_image_get_size_x(image);
122 cxint ismax = ny * nx;
125 cx_assert(xis != NULL);
126 cx_assert(yis != NULL);
127 cx_assert(zis != NULL);
129 cx_assert(setup->slices != NULL);
132 if (nx != cpl_image_get_size_y(locy) ||
133 nx != cpl_image_get_size_y(locw)) {
137 if (setup->istrim == FALSE) {
139 cxint nregions = cpl_image_get_size_x(locy) - 1;
144 for (xs = 0; xs < cpl_matrix_get_nrow(setup->slices); xs++) {
146 cxint xstart = CX_MAX(cpl_matrix_get(setup->slices, xs, 0), oxend);
147 cxint xend = CX_MIN(cpl_matrix_get(setup->slices, xs, 1), nx - 1);
148 cxint xstep = CX_MAX(cpl_matrix_get(setup->slices, xs, 2), 1);
151 for (x = oxend; x < xstart; x += setup->xstep) {
154 cxint lx = x * cpl_image_get_size_x(locy);
158 const cxdouble* _locy = cpl_image_get_data_const(locy);
159 const cxdouble* _locw = cpl_image_get_data_const(locw);
160 const cxdouble* _image = cpl_image_get_data_const(image);
163 if (_locw[lx] <= 0. || _locw[lx + nregions] <= 0.) {
167 ylower = (cxint)floor(_locy[lx] -
168 (_locw[lx] + setup->ewidth));
169 yupper = (cxint)ceil(_locy[lx + nregions] +
170 (_locw[lx + nregions] + setup->ewidth));
172 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
173 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
180 if (ylower > setup->iswidth) {
184 for (k = 0; k <= ylower; k += setup->ystep) {
185 cpl_matrix_set(xis, iscount, 0, x);
186 cpl_matrix_set(yis, iscount, 0, k);
187 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
198 if (ny - yupper > setup->iswidth) {
202 for (k = yupper; k < kmax; k += setup->ystep) {
203 cpl_matrix_set(xis, iscount, 0, x);
204 cpl_matrix_set(yis, iscount, 0, k);
205 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
213 for (x = xstart; x <= xend; x +=xstep) {
216 cxint lx = x * cpl_image_get_size_x(locy);
220 const cxdouble* _locy = cpl_image_get_data_const(locy);
221 const cxdouble* _locw = cpl_image_get_data_const(locw);
222 const cxdouble* _image = cpl_image_get_data_const(image);
225 if (_locw[lx] <= 0. || _locw[lx + nregions] <= 0.) {
229 ylower = (cxint)floor(_locy[lx] -
230 (_locw[lx] + setup->ewidth));
231 yupper = (cxint)ceil(_locy[lx + nregions] +
232 (_locw[lx + nregions] + setup->ewidth));
234 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
235 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
242 if (ylower > setup->iswidth) {
246 for (k = 0; k <= ylower; k += setup->ystep) {
247 cpl_matrix_set(xis, iscount, 0, x);
248 cpl_matrix_set(yis, iscount, 0, k);
249 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
260 if (ny - yupper > setup->iswidth) {
264 for (k = yupper; k < kmax; k += setup->ystep) {
265 cpl_matrix_set(xis, iscount, 0, x);
266 cpl_matrix_set(yis, iscount, 0, k);
267 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
279 for (x = oxend; x < nx; x += setup->xstep) {
282 cxint lx = x * cpl_image_get_size_x(locy);
286 const cxdouble* _locy = cpl_image_get_data_const(locy);
287 const cxdouble* _locw = cpl_image_get_data_const(locw);
288 const cxdouble* _image = cpl_image_get_data_const(image);
291 if (_locw[lx] <= 0. || _locw[lx + nregions] <= 0.) {
295 ylower = (cxint)floor(_locy[lx] -
296 (_locw[lx] + setup->ewidth));
297 yupper = (cxint)ceil(_locy[lx + nregions] +
298 (_locw[lx + nregions] + setup->ewidth));
300 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
301 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
308 if (ylower > setup->iswidth) {
312 for (k = 0; k <= ylower; k += setup->ystep) {
313 cpl_matrix_set(xis, iscount, 0, x);
314 cpl_matrix_set(yis, iscount, 0, k);
315 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
326 if (ny - yupper > setup->iswidth) {
330 for (k = yupper; k < kmax; k += setup->ystep) {
331 cpl_matrix_set(xis, iscount, 0, x);
332 cpl_matrix_set(yis, iscount, 0, k);
333 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
343 nsmax = cpl_image_get_size_x(locy) - 1;
344 for (ns = 0; ns < nsmax; ns++) {
346 cxint nregions = ns + 1;
352 for (xs = 0; xs < cpl_matrix_get_nrow(setup->slices); xs++) {
354 cxint xstart = CX_MAX(cpl_matrix_get(setup->slices, xs, 0), oxend);
355 cxint xend = CX_MIN(cpl_matrix_get(setup->slices, xs, 1), nx - 1);
358 for (x = oxend; x < xstart; x += setup->xstep) {
362 cxint lx = x * cpl_image_get_size_x(locy);
366 const cxdouble* _locy = cpl_image_get_data_const(locy);
367 const cxdouble* _locw = cpl_image_get_data_const(locw);
368 const cxdouble* _image = cpl_image_get_data_const(image);
371 if (_locw[lx + ns] <= 0.) {
375 while (_locw[lx + nregions] <= 0. &&
376 _locy[lx + nregions] <= 0.) {
382 ylower = (cxint)floor(_locy[lx + nregions] -
383 (_locw[lx + nregions] + setup->ewidth));
387 yupper = (cxint)ceil(_locy[lx + ns] +
388 (_locw[lx + ns] + setup->ewidth));
390 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
391 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
393 if (ylower - yupper <= setup->iswidth) {
397 for (k = yupper; k <= ylower && iscount < ismax;
399 cpl_matrix_set(xis, iscount, 0, x);
400 cpl_matrix_set(yis, iscount, 0, k);
401 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
407 for (x = xstart; x <= xend; x += setup->xstep) {
411 cxint lx = x * cpl_image_get_size_x(locy);
415 const cxdouble* _locy = cpl_image_get_data_const(locy);
416 const cxdouble* _locw = cpl_image_get_data_const(locw);
417 const cxdouble* _image = cpl_image_get_data_const(image);
420 if (_locw[lx + ns] <= 0.) {
424 while (_locw[lx + nregions] <= 0. &&
425 _locy[lx + nregions] <= 0.) {
431 ylower = (cxint)floor(_locy[lx + nregions] -
432 (_locw[lx + nregions] + setup->ewidth));
436 yupper = (cxint)ceil(_locy[lx + ns] +
437 (_locw[lx + ns] + setup->ewidth));
439 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
440 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
442 if (ylower - yupper <= setup->iswidth) {
446 for (k = yupper; k <= ylower && iscount < ismax;
448 cpl_matrix_set(xis, iscount, 0, x);
449 cpl_matrix_set(yis, iscount, 0, k);
450 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
460 for (x = oxend; x < nx; x += setup->xstep) {
464 cxint lx = x * cpl_image_get_size_x(locy);
468 const cxdouble* _locy = cpl_image_get_data_const(locy);
469 const cxdouble* _locw = cpl_image_get_data_const(locw);
470 const cxdouble* _image = cpl_image_get_data_const(image);
473 if (_locw[lx + ns] <= 0.) {
477 while (_locw[lx + nregions] <= 0. &&
478 _locy[lx + nregions] <= 0.) {
484 ylower = (cxint)floor(_locy[lx + nregions] -
485 (_locw[lx + nregions] + setup->ewidth));
489 yupper = (cxint)ceil(_locy[lx + ns] +
490 (_locw[lx + ns] + setup->ewidth));
492 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
493 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
495 if (ylower - yupper <= setup->iswidth) {
499 for (k = yupper; k <= ylower && iscount < ismax;
501 cpl_matrix_set(xis, iscount, 0, x);
502 cpl_matrix_set(yis, iscount, 0, k);
503 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
517 _giraffe_compute_isregion_bpm(cpl_matrix* xis, cpl_matrix* yis,
518 cpl_matrix* zis,
const cpl_image* image,
519 const cpl_image* locy,
const cpl_image* locw,
520 const cpl_image* bpixel,
521 const GiSLightSetup* setup)
524 cxint nx = cpl_image_get_size_y(image);
525 cxint ny = cpl_image_get_size_x(image);
530 cxint ismax = ny * nx;
533 cx_assert(xis != NULL);
534 cx_assert(yis != NULL);
535 cx_assert(zis != NULL);
537 cx_assert(setup->slices != NULL);
540 if (nx != cpl_image_get_size_y(locy) ||
541 nx != cpl_image_get_size_y(locw)) {
545 if (nx != cpl_image_get_size_y(bpixel) ||
546 nx != cpl_image_get_size_y(bpixel)) {
550 if (setup->istrim == FALSE) {
552 cxint nregions = cpl_image_get_size_x(locy) - 1;
558 for (xs = 0; xs < cpl_matrix_get_nrow(setup->slices); xs++) {
560 cxint xstart = CX_MAX(cpl_matrix_get(setup->slices, xs, 0), oxend);
561 cxint xend = CX_MIN(cpl_matrix_get(setup->slices, xs, 1), nx - 1);
562 cxint xstep = CX_MAX(cpl_matrix_get(setup->slices, xs, 2), 1);
565 for (x = oxend; x < xstart; x += setup->xstep) {
568 cxint lx = x * cpl_image_get_size_x(locy);
572 const cxdouble* _locy = cpl_image_get_data_const(locy);
573 const cxdouble* _locw = cpl_image_get_data_const(locw);
574 const cxdouble* _image = cpl_image_get_data_const(image);
577 if (_locw[lx] <= 0. || _locw[lx + nregions] <= 0.) {
581 ylower = (cxint)floor(_locy[lx] -
582 (_locw[lx] + setup->ewidth));
583 yupper = (cxint)ceil(_locy[lx + nregions] +
584 (_locw[lx + nregions] + setup->ewidth));
586 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
587 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
594 if (ylower > setup->iswidth) {
598 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
601 for (k = 0; k <= ylower; k += setup->ystep) {
603 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
607 cpl_matrix_set(xis, iscount, 0, x);
608 cpl_matrix_set(yis, iscount, 0, k);
609 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
620 if (ny - yupper > setup->iswidth) {
624 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
627 for (k = yupper; k < kmax; k += setup->ystep) {
629 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
633 cpl_matrix_set(xis, iscount, 0, x);
634 cpl_matrix_set(yis, iscount, 0, k);
635 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
643 for (x = xstart; x <= xend; x +=xstep) {
646 cxint lx = x * cpl_image_get_size_x(locy);
650 const cxdouble* _locy = cpl_image_get_data_const(locy);
651 const cxdouble* _locw = cpl_image_get_data_const(locw);
652 const cxdouble* _image = cpl_image_get_data_const(image);
655 if (_locw[lx] <= 0. || _locw[lx + nregions] <= 0.) {
659 ylower = (cxint)floor(_locy[lx] -
660 (_locw[lx] + setup->ewidth));
661 yupper = (cxint)ceil(_locy[lx + nregions] +
662 (_locw[lx + nregions] + setup->ewidth));
664 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
665 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
672 if (ylower > setup->iswidth) {
676 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
679 for (k = 0; k <= ylower; k += setup->ystep) {
681 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
685 cpl_matrix_set(xis, iscount, 0, x);
686 cpl_matrix_set(yis, iscount, 0, k);
687 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
698 if (ny - yupper > setup->iswidth) {
702 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
705 for (k = yupper; k < kmax; k += setup->ystep) {
707 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
711 cpl_matrix_set(xis, iscount, 0, x);
712 cpl_matrix_set(yis, iscount, 0, k);
713 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
725 for (x = oxend; x < nx; x += setup->xstep) {
728 cxint lx = x * cpl_image_get_size_x(locy);
732 const cxdouble* _locy = cpl_image_get_data_const(locy);
733 const cxdouble* _locw = cpl_image_get_data_const(locw);
734 const cxdouble* _image = cpl_image_get_data_const(image);
737 if (_locw[lx] <= 0. || _locw[lx + nregions] <= 0.) {
741 ylower = (cxint)floor(_locy[lx] -
742 (_locw[lx] + setup->ewidth));
743 yupper = (cxint)ceil(_locy[lx + nregions] +
744 (_locw[lx + nregions] + setup->ewidth));
746 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
747 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
754 if (ylower > setup->iswidth) {
758 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
761 for (k = 0; k <= ylower; k += setup->ystep) {
763 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
767 cpl_matrix_set(xis, iscount, 0, x);
768 cpl_matrix_set(yis, iscount, 0, k);
769 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
780 if (ny - yupper > setup->iswidth) {
784 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
787 for (k = yupper; k < kmax; k += setup->ystep) {
789 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
793 cpl_matrix_set(xis, iscount, 0, x);
794 cpl_matrix_set(yis, iscount, 0, k);
795 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
805 nsmax = cpl_image_get_size_x(locy) - 1;
806 for (ns = 0; ns < nsmax; ns++) {
808 cxint nregions = ns + 1;
814 for (xs = 0; xs < cpl_matrix_get_nrow(setup->slices); xs++) {
816 cxint xstart = CX_MAX(cpl_matrix_get(setup->slices, xs, 0), oxend);
817 cxint xend = CX_MIN(cpl_matrix_get(setup->slices, xs, 1), nx - 1);
820 for (x = oxend; x < xstart; x += setup->xstep) {
823 cxint lx = x * cpl_image_get_size_x(locy);
827 const cxdouble* _locy = cpl_image_get_data_const(locy);
828 const cxdouble* _locw = cpl_image_get_data_const(locw);
829 const cxdouble* _image = cpl_image_get_data_const(image);
832 if (_locw[lx + ns] <= 0.) {
836 while (_locw[lx + nregions] <= 0. &&
837 _locy[lx + nregions] <= 0.) {
843 ylower = (cxint)floor(_locy[lx + nregions] -
844 (_locw[lx + nregions] + setup->ewidth));
848 yupper = (cxint)ceil(_locy[lx + ns] +
849 (_locw[lx + ns] + setup->ewidth));
851 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
852 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
854 if (ylower - yupper > setup->iswidth) {
858 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
861 for (k = yupper; k <= ylower && iscount < ismax;
864 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
868 cpl_matrix_set(xis, iscount, 0, x);
869 cpl_matrix_set(yis, iscount, 0, k);
870 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
878 for (x = xstart; x <= xend; x += setup->xstep) {
881 cxint lx = x * cpl_image_get_size_x(locy);
885 const cxdouble* _locy = cpl_image_get_data_const(locy);
886 const cxdouble* _locw = cpl_image_get_data_const(locw);
887 const cxdouble* _image = cpl_image_get_data_const(image);
890 if (_locw[lx + ns] <= 0.) {
894 while (_locw[lx + nregions] <= 0. &&
895 _locy[lx + nregions] <= 0.) {
901 ylower = (cxint)floor(_locy[lx + nregions] -
902 (_locw[lx + nregions] + setup->ewidth));
906 yupper = (cxint)ceil(_locy[lx + ns] +
907 (_locw[lx + ns] + setup->ewidth));
909 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
910 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
912 if (ylower - yupper > setup->iswidth) {
916 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
918 for (k = yupper; k <= ylower && iscount < ismax;
921 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
925 cpl_matrix_set(xis, iscount, 0, x);
926 cpl_matrix_set(yis, iscount, 0, k);
927 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
940 for (x = oxend; x < nx; x += setup->xstep) {
943 cxint lx = x * cpl_image_get_size_x(locy);
947 const cxdouble* _locy = cpl_image_get_data_const(locy);
948 const cxdouble* _locw = cpl_image_get_data_const(locw);
949 const cxdouble* _image = cpl_image_get_data_const(image);
952 if (_locw[lx + ns] <= 0.) {
956 while (_locw[lx + nregions] <= 0. &&
957 _locy[lx + nregions] <= 0.) {
963 ylower = (cxint)floor(_locy[lx + nregions] -
964 (_locw[lx + nregions] + setup->ewidth));
968 yupper = (cxint)ceil(_locy[lx + ns] +
969 (_locw[lx + ns] + setup->ewidth));
971 ylower = CX_MAX(CX_MIN(ny, ylower), 0);
972 yupper = CX_MAX(CX_MIN(ny, yupper), 0);
974 if (ylower - yupper > setup->iswidth) {
978 const cxint* _bpixel = cpl_image_get_data_const(bpixel);
981 for (k = yupper; k <= ylower && iscount < ismax;
984 if (_bpixel[zx + k] & GIR_M_PIX_SET) {
988 cpl_matrix_set(xis, iscount, 0, x);
989 cpl_matrix_set(yis, iscount, 0, k);
990 cpl_matrix_set(zis, 0, iscount, _image[zx + k]);
1005 _giraffe_slight_fit_polynom(
const cpl_image* image,
const cpl_image* locy,
1006 const cpl_image* locw,
const cpl_image* bpixel,
1007 cxint xorder, cxint yorder, cxint *iscount,
1008 const GiSLightSetup* setup)
1013 cxint nx = cpl_image_get_size_y(image);
1014 cxint ny = cpl_image_get_size_x(image);
1016 cpl_image* slfit = NULL;
1018 cpl_matrix* xis = cpl_matrix_new(nx * ny, 1);
1019 cpl_matrix* yis = cpl_matrix_new(nx * ny, 1);
1020 cpl_matrix* zis = cpl_matrix_new(1, nx * ny);
1025 if (bpixel != NULL) {
1026 *iscount = _giraffe_compute_isregion_bpm(xis, yis, zis, image, locy,
1027 locw, bpixel, setup);
1030 *iscount = _giraffe_compute_isregion(xis, yis, zis, image, locy,
1034 if (*iscount <= 0 || *iscount >= nx * ny) {
1036 cpl_matrix_delete(xis);
1039 cpl_matrix_delete(yis);
1042 cpl_matrix_delete(zis);
1052 cpl_matrix* base = NULL;
1053 cpl_matrix* coeff = NULL;
1054 cpl_matrix* chebyshev = NULL;
1056 GiChebyshev2D* fit = NULL;
1058 cpl_matrix_set_size(xis, *iscount, 1);
1059 cpl_matrix_set_size(yis, *iscount, 1);
1060 cpl_matrix_set_size(zis, 1, *iscount);
1066 cpl_image* tmp = cpl_image_new(ny, nx, CPL_TYPE_DOUBLE);
1067 cxdouble* _tmp = cpl_image_get_data(tmp);
1069 for (i = 0; i < *iscount; i++) {
1070 cxint k = cpl_matrix_get(xis, i, 0) * cpl_image_get_size_x(tmp) +
1071 cpl_matrix_get(yis, i, 0);
1072 _tmp[k] = cpl_matrix_get(zis, 0, i);
1075 cpl_image_save(tmp,
"idiot.fits", CPL_BPP_IEEE_FLOAT, NULL,
1077 cpl_image_delete(tmp);
1082 base = giraffe_chebyshev_base2d(0., 0., nx, ny, xorder + 1,
1083 yorder + 1, xis, yis);
1087 if (coeff == NULL) {
1088 cpl_matrix_delete(base);
1091 cpl_matrix_delete(xis);
1094 cpl_matrix_delete(yis);
1097 cpl_matrix_delete(zis);
1103 cpl_matrix_delete(base);
1106 cpl_matrix_delete(xis);
1109 cpl_matrix_delete(yis);
1112 cpl_matrix_delete(zis);
1120 chebyshev = cpl_matrix_wrap(xorder + 1, yorder + 1,
1121 cpl_matrix_get_data(coeff));
1123 fit = giraffe_chebyshev2d_new(xorder, yorder);
1124 status = giraffe_chebyshev2d_set(fit, 0., nx, 0., ny, chebyshev);
1128 giraffe_chebyshev2d_delete(fit);
1131 cpl_matrix_unwrap(chebyshev);
1134 cpl_matrix_delete(coeff);
1141 cpl_matrix_unwrap(chebyshev);
1144 cpl_matrix_delete(coeff);
1147 slfit = cpl_image_new(ny, nx, CPL_TYPE_DOUBLE);
1149 if (slfit == NULL) {
1150 giraffe_chebyshev2d_delete(fit);
1157 for (i = 0; i < nx; i++) {
1159 cxdouble* _slfit = cpl_image_get_data(slfit);
1161 for (j = 0; j < ny; j++) {
1162 cxint k = i * ny + j;
1163 cxdouble value = giraffe_chebyshev2d_eval(fit, i, j);
1165 _slfit[k] = value > 0. ? value : 0.;
1170 giraffe_chebyshev2d_delete(fit);
1206 const GiLocalization* localization,
1207 const GiImage* bpixel, GiImage* phff,
1208 const GiSLightConfig* config)
1211 const cxchar *
const fctid =
"giraffe_adjust_scattered_light";
1214 if (image == NULL) {
1218 if (localization == NULL) {
1222 if (localization->locy == NULL || localization->locw == NULL) {
1226 if (config == NULL) {
1237 cpl_msg_warning(fctid,
"Photometric flat field correction is not "
1238 "implemented! Ignoring photometric flat field.");
1242 if (strncmp(config->model,
"polynom", 7) != 0) {
1243 cpl_msg_error(fctid,
"Scattered light model `%s' is not supported!",
1251 cx_string* s = NULL;
1256 const cpl_image* _bpixel = NULL;
1258 cpl_propertylist* properties = NULL;
1260 cpl_image* slfit = NULL;
1262 GiSLightSetup* setup = _giraffe_slightsetup_new(1);
1265 setup->xstep = config->xstep;
1266 setup->ystep = config->ystep;
1267 setup->ewidth = config->ewidth;
1268 setup->iswidth = config->iswidth;
1269 setup->istrim = config->istrim;
1271 cpl_matrix_set(setup->slices, 0, 0, 0);
1272 cpl_matrix_set(setup->slices, 0, 1, cpl_image_get_size_y(_image));
1273 cpl_matrix_set(setup->slices, 0, 2, config->xstep);
1276 if (bpixel != NULL) {
1280 slfit = _giraffe_slight_fit_polynom(_image, _locy, _locw, _bpixel,
1284 if (slfit == NULL) {
1285 cpl_msg_error(fctid,
"Fitting scattered light model failed!");
1287 _giraffe_slightsetup_delete(setup);
1293 _giraffe_slightsetup_delete(setup);
1298 cpl_image_delete(slfit);
1305 cpl_propertylist_update_string(properties, GIALIAS_SLMNAME,
1307 cpl_propertylist_set_comment(properties, GIALIAS_SLMNAME,
1308 "Scattered light model type.");
1311 s = cx_string_new();
1313 if (strncmp(config->model,
"polynom", 7) == 0) {
1315 cx_string_sprintf(s,
"%d:%d", config->xorder[0],
1318 cpl_propertylist_update_string(properties, GIALIAS_SLMORDER,
1320 cpl_propertylist_set_comment(properties, GIALIAS_SLMORDER,
1321 "Scattered light polynom order "
1325 else if (strncmp(config->model,
"polyfrac", 8) == 0) {
1327 cx_string_sprintf(s,
"%d:%d/%d:%d", config->xorder[0],
1328 config->yorder[0], config->xorder[1],
1331 cpl_propertylist_update_string(properties, GIALIAS_SLMORDER,
1333 cpl_propertylist_set_comment(properties, GIALIAS_SLMORDER,
1334 "Scattered light polynom fraction "
1335 "order Xn:Yn/Xd:Xd.");
1340 cx_string_sprintf(s,
"%d:%d", config->xstep, config->ystep);
1342 cpl_propertylist_update_string(properties, GIALIAS_SLMSTEPS,
1344 cpl_propertylist_set_comment(properties, GIALIAS_SLMSTEPS,
1345 "Scattered light X, Y sampling step.");
1347 cx_string_delete(s);
1351 cpl_propertylist_update_double(properties, GIALIAS_SLMEWIDTH,
1353 cpl_propertylist_set_comment(properties, GIALIAS_SLMEWIDTH,
1354 "Extra pixels added to spectrum "
1357 cpl_propertylist_update_int(properties, GIALIAS_SLMIWIDTH,
1359 cpl_propertylist_set_comment(properties, GIALIAS_SLMIWIDTH,
1360 "Minimum required inter-spectrum "
1363 cpl_propertylist_update_bool(properties, GIALIAS_SLMTRIM,
1365 cpl_propertylist_set_comment(properties, GIALIAS_SLMTRIM,
1366 "Removal of first and last "
1367 "inter-spectrum region.");
1392 cpl_parameter* p = NULL;
1394 GiSLightConfig* config = NULL;
1401 config = cx_calloc(1,
sizeof *config);
1403 p = cpl_parameterlist_find(list,
"giraffe.slight.model.name");
1404 config->model = cx_strdup(cpl_parameter_get_string(p));
1406 if (strncmp(config->model,
"polynom", 7) != 0 &&
1407 strncmp(config->model,
"polyfrac", 8) != 0) {
1412 p = cpl_parameterlist_find(list,
"giraffe.slight.model.order");
1413 s = cpl_parameter_get_default_string(p);
1415 if (sscanf(s,
"%d,%d", &config->xorder[0], &config->yorder[0]) != 2) {
1420 config->xorder[1] = 0;
1421 config->yorder[1] = 0;
1423 s = cpl_parameter_get_string(p);
1431 cxchar** values = cx_strsplit(s,
",", 5);
1433 if (values == NULL) {
1441 config->xorder[0] = strtol(values[0], &last, 10);
1443 if (*last !=
'\0') {
1444 cx_strfreev(values);
1450 if (values[1] != NULL) {
1452 config->yorder[0] = strtol(values[1], &last, 10);
1454 if (*last !=
'\0') {
1455 cx_strfreev(values);
1463 if (strncmp(config->model,
"polyfrac", 8) == 0) {
1465 if (values[2] != NULL) {
1467 config->xorder[1] = strtol(values[2], &last, 10);
1469 if (*last !=
'\0') {
1470 cx_strfreev(values);
1478 if (values[3] != NULL) {
1480 config->yorder[1] = strtol(values[3], &last, 10);
1482 if (*last !=
'\0') {
1483 cx_strfreev(values);
1493 cx_strfreev(values);
1501 p = cpl_parameterlist_find(list,
"giraffe.slight.xstep");
1502 config->xstep = cpl_parameter_get_int(p);
1504 p = cpl_parameterlist_find(list,
"giraffe.slight.ystep");
1505 config->ystep = cpl_parameter_get_int(p);
1507 p = cpl_parameterlist_find(list,
"giraffe.slight.xslice");
1508 s = cpl_parameter_get_default_string(p);
1516 if (strncmp(s,
"none", 4) != 0) {
1521 s = cpl_parameter_get_string(p);
1529 cxchar** slices = cx_strsplit(s,
",", -1);
1531 if (slices == NULL) {
1536 cx_strfreev(slices);
1543 p = cpl_parameterlist_find(list,
"giraffe.slight.ewidth");
1544 config->ewidth = cpl_parameter_get_double(p);
1546 p = cpl_parameterlist_find(list,
"giraffe.slight.iswidth");
1547 config->iswidth = cpl_parameter_get_int(p);
1549 p = cpl_parameterlist_find(list,
"giraffe.slight.istrim");
1550 config->istrim = cpl_parameter_get_bool(p);
1552 p = cpl_parameterlist_find(list,
"giraffe.slight.phffcorrection");
1553 config->phffcor = cpl_parameter_get_bool(p);
1555 p = cpl_parameterlist_find(list,
"giraffe.slight.remove");
1556 config->remove = cpl_parameter_get_bool(p);
1580 if (config != NULL) {
1582 if (config->model != NULL) {
1583 cx_free((cxchar*)config->model);
1584 config->model = NULL;
1619 p = cpl_parameter_new_enum(
"giraffe.slight.model.name",
1621 "Name of the scattered light model to use.",
1623 "polynom", 2,
"polynom",
"polyfrac");
1624 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-model");
1625 cpl_parameterlist_append(list, p);
1628 p = cpl_parameter_new_value(
"giraffe.slight.model.order",
1630 "Scattered light model fit X and Y order.",
1633 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-order");
1634 cpl_parameterlist_append(list, p);
1637 p = cpl_parameter_new_value(
"giraffe.slight.xstep",
1639 "Interspectrum region sampling step along "
1640 "the dispersion direction.",
1643 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-xstep");
1644 cpl_parameterlist_append(list, p);
1647 p = cpl_parameter_new_value(
"giraffe.slight.ystep",
1649 "Interspectrum region sampling step along "
1650 "the spatial direction.",
1653 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-ystep");
1654 cpl_parameterlist_append(list, p);
1657 p = cpl_parameter_new_value(
"giraffe.slight.xslice",
1659 "Interspectrum region sampling step along "
1660 "the dispersion direction for a specific "
1661 "region. This overrides 'xstep' for the "
1665 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-xslice");
1666 cpl_parameterlist_append(list, p);
1669 p = cpl_parameter_new_value(
"giraffe.slight.ewidth",
1671 "Extra width [pixels] added to both sides "
1672 "of a spectrum trace.",
1675 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-ewidth");
1676 cpl_parameterlist_append(list, p);
1679 p = cpl_parameter_new_value(
"giraffe.slight.iswidth",
1681 "Minimum width [pixels] required for "
1682 "interspectrum regions.",
1685 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-iswidth");
1686 cpl_parameterlist_append(list, p);
1689 p = cpl_parameter_new_value(
"giraffe.slight.istrim",
1691 "Turn off using the first and last "
1692 "interspectrum region.",
1695 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-istrim");
1696 cpl_parameterlist_append(list, p);
1699 p = cpl_parameter_new_value(
"giraffe.slight.phffcorrection",
1701 "Use photometric flat field correction.",
1704 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-phff");
1705 cpl_parameterlist_append(list, p);
1708 p = cpl_parameter_new_value(
"giraffe.slight.remove",
1710 "Remove scattered light from the input "
1714 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slight-remove");
1715 cpl_parameterlist_append(list, p);