37 #include <cxmessages.h>
39 #include <cxstrutils.h>
41 #include <cpl_error.h>
42 #include <cpl_image.h>
43 #include <cpl_table.h>
44 #include <cpl_parameterlist.h>
49 #include "gimessages.h"
51 #include "gichebyshev.h"
53 #include "gipsfdata.h"
54 #include "gilocalization.h"
58 #include "gifiberutils.h"
71 PROFILE_PSFEXP = 1 << 1,
72 PROFILE_PSFEXP2 = 1 << 2,
73 PROFILE_GAUSSIAN = 1 << 3
76 typedef enum GiProfileId GiProfileId;
86 typedef struct GiPsfParams GiPsfParams;
97 typedef struct GiPsfBin GiPsfBin;
99 struct GiPsfParameterFit {
104 typedef struct GiPsfParameterFit GiPsfParameterFit;
139 _giraffe_psf_fit_profile1d(GiPsfParameterFit* result,
140 const GiPsfData* psfdata,
const cxchar* name,
141 const cpl_table* fibers, cxint order,
142 const GiClipParams* setup)
150 cpl_matrix* x = NULL;
151 cpl_matrix* base = NULL;
153 const cpl_image* parameter = NULL;
156 cx_assert(result != NULL);
157 cx_assert(result->coeffs != NULL);
158 cx_assert(result->fit != NULL);
159 cx_assert(psfdata != NULL && name != NULL);
160 cx_assert(fibers != NULL);
161 cx_assert(setup != NULL);
163 nb = giraffe_psfdata_bins(psfdata);
164 ns = giraffe_psfdata_fibers(psfdata);
165 nx = giraffe_psfdata_ysize(psfdata);
167 if (ns != cpl_table_get_nrow(fibers)) {
171 if ((cpl_image_get_size_x(result->fit) != ns) ||
172 (cpl_image_get_size_y(result->fit) != nx)) {
176 if ((cpl_matrix_get_nrow(result->coeffs) != order + 1) ||
177 (cpl_matrix_get_ncol(result->coeffs) != ns)) {
181 for (i = 0; i < ns; i++) {
183 register cxint j = 0;
184 register cxint valid_bins = 0;
186 for (j = 0; j < nb; j++) {
187 if (giraffe_psfdata_get_bin(psfdata, i, j) >= 0.) {
192 if (valid_bins < order + 1) {
203 x = cpl_matrix_new(nx, 1);
205 for (i = 0; i < nx; i++) {
206 cpl_matrix_set(x, i, 0, i);
209 base = giraffe_chebyshev_base1d(0., (cxdouble)nx, order + 1, x);
212 cpl_matrix_delete(x);
218 cpl_matrix_delete(x);
226 parameter = giraffe_psfdata_get_data(psfdata, name);
228 if (parameter == NULL) {
232 for (i = 0; i < ns; i++) {
240 const cxdouble* _parameter =
241 cpl_image_get_data_double_const(parameter);
244 cxdouble* _fit = cpl_image_get_data_double(result->fit);
246 cpl_matrix* y = NULL;
247 cpl_matrix* ydiff = NULL;
248 cpl_matrix* coeffs = NULL;
249 cpl_matrix* fit = NULL;
252 x = cpl_matrix_new(nb, 1);
253 y = cpl_matrix_new(1, nb);
254 ydiff = cpl_matrix_new(1, nb);
256 for (j = 0; j < nb; j++) {
258 cxdouble bin = giraffe_psfdata_get_bin(psfdata, i, j);
262 cpl_matrix_set(x, k, 0, bin);
263 cpl_matrix_set(y, 0, k, _parameter[j * ns + i]);
274 cpl_matrix_set_size(x, k, 1);
275 cpl_matrix_set_size(y, 1, k);
276 cpl_matrix_set_size(ydiff, 1, k);
278 ntotal = cpl_matrix_get_nrow(x);
281 while ((naccepted > 0) && (iteration < setup->iterations) &&
282 (ratio > setup->fraction)) {
286 cpl_matrix* _base = NULL;
289 if (coeffs != NULL) {
290 cpl_matrix_delete(coeffs);
295 cpl_matrix_delete(fit);
299 _base = giraffe_chebyshev_base1d(0., (cxdouble)nx, order + 1, x);
302 if (coeffs == NULL) {
303 cpl_matrix_delete(_base);
307 cpl_matrix_delete(_base);
310 fit = cpl_matrix_product_create(coeffs, base);
312 for (j = 0; j < cpl_matrix_get_nrow(x); j++) {
314 cxint xlower = (cxint) ceil(cpl_matrix_get(x, j, 0));
315 cxint xupper = (cxint) floor(cpl_matrix_get(x, j, 0));
317 cxdouble ylower = cpl_matrix_get(fit, 0, xlower);
318 cxdouble yupper = cpl_matrix_get(fit, 0, xupper);
319 cxdouble yfit = (yupper + ylower) / 2.;
321 cpl_matrix_set(ydiff, 0, j, cpl_matrix_get(y, 0, j) - yfit);
333 for (j = 0; j < cpl_matrix_get_ncol(ydiff); j++) {
334 if (fabs(cpl_matrix_get(ydiff, 0, j)) <= sigma) {
335 cpl_matrix_set(x, k, 0, cpl_matrix_get(x, j, 0));
336 cpl_matrix_set(y, 0, k, cpl_matrix_get(y, 0, j));
341 cpl_matrix_set_size(x, k, 1);
342 cpl_matrix_set_size(y, 1, k);
343 cpl_matrix_set_size(ydiff, 1, k);
353 if (k == naccepted) {
358 ratio = (cxdouble)naccepted / (cxdouble) ntotal;
370 cx_assert(cpl_matrix_get_ncol(coeffs) == order + 1);
372 for (j = 0; j < cpl_matrix_get_ncol(coeffs); j++) {
373 cpl_matrix_set(result->coeffs, j, i,
374 cpl_matrix_get(coeffs, 0, j));
377 for (j = 0; j < nx; j++) {
378 _fit[j * ns + i] = cpl_matrix_get(fit, 0, j);
386 cpl_matrix_delete(x);
389 cpl_matrix_delete(y);
392 cpl_matrix_delete(ydiff);
395 cpl_matrix_delete(coeffs);
398 cpl_matrix_delete(fit);
403 cpl_matrix_delete(base);
455 _giraffe_psf_fit_profile2d(GiPsfParameterFit* result,
const cpl_table* fibers,
456 const cpl_image* psfdata,
const cpl_image* xbin,
457 const cpl_image* ybin, cxint xorder, cxint yorder,
458 const cpl_image* yfit, cxint ystart, cxint yend,
459 const GiClipParams* setup)
473 cxint ncx = xorder + 1;
474 cxint ncy = yorder + 1;
478 cpl_matrix* x = NULL;
479 cpl_matrix* y = NULL;
480 cpl_matrix* z = NULL;
481 cpl_matrix* zdiff = NULL;
482 cpl_matrix* nbins = NULL;
484 GiChebyshev2D* fit = NULL;
487 cx_assert(result != NULL);
488 cx_assert(result->coeffs != NULL);
489 cx_assert(result->fit != NULL);
490 cx_assert(fibers != NULL);
491 cx_assert(psfdata != NULL);
492 cx_assert(xbin != NULL && ybin != NULL);
493 cx_assert(yfit != NULL);
494 cx_assert(setup != NULL);
496 nb = cpl_image_get_size_y(xbin);
497 ns = cpl_image_get_size_x(xbin);
498 nx = cpl_image_get_size_y(result->fit);
500 if (ns != cpl_table_get_nrow(fibers)) {
504 if ((cpl_image_get_size_x(result->fit) != ns) ||
505 (cpl_image_get_size_y(result->fit) != nx)) {
509 if ((cpl_matrix_get_nrow(result->coeffs) != ncx) ||
510 (cpl_matrix_get_ncol(result->coeffs) != ncy)) {
514 for (i = 0; i < ns; i++) {
516 register cxint j = 0;
517 register cxint valid_bins = 0;
519 const cxdouble* _xbin = cpl_image_get_data_double_const(xbin);
521 for (j = 0; j < nb; j++) {
522 if (_xbin[j * ns + i] >= 0.) {
527 if (valid_bins < ncx * ncy) {
538 x = cpl_matrix_new(nb * ns, 1);
539 y = cpl_matrix_new(nb * ns, 1);
540 z = cpl_matrix_new(1, nb * ns);
541 zdiff = cpl_matrix_new(1, nb * ns);
542 nbins = cpl_matrix_new(nb * ns, 1);
544 for (i = 0; i < ns; i++) {
546 register cxint j = 0;
548 const cxdouble* _xbin = cpl_image_get_data_double_const(xbin);
549 const cxdouble* _ybin = cpl_image_get_data_double_const(ybin);
550 const cxdouble* _zbin = cpl_image_get_data_double_const(psfdata);
553 for ( j = 0; j < nb; j++) {
555 register cxint l = j * ns + i;
558 if (_xbin[l] >= 0.) {
559 cpl_matrix_set(nbins, k, 0, nspectra);
560 cpl_matrix_set(x, k, 0, _xbin[l]);
561 cpl_matrix_set(y, k, 0, _ybin[l]);
562 cpl_matrix_set(z, 0, k, _zbin[l]);
577 cpl_matrix_set_size(x, k, 1);
578 cpl_matrix_set_size(y, k, 1);
579 cpl_matrix_set_size(z, 1, k);
580 cpl_matrix_set_size(zdiff, 1, k);
581 cpl_matrix_set_size(nbins, k, 1);
583 ntotal = cpl_matrix_get_nrow(x);
586 while ((naccepted > 0) && (iteration < setup->iterations) &&
587 (ratio > setup->fraction))
592 cpl_matrix* base = NULL;
593 cpl_matrix* coeffs = NULL;
594 cpl_matrix* _coeffs = NULL;
596 register cxdouble* _pfit = cpl_image_get_data_double(result->fit);
599 base = giraffe_chebyshev_base2d(0., ystart, nx, yend, ncx, ncy, x, y);
602 cpl_matrix_delete(nbins);
605 cpl_matrix_delete(zdiff);
608 cpl_matrix_delete(z);
611 cpl_matrix_delete(y);
614 cpl_matrix_delete(x);
622 if (_coeffs == NULL) {
623 cpl_matrix_delete(base);
626 cpl_matrix_delete(nbins);
629 cpl_matrix_delete(zdiff);
632 cpl_matrix_delete(z);
635 cpl_matrix_delete(y);
638 cpl_matrix_delete(x);
644 cpl_matrix_delete(base);
653 coeffs = cpl_matrix_wrap(xorder + 1, yorder + 1,
654 cpl_matrix_get_data(_coeffs));
657 giraffe_chebyshev2d_delete(fit);
661 fit = giraffe_chebyshev2d_new(xorder, yorder);
662 status = giraffe_chebyshev2d_set(fit, 0., nx, ystart, yend, coeffs);
665 giraffe_chebyshev2d_delete(fit);
668 cpl_matrix_unwrap(coeffs);
671 cpl_matrix_delete(_coeffs);
674 cpl_matrix_delete(nbins);
677 cpl_matrix_delete(zdiff);
680 cpl_matrix_delete(z);
683 cpl_matrix_delete(y);
686 cpl_matrix_delete(x);
692 cpl_matrix_unwrap(coeffs);
695 cpl_matrix_delete(_coeffs);
706 for (i = 0; i < ns; i++) {
708 register cxint j = 0;
710 register const cxdouble* _yfit =
711 cpl_image_get_data_double_const(yfit);
713 for (j = 0; j < nx; j++) {
715 register cxint l = j * ns + i;
717 _pfit[l] = giraffe_chebyshev2d_eval(fit, j, _yfit[l]);
723 for (i = 0; i < cpl_matrix_get_nrow(x); i++) {
725 cxint n = cpl_matrix_get(nbins, i, 0);
726 cxint lower = (cxint) ceil(cpl_matrix_get(x, i, 0)) * ns + n;
727 cxint upper = (cxint) floor(cpl_matrix_get(x, i, 0)) * ns + n;
729 cxdouble zfit = (_pfit[lower] + _pfit[upper]) / 2.;
731 cpl_matrix_set(zdiff, 0, i, cpl_matrix_get(z, 0, i) - zfit);
738 for (i = 0; i < cpl_matrix_get_ncol(zdiff); i++) {
739 if (fabs(cpl_matrix_get(zdiff, 0, i)) <= sigma) {
740 cpl_matrix_set(x, k, 0, cpl_matrix_get(x, i, 0));
741 cpl_matrix_set(y, k, 0, cpl_matrix_get(y, i, 0));
742 cpl_matrix_set(z, 0, k, cpl_matrix_get(z, 0, i));
743 cpl_matrix_set(nbins, k, 0, cpl_matrix_get(nbins, i, 0));
748 cpl_matrix_set_size(x, k, 1);
749 cpl_matrix_set_size(y, k, 1);
750 cpl_matrix_set_size(z, 1, k);
751 cpl_matrix_set_size(zdiff, 1, k);
752 cpl_matrix_set_size(nbins, k, 1);
762 if (k == naccepted) {
767 ratio = (cxdouble)naccepted / (cxdouble) ntotal;
778 for (i = 0; i < cpl_matrix_get_nrow(result->coeffs); i++) {
780 register cxint j = 0;
782 const cpl_matrix* c = giraffe_chebyshev2d_coeffs(fit);
785 for (j = 0; j < cpl_matrix_get_ncol(result->coeffs); j++) {
786 cpl_matrix_set(result->coeffs, i, j, cpl_matrix_get(c, i, j));
796 giraffe_chebyshev2d_delete(fit);
799 cpl_matrix_delete(nbins);
802 cpl_matrix_delete(zdiff);
805 cpl_matrix_delete(z);
808 cpl_matrix_delete(y);
811 cpl_matrix_delete(x);
845 _giraffe_psf_compute_profile(GiPsfData* result, cpl_image* zraw,
846 cpl_image* zvar, cpl_image* locy,
847 cpl_image* locw, cpl_table* fibers,
848 cpl_image* bpm, GiModel* profile,
852 const cxchar* model = NULL;
853 const cxchar* ridx = NULL;
855 const cxdouble cutoff = log(config->limit);
868 cpl_matrix* mx = NULL;
869 cpl_matrix* my = NULL;
870 cpl_matrix* ms = NULL;
872 cpl_image* zx = NULL;
873 cpl_image* zv = NULL;
875 GiProfileId psfmodel = 0;
878 cx_assert(result != NULL);
879 cx_assert((zraw != NULL) && (zvar != NULL));
880 cx_assert((locy != NULL) && (locw != NULL));
881 cx_assert(fibers != NULL);
882 cx_assert(profile != NULL);
883 cx_assert(config != NULL);
885 cx_assert(cpl_image_get_size_x(zraw) == cpl_image_get_size_x(zvar));
886 cx_assert(cpl_image_get_size_y(zraw) == cpl_image_get_size_y(zvar));
888 cx_assert(cpl_image_get_size_x(locy) == cpl_image_get_size_x(locw));
889 cx_assert(cpl_image_get_size_y(locy) == cpl_image_get_size_y(locw));
892 nx = cpl_image_get_size_y(zraw);
893 ny = cpl_image_get_size_x(zraw);
894 ns = cpl_table_get_nrow(fibers);
896 nbins = (cxint) giraffe_psfdata_bins(result);
898 if (ns != cpl_image_get_size_x(locy)) {
902 if ((bpm != NULL) && (cpl_image_get_type(bpm) != CPL_TYPE_INT)) {
906 if (giraffe_psfdata_fibers(result) != (cxsize) ns) {
910 if ((giraffe_psfdata_xsize(result) != (cxsize) ny) ||
911 (giraffe_psfdata_ysize(result) != (cxsize) nx)) {
921 model = giraffe_model_get_name(profile);
923 if (strcmp(model,
"psfexp") == 0) {
924 psfmodel = PROFILE_PSFEXP;
926 else if (strcmp(model,
"psfexp2") == 0) {
927 psfmodel = PROFILE_PSFEXP2;
929 else if (strcmp(model,
"gaussian") == 0) {
930 psfmodel = PROFILE_GAUSSIAN;
937 if (config->normalize != FALSE) {
942 cxdouble* zsum = cx_calloc(nx,
sizeof(cxdouble));
952 for (x = 0; x < nx; x++) {
954 register cxint y = 0;
956 register const cxdouble* _zraw =
957 cpl_image_get_data_double(zraw);
960 for (y = 0; y < ny; y++) {
961 zsum[x] += _zraw[x * ny + y];
964 if (zsum[x] > zmax) {
972 for (x = 0; x < nx; x++) {
974 register cxint y = 0;
975 register const cxint* _bpm = cpl_image_get_data_int(bpm);
977 register const cxdouble* _zraw =
978 cpl_image_get_data_double(zraw);
981 for (y = 0; y < ny; y++) {
982 register cxint i = x * ny + y;
989 if (zsum[x] > zmax) {
1002 zx = cpl_image_new(ny, nx, CPL_TYPE_DOUBLE);
1003 zv = cpl_image_new(ny, nx, CPL_TYPE_DOUBLE);
1006 for (x = 0; x < nx; x++) {
1008 register cxint y = 0;
1010 register cxdouble scale = zmax / zsum[x];
1011 register const cxdouble* _zraw = cpl_image_get_data_double(zraw);
1012 register const cxdouble* _zvar = cpl_image_get_data_double(zvar);
1013 register cxdouble* _zx = cpl_image_get_data_double(zx);
1014 register cxdouble* _zv = cpl_image_get_data_double(zv);
1016 for(y = 0; y < nx; y++) {
1017 register cxint i = x * ny + y;
1019 _zx[i] = _zraw[i] * scale;
1020 _zv[i] = _zvar[i] * scale;
1040 giraffe_error_push();
1042 exponent = giraffe_model_get_parameter(profile,
"Width2");
1044 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1048 giraffe_error_pop();
1065 mx = cpl_matrix_new(nbins * config->mwidth, 1);
1066 my = cpl_matrix_new(nbins * config->mwidth, 1);
1067 ms = cpl_matrix_new(nbins * config->mwidth, 1);
1069 if ((mx == NULL) || (my == NULL) || (ms == NULL)) {
1070 if (config->normalize == TRUE) {
1071 cpl_image_delete(zx);
1074 cpl_image_delete(zv);
1079 cpl_matrix_delete(mx);
1084 cpl_matrix_delete(my);
1089 cpl_matrix_delete(ms);
1102 giraffe_psfdata_set_model(result, giraffe_model_get_name(profile));
1104 for (n = 0; n < giraffe_model_count_parameters(profile); n++) {
1106 const cxchar* name = giraffe_model_parameter_name(profile, n);
1108 cpl_image* values = cpl_image_new(ns, nbins, CPL_TYPE_DOUBLE);
1110 if ((name == NULL) || (values == NULL)) {
1112 giraffe_psfdata_clear(result);
1114 cpl_matrix_delete(mx);
1117 cpl_matrix_delete(my);
1120 cpl_matrix_delete(ms);
1123 if (config->normalize == TRUE) {
1124 cpl_image_delete(zx);
1127 cpl_image_delete(zv);
1134 giraffe_psfdata_set_data(result, name, values);
1143 for (fiber = 0; fiber < ns; fiber++) {
1147 cxint cs = cpl_table_get_int(fibers, ridx, fiber, NULL) - 1;
1148 const cxint* _bpm = NULL;
1150 const cxdouble* _locy = cpl_image_get_data_double(locy);
1151 const cxdouble* _locw = cpl_image_get_data_double(locw);
1152 const cxdouble* _zx = cpl_image_get_data_double(zx);
1153 const cxdouble* _zv = cpl_image_get_data_double(zv);
1157 _bpm = cpl_image_get_data_int(bpm);
1165 for (x = 0, bin = 0; x < nx; x += config->bsize, bin++) {
1167 register cxint k = 0;
1168 register cxint xx = 0;
1172 cxint iterations = giraffe_model_get_iterations(profile);
1174 cxdouble amplitude = 0.;
1175 cxdouble bckground = 0.;
1176 cxdouble center = 0.;
1177 cxdouble width1 = 0.;
1178 cxdouble width2 = 0.;
1180 GiPsfBin xbin = {0., 0., 0., 0., 0.};
1187 for (k = 0, xx = x; (k < config->bsize) && (xx < nx); k++, xx++) {
1189 register cxint y = 0;
1190 register cxint l = xx * ns + cs;
1191 register cxint m = xx * ny;
1193 cxdouble zxmin = CX_MAXDOUBLE;
1194 cxdouble zxmax = 0.;
1195 cxdouble swidth = CX_MIN(_locw[l], config->mwidth);
1196 cxdouble ylo = (cxint) floor(_locy[l] - swidth);
1197 cxdouble yup = (cxint) ceil(_locy[l] + swidth);
1198 cxdouble ycenter = _locy[l];
1201 ylo = CX_MAX(0., ylo);
1202 yup = CX_MIN(ny, yup);
1206 for (y = ylo; y < yup; y++) {
1208 register cxint i = m + y;
1210 cpl_matrix_set(mx, ndata, 0, (cxdouble)y - ycenter);
1211 cpl_matrix_set(my, ndata, 0, _zx[i]);
1212 cpl_matrix_set(ms, ndata, 0, sqrt(_zv[i]));
1214 if (_zx[i] > zxmax) {
1218 if (_zx[i] < zxmin) {
1229 for (y = ylo; y < yup; y++) {
1231 register cxint i = m + y;
1234 cpl_matrix_set(mx, ndata, 0,
1235 (cxdouble)y - ycenter);
1236 cpl_matrix_set(my, ndata, 0, _zx[i]);
1237 cpl_matrix_set(ms, ndata, 0, sqrt(_zv[i]));
1239 if (_zx[i] > zxmax) {
1243 if (_zx[i] < zxmin) {
1257 xbin.ycenter += ycenter;
1258 xbin.ywidth += swidth;
1278 xbin.zmin = CX_MAX(0., xbin.zmin);
1285 giraffe_model_set_parameter(profile,
"Amplitude",
1286 xbin.zmax - xbin.zmin);
1287 giraffe_model_set_parameter(profile,
"Center", 0.);
1288 giraffe_model_set_parameter(profile,
"Background", xbin.zmin);
1291 case PROFILE_PSFEXP:
1292 width1 = pow(xbin.ywidth, exponent) / cutoff;
1293 giraffe_model_set_parameter(profile,
"Width2", exponent);
1296 case PROFILE_PSFEXP2:
1297 width1 = xbin.ywidth / pow(cutoff, 1. / exponent);
1298 giraffe_model_set_parameter(profile,
"Width2", exponent);
1301 case PROFILE_GAUSSIAN:
1302 width1 = xbin.ywidth / pow(cutoff, 0.5);
1309 giraffe_model_set_parameter(profile,
"Width1", width1);
1316 status = giraffe_model_fit_sequence(profile, mx, my, ms,
1319 amplitude = giraffe_model_get_parameter(profile,
"Amplitude");
1320 bckground = giraffe_model_get_parameter(profile,
"Background");
1321 center = giraffe_model_get_parameter(profile,
"Center");
1322 width1 = giraffe_model_get_parameter(profile,
"Width1");
1324 if ((psfmodel == PROFILE_PSFEXP) ||
1325 (psfmodel == PROFILE_PSFEXP2)) {
1326 width2 = giraffe_model_get_parameter(profile,
"Width2");
1335 if ((status != 0) ||
1336 (giraffe_model_get_position(profile) >= iterations) ||
1337 (amplitude <= 0.) ||
1349 giraffe_psfdata_set_bin(result, fiber, bin, xbin.xcenter);
1351 giraffe_psfdata_set(result,
"Amplitude", fiber, bin, amplitude);
1352 giraffe_psfdata_set(result,
"Center", fiber, bin,
1353 xbin.ycenter + center);
1354 giraffe_psfdata_set(result,
"Background", fiber, bin, bckground);
1355 giraffe_psfdata_set(result,
"Width1", fiber, bin, width1);
1357 if ((psfmodel == PROFILE_PSFEXP) ||
1358 (psfmodel == PROFILE_PSFEXP2)) {
1359 giraffe_psfdata_set(result,
"Width2", fiber, bin, width2);
1373 cpl_matrix_delete(mx);
1376 cpl_matrix_delete(my);
1379 cpl_matrix_delete(ms);
1382 if (config->normalize == TRUE) {
1383 cpl_image_delete(zx);
1386 cpl_image_delete(zv);
1422 _giraffe_psf_refine_profile(GiPsfData* result,
const GiPsfData* psfdata,
1423 cpl_image* zraw, cpl_image* zvar,
1424 cpl_table* fibers, cpl_image* bpm,
1425 GiModel* profile, GiPsfParams* config)
1428 const cxchar* model = NULL;
1430 const cxdouble cutoff = log(config->limit);
1442 cpl_matrix* mx = NULL;
1443 cpl_matrix* my = NULL;
1444 cpl_matrix* ms = NULL;
1446 GiProfileId psfmodel = 0;
1449 cx_assert(result != NULL);
1450 cx_assert(psfdata != NULL);
1451 cx_assert((zraw != NULL) && (zvar != NULL));
1452 cx_assert(fibers != NULL);
1453 cx_assert(profile != NULL);
1454 cx_assert(config != NULL);
1456 cx_assert(cpl_image_get_size_x(zraw) == cpl_image_get_size_x(zvar));
1457 cx_assert(cpl_image_get_size_y(zraw) == cpl_image_get_size_y(zvar));
1460 nx = cpl_image_get_size_y(zraw);
1461 ny = cpl_image_get_size_x(zraw);
1462 ns = cpl_table_get_nrow(fibers);
1464 if ((bpm != NULL) && (cpl_image_get_type(bpm) != CPL_TYPE_INT)) {
1468 if ((giraffe_psfdata_fibers(result) != (cxsize) ns) ||
1469 (giraffe_psfdata_bins(result) != (cxsize) nx)) {
1473 if ((giraffe_psfdata_xsize(result) != (cxsize) ny) ||
1474 (giraffe_psfdata_ysize(result) != (cxsize) nx)) {
1478 nbins = giraffe_psfdata_bins(result);
1480 if ((giraffe_psfdata_fibers(psfdata) != (cxsize) ns)) {
1484 if ((giraffe_psfdata_xsize(psfdata) != (cxsize) ny) ||
1485 (giraffe_psfdata_ysize(psfdata) != (cxsize) nx)) {
1489 binsize = nx / giraffe_psfdata_bins(psfdata);
1497 model = giraffe_model_get_name(profile);
1499 if (strcmp(model,
"psfexp") == 0) {
1500 psfmodel = PROFILE_PSFEXP;
1502 else if (strcmp(model,
"psfexp2") == 0) {
1503 psfmodel = PROFILE_PSFEXP2;
1505 else if (strcmp(model,
"gaussian") == 0) {
1506 psfmodel = PROFILE_GAUSSIAN;
1519 mx = cpl_matrix_new(nbins * config->mwidth, 1);
1520 my = cpl_matrix_new(nbins * config->mwidth, 1);
1521 ms = cpl_matrix_new(nbins * config->mwidth, 1);
1523 if ((mx == NULL) || (my == NULL) || (ms == NULL)) {
1526 cpl_matrix_delete(mx);
1531 cpl_matrix_delete(my);
1536 cpl_matrix_delete(ms);
1550 giraffe_psfdata_set_model(result, giraffe_model_get_name(profile));
1552 for (n = 0; n < giraffe_model_count_parameters(profile); n++) {
1554 const cxchar* name = giraffe_model_parameter_name(profile, n);
1556 cpl_image* values = cpl_image_new(ns, nbins, CPL_TYPE_DOUBLE);
1559 if ((name == NULL) || (values == NULL)) {
1561 giraffe_psfdata_clear(result);
1563 cpl_matrix_delete(mx);
1566 cpl_matrix_delete(my);
1569 cpl_matrix_delete(ms);
1576 giraffe_psfdata_set_data(result, name, values);
1585 for (fiber = 0; fiber < ns; fiber++) {
1588 const cxint* _bpm = NULL;
1590 const cxdouble* _zx = cpl_image_get_data_double(zraw);
1591 const cxdouble* _zv = cpl_image_get_data_double(zvar);
1595 _bpm = cpl_image_get_data_int(bpm);
1603 for (x = 0; x < nx; x++) {
1605 register cxint y = 0;
1606 register cxint m = x * ny;
1607 register cxint bin = CX_MAX(0, CX_MIN((cxint) floor(x / binsize),
1612 cxint iterations = giraffe_model_get_iterations(profile);
1614 cxdouble xcenter = 0.;
1615 cxdouble ycenter = 0.;
1616 cxdouble swidth = 0.;
1619 cxdouble amplitude = giraffe_psfdata_get(psfdata,
"Amplitude",
1621 cxdouble bckground = giraffe_psfdata_get(psfdata,
"Background",
1623 cxdouble center = giraffe_psfdata_get(psfdata,
"Center",
1625 cxdouble width1 = giraffe_psfdata_get(psfdata,
"Width1",
1627 cxdouble width2 = 0.;
1631 case PROFILE_PSFEXP:
1632 width2 = giraffe_psfdata_get(psfdata,
"Width2",
1634 swidth = pow(width1 * cutoff, 1./ width2);
1637 case PROFILE_PSFEXP2:
1638 width2 = giraffe_psfdata_get(psfdata,
"Width2",
1640 swidth = width1 * pow(cutoff, 1./ width2);
1643 case PROFILE_GAUSSIAN:
1644 swidth = width1 * pow(cutoff, 0.5);
1651 swidth = CX_MIN(swidth, config->mwidth);
1653 ylo = (cxint) floor(center - swidth);
1654 ylo = CX_MAX(0., ylo);
1656 yup = (cxint) ceil(center + swidth);
1657 yup = CX_MIN(ny, yup);
1661 for (y = ylo; y < yup; y++) {
1663 register cxint i = m + y;
1665 cpl_matrix_set(mx, ndata, 0, (cxdouble)y - center);
1666 cpl_matrix_set(my, ndata, 0, _zx[i]);
1667 cpl_matrix_set(ms, ndata, 0, sqrt(_zv[i]));
1676 for (y = ylo; y < yup; y++) {
1678 register cxint i = m + y;
1681 cpl_matrix_set(mx, ndata, 0, (cxdouble)y - center);
1682 cpl_matrix_set(my, ndata, 0, _zx[i]);
1683 cpl_matrix_set(ms, ndata, 0, sqrt(_zv[i]));
1697 bckground = CX_MAX(0., bckground);
1704 giraffe_model_set_parameter(profile,
"Amplitude", amplitude);
1705 giraffe_model_set_parameter(profile,
"Center", 0.);
1706 giraffe_model_set_parameter(profile,
"Background", bckground);
1707 giraffe_model_set_parameter(profile,
"Width1", width1);
1710 case PROFILE_PSFEXP:
1711 giraffe_model_set_parameter(profile,
"Width2", width2);
1714 case PROFILE_PSFEXP2:
1715 giraffe_model_set_parameter(profile,
"Width2", width2);
1718 case PROFILE_GAUSSIAN:
1730 status = giraffe_model_fit_sequence(profile, mx, my, ms,
1733 amplitude = giraffe_model_get_parameter(profile,
"Amplitude");
1734 bckground = giraffe_model_get_parameter(profile,
"Background");
1735 ycenter = giraffe_model_get_parameter(profile,
"Center");
1736 width1 = giraffe_model_get_parameter(profile,
"Width1");
1738 if ((psfmodel == PROFILE_PSFEXP) ||
1739 (psfmodel == PROFILE_PSFEXP2)) {
1740 width2 = giraffe_model_get_parameter(profile,
"Width2");
1750 if ((status != 0) ||
1751 (giraffe_model_get_position(profile) >= iterations) ||
1752 (amplitude <= 0.) ||
1767 giraffe_psfdata_set_bin(result, fiber, x, xcenter);
1769 giraffe_psfdata_set(result,
"Amplitude", fiber, x, amplitude);
1770 giraffe_psfdata_set(result,
"Center", fiber, x,
1772 giraffe_psfdata_set(result,
"Background", fiber, x, bckground);
1773 giraffe_psfdata_set(result,
"Width1", fiber, x, width1);
1775 if ((psfmodel == PROFILE_PSFEXP) ||
1776 (psfmodel == PROFILE_PSFEXP2)) {
1777 giraffe_psfdata_set(result,
"Width2", fiber, x, width2);
1791 cpl_matrix_delete(mx);
1794 cpl_matrix_delete(my);
1797 cpl_matrix_delete(ms);
1822 inline static GiPsfData*
1823 _giraffe_psf_fit_parameters1d(
const GiPsfData* psfdata,
1824 const cpl_table* fibers,
1825 const cxchar** names,
1827 const GiClipParams* setup)
1836 GiPsfData* psffit = NULL;
1839 cx_assert(psfdata != NULL);
1840 cx_assert(fibers != NULL);
1841 cx_assert(setup != NULL);
1843 ns = giraffe_psfdata_fibers(psfdata);
1844 nx = giraffe_psfdata_ysize(psfdata);
1845 ny = giraffe_psfdata_xsize(psfdata);
1847 psffit = giraffe_psfdata_create(ns, nx, ny, nx);
1849 giraffe_psfdata_set_model(psffit, giraffe_psfdata_get_model(psfdata));
1858 for (i = 0; i < ns; i++) {
1860 register cxint j = 0;
1862 for (j = 0; j < nx; j++) {
1863 giraffe_psfdata_set_bin(psffit, i, j, j);
1869 if (names == NULL) {
1872 cxsize count = giraffe_psfdata_parameters(psfdata);
1874 for (j = 0; j < count; j++) {
1876 const cxchar* name = giraffe_psfdata_get_name(psfdata, j);
1878 GiPsfParameterFit pfit = {NULL, NULL};
1881 pfit.fit = cpl_image_new(ns, nx, CPL_TYPE_DOUBLE);
1882 pfit.coeffs = cpl_matrix_new(order + 1, ns);
1884 status = _giraffe_psf_fit_profile1d(&pfit, psfdata, name,
1885 fibers, order, setup);
1888 cpl_matrix_delete(pfit.coeffs);
1891 cpl_image_delete(pfit.fit);
1894 giraffe_psfdata_delete(psffit);
1900 giraffe_psfdata_set_data(psffit, name, pfit.fit);
1903 cpl_matrix_delete(pfit.coeffs);
1919 while (names[i] != NULL) {
1921 if (giraffe_psfdata_contains(psfdata, names[i]) == TRUE) {
1923 GiPsfParameterFit pfit = {NULL, NULL};
1926 pfit.fit = cpl_image_new(ns, nx, CPL_TYPE_DOUBLE);
1927 pfit.coeffs = cpl_matrix_new(order + 1, ns);
1929 status = _giraffe_psf_fit_profile1d(&pfit, psfdata, names[i],
1930 fibers, order, setup);
1933 cpl_matrix_delete(pfit.coeffs);
1936 cpl_image_delete(pfit.fit);
1939 giraffe_psfdata_delete(psffit);
1945 giraffe_psfdata_set_data(psffit, names[i], pfit.fit);
1948 cpl_matrix_delete(pfit.coeffs);
1978 inline static GiPsfData*
1979 _giraffe_psf_fit_parameters(
const GiPsfData* psfdata,
1980 const cpl_table* fibers,
1981 const cxchar** names,
1982 cxint yorder, cxint worder,
1983 const GiClipParams* setup)
1986 const cxchar* center = NULL;
1994 GiPsfData* psffit = NULL;
1997 cx_assert(psfdata != NULL);
1998 cx_assert(fibers != NULL);
1999 cx_assert(names != NULL);
2000 cx_assert(setup != NULL);
2002 ns = giraffe_psfdata_fibers(psfdata);
2003 nx = giraffe_psfdata_ysize(psfdata);
2004 ny = giraffe_psfdata_xsize(psfdata);
2006 psffit = giraffe_psfdata_create(ns, nx, ny, nx);
2008 giraffe_psfdata_set_model(psffit, giraffe_psfdata_get_model(psfdata));
2017 for (i = 0; i < ns; i++) {
2019 register cxint j = 0;
2021 for (j = 0; j < nx; j++) {
2022 giraffe_psfdata_set_bin(psffit, i, j, j);
2028 if (giraffe_psfdata_contains(psfdata, center) == FALSE) {
2030 giraffe_psfdata_delete(psffit);
2038 GiPsfParameterFit pfit = {NULL, NULL};
2041 pfit.fit = cpl_image_new(ns, nx, CPL_TYPE_DOUBLE);
2042 pfit.coeffs = cpl_matrix_new(yorder + 1, ns);
2044 status = _giraffe_psf_fit_profile1d(&pfit, psfdata, center, fibers,
2048 cpl_matrix_delete(pfit.coeffs);
2051 cpl_image_delete(pfit.fit);
2054 giraffe_psfdata_delete(psffit);
2060 giraffe_psfdata_set_data(psffit, center, pfit.fit);
2063 cpl_matrix_delete(pfit.coeffs);
2072 while (names[i] != NULL) {
2074 if (giraffe_psfdata_contains(psfdata, names[i]) == TRUE) {
2076 const cpl_image* xbin = giraffe_psfdata_get_bins(psfdata);
2077 const cpl_image* ybin = giraffe_psfdata_get_data(psfdata, center);
2078 const cpl_image* yfit = giraffe_psfdata_get_data(psffit, center);
2079 const cpl_image* pdata = giraffe_psfdata_get_data(psfdata,
2082 GiPsfParameterFit pfit = {NULL, NULL};
2085 pfit.fit = cpl_image_new(ns, nx, CPL_TYPE_DOUBLE);
2086 pfit.coeffs = cpl_matrix_new(yorder + 1, worder + 1);
2088 status = _giraffe_psf_fit_profile2d(&pfit, fibers, pdata, xbin,
2089 ybin, yorder, worder, yfit,
2093 cpl_matrix_delete(pfit.coeffs);
2096 cpl_image_delete(pfit.fit);
2099 giraffe_psfdata_delete(psffit);
2105 giraffe_psfdata_set_data(psffit, names[i], pfit.fit);
2108 cpl_matrix_delete(pfit.coeffs);
2135 _giraffe_psf_compute_mask(GiMaskPosition* positions, GiMaskPosition* coeffs,
2136 const GiPsfData* psfdata,
const cpl_table* fibers,
2137 cxint yorder, cxint worder,
2138 const GiClipParams* setup)
2141 const cxchar*
const lcenter =
"Center";
2142 const cxchar*
const lwidth =
"Width1";
2143 const cxchar*
const lexponent =
"Width2";
2144 const cxchar* model = NULL;
2152 const cpl_image* xbin = NULL;
2153 const cpl_image* ybin = NULL;
2154 cpl_image* width = NULL;
2156 GiPsfParameterFit center = {NULL, NULL};
2157 GiPsfParameterFit halfwidth = {NULL, NULL};
2159 GiProfileId psfmodel = 0;
2162 cx_assert((positions != NULL) &&
2163 (positions->type == GIMASK_FITTED_DATA) &&
2164 (positions->my != NULL) &&
2165 (positions->mw != NULL));
2166 cx_assert((coeffs != NULL) &&
2167 (coeffs->type == GIMASK_FIT_COEFFS) &&
2168 (coeffs->my != NULL) &&
2169 (coeffs->mw != NULL));
2170 cx_assert(psfdata != NULL);
2171 cx_assert(fibers != NULL);
2172 cx_assert(setup != NULL);
2174 model = giraffe_psfdata_get_model(psfdata);
2176 if (strcmp(model,
"psfexp") == 0) {
2177 psfmodel = PROFILE_PSFEXP;
2179 else if (strcmp(model,
"psfexp2") == 0) {
2180 psfmodel = PROFILE_PSFEXP2;
2182 else if (strcmp(model,
"gaussian") == 0) {
2183 psfmodel = PROFILE_GAUSSIAN;
2189 ns = giraffe_psfdata_fibers(psfdata);
2190 nx = giraffe_psfdata_ysize(psfdata);
2191 ny = giraffe_psfdata_xsize(psfdata);
2193 if ((cpl_matrix_get_nrow(positions->my) != nx) ||
2194 (cpl_matrix_get_ncol(positions->my) != ns) ||
2195 (cpl_matrix_get_nrow(positions->mw) != nx) ||
2196 (cpl_matrix_get_ncol(positions->mw) != ns)) {
2200 if ((cpl_matrix_get_nrow(coeffs->my) != yorder + 1) ||
2201 (cpl_matrix_get_ncol(coeffs->my) != ns)) {
2205 if ((cpl_matrix_get_nrow(coeffs->mw) != worder + 1) ||
2206 (cpl_matrix_get_ncol(coeffs->mw) != worder + 1)) {
2210 if (giraffe_psfdata_contains(psfdata, lcenter) == FALSE ||
2211 giraffe_psfdata_contains(psfdata, lwidth) == FALSE) {
2215 center.fit = cpl_image_wrap_double(ns, nx,
2216 cpl_matrix_get_data(positions->my));
2217 center.coeffs = coeffs->my;
2219 status = _giraffe_psf_fit_profile1d(¢er, psfdata, lcenter, fibers,
2223 cpl_image_unwrap(center.fit);
2226 center.coeffs = NULL;
2231 width = cpl_image_new(ns, nx, CPL_TYPE_DOUBLE);
2234 case PROFILE_PSFEXP:
2237 const cxdouble LOG2 = log(2.);
2239 if (giraffe_psfdata_contains(psfdata, lexponent) == FALSE) {
2240 cpl_image_delete(width);
2243 cpl_image_unwrap(center.fit);
2245 center.coeffs = NULL;
2250 for (i = 0; i < ns; i++) {
2252 register cxint j = 0;
2254 register cxdouble* _width = cpl_image_get_data_double(width);
2257 for (j = 0; j < nx; j++) {
2259 register cxint k = j * ns + i;
2262 giraffe_psfdata_get(psfdata, lwidth, i, j);
2264 giraffe_psfdata_get(psfdata, lexponent, i, j);
2267 _width[k] = 2. * pow(LOG2 * width1, 1. / width2);
2276 case PROFILE_PSFEXP2:
2279 const cxdouble LOG2 = log(2.);
2281 if (giraffe_psfdata_contains(psfdata, lexponent) == FALSE) {
2282 cpl_image_delete(width);
2285 cpl_image_unwrap(center.fit);
2287 center.coeffs = NULL;
2292 for (i = 0; i < ns; i++) {
2294 register cxint j = 0;
2296 register cxdouble* _width = cpl_image_get_data_double(width);
2299 for (j = 0; j < nx; j++) {
2301 register cxint k = j * ns + i;
2304 giraffe_psfdata_get(psfdata, lwidth, i, j);
2306 giraffe_psfdata_get(psfdata, lexponent, i, j);
2309 _width[k] = 2. * pow(LOG2, 1. / width2) * width1;
2318 case PROFILE_GAUSSIAN:
2321 const cxdouble fwhmscale = 4. * sqrt(2. * log(2.));
2323 for (i = 0; i < ns; i++) {
2325 register cxint j = 0;
2327 register cxdouble* _width = cpl_image_get_data_double(width);
2330 for (j = 0; j < nx; j++) {
2332 register cxint k = j * ns + i;
2334 _width[k] = fwhmscale *
2335 giraffe_psfdata_get(psfdata, lwidth, i, j);
2346 cpl_image_delete(width);
2349 cpl_image_unwrap(center.fit);
2351 center.coeffs = NULL;
2353 gi_error(
"Unsupported PSF profile model encountered!");
2358 xbin = giraffe_psfdata_get_bins(psfdata);
2359 ybin = giraffe_psfdata_get_data(psfdata, lcenter);
2362 halfwidth.fit = cpl_image_wrap_double(ns, nx,
2363 cpl_matrix_get_data(positions->mw));
2364 halfwidth.coeffs = coeffs->mw;
2366 status = _giraffe_psf_fit_profile2d(&halfwidth, fibers, width, xbin,
2367 ybin, worder, worder, center.fit,
2371 cpl_image_unwrap(halfwidth.fit);
2372 halfwidth.fit = NULL;
2373 halfwidth.coeffs = NULL;
2375 cpl_image_delete(width);
2378 cpl_image_unwrap(center.fit);
2380 center.coeffs = NULL;
2385 cpl_image_unwrap(halfwidth.fit);
2386 halfwidth.fit = NULL;
2387 halfwidth.coeffs = NULL;
2389 cpl_image_delete(width);
2392 cpl_image_unwrap(center.fit);
2394 center.coeffs = NULL;
2401 inline static cpl_image*
2402 _giraffe_psf_simulate_mask(
const GiPsfData* psfdata,
2403 const cpl_image* amplitude,
2404 const cpl_image* background,
2408 const cxchar* model = NULL;
2418 cxdouble bsize = 1.;
2419 cxdouble _bsize = 1.;
2420 cxdouble* _mask = NULL;
2422 const cpl_image* center = NULL;
2423 const cpl_image* width = NULL;
2424 const cpl_image* exponent = NULL;
2426 cpl_image* mask = NULL;
2428 GiModel* profile = NULL;
2430 GiProfileId psfmodel = 0;
2433 cx_assert(psfdata != NULL);
2435 model = giraffe_psfdata_get_model(psfdata);
2437 if (strcmp(model,
"psfexp") == 0) {
2438 psfmodel = PROFILE_PSFEXP;
2440 else if (strcmp(model,
"psfexp2") == 0) {
2441 psfmodel = PROFILE_PSFEXP2;
2443 else if (strcmp(model,
"gaussian") == 0) {
2444 psfmodel = PROFILE_GAUSSIAN;
2450 nfibers = giraffe_psfdata_fibers(psfdata);
2451 nbins = giraffe_psfdata_bins(psfdata);
2452 nx = giraffe_psfdata_ysize(psfdata);
2453 ny = giraffe_psfdata_xsize(psfdata);
2455 center = giraffe_psfdata_get_data(psfdata,
"Center");
2456 width = giraffe_psfdata_get_data(psfdata,
"Width1");
2457 exponent = giraffe_psfdata_get_data(psfdata,
"Width2");
2459 if (amplitude == NULL) {
2460 amplitude = giraffe_psfdata_get_data(psfdata,
"Amplitude");
2463 if ((cpl_image_get_size_x(amplitude) != nfibers) ||
2464 (cpl_image_get_size_y(amplitude) > nbins)) {
2469 if (background == NULL) {
2470 background = giraffe_psfdata_get_data(psfdata,
"Background");
2473 if ((cpl_image_get_size_x(background) != nfibers) ||
2474 (cpl_image_get_size_y(background) > nbins)) {
2479 bsize = (cxdouble)nx / (cxdouble)nbins;
2481 _nbins = cpl_image_get_size_y(amplitude);
2482 _bsize = (cxdouble)nx / (cxdouble)_nbins;
2484 mask = cpl_image_new(ny, nx, CPL_TYPE_DOUBLE);
2485 _mask = cpl_image_get_data_double(mask);
2487 profile = giraffe_model_new(model);
2489 for (fiber = 0; fiber < nfibers; fiber++) {
2494 const cxdouble* _amplitude =
2495 cpl_image_get_data_double_const(amplitude);
2496 const cxdouble* _center =
2497 cpl_image_get_data_double_const(center);
2498 const cxdouble* _width =
2499 cpl_image_get_data_double_const(width);
2500 const cxdouble* _exponent =
2501 cpl_image_get_data_double_const(exponent);
2503 for (i = 0; i < nx; i++) {
2505 register cxint j = 0;
2506 register cxint k = 0;
2507 register cxint l = 0;
2508 register cxint bin = 0;
2510 register cxdouble a = 1.;
2511 register cxdouble b = 0.;
2512 register cxdouble c = 0.;
2513 register cxdouble s = 0.;
2514 register cxdouble e = 0.;
2517 bin = CX_MAX(0, CX_MIN((cxint)floor(i / bsize), nbins - 1));
2518 k = bin * nfibers + fiber;
2520 bin = CX_MAX(0, CX_MIN((cxint)floor(i / _bsize), _nbins - 1));
2521 l = bin * nfibers + fiber;
2528 giraffe_model_set_parameter(profile,
"Amplitude", a);
2529 giraffe_model_set_parameter(profile,
"Background", b);
2530 giraffe_model_set_parameter(profile,
"Center", c);
2531 giraffe_model_set_parameter(profile,
"Width1", s);
2532 giraffe_model_set_parameter(profile,
"Width2", e);
2535 case PROFILE_PSFEXP:
2537 cxdouble w = pow(s * log(1. / cutoff), 1. / e);
2539 ylower = (cxint) floor(c - w);
2540 yupper = (cxint) ceil(c + w);
2544 case PROFILE_PSFEXP2:
2546 cxdouble w = s * pow(log(1. / cutoff), 1. / e);
2548 ylower = (cxint) floor(c - w);
2549 yupper = (cxint) ceil(c + w);
2553 case PROFILE_GAUSSIAN:
2555 cxdouble w = s * sqrt(log(1. / cutoff));
2556 ylower = (cxint) floor(c - w);
2557 yupper = (cxint) ceil(c + w);
2562 gi_error(
"Unsupported PSF profile model encountered!");
2566 ylower = CX_MAX(0, ylower);
2567 yupper = CX_MIN(ny, yupper);
2569 for (j = ylower; j < yupper; j++) {
2573 cxdouble value = 0.;
2579 giraffe_model_set_argument(profile,
"x", j);
2580 giraffe_model_evaluate(profile, &value, &status);
2582 _mask[i * ny + j] += value;
2590 giraffe_model_delete(profile);
2610 GiTable* fibers, GiLocalization* master,
2611 GiImage* bpixel, GiPsfConfig* config)
2614 const cxchar*
const _func =
"giraffe_compute_fiber_profiles";
2624 cxdouble conad = 1.;
2625 cxdouble bias_ron = 0.;
2626 cxdouble bias_sigma = 0.;
2627 cxdouble dark_value = 0.;
2629 cx_string* s = NULL;
2631 cpl_table* _fibers = NULL;
2632 cpl_table* locc = NULL;
2634 cpl_matrix* my = NULL;
2636 cpl_image* _image = NULL;
2637 cpl_image* _variance = NULL;
2638 cpl_image* _locy = NULL;
2639 cpl_image* _locw = NULL;
2640 cpl_image* _bpixel = NULL;
2642 cpl_propertylist* properties = NULL;
2644 GiModel* psfmodel = NULL;
2646 GiPsfData* psfdata = NULL;
2647 GiPsfData* psffit = NULL;
2649 GiMaskPosition positions = {GIMASK_FITTED_DATA, NULL, NULL};
2650 GiMaskPosition coeffs = {GIMASK_FIT_COEFFS, NULL, NULL};
2652 GiPsfParams psf_setup = {0, 0, 1000., FALSE};
2655 if ((result == NULL) || (image == NULL) || (fibers == NULL) ||
2656 (master == NULL) || (config == NULL)) {
2657 cpl_error_set(_func, CPL_ERROR_NULL_INPUT);
2661 if ((master->locy == NULL) || (master->locw == NULL)) {
2662 cpl_error_set(_func, CPL_ERROR_NULL_INPUT);
2666 if ((result->locy != NULL) || (result->locw != NULL) ||
2667 (result->locc != NULL) || (result->psf != NULL)) {
2668 cpl_error_set(_func, CPL_ERROR_ILLEGAL_INPUT);
2676 if (bpixel != NULL) {
2682 if (_fibers == NULL) {
2683 cpl_error_set(_func, CPL_ERROR_DATA_NOT_FOUND);
2687 nfibers = cpl_table_get_nrow(_fibers);
2689 nx = cpl_image_get_size_y(_image);
2690 ny = cpl_image_get_size_x(_image);
2692 nbins = (cxint) ceil(nx / config->binsize);
2701 if (cpl_propertylist_has(properties, GIALIAS_NFIBERS) == FALSE) {
2702 cpl_propertylist_append_int(properties, GIALIAS_NFIBERS, nfibers);
2703 cpl_propertylist_set_comment(properties, GIALIAS_NFIBERS,
2704 "Number of fibres");
2708 cxint _nfibers = cpl_propertylist_get_int(properties,
2711 if (nfibers != _nfibers) {
2712 cpl_error_set(_func, CPL_ERROR_ILLEGAL_INPUT);
2719 if (!cpl_propertylist_has(properties, GIALIAS_CONAD)) {
2720 cpl_msg_error(_func,
"Missing detector gain property (%s)! ",
2725 conad = cpl_propertylist_get_double(properties, GIALIAS_CONAD);
2729 if (!cpl_propertylist_has(properties, GIALIAS_BIASERROR)) {
2730 cpl_msg_warning(_func,
"Missing bias error property (%s)! Setting "
2731 "bias error to 0.", GIALIAS_BIASERROR);
2735 bias_sigma = cpl_propertylist_get_double(properties, GIALIAS_BIASERROR);
2739 giraffe_error_push();
2743 if (cpl_error_get_code() != CPL_ERROR_NONE) {
2747 giraffe_error_pop();
2750 if (cpl_propertylist_has(properties, GIALIAS_DARKVALUE) == FALSE) {
2751 cpl_msg_warning(_func,
"Missing dark value property (%s) will be "
2752 "set to %.2f!", GIALIAS_DARKVALUE, dark_value);
2753 cpl_propertylist_append_double(properties, GIALIAS_DARKVALUE,
2757 dark_value = cpl_propertylist_get_double(properties,
2762 if (cpl_propertylist_has(properties, GIALIAS_DATANCOM)) {
2763 nframes = cpl_propertylist_get_int(properties, GIALIAS_DATANCOM);
2771 bias_sigma *= conad;
2772 dark_value *= conad;
2779 giraffe_error_push();
2781 _image = cpl_image_multiply_scalar_create(_image, nframes * conad);
2782 _variance = cpl_image_abs_create(_image);
2784 cpl_image_add_scalar(_variance,
2785 nframes * (bias_ron * bias_ron + nframes *
2786 (bias_sigma * bias_sigma + dark_value * dark_value)));
2788 if (cpl_error_get_code() != CPL_ERROR_NONE) {
2789 if (_variance != NULL) {
2790 cpl_image_delete(_variance);
2794 cpl_image_delete(_image);
2800 giraffe_error_pop();
2807 psfmodel = giraffe_model_new(config->profile);
2809 giraffe_model_thaw(psfmodel);
2811 giraffe_model_set_parameter(psfmodel,
"Amplitude", 1.);
2812 giraffe_model_set_parameter(psfmodel,
"Background", 0.);
2813 giraffe_model_set_parameter(psfmodel,
"Center", 0.);
2814 giraffe_model_set_parameter(psfmodel,
"Width1", config->width);
2816 if (cx_strncasecmp(config->profile,
"psfexp", 6) == 0) {
2818 cxdouble _exponent = fabs(config->exponent);
2820 giraffe_model_set_parameter(psfmodel,
"Width2", _exponent);
2822 if (config->exponent > 0) {
2823 giraffe_model_freeze_parameter(psfmodel,
"Width2");
2828 giraffe_model_set_iterations(psfmodel, config->fit.iterations);
2829 giraffe_model_set_delta(psfmodel, config->fit.delta);
2830 giraffe_model_set_tests(psfmodel, config->fit.tests);
2838 cpl_msg_info(_func,
"Fitting fiber profiles ...");
2840 psf_setup.bsize = config->binsize;
2841 psf_setup.mwidth = config->maxwidth;
2842 psf_setup.normalize = config->normalize;
2844 psfdata = giraffe_psfdata_create(nfibers, nbins, ny, nx);
2846 status = _giraffe_psf_compute_profile(psfdata, _image, _variance, _locy,
2847 _locw, _fibers, _bpixel, psfmodel,
2850 cpl_image_delete(_image);
2854 giraffe_psfdata_delete(psfdata);
2857 giraffe_model_delete(psfmodel);
2860 cpl_image_delete(_variance);
2863 cpl_msg_error(_func,
"Fiber profile fit failed!");
2874 _image = (cpl_image*) giraffe_psfdata_get_data(psfdata,
"Amplitude");
2875 cpl_image_divide_scalar(_image, nframes * conad);
2877 _image = (cpl_image*) giraffe_psfdata_get_data(psfdata,
"Background");
2878 cpl_image_divide_scalar(_image, nframes * conad);
2888 cpl_msg_info(_func,
"Fitting PSF profile parameters ...");
2890 if (config->parameter_fit == TRUE) {
2892 const cxchar* parameters[] = {
"Center",
"Amplitude",
"Background",
2893 "Width1",
"Width2", NULL};
2895 psffit = _giraffe_psf_fit_parameters(psfdata, _fibers, parameters,
2896 config->yorder, config->worder,
2902 psffit = _giraffe_psf_fit_parameters1d(psfdata, _fibers,
2903 NULL, config->yorder,
2908 if (psffit == NULL) {
2909 giraffe_psfdata_delete(psfdata);
2912 giraffe_model_delete(psfmodel);
2915 cpl_image_delete(_variance);
2918 cpl_msg_error(_func,
"PSF parameter fit failed!");
2922 giraffe_model_delete(psfmodel);
2925 cpl_image_delete(_variance);
2933 positions.my = cpl_matrix_new(nx, nfibers);
2934 positions.mw = cpl_matrix_new(nx, nfibers);
2936 coeffs.my = cpl_matrix_new(config->yorder + 1, nfibers);
2937 coeffs.mw = cpl_matrix_new(config->worder + 1, config->worder + 1);
2939 status = _giraffe_psf_compute_mask(&positions, &coeffs, psfdata, _fibers,
2940 config->yorder, config->worder,
2945 giraffe_psfdata_delete(psffit);
2948 giraffe_psfdata_delete(psfdata);
2951 cpl_msg_error(_func,
"Computation of localization mask from "
2952 "the fiber profile failed!");
2957 giraffe_psfdata_delete(psfdata);
2968 cpl_propertylist_update_string(properties, GIALIAS_PSFMODEL,
2970 cpl_propertylist_set_comment(properties, GIALIAS_PSFMODEL,
2971 "PSF profile model identifier");
2973 cpl_propertylist_update_int(properties, GIALIAS_PSFXBINS,
2975 cpl_propertylist_set_comment(properties, GIALIAS_PSFXBINS,
2976 "Size of bins along the dispersion "
2979 cpl_propertylist_update_int(properties, GIALIAS_PSFYDEG,
2981 cpl_propertylist_set_comment(properties, GIALIAS_PSFYDEG,
2982 "Order of the fiber center polynomial "
2985 cpl_propertylist_update_int(properties, GIALIAS_PSFWDEG,
2987 cpl_propertylist_set_comment(properties, GIALIAS_PSFWDEG,
2988 "Order of the fiber width 2d polynomial "
2991 cpl_propertylist_update_int(properties, GIALIAS_PSFWDEG,
2993 cpl_propertylist_set_comment(properties, GIALIAS_PSFWDEG,
2994 "Order of the fiber width 2d polynomial "
2997 cpl_propertylist_update_bool(properties, GIALIAS_PSFNORM,
2999 cpl_propertylist_set_comment(properties, GIALIAS_PSFNORM,
3000 "Pixel value normalization.");
3002 cpl_propertylist_update_int(properties, GIALIAS_PSFNX,
3003 cpl_matrix_get_nrow(positions.my));
3004 cpl_propertylist_set_comment(properties, GIALIAS_PSFNX,
3005 "Number of pixels per spectrum.");
3007 cpl_propertylist_update_int(properties, GIALIAS_PSFNS,
3008 cpl_matrix_get_ncol(positions.my));
3009 cpl_propertylist_set_comment(properties, GIALIAS_PSFNS,
3010 "Number of detected fibers.");
3012 cpl_propertylist_update_double(properties, GIALIAS_PSFSIGMA,
3013 config->clip.level);
3014 cpl_propertylist_set_comment(properties, GIALIAS_PSFSIGMA,
3015 "Sigma multiplier used for the PSF "
3018 cpl_propertylist_update_double(properties, GIALIAS_PSFSIGMA,
3019 config->clip.level);
3020 cpl_propertylist_set_comment(properties, GIALIAS_PSFSIGMA,
3021 "Sigma multiplier used for the fit of PSF "
3024 cpl_propertylist_update_int(properties, GIALIAS_PSFNITER,
3025 config->clip.iterations);
3026 cpl_propertylist_set_comment(properties, GIALIAS_PSFNITER,
3027 "Number of iterations used for the fit "
3028 "of PSF parameters.");
3030 cpl_propertylist_update_double(properties, GIALIAS_PSFMFRAC,
3031 config->clip.fraction);
3032 cpl_propertylist_set_comment(properties, GIALIAS_PSFMFRAC,
3033 "Minimum allowed fraction of accepted "
3034 "over total data points used for the "
3035 "fit of PSF parameters.");
3041 cpl_matrix_get_ncol(positions.my),
3042 cpl_matrix_get_nrow(positions.my));
3045 cpl_matrix_delete(positions.my);
3046 positions.my = NULL;
3051 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
"LOCY");
3052 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
3053 "GIRAFFE localization centroid");
3059 cpl_matrix_get_ncol(positions.mw),
3060 cpl_matrix_get_nrow(positions.mw));
3063 cpl_matrix_delete(positions.mw);
3064 positions.mw = NULL;
3071 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
"LOCWY");
3072 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
3073 "GIRAFFE localization half-width");
3078 locc = cpl_table_new(cpl_matrix_get_ncol(coeffs.my));
3080 cpl_table_new_column(locc,
"BUTTON", CPL_TYPE_INT);
3081 for (i = 0; i < cpl_table_get_nrow(locc); i++) {
3082 cpl_table_set_int(locc,
"BUTTON", i, i);
3085 for (i = 0; i < cpl_matrix_get_nrow(coeffs.my); i++) {
3087 cxchar* label = NULL;
3089 cx_asprintf(&label,
"YC%d", i);
3090 cpl_table_new_column(locc, label, CPL_TYPE_DOUBLE);
3100 cpl_table_delete(locc);
3103 my = cpl_matrix_transpose_create(coeffs.my);
3106 cpl_matrix_delete(my);
3109 cpl_matrix_delete(coeffs.my);
3115 s = cx_string_new();
3117 for (i = 0; i < cpl_matrix_get_ncol(coeffs.mw); i++) {
3118 cx_string_sprintf(s,
"%s%d", GIALIAS_LOCWIDCOEF, i);
3119 cpl_propertylist_update_double(properties, cx_string_get(s),
3120 cpl_matrix_get(coeffs.mw, 0, i));
3123 cx_string_delete(s);
3126 cpl_matrix_delete(coeffs.mw);
3129 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
3131 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
3132 "GIRAFFE localization fit coefficients");
3137 if (psffit != NULL) {
3138 result->psf = psffit;
3162 GiPsfConfig *
self = NULL;
3169 self = cx_calloc(1,
sizeof *
self);
3171 p = cpl_parameterlist_find(list,
"giraffe.psf.model");
3172 self->profile = cx_strdup(cpl_parameter_get_string(p));
3174 if (cx_strncasecmp(self->profile,
"psfexp", 6) == 0) {
3181 p = cpl_parameterlist_find(list,
"giraffe.psf.binsize");
3182 self->binsize = cpl_parameter_get_int(p);
3184 if (self->binsize < 1) {
3188 p = cpl_parameterlist_find(list,
"giraffe.psf.maxwidth");
3189 self->maxwidth = cpl_parameter_get_double(p);
3191 if (self->width > 0.) {
3192 p = cpl_parameterlist_find(list,
"giraffe.psf.width");
3193 self->width = cpl_parameter_get_double(p);
3196 if (self->width > self->maxwidth) {
3197 self->width =
self->maxwidth;
3200 p = cpl_parameterlist_find(list,
"giraffe.psf.exponent");
3201 self->exponent = cpl_parameter_get_double(p);
3203 p = cpl_parameterlist_find(list,
"giraffe.psf.normalize");
3204 self->normalize = cpl_parameter_get_bool(p);
3206 p = cpl_parameterlist_find(list,
"giraffe.psf.profile.iterations");
3207 self->fit.iterations = cpl_parameter_get_int(p);
3209 p = cpl_parameterlist_find(list,
"giraffe.psf.profile.tests");
3210 self->fit.tests = cpl_parameter_get_int(p);
3212 p = cpl_parameterlist_find(list,
"giraffe.psf.profile.dchisquare");
3213 self->fit.delta = cpl_parameter_get_double(p);
3215 p = cpl_parameterlist_find(list,
"giraffe.psf.parameters.fit");
3216 self->parameter_fit = cpl_parameter_get_bool(p);
3218 p = cpl_parameterlist_find(list,
"giraffe.psf.parameters.yorder");
3219 self->yorder = cpl_parameter_get_int(p);
3221 if (self->yorder < 0) {
3226 p = cpl_parameterlist_find(list,
"giraffe.psf.parameters.worder");
3227 self->worder = cpl_parameter_get_int(p);
3229 if (self->worder < 0) {
3234 p = cpl_parameterlist_find(list,
"giraffe.psf.parameters.sigma");
3235 self->clip.level = cpl_parameter_get_double(p);
3237 p = cpl_parameterlist_find(list,
"giraffe.psf.parameters.iterations");
3238 self->clip.iterations = cpl_parameter_get_int(p);
3240 p = cpl_parameterlist_find(list,
"giraffe.psf.parameters.fraction");
3241 self->clip.fraction = cpl_parameter_get_double(p);
3265 if (self->profile != NULL) {
3266 cx_free((cxptr) self->profile);
3267 self->profile = NULL;
3293 cpl_parameter* p = NULL;
3300 p = cpl_parameter_new_enum(
"giraffe.psf.model",
3302 "PSF profile model: `psfexp', `psfexp2'",
3304 "psfexp2", 3,
"psfexp",
"psfexp2",
"gaussian");
3305 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-model");
3306 cpl_parameterlist_append(list, p);
3308 p = cpl_parameter_new_value(
"giraffe.psf.normalize",
3310 "Use normalized pixel values.",
3313 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-norm");
3314 cpl_parameterlist_append(list, p);
3317 p = cpl_parameter_new_value(
"giraffe.psf.binsize",
3319 "Size of bin along dispersion axis",
3322 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-binsize");
3323 cpl_parameterlist_append(list, p);
3326 p = cpl_parameter_new_value(
"giraffe.psf.maxwidth",
3328 "Maximum width of the PSF profile.",
3331 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-maxwidth");
3332 cpl_parameterlist_append(list, p);
3335 p = cpl_parameter_new_value(
"giraffe.psf.width",
3337 "Initial width of the PSF profile.",
3340 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-width");
3341 cpl_parameterlist_append(list, p);
3344 p = cpl_parameter_new_value(
"giraffe.psf.exponent",
3346 "Exponent of the exponential PSF profile "
3347 "(will not be fitted if > 0).",
3350 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-exponent");
3351 cpl_parameterlist_append(list, p);
3354 p = cpl_parameter_new_value(
"giraffe.psf.profile.iterations",
3356 "Maximum number of iterations used for "
3357 "the fit of the fiber PSF profile.",
3361 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-pfniter");
3362 cpl_parameterlist_append(list, p);
3365 p = cpl_parameter_new_value(
"giraffe.psf.profile.tests",
3367 "Maximum number of tests used for the fit "
3368 "of the fiber PSF profile",
3372 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-pfntest");
3373 cpl_parameterlist_append(list, p);
3376 p = cpl_parameter_new_value(
"giraffe.psf.profile.dchisquare",
3378 "Minimum chi-square difference used for the "
3379 "fit of the fiber PSF profile.",
3383 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-pfdchisq");
3384 cpl_parameterlist_append(list, p);
3387 p = cpl_parameter_new_value(
"giraffe.psf.parameters.fit",
3389 "2D fit of the PSF profile parameters "
3390 "using a Chebyshev polynomial model.",
3393 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-prmfit");
3394 cpl_parameterlist_append(list, p);
3397 p = cpl_parameter_new_value(
"giraffe.psf.parameters.yorder",
3399 "Order of Chebyshev polynomial fit.",
3402 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-yorder");
3403 cpl_parameterlist_append(list, p);
3406 p = cpl_parameter_new_value(
"giraffe.psf.parameters.worder",
3408 "Order of Chebyshev 2D polynomial fit.",
3411 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-worder");
3412 cpl_parameterlist_append(list, p);
3415 p = cpl_parameter_new_value(
"giraffe.psf.parameters.sigma",
3417 "PSF parameter fitting: sigma threshold "
3421 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-sigma");
3422 cpl_parameterlist_append(list, p);
3425 p = cpl_parameter_new_value(
"giraffe.psf.parameters.iterations",
3427 "PSF parameter fitting: number of "
3431 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-niter");
3432 cpl_parameterlist_append(list, p);
3435 p = cpl_parameter_new_range(
"giraffe.psf.parameters.fraction",
3437 "PSF parameter fitting: minimum fraction "
3438 "of points accepted/total.",
3441 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"psf-mfrac");
3442 cpl_parameterlist_append(list, p);