00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 # include <config.h>
00030 #endif
00031
00032
00033 #include <string.h>
00034 #include <math.h>
00035
00036 #include <cxmacros.h>
00037 #include <cxmessages.h>
00038 #include <cxmemory.h>
00039 #include <cxstrutils.h>
00040
00041 #include <cpl_error.h>
00042 #include <cpl_image.h>
00043 #include <cpl_table.h>
00044 #include <cpl_parameterlist.h>
00045 #include <cpl_msg.h>
00046
00047 #include "gialias.h"
00048 #include "gierror.h"
00049 #include "gimessages.h"
00050 #include "gimatrix.h"
00051 #include "gichebyshev.h"
00052 #include "gimodel.h"
00053 #include "gipsfdata.h"
00054 #include "gilocalization.h"
00055 #include "gimask.h"
00056 #include "gimath.h"
00057 #include "giclip.h"
00058 #include "gifiberutils.h"
00059 #include "gipsf.h"
00060
00061
00070 enum GiProfileId {
00071 PROFILE_PSFEXP = 1 << 1,
00072 PROFILE_PSFEXP2 = 1 << 2,
00073 PROFILE_GAUSSIAN = 1 << 3
00074 };
00075
00076 typedef enum GiProfileId GiProfileId;
00077
00078
00079 struct GiPsfParams {
00080 cxint bsize;
00081 cxint mwidth;
00082 cxdouble limit;
00083 cxbool normalize;
00084 };
00085
00086 typedef struct GiPsfParams GiPsfParams;
00087
00088
00089 struct GiPsfBin {
00090 cxdouble zmin;
00091 cxdouble zmax;
00092 cxdouble xcenter;
00093 cxdouble ycenter;
00094 cxdouble ywidth;
00095 };
00096
00097 typedef struct GiPsfBin GiPsfBin;
00098
00099 struct GiPsfParameterFit {
00100 cpl_image* fit;
00101 cpl_matrix* coeffs;
00102 };
00103
00104 typedef struct GiPsfParameterFit GiPsfParameterFit;
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 inline static cxint
00139 _giraffe_psf_fit_profile1d(GiPsfParameterFit* result,
00140 const GiPsfData* psfdata, const cxchar* name,
00141 const cpl_table* fibers, cxint order,
00142 const GiClipParams* setup)
00143 {
00144
00145 cxint i = 0;
00146 cxint ns = 0;
00147 cxint nx = 0;
00148 cxint nb = 0;
00149
00150 cpl_matrix* x = NULL;
00151 cpl_matrix* base = NULL;
00152
00153 const cpl_image* parameter = NULL;
00154
00155
00156 cx_assert(result != NULL);
00157 cx_assert(result->coeffs != NULL);
00158 cx_assert(result->fit != NULL);
00159 cx_assert(psfdata != NULL && name != NULL);
00160 cx_assert(fibers != NULL);
00161 cx_assert(setup != NULL);
00162
00163 nb = giraffe_psfdata_bins(psfdata);
00164 ns = giraffe_psfdata_fibers(psfdata);
00165 nx = giraffe_psfdata_ysize(psfdata);
00166
00167 if (ns != cpl_table_get_nrow(fibers)) {
00168 return -1;
00169 }
00170
00171 if ((cpl_image_get_size_x(result->fit) != ns) ||
00172 (cpl_image_get_size_y(result->fit) != nx)) {
00173 return -1;
00174 }
00175
00176 if ((cpl_matrix_get_nrow(result->coeffs) != order + 1) ||
00177 (cpl_matrix_get_ncol(result->coeffs) != ns)) {
00178 return -1;
00179 }
00180
00181 for (i = 0; i < ns; i++) {
00182
00183 register cxint j = 0;
00184 register cxint valid_bins = 0;
00185
00186 for (j = 0; j < nb; j++) {
00187 if (giraffe_psfdata_get_bin(psfdata, i, j) >= 0.) {
00188 ++valid_bins;
00189 }
00190 }
00191
00192 if (valid_bins < order + 1) {
00193 return 1;
00194 }
00195
00196 }
00197
00198
00199
00200
00201
00202
00203 x = cpl_matrix_new(nx, 1);
00204
00205 for (i = 0; i < nx; i++) {
00206 cpl_matrix_set(x, i, 0, i);
00207 }
00208
00209 base = giraffe_chebyshev_base1d(0., (cxdouble)nx, order + 1, x);
00210
00211 if (base == NULL) {
00212 cpl_matrix_delete(x);
00213 x = NULL;
00214
00215 return 2;
00216 }
00217
00218 cpl_matrix_delete(x);
00219 x = NULL;
00220
00221
00222
00223
00224
00225
00226 parameter = giraffe_psfdata_get_data(psfdata, name);
00227
00228 if (parameter == NULL) {
00229 return 3;
00230 }
00231
00232 for (i = 0; i < ns; i++) {
00233
00234 cxint j = 0;
00235 cxint k = 0;
00236 cxint naccepted = 0;
00237 cxint ntotal = 0;
00238 cxint iteration = 0;
00239
00240 const cxdouble* _parameter =
00241 cpl_image_get_data_double_const(parameter);
00242
00243 cxdouble ratio = 1.;
00244 cxdouble* _fit = cpl_image_get_data_double(result->fit);
00245
00246 cpl_matrix* y = NULL;
00247 cpl_matrix* ydiff = NULL;
00248 cpl_matrix* coeffs = NULL;
00249 cpl_matrix* fit = NULL;
00250
00251
00252 x = cpl_matrix_new(nb, 1);
00253 y = cpl_matrix_new(1, nb);
00254 ydiff = cpl_matrix_new(1, nb);
00255
00256 for (j = 0; j < nb; j++) {
00257
00258 cxdouble bin = giraffe_psfdata_get_bin(psfdata, i, j);
00259
00260
00261 if (bin >= 0.) {
00262 cpl_matrix_set(x, k, 0, bin);
00263 cpl_matrix_set(y, 0, k, _parameter[j * ns + i]);
00264 ++k;
00265 }
00266
00267 }
00268
00269
00270
00271
00272
00273
00274 cpl_matrix_set_size(x, k, 1);
00275 cpl_matrix_set_size(y, 1, k);
00276 cpl_matrix_set_size(ydiff, 1, k);
00277
00278 ntotal = cpl_matrix_get_nrow(x);
00279 naccepted = ntotal;
00280
00281 while ((naccepted > 0) && (iteration < setup->iterations) &&
00282 (ratio > setup->fraction)) {
00283
00284 cxdouble sigma = 0.;
00285
00286 cpl_matrix* _base = NULL;
00287
00288
00289 if (coeffs != NULL) {
00290 cpl_matrix_delete(coeffs);
00291 coeffs = NULL;
00292 }
00293
00294 if (fit != NULL) {
00295 cpl_matrix_delete(fit);
00296 fit = NULL;
00297 }
00298
00299 _base = giraffe_chebyshev_base1d(0., (cxdouble)nx, order + 1, x);
00300 coeffs = giraffe_matrix_leastsq(_base, y);
00301
00302 if (coeffs == NULL) {
00303 cpl_matrix_delete(_base);
00304 _base = NULL;
00305 }
00306
00307 cpl_matrix_delete(_base);
00308 _base = NULL;
00309
00310 fit = cpl_matrix_product_create(coeffs, base);
00311
00312 for (j = 0; j < cpl_matrix_get_nrow(x); j++) {
00313
00314 cxint xlower = (cxint) ceil(cpl_matrix_get(x, j, 0));
00315 cxint xupper = (cxint) floor(cpl_matrix_get(x, j, 0));
00316
00317 cxdouble ylower = cpl_matrix_get(fit, 0, xlower);
00318 cxdouble yupper = cpl_matrix_get(fit, 0, xupper);
00319 cxdouble yfit = (yupper + ylower) / 2.;
00320
00321 cpl_matrix_set(ydiff, 0, j, cpl_matrix_get(y, 0, j) - yfit);
00322
00323 }
00324
00325 sigma = setup->level * giraffe_matrix_sigma_mean(ydiff, 0.);
00326
00327
00328
00329
00330
00331
00332 k = 0;
00333 for (j = 0; j < cpl_matrix_get_ncol(ydiff); j++) {
00334 if (fabs(cpl_matrix_get(ydiff, 0, j)) <= sigma) {
00335 cpl_matrix_set(x, k, 0, cpl_matrix_get(x, j, 0));
00336 cpl_matrix_set(y, 0, k, cpl_matrix_get(y, 0, j));
00337 ++k;
00338 }
00339 }
00340
00341 cpl_matrix_set_size(x, k, 1);
00342 cpl_matrix_set_size(y, 1, k);
00343 cpl_matrix_set_size(ydiff, 1, k);
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 if (k == naccepted) {
00354 break;
00355 }
00356 else {
00357 naccepted = k;
00358 ratio = (cxdouble)naccepted / (cxdouble) ntotal;
00359 ++iteration;
00360 }
00361
00362 }
00363
00364
00365
00366
00367
00368
00369
00370 cx_assert(cpl_matrix_get_ncol(coeffs) == order + 1);
00371
00372 for (j = 0; j < cpl_matrix_get_ncol(coeffs); j++) {
00373 cpl_matrix_set(result->coeffs, j, i,
00374 cpl_matrix_get(coeffs, 0, j));
00375 }
00376
00377 for (j = 0; j < nx; j++) {
00378 _fit[j * ns + i] = cpl_matrix_get(fit, 0, j);
00379 }
00380
00381
00382
00383
00384
00385
00386 cpl_matrix_delete(x);
00387 x = NULL;
00388
00389 cpl_matrix_delete(y);
00390 y = NULL;
00391
00392 cpl_matrix_delete(ydiff);
00393 ydiff = NULL;
00394
00395 cpl_matrix_delete(coeffs);
00396 coeffs = NULL;
00397
00398 cpl_matrix_delete(fit);
00399 fit = NULL;
00400
00401 }
00402
00403 cpl_matrix_delete(base);
00404 base = NULL;
00405
00406 return 0;
00407
00408 }
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 inline static cxint
00455 _giraffe_psf_fit_profile2d(GiPsfParameterFit* result, const cpl_table* fibers,
00456 const cpl_image* psfdata, const cpl_image* xbin,
00457 const cpl_image* ybin, cxint xorder, cxint yorder,
00458 const cpl_image* yfit, cxint ystart, cxint yend,
00459 const GiClipParams* setup)
00460 {
00461
00462
00463 cxint i = 0;
00464 cxint k = 0;
00465 cxint ns = 0;
00466 cxint nb = 0;
00467 cxint nx = 0;
00468 cxint iteration = 0;
00469 cxint ntotal = 0;
00470 cxint naccepted = 0;
00471 cxint nspectra = 0;
00472 cxint status = 0;
00473 cxint ncx = xorder + 1;
00474 cxint ncy = yorder + 1;
00475
00476 cxdouble ratio = 1.;
00477
00478 cpl_matrix* x = NULL;
00479 cpl_matrix* y = NULL;
00480 cpl_matrix* z = NULL;
00481 cpl_matrix* zdiff = NULL;
00482 cpl_matrix* nbins = NULL;
00483
00484 GiChebyshev2D* fit = NULL;
00485
00486
00487 cx_assert(result != NULL);
00488 cx_assert(result->coeffs != NULL);
00489 cx_assert(result->fit != NULL);
00490 cx_assert(fibers != NULL);
00491 cx_assert(psfdata != NULL);
00492 cx_assert(xbin != NULL && ybin != NULL);
00493 cx_assert(yfit != NULL);
00494 cx_assert(setup != NULL);
00495
00496 nb = cpl_image_get_size_y(xbin);
00497 ns = cpl_image_get_size_x(xbin);
00498 nx = cpl_image_get_size_y(result->fit);
00499
00500 if (ns != cpl_table_get_nrow(fibers)) {
00501 return -1;
00502 }
00503
00504 if ((cpl_image_get_size_x(result->fit) != ns) ||
00505 (cpl_image_get_size_y(result->fit) != nx)) {
00506 return -1;
00507 }
00508
00509 if ((cpl_matrix_get_nrow(result->coeffs) != ncx) ||
00510 (cpl_matrix_get_ncol(result->coeffs) != ncy)) {
00511 return -1;
00512 }
00513
00514 for (i = 0; i < ns; i++) {
00515
00516 register cxint j = 0;
00517 register cxint valid_bins = 0;
00518
00519 const cxdouble* _xbin = cpl_image_get_data_double_const(xbin);
00520
00521 for (j = 0; j < nb; j++) {
00522 if (_xbin[j * ns + i] >= 0.) {
00523 ++valid_bins;
00524 }
00525 }
00526
00527 if (valid_bins < ncx * ncy) {
00528 return 1;
00529 }
00530
00531 }
00532
00533
00534
00535
00536
00537
00538 x = cpl_matrix_new(nb * ns, 1);
00539 y = cpl_matrix_new(nb * ns, 1);
00540 z = cpl_matrix_new(1, nb * ns);
00541 zdiff = cpl_matrix_new(1, nb * ns);
00542 nbins = cpl_matrix_new(nb * ns, 1);
00543
00544 for (i = 0; i < ns; i++) {
00545
00546 register cxint j = 0;
00547
00548 const cxdouble* _xbin = cpl_image_get_data_double_const(xbin);
00549 const cxdouble* _ybin = cpl_image_get_data_double_const(ybin);
00550 const cxdouble* _zbin = cpl_image_get_data_double_const(psfdata);
00551
00552
00553 for ( j = 0; j < nb; j++) {
00554
00555 register cxint l = j * ns + i;
00556
00557
00558 if (_xbin[l] >= 0.) {
00559 cpl_matrix_set(nbins, k, 0, nspectra);
00560 cpl_matrix_set(x, k, 0, _xbin[l]);
00561 cpl_matrix_set(y, k, 0, _ybin[l]);
00562 cpl_matrix_set(z, 0, k, _zbin[l]);
00563 ++k;
00564 }
00565
00566 }
00567
00568 ++nspectra;
00569
00570 }
00571
00572
00573
00574
00575
00576
00577 cpl_matrix_set_size(x, k, 1);
00578 cpl_matrix_set_size(y, k, 1);
00579 cpl_matrix_set_size(z, 1, k);
00580 cpl_matrix_set_size(zdiff, 1, k);
00581 cpl_matrix_set_size(nbins, k, 1);
00582
00583 ntotal = cpl_matrix_get_nrow(x);
00584 naccepted = ntotal;
00585
00586 while ((naccepted > 0) && (iteration < setup->iterations) &&
00587 (ratio > setup->fraction))
00588 {
00589
00590 cxdouble sigma = 0.;
00591
00592 cpl_matrix* base = NULL;
00593 cpl_matrix* coeffs = NULL;
00594 cpl_matrix* _coeffs = NULL;
00595
00596 register cxdouble* _pfit = cpl_image_get_data_double(result->fit);
00597
00598
00599 base = giraffe_chebyshev_base2d(0., ystart, nx, yend, ncx, ncy, x, y);
00600
00601 if (base == NULL) {
00602 cpl_matrix_delete(nbins);
00603 nbins = NULL;
00604
00605 cpl_matrix_delete(zdiff);
00606 zdiff = NULL;
00607
00608 cpl_matrix_delete(z);
00609 z = NULL;
00610
00611 cpl_matrix_delete(y);
00612 y = NULL;
00613
00614 cpl_matrix_delete(x);
00615 x = NULL;
00616
00617 return 1;
00618 }
00619
00620 _coeffs = giraffe_matrix_leastsq(base, z);
00621
00622 if (_coeffs == NULL) {
00623 cpl_matrix_delete(base);
00624 base = NULL;
00625
00626 cpl_matrix_delete(nbins);
00627 nbins = NULL;
00628
00629 cpl_matrix_delete(zdiff);
00630 zdiff = NULL;
00631
00632 cpl_matrix_delete(z);
00633 z = NULL;
00634
00635 cpl_matrix_delete(y);
00636 y = NULL;
00637
00638 cpl_matrix_delete(x);
00639 x = NULL;
00640
00641 return 1;
00642 }
00643
00644 cpl_matrix_delete(base);
00645 base = NULL;
00646
00647
00648
00649
00650
00651
00652
00653 coeffs = cpl_matrix_wrap(xorder + 1, yorder + 1,
00654 cpl_matrix_get_data(_coeffs));
00655
00656 if (fit != NULL) {
00657 giraffe_chebyshev2d_delete(fit);
00658 fit = NULL;
00659 }
00660
00661 fit = giraffe_chebyshev2d_new(xorder, yorder);
00662 status = giraffe_chebyshev2d_set(fit, 0., nx, ystart, yend, coeffs);
00663
00664 if (status != 0) {
00665 giraffe_chebyshev2d_delete(fit);
00666 fit = NULL;
00667
00668 cpl_matrix_unwrap(coeffs);
00669 coeffs = NULL;
00670
00671 cpl_matrix_delete(_coeffs);
00672 _coeffs = NULL;
00673
00674 cpl_matrix_delete(nbins);
00675 nbins = NULL;
00676
00677 cpl_matrix_delete(zdiff);
00678 zdiff = NULL;
00679
00680 cpl_matrix_delete(z);
00681 z = NULL;
00682
00683 cpl_matrix_delete(y);
00684 y = NULL;
00685
00686 cpl_matrix_delete(x);
00687 x = NULL;
00688
00689 return 1;
00690 }
00691
00692 cpl_matrix_unwrap(coeffs);
00693 coeffs = NULL;
00694
00695 cpl_matrix_delete(_coeffs);
00696 _coeffs = NULL;
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 for (i = 0; i < ns; i++) {
00707
00708 register cxint j = 0;
00709
00710 register const cxdouble* _yfit =
00711 cpl_image_get_data_double_const(yfit);
00712
00713 for (j = 0; j < nx; j++) {
00714
00715 register cxint l = j * ns + i;
00716
00717 _pfit[l] = giraffe_chebyshev2d_eval(fit, j, _yfit[l]);
00718
00719 }
00720
00721 }
00722
00723 for (i = 0; i < cpl_matrix_get_nrow(x); i++) {
00724
00725 cxint n = cpl_matrix_get(nbins, i, 0);
00726 cxint lower = (cxint) ceil(cpl_matrix_get(x, i, 0)) * ns + n;
00727 cxint upper = (cxint) floor(cpl_matrix_get(x, i, 0)) * ns + n;
00728
00729 cxdouble zfit = (_pfit[lower] + _pfit[upper]) / 2.;
00730
00731 cpl_matrix_set(zdiff, 0, i, cpl_matrix_get(z, 0, i) - zfit);
00732
00733 }
00734
00735 sigma = setup->level * giraffe_matrix_sigma_mean(zdiff, 0.);
00736
00737 k = 0;
00738 for (i = 0; i < cpl_matrix_get_ncol(zdiff); i++) {
00739 if (fabs(cpl_matrix_get(zdiff, 0, i)) <= sigma) {
00740 cpl_matrix_set(x, k, 0, cpl_matrix_get(x, i, 0));
00741 cpl_matrix_set(y, k, 0, cpl_matrix_get(y, i, 0));
00742 cpl_matrix_set(z, 0, k, cpl_matrix_get(z, 0, i));
00743 cpl_matrix_set(nbins, k, 0, cpl_matrix_get(nbins, i, 0));
00744 ++k;
00745 }
00746 }
00747
00748 cpl_matrix_set_size(x, k, 1);
00749 cpl_matrix_set_size(y, k, 1);
00750 cpl_matrix_set_size(z, 1, k);
00751 cpl_matrix_set_size(zdiff, 1, k);
00752 cpl_matrix_set_size(nbins, k, 1);
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762 if (k == naccepted) {
00763 break;
00764 }
00765 else {
00766 naccepted = k;
00767 ratio = (cxdouble)naccepted / (cxdouble) ntotal;
00768 ++iteration;
00769 }
00770
00771 }
00772
00773
00774
00775
00776
00777
00778 for (i = 0; i < cpl_matrix_get_nrow(result->coeffs); i++) {
00779
00780 register cxint j = 0;
00781
00782 const cpl_matrix* c = giraffe_chebyshev2d_coeffs(fit);
00783
00784
00785 for (j = 0; j < cpl_matrix_get_ncol(result->coeffs); j++) {
00786 cpl_matrix_set(result->coeffs, i, j, cpl_matrix_get(c, i, j));
00787 }
00788
00789 }
00790
00791
00792
00793
00794
00795
00796 giraffe_chebyshev2d_delete(fit);
00797 fit = NULL;
00798
00799 cpl_matrix_delete(nbins);
00800 nbins = NULL;
00801
00802 cpl_matrix_delete(zdiff);
00803 zdiff = NULL;
00804
00805 cpl_matrix_delete(z);
00806 z = NULL;
00807
00808 cpl_matrix_delete(y);
00809 y = NULL;
00810
00811 cpl_matrix_delete(x);
00812 x = NULL;
00813
00814 return 0;
00815 }
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844 inline static cxint
00845 _giraffe_psf_compute_profile(GiPsfData* result, cpl_image* zraw,
00846 cpl_image* zvar, cpl_image* locy,
00847 cpl_image* locw, cpl_table* fibers,
00848 cpl_image* bpm, GiModel* profile,
00849 GiPsfParams* config)
00850 {
00851
00852 const cxchar* model = NULL;
00853 const cxchar* ridx = NULL;
00854
00855 const cxdouble cutoff = log(config->limit);
00856
00857 cxint nx = 0;
00858 cxint ny = 0;
00859 cxint ns = 0;
00860 cxint fiber = 0;
00861 cxint nbins = 0;
00862 cxint nspectra = 0;
00863
00864 cxsize n = 0;
00865
00866 cxdouble exponent;
00867
00868 cpl_matrix* mx = NULL;
00869 cpl_matrix* my = NULL;
00870 cpl_matrix* ms = NULL;
00871
00872 cpl_image* zx = NULL;
00873 cpl_image* zv = NULL;
00874
00875 GiProfileId psfmodel = 0;
00876
00877
00878 cx_assert(result != NULL);
00879 cx_assert((zraw != NULL) && (zvar != NULL));
00880 cx_assert((locy != NULL) && (locw != NULL));
00881 cx_assert(fibers != NULL);
00882 cx_assert(profile != NULL);
00883 cx_assert(config != NULL);
00884
00885 cx_assert(cpl_image_get_size_x(zraw) == cpl_image_get_size_x(zvar));
00886 cx_assert(cpl_image_get_size_y(zraw) == cpl_image_get_size_y(zvar));
00887
00888 cx_assert(cpl_image_get_size_x(locy) == cpl_image_get_size_x(locw));
00889 cx_assert(cpl_image_get_size_y(locy) == cpl_image_get_size_y(locw));
00890
00891
00892 nx = cpl_image_get_size_y(zraw);
00893 ny = cpl_image_get_size_x(zraw);
00894 ns = cpl_table_get_nrow(fibers);
00895
00896 nbins = (cxint) giraffe_psfdata_bins(result);
00897
00898 if (ns != cpl_image_get_size_x(locy)) {
00899 return -1;
00900 }
00901
00902 if ((bpm != NULL) && (cpl_image_get_type(bpm) != CPL_TYPE_INT)) {
00903 return -2;
00904 }
00905
00906 if (giraffe_psfdata_fibers(result) != (cxsize) ns) {
00907 return -3;
00908 }
00909
00910 if ((giraffe_psfdata_xsize(result) != (cxsize) ny) ||
00911 (giraffe_psfdata_ysize(result) != (cxsize) nx)) {
00912 return -3;
00913 }
00914
00915
00916
00917
00918
00919
00920
00921 model = giraffe_model_get_name(profile);
00922
00923 if (strcmp(model, "psfexp") == 0) {
00924 psfmodel = PROFILE_PSFEXP;
00925 }
00926 else if (strcmp(model, "psfexp2") == 0) {
00927 psfmodel = PROFILE_PSFEXP2;
00928 }
00929 else if (strcmp(model, "gaussian") == 0) {
00930 psfmodel = PROFILE_GAUSSIAN;
00931 }
00932 else {
00933 return -4;
00934 }
00935
00936
00937 if (config->normalize != FALSE) {
00938
00939 cxint x = 0;
00940
00941 cxdouble zmax = 0.;
00942 cxdouble* zsum = cx_calloc(nx, sizeof(cxdouble));
00943
00944
00945
00946
00947
00948
00949
00950 if (bpm == NULL) {
00951
00952 for (x = 0; x < nx; x++) {
00953
00954 register cxint y = 0;
00955
00956 register const cxdouble* _zraw =
00957 cpl_image_get_data_double(zraw);
00958
00959
00960 for (y = 0; y < ny; y++) {
00961 zsum[x] += _zraw[x * ny + y];
00962 }
00963
00964 if (zsum[x] > zmax) {
00965 zmax = zsum[x];
00966 }
00967 }
00968
00969 }
00970 else {
00971
00972 for (x = 0; x < nx; x++) {
00973
00974 register cxint y = 0;
00975 register const cxint* _bpm = cpl_image_get_data_int(bpm);
00976
00977 register const cxdouble* _zraw =
00978 cpl_image_get_data_double(zraw);
00979
00980
00981 for (y = 0; y < ny; y++) {
00982 register cxint i = x * ny + y;
00983
00984 if (_bpm[i] == 0) {
00985 zsum[x] += _zraw[i];
00986 }
00987 }
00988
00989 if (zsum[x] > zmax) {
00990 zmax = zsum[x];
00991 }
00992 }
00993
00994 }
00995
00996
00997
00998
00999
01000
01001
01002 zx = cpl_image_new(ny, nx, CPL_TYPE_DOUBLE);
01003 zv = cpl_image_new(ny, nx, CPL_TYPE_DOUBLE);
01004
01005
01006 for (x = 0; x < nx; x++) {
01007
01008 register cxint y = 0;
01009
01010 register cxdouble scale = zmax / zsum[x];
01011 register const cxdouble* _zraw = cpl_image_get_data_double(zraw);
01012 register const cxdouble* _zvar = cpl_image_get_data_double(zvar);
01013 register cxdouble* _zx = cpl_image_get_data_double(zx);
01014 register cxdouble* _zv = cpl_image_get_data_double(zv);
01015
01016 for(y = 0; y < nx; y++) {
01017 register cxint i = x * ny + y;
01018
01019 _zx[i] = _zraw[i] * scale;
01020 _zv[i] = _zvar[i] * scale;
01021 }
01022
01023 }
01024
01025 cx_free(zsum);
01026 zsum = NULL;
01027
01028 }
01029 else {
01030 zx = zraw;
01031 zv = zvar;
01032 }
01033
01034
01035
01036
01037
01038
01039
01040 giraffe_error_push();
01041
01042 exponent = giraffe_model_get_parameter(profile, "Width2");
01043
01044 if (cpl_error_get_code() != CPL_ERROR_NONE) {
01045 exponent = 0.;
01046 }
01047
01048 giraffe_error_pop();
01049
01050
01051
01052
01053
01054
01055
01056 ridx = giraffe_fiberlist_query_index(fibers);
01057
01058
01059
01060
01061
01062
01063
01064
01065 mx = cpl_matrix_new(nbins * config->mwidth, 1);
01066 my = cpl_matrix_new(nbins * config->mwidth, 1);
01067 ms = cpl_matrix_new(nbins * config->mwidth, 1);
01068
01069 if ((mx == NULL) || (my == NULL) || (ms == NULL)) {
01070 if (config->normalize == TRUE) {
01071 cpl_image_delete(zx);
01072 zx = NULL;
01073
01074 cpl_image_delete(zv);
01075 zv = NULL;
01076 }
01077
01078 if (mx != NULL) {
01079 cpl_matrix_delete(mx);
01080 mx = NULL;
01081 }
01082
01083 if (my != NULL) {
01084 cpl_matrix_delete(my);
01085 my = NULL;
01086 }
01087
01088 if (ms != NULL) {
01089 cpl_matrix_delete(ms);
01090 ms = NULL;
01091 }
01092
01093 return 1;
01094 }
01095
01096
01097
01098
01099
01100
01101
01102 giraffe_psfdata_set_model(result, giraffe_model_get_name(profile));
01103
01104 for (n = 0; n < giraffe_model_count_parameters(profile); n++) {
01105
01106 const cxchar* name = giraffe_model_parameter_name(profile, n);
01107
01108 cpl_image* values = cpl_image_new(ns, nbins, CPL_TYPE_DOUBLE);
01109
01110 if ((name == NULL) || (values == NULL)) {
01111
01112 giraffe_psfdata_clear(result);
01113
01114 cpl_matrix_delete(mx);
01115 mx = NULL;
01116
01117 cpl_matrix_delete(my);
01118 my = NULL;
01119
01120 cpl_matrix_delete(ms);
01121 ms = NULL;
01122
01123 if (config->normalize == TRUE) {
01124 cpl_image_delete(zx);
01125 zx = NULL;
01126
01127 cpl_image_delete(zv);
01128 zv = NULL;
01129 }
01130
01131 return 1;
01132 }
01133
01134 giraffe_psfdata_set_data(result, name, values);
01135
01136 }
01137
01138
01139
01140
01141
01142
01143 for (fiber = 0; fiber < ns; fiber++) {
01144
01145 cxint x = 0;
01146 cxint bin = 0;
01147 cxint cs = cpl_table_get_int(fibers, ridx, fiber, NULL) - 1;
01148 const cxint* _bpm = NULL;
01149
01150 const cxdouble* _locy = cpl_image_get_data_double(locy);
01151 const cxdouble* _locw = cpl_image_get_data_double(locw);
01152 const cxdouble* _zx = cpl_image_get_data_double(zx);
01153 const cxdouble* _zv = cpl_image_get_data_double(zv);
01154
01155
01156 if (bpm != NULL) {
01157 _bpm = cpl_image_get_data_int(bpm);
01158 }
01159
01160
01161
01162
01163
01164
01165 for (x = 0, bin = 0; x < nx; x += config->bsize, bin++) {
01166
01167 register cxint k = 0;
01168 register cxint xx = 0;
01169
01170 cxint status = 0;
01171 cxint ndata = 0;
01172 cxint iterations = giraffe_model_get_iterations(profile);
01173
01174 cxdouble amplitude = 0.;
01175 cxdouble bckground = 0.;
01176 cxdouble center = 0.;
01177 cxdouble width1 = 0.;
01178 cxdouble width2 = 0.;
01179
01180 GiPsfBin xbin = {0., 0., 0., 0., 0.};
01181
01182
01183
01184
01185
01186
01187 for (k = 0, xx = x; (k < config->bsize) && (xx < nx); k++, xx++) {
01188
01189 register cxint y = 0;
01190 register cxint l = xx * ns + cs;
01191 register cxint m = xx * ny;
01192
01193 cxdouble zxmin = CX_MAXDOUBLE;
01194 cxdouble zxmax = 0.;
01195 cxdouble swidth = CX_MIN(_locw[l], config->mwidth);
01196 cxdouble ylo = (cxint) floor(_locy[l] - swidth);
01197 cxdouble yup = (cxint) ceil(_locy[l] + swidth);
01198 cxdouble ycenter = _locy[l];
01199
01200
01201 ylo = CX_MAX(0., ylo);
01202 yup = CX_MIN(ny, yup);
01203
01204 if (_bpm == NULL) {
01205
01206 for (y = ylo; y < yup; y++) {
01207
01208 register cxint i = m + y;
01209
01210 cpl_matrix_set(mx, ndata, 0, (cxdouble)y - ycenter);
01211 cpl_matrix_set(my, ndata, 0, _zx[i]);
01212 cpl_matrix_set(ms, ndata, 0, sqrt(_zv[i]));
01213
01214 if (_zx[i] > zxmax) {
01215 zxmax = _zx[i];
01216 }
01217
01218 if (_zx[i] < zxmin) {
01219 zxmin = _zx[i];
01220 }
01221
01222 ++ndata;
01223
01224 }
01225
01226 }
01227 else {
01228
01229 for (y = ylo; y < yup; y++) {
01230
01231 register cxint i = m + y;
01232
01233 if (_bpm[i] == 0) {
01234 cpl_matrix_set(mx, ndata, 0,
01235 (cxdouble)y - ycenter);
01236 cpl_matrix_set(my, ndata, 0, _zx[i]);
01237 cpl_matrix_set(ms, ndata, 0, sqrt(_zv[i]));
01238
01239 if (_zx[i] > zxmax) {
01240 zxmax = _zx[i];
01241 }
01242
01243 if (_zx[i] < zxmin) {
01244 zxmin = _zx[i];
01245 }
01246
01247 ++ndata;
01248 }
01249
01250 }
01251
01252 }
01253
01254 xbin.zmin += zxmin;
01255 xbin.zmax += zxmax;
01256 xbin.xcenter += xx;
01257 xbin.ycenter += ycenter;
01258 xbin.ywidth += swidth;
01259
01260 }
01261
01262
01263
01264
01265
01266
01267 xbin.zmin /= k;
01268 xbin.zmax /= k;
01269 xbin.xcenter /= k;
01270 xbin.ycenter /= k;
01271 xbin.ywidth /= k;
01272
01273
01274
01275
01276
01277
01278 xbin.zmin = CX_MAX(0., xbin.zmin);
01279
01280
01281
01282
01283
01284
01285 giraffe_model_set_parameter(profile, "Amplitude",
01286 xbin.zmax - xbin.zmin);
01287 giraffe_model_set_parameter(profile, "Center", 0.);
01288 giraffe_model_set_parameter(profile, "Background", xbin.zmin);
01289
01290 switch (psfmodel) {
01291 case PROFILE_PSFEXP:
01292 width1 = pow(xbin.ywidth, exponent) / cutoff;
01293 giraffe_model_set_parameter(profile, "Width2", exponent);
01294 break;
01295
01296 case PROFILE_PSFEXP2:
01297 width1 = xbin.ywidth / pow(cutoff, 1. / exponent);
01298 giraffe_model_set_parameter(profile, "Width2", exponent);
01299 break;
01300
01301 case PROFILE_GAUSSIAN:
01302 width1 = xbin.ywidth / pow(cutoff, 0.5);
01303 break;
01304
01305 default:
01306 break;
01307 }
01308
01309 giraffe_model_set_parameter(profile, "Width1", width1);
01310
01311
01312
01313
01314
01315
01316 status = giraffe_model_fit_sequence(profile, mx, my, ms,
01317 ndata, 0, 1);
01318
01319 amplitude = giraffe_model_get_parameter(profile, "Amplitude");
01320 bckground = giraffe_model_get_parameter(profile, "Background");
01321 center = giraffe_model_get_parameter(profile, "Center");
01322 width1 = giraffe_model_get_parameter(profile, "Width1");
01323
01324 if ((psfmodel == PROFILE_PSFEXP) ||
01325 (psfmodel == PROFILE_PSFEXP2)) {
01326 width2 = giraffe_model_get_parameter(profile, "Width2");
01327 }
01328
01329
01330
01331
01332
01333
01334
01335 if ((status != 0) ||
01336 (giraffe_model_get_position(profile) >= iterations) ||
01337 (amplitude <= 0.) ||
01338 (width1 <= 0.)) {
01339
01340 xbin.xcenter = -1.;
01341 amplitude = 0.;
01342 bckground = 0.;
01343 center = 0.;
01344 width1 = 0.;
01345 width2 = 0.;
01346
01347 }
01348
01349 giraffe_psfdata_set_bin(result, fiber, bin, xbin.xcenter);
01350
01351 giraffe_psfdata_set(result, "Amplitude", fiber, bin, amplitude);
01352 giraffe_psfdata_set(result, "Center", fiber, bin,
01353 xbin.ycenter + center);
01354 giraffe_psfdata_set(result, "Background", fiber, bin, bckground);
01355 giraffe_psfdata_set(result, "Width1", fiber, bin, width1);
01356
01357 if ((psfmodel == PROFILE_PSFEXP) ||
01358 (psfmodel == PROFILE_PSFEXP2)) {
01359 giraffe_psfdata_set(result, "Width2", fiber, bin, width2);
01360 }
01361
01362 }
01363
01364 ++nspectra;
01365
01366 }
01367
01368
01369
01370
01371
01372
01373 cpl_matrix_delete(mx);
01374 mx = NULL;
01375
01376 cpl_matrix_delete(my);
01377 my = NULL;
01378
01379 cpl_matrix_delete(ms);
01380 ms = NULL;
01381
01382 if (config->normalize == TRUE) {
01383 cpl_image_delete(zx);
01384 zx = NULL;
01385
01386 cpl_image_delete(zv);
01387 zv = NULL;
01388 }
01389
01390 return 0;
01391
01392 }
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421 inline static cxint
01422 _giraffe_psf_refine_profile(GiPsfData* result, const GiPsfData* psfdata,
01423 cpl_image* zraw, cpl_image* zvar,
01424 cpl_table* fibers, cpl_image* bpm,
01425 GiModel* profile, GiPsfParams* config)
01426 {
01427
01428 const cxchar* model = NULL;
01429
01430 const cxdouble cutoff = log(config->limit);
01431
01432 cxint nx = 0;
01433 cxint ny = 0;
01434 cxint ns = 0;
01435 cxint fiber = 0;
01436 cxint nbins = 0;
01437 cxint nspectra = 0;
01438 cxint binsize = 0;
01439
01440 cxsize n = 0;
01441
01442 cpl_matrix* mx = NULL;
01443 cpl_matrix* my = NULL;
01444 cpl_matrix* ms = NULL;
01445
01446 GiProfileId psfmodel = 0;
01447
01448
01449 cx_assert(result != NULL);
01450 cx_assert(psfdata != NULL);
01451 cx_assert((zraw != NULL) && (zvar != NULL));
01452 cx_assert(fibers != NULL);
01453 cx_assert(profile != NULL);
01454 cx_assert(config != NULL);
01455
01456 cx_assert(cpl_image_get_size_x(zraw) == cpl_image_get_size_x(zvar));
01457 cx_assert(cpl_image_get_size_y(zraw) == cpl_image_get_size_y(zvar));
01458
01459
01460 nx = cpl_image_get_size_y(zraw);
01461 ny = cpl_image_get_size_x(zraw);
01462 ns = cpl_table_get_nrow(fibers);
01463
01464 if ((bpm != NULL) && (cpl_image_get_type(bpm) != CPL_TYPE_INT)) {
01465 return -1;
01466 }
01467
01468 if ((giraffe_psfdata_fibers(result) != (cxsize) ns) ||
01469 (giraffe_psfdata_bins(result) != (cxsize) nx)) {
01470 return -2;
01471 }
01472
01473 if ((giraffe_psfdata_xsize(result) != (cxsize) ny) ||
01474 (giraffe_psfdata_ysize(result) != (cxsize) nx)) {
01475 return -2;
01476 }
01477
01478 nbins = giraffe_psfdata_bins(result);
01479
01480 if ((giraffe_psfdata_fibers(psfdata) != (cxsize) ns)) {
01481 return -3;
01482 }
01483
01484 if ((giraffe_psfdata_xsize(psfdata) != (cxsize) ny) ||
01485 (giraffe_psfdata_ysize(psfdata) != (cxsize) nx)) {
01486 return -3;
01487 }
01488
01489 binsize = nx / giraffe_psfdata_bins(psfdata);
01490
01491
01492
01493
01494
01495
01496
01497 model = giraffe_model_get_name(profile);
01498
01499 if (strcmp(model, "psfexp") == 0) {
01500 psfmodel = PROFILE_PSFEXP;
01501 }
01502 else if (strcmp(model, "psfexp2") == 0) {
01503 psfmodel = PROFILE_PSFEXP2;
01504 }
01505 else if (strcmp(model, "gaussian") == 0) {
01506 psfmodel = PROFILE_GAUSSIAN;
01507 }
01508 else {
01509 return -4;
01510 }
01511
01512
01513
01514
01515
01516
01517
01518
01519 mx = cpl_matrix_new(nbins * config->mwidth, 1);
01520 my = cpl_matrix_new(nbins * config->mwidth, 1);
01521 ms = cpl_matrix_new(nbins * config->mwidth, 1);
01522
01523 if ((mx == NULL) || (my == NULL) || (ms == NULL)) {
01524
01525 if (mx != NULL) {
01526 cpl_matrix_delete(mx);
01527 mx = NULL;
01528 }
01529
01530 if (my != NULL) {
01531 cpl_matrix_delete(my);
01532 my = NULL;
01533 }
01534
01535 if (ms != NULL) {
01536 cpl_matrix_delete(ms);
01537 ms = NULL;
01538 }
01539
01540 return 1;
01541
01542 }
01543
01544
01545
01546
01547
01548
01549
01550 giraffe_psfdata_set_model(result, giraffe_model_get_name(profile));
01551
01552 for (n = 0; n < giraffe_model_count_parameters(profile); n++) {
01553
01554 const cxchar* name = giraffe_model_parameter_name(profile, n);
01555
01556 cpl_image* values = cpl_image_new(ns, nbins, CPL_TYPE_DOUBLE);
01557
01558
01559 if ((name == NULL) || (values == NULL)) {
01560
01561 giraffe_psfdata_clear(result);
01562
01563 cpl_matrix_delete(mx);
01564 mx = NULL;
01565
01566 cpl_matrix_delete(my);
01567 my = NULL;
01568
01569 cpl_matrix_delete(ms);
01570 ms = NULL;
01571
01572 return 1;
01573
01574 }
01575
01576 giraffe_psfdata_set_data(result, name, values);
01577
01578 }
01579
01580
01581
01582
01583
01584
01585 for (fiber = 0; fiber < ns; fiber++) {
01586
01587 cxint x = 0;
01588 const cxint* _bpm = NULL;
01589
01590 const cxdouble* _zx = cpl_image_get_data_double(zraw);
01591 const cxdouble* _zv = cpl_image_get_data_double(zvar);
01592
01593
01594 if (bpm != NULL) {
01595 _bpm = cpl_image_get_data_int(bpm);
01596 }
01597
01598
01599
01600
01601
01602
01603 for (x = 0; x < nx; x++) {
01604
01605 register cxint y = 0;
01606 register cxint m = x * ny;
01607 register cxint bin = CX_MAX(0, CX_MIN((cxint) floor(x / binsize),
01608 nbins));
01609
01610 cxint status = 0;
01611 cxint ndata = 0;
01612 cxint iterations = giraffe_model_get_iterations(profile);
01613
01614 cxdouble xcenter = 0.;
01615 cxdouble ycenter = 0.;
01616 cxdouble swidth = 0.;
01617 cxdouble ylo = 0.;
01618 cxdouble yup = ny;
01619 cxdouble amplitude = giraffe_psfdata_get(psfdata, "Amplitude",
01620 fiber, bin);
01621 cxdouble bckground = giraffe_psfdata_get(psfdata, "Background",
01622 fiber, bin);
01623 cxdouble center = giraffe_psfdata_get(psfdata, "Center",
01624 fiber, bin);
01625 cxdouble width1 = giraffe_psfdata_get(psfdata, "Width1",
01626 fiber, bin);
01627 cxdouble width2 = 0.;
01628
01629
01630 switch (psfmodel) {
01631 case PROFILE_PSFEXP:
01632 width2 = giraffe_psfdata_get(psfdata, "Width2",
01633 fiber, bin);
01634 swidth = pow(width1 * cutoff, 1./ width2);
01635 break;
01636
01637 case PROFILE_PSFEXP2:
01638 width2 = giraffe_psfdata_get(psfdata, "Width2",
01639 fiber, bin);
01640 swidth = width1 * pow(cutoff, 1./ width2);
01641 break;
01642
01643 case PROFILE_GAUSSIAN:
01644 swidth = width1 * pow(cutoff, 0.5);
01645 break;
01646
01647 default:
01648 break;
01649 }
01650
01651 swidth = CX_MIN(swidth, config->mwidth);
01652
01653 ylo = (cxint) floor(center - swidth);
01654 ylo = CX_MAX(0., ylo);
01655
01656 yup = (cxint) ceil(center + swidth);
01657 yup = CX_MIN(ny, yup);
01658
01659 if (_bpm == NULL) {
01660
01661 for (y = ylo; y < yup; y++) {
01662
01663 register cxint i = m + y;
01664
01665 cpl_matrix_set(mx, ndata, 0, (cxdouble)y - center);
01666 cpl_matrix_set(my, ndata, 0, _zx[i]);
01667 cpl_matrix_set(ms, ndata, 0, sqrt(_zv[i]));
01668
01669 ++ndata;
01670
01671 }
01672
01673 }
01674 else {
01675
01676 for (y = ylo; y < yup; y++) {
01677
01678 register cxint i = m + y;
01679
01680 if (_bpm[i] == 0) {
01681 cpl_matrix_set(mx, ndata, 0, (cxdouble)y - center);
01682 cpl_matrix_set(my, ndata, 0, _zx[i]);
01683 cpl_matrix_set(ms, ndata, 0, sqrt(_zv[i]));
01684
01685 ++ndata;
01686 }
01687
01688 }
01689
01690 }
01691
01692
01693
01694
01695
01696
01697 bckground = CX_MAX(0., bckground);
01698
01699
01700
01701
01702
01703
01704 giraffe_model_set_parameter(profile, "Amplitude", amplitude);
01705 giraffe_model_set_parameter(profile, "Center", 0.);
01706 giraffe_model_set_parameter(profile, "Background", bckground);
01707 giraffe_model_set_parameter(profile, "Width1", width1);
01708
01709 switch (psfmodel) {
01710 case PROFILE_PSFEXP:
01711 giraffe_model_set_parameter(profile, "Width2", width2);
01712 break;
01713
01714 case PROFILE_PSFEXP2:
01715 giraffe_model_set_parameter(profile, "Width2", width2);
01716 break;
01717
01718 case PROFILE_GAUSSIAN:
01719 break;
01720
01721 default:
01722 break;
01723 }
01724
01725
01726
01727
01728
01729
01730 status = giraffe_model_fit_sequence(profile, mx, my, ms,
01731 ndata, 0, 1);
01732
01733 amplitude = giraffe_model_get_parameter(profile, "Amplitude");
01734 bckground = giraffe_model_get_parameter(profile, "Background");
01735 ycenter = giraffe_model_get_parameter(profile, "Center");
01736 width1 = giraffe_model_get_parameter(profile, "Width1");
01737
01738 if ((psfmodel == PROFILE_PSFEXP) ||
01739 (psfmodel == PROFILE_PSFEXP2)) {
01740 width2 = giraffe_model_get_parameter(profile, "Width2");
01741 }
01742
01743
01744
01745
01746
01747
01748
01749
01750 if ((status != 0) ||
01751 (giraffe_model_get_position(profile) >= iterations) ||
01752 (amplitude <= 0.) ||
01753 (width1 <= 0.)) {
01754
01755 xcenter = -1.;
01756 ycenter = 0.;
01757 amplitude = 0.;
01758 bckground = 0.;
01759 width1 = 0.;
01760 width2 = 0.;
01761
01762 }
01763 else {
01764 xcenter = x;
01765 }
01766
01767 giraffe_psfdata_set_bin(result, fiber, x, xcenter);
01768
01769 giraffe_psfdata_set(result, "Amplitude", fiber, x, amplitude);
01770 giraffe_psfdata_set(result, "Center", fiber, x,
01771 ycenter + center);
01772 giraffe_psfdata_set(result, "Background", fiber, x, bckground);
01773 giraffe_psfdata_set(result, "Width1", fiber, x, width1);
01774
01775 if ((psfmodel == PROFILE_PSFEXP) ||
01776 (psfmodel == PROFILE_PSFEXP2)) {
01777 giraffe_psfdata_set(result, "Width2", fiber, x, width2);
01778 }
01779
01780 }
01781
01782 ++nspectra;
01783
01784 }
01785
01786
01787
01788
01789
01790
01791 cpl_matrix_delete(mx);
01792 mx = NULL;
01793
01794 cpl_matrix_delete(my);
01795 my = NULL;
01796
01797 cpl_matrix_delete(ms);
01798 ms = NULL;
01799
01800 return 0;
01801
01802 }
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822 inline static GiPsfData*
01823 _giraffe_psf_fit_parameters1d(const GiPsfData* psfdata,
01824 const cpl_table* fibers,
01825 const cxchar** names,
01826 cxint order,
01827 const GiClipParams* setup)
01828 {
01829
01830 cxint i = 0;
01831 cxint ns = 0;
01832 cxint nx = 0;
01833 cxint ny = 0;
01834 cxint status = 0;
01835
01836 GiPsfData* psffit = NULL;
01837
01838
01839 cx_assert(psfdata != NULL);
01840 cx_assert(fibers != NULL);
01841 cx_assert(setup != NULL);
01842
01843 ns = giraffe_psfdata_fibers(psfdata);
01844 nx = giraffe_psfdata_ysize(psfdata);
01845 ny = giraffe_psfdata_xsize(psfdata);
01846
01847 psffit = giraffe_psfdata_create(ns, nx, ny, nx);
01848
01849 giraffe_psfdata_set_model(psffit, giraffe_psfdata_get_model(psfdata));
01850
01851
01852
01853
01854
01855
01856
01857
01858 for (i = 0; i < ns; i++) {
01859
01860 register cxint j = 0;
01861
01862 for (j = 0; j < nx; j++) {
01863 giraffe_psfdata_set_bin(psffit, i, j, j);
01864 }
01865
01866 }
01867
01868
01869 if (names == NULL) {
01870
01871 cxsize j = 0;
01872 cxsize count = giraffe_psfdata_parameters(psfdata);
01873
01874 for (j = 0; j < count; j++) {
01875
01876 const cxchar* name = giraffe_psfdata_get_name(psfdata, j);
01877
01878 GiPsfParameterFit pfit = {NULL, NULL};
01879
01880
01881 pfit.fit = cpl_image_new(ns, nx, CPL_TYPE_DOUBLE);
01882 pfit.coeffs = cpl_matrix_new(order + 1, ns);
01883
01884 status = _giraffe_psf_fit_profile1d(&pfit, psfdata, name,
01885 fibers, order, setup);
01886
01887 if (status != 0) {
01888 cpl_matrix_delete(pfit.coeffs);
01889 pfit.coeffs = NULL;
01890
01891 cpl_image_delete(pfit.fit);
01892 pfit.fit = NULL;
01893
01894 giraffe_psfdata_delete(psffit);
01895 psffit = NULL;
01896
01897 return NULL;
01898 }
01899 else {
01900 giraffe_psfdata_set_data(psffit, name, pfit.fit);
01901 pfit.fit = NULL;
01902
01903 cpl_matrix_delete(pfit.coeffs);
01904 pfit.coeffs = NULL;
01905
01906 }
01907
01908 }
01909
01910 }
01911 else {
01912
01913
01914
01915
01916
01917
01918 i = 0;
01919 while (names[i] != NULL) {
01920
01921 if (giraffe_psfdata_contains(psfdata, names[i]) == TRUE) {
01922
01923 GiPsfParameterFit pfit = {NULL, NULL};
01924
01925
01926 pfit.fit = cpl_image_new(ns, nx, CPL_TYPE_DOUBLE);
01927 pfit.coeffs = cpl_matrix_new(order + 1, ns);
01928
01929 status = _giraffe_psf_fit_profile1d(&pfit, psfdata, names[i],
01930 fibers, order, setup);
01931
01932 if (status != 0) {
01933 cpl_matrix_delete(pfit.coeffs);
01934 pfit.coeffs = NULL;
01935
01936 cpl_image_delete(pfit.fit);
01937 pfit.fit = NULL;
01938
01939 giraffe_psfdata_delete(psffit);
01940 psffit = NULL;
01941
01942 return NULL;
01943 }
01944 else {
01945 giraffe_psfdata_set_data(psffit, names[i], pfit.fit);
01946 pfit.fit = NULL;
01947
01948 cpl_matrix_delete(pfit.coeffs);
01949 pfit.coeffs = NULL;
01950
01951 }
01952
01953 }
01954
01955 ++i;
01956
01957 }
01958
01959 }
01960
01961 return psffit;
01962
01963 }
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978 inline static GiPsfData*
01979 _giraffe_psf_fit_parameters(const GiPsfData* psfdata,
01980 const cpl_table* fibers,
01981 const cxchar** names,
01982 cxint yorder, cxint worder,
01983 const GiClipParams* setup)
01984 {
01985
01986 const cxchar* center = NULL;
01987
01988 cxint i = 0;
01989 cxint ns = 0;
01990 cxint nx = 0;
01991 cxint ny = 0;
01992 cxint status = 0;
01993
01994 GiPsfData* psffit = NULL;
01995
01996
01997 cx_assert(psfdata != NULL);
01998 cx_assert(fibers != NULL);
01999 cx_assert(names != NULL);
02000 cx_assert(setup != NULL);
02001
02002 ns = giraffe_psfdata_fibers(psfdata);
02003 nx = giraffe_psfdata_ysize(psfdata);
02004 ny = giraffe_psfdata_xsize(psfdata);
02005
02006 psffit = giraffe_psfdata_create(ns, nx, ny, nx);
02007
02008 giraffe_psfdata_set_model(psffit, giraffe_psfdata_get_model(psfdata));
02009
02010
02011
02012
02013
02014
02015
02016
02017 for (i = 0; i < ns; i++) {
02018
02019 register cxint j = 0;
02020
02021 for (j = 0; j < nx; j++) {
02022 giraffe_psfdata_set_bin(psffit, i, j, j);
02023 }
02024
02025 }
02026
02027 center = names[0];
02028 if (giraffe_psfdata_contains(psfdata, center) == FALSE) {
02029
02030 giraffe_psfdata_delete(psffit);
02031 psffit = NULL;
02032
02033 return NULL;
02034
02035 }
02036 else {
02037
02038 GiPsfParameterFit pfit = {NULL, NULL};
02039
02040
02041 pfit.fit = cpl_image_new(ns, nx, CPL_TYPE_DOUBLE);
02042 pfit.coeffs = cpl_matrix_new(yorder + 1, ns);
02043
02044 status = _giraffe_psf_fit_profile1d(&pfit, psfdata, center, fibers,
02045 yorder, setup);
02046
02047 if (status != 0) {
02048 cpl_matrix_delete(pfit.coeffs);
02049 pfit.coeffs = NULL;
02050
02051 cpl_image_delete(pfit.fit);
02052 pfit.fit = NULL;
02053
02054 giraffe_psfdata_delete(psffit);
02055 psffit = NULL;
02056
02057 return NULL;
02058 }
02059 else {
02060 giraffe_psfdata_set_data(psffit, center, pfit.fit);
02061 pfit.fit = NULL;
02062
02063 cpl_matrix_delete(pfit.coeffs);
02064 pfit.coeffs = NULL;
02065
02066 }
02067
02068 }
02069
02070
02071 i = 1;
02072 while (names[i] != NULL) {
02073
02074 if (giraffe_psfdata_contains(psfdata, names[i]) == TRUE) {
02075
02076 const cpl_image* xbin = giraffe_psfdata_get_bins(psfdata);
02077 const cpl_image* ybin = giraffe_psfdata_get_data(psfdata, center);
02078 const cpl_image* yfit = giraffe_psfdata_get_data(psffit, center);
02079 const cpl_image* pdata = giraffe_psfdata_get_data(psfdata,
02080 names[i]);
02081
02082 GiPsfParameterFit pfit = {NULL, NULL};
02083
02084
02085 pfit.fit = cpl_image_new(ns, nx, CPL_TYPE_DOUBLE);
02086 pfit.coeffs = cpl_matrix_new(yorder + 1, worder + 1);
02087
02088 status = _giraffe_psf_fit_profile2d(&pfit, fibers, pdata, xbin,
02089 ybin, yorder, worder, yfit,
02090 0, ny, setup);
02091
02092 if (status != 0) {
02093 cpl_matrix_delete(pfit.coeffs);
02094 pfit.coeffs = NULL;
02095
02096 cpl_image_delete(pfit.fit);
02097 pfit.fit = NULL;
02098
02099 giraffe_psfdata_delete(psffit);
02100 psffit = NULL;
02101
02102 return NULL;
02103 }
02104 else {
02105 giraffe_psfdata_set_data(psffit, names[i], pfit.fit);
02106 pfit.fit = NULL;
02107
02108 cpl_matrix_delete(pfit.coeffs);
02109 pfit.coeffs = NULL;
02110
02111 }
02112 }
02113
02114 ++i;
02115
02116 }
02117
02118 return psffit;
02119
02120 }
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134 inline static int
02135 _giraffe_psf_compute_mask(GiMaskPosition* positions, GiMaskPosition* coeffs,
02136 const GiPsfData* psfdata, const cpl_table* fibers,
02137 cxint yorder, cxint worder,
02138 const GiClipParams* setup)
02139 {
02140
02141 const cxchar* const lcenter = "Center";
02142 const cxchar* const lwidth = "Width1";
02143 const cxchar* const lexponent = "Width2";
02144 const cxchar* model = NULL;
02145
02146 cxint i = 0;
02147 cxint ns = 0;
02148 cxint nx = 0;
02149 cxint ny = 0;
02150 cxint status = 0;
02151
02152 const cpl_image* xbin = NULL;
02153 const cpl_image* ybin = NULL;
02154 cpl_image* width = NULL;
02155
02156 GiPsfParameterFit center = {NULL, NULL};
02157 GiPsfParameterFit halfwidth = {NULL, NULL};
02158
02159 GiProfileId psfmodel = 0;
02160
02161
02162 cx_assert((positions != NULL) &&
02163 (positions->type == GIMASK_FITTED_DATA) &&
02164 (positions->my != NULL) &&
02165 (positions->mw != NULL));
02166 cx_assert((coeffs != NULL) &&
02167 (coeffs->type == GIMASK_FIT_COEFFS) &&
02168 (coeffs->my != NULL) &&
02169 (coeffs->mw != NULL));
02170 cx_assert(psfdata != NULL);
02171 cx_assert(fibers != NULL);
02172 cx_assert(setup != NULL);
02173
02174 model = giraffe_psfdata_get_model(psfdata);
02175
02176 if (strcmp(model, "psfexp") == 0) {
02177 psfmodel = PROFILE_PSFEXP;
02178 }
02179 else if (strcmp(model, "psfexp2") == 0) {
02180 psfmodel = PROFILE_PSFEXP2;
02181 }
02182 else if (strcmp(model, "gaussian") == 0) {
02183 psfmodel = PROFILE_GAUSSIAN;
02184 }
02185 else {
02186 return -1;
02187 }
02188
02189 ns = giraffe_psfdata_fibers(psfdata);
02190 nx = giraffe_psfdata_ysize(psfdata);
02191 ny = giraffe_psfdata_xsize(psfdata);
02192
02193 if ((cpl_matrix_get_nrow(positions->my) != nx) ||
02194 (cpl_matrix_get_ncol(positions->my) != ns) ||
02195 (cpl_matrix_get_nrow(positions->mw) != nx) ||
02196 (cpl_matrix_get_ncol(positions->mw) != ns)) {
02197 return -1;
02198 }
02199
02200 if ((cpl_matrix_get_nrow(coeffs->my) != yorder + 1) ||
02201 (cpl_matrix_get_ncol(coeffs->my) != ns)) {
02202 return -1;
02203 }
02204
02205 if ((cpl_matrix_get_nrow(coeffs->mw) != worder + 1) ||
02206 (cpl_matrix_get_ncol(coeffs->mw) != worder + 1)) {
02207 return -1;
02208 }
02209
02210 if (giraffe_psfdata_contains(psfdata, lcenter) == FALSE ||
02211 giraffe_psfdata_contains(psfdata, lwidth) == FALSE) {
02212 return 1;
02213 }
02214
02215 center.fit = cpl_image_wrap_double(ns, nx,
02216 cpl_matrix_get_data(positions->my));
02217 center.coeffs = coeffs->my;
02218
02219 status = _giraffe_psf_fit_profile1d(¢er, psfdata, lcenter, fibers,
02220 yorder, setup);
02221
02222 if (status != 0) {
02223 cpl_image_unwrap(center.fit);
02224
02225 center.fit = NULL;
02226 center.coeffs = NULL;
02227
02228 return 1;
02229 }
02230
02231 width = cpl_image_new(ns, nx, CPL_TYPE_DOUBLE);
02232
02233 switch (psfmodel) {
02234 case PROFILE_PSFEXP:
02235 {
02236
02237 const cxdouble log2 = log(2.);
02238
02239 if (giraffe_psfdata_contains(psfdata, lexponent) == FALSE) {
02240 cpl_image_delete(width);
02241 width = NULL;
02242
02243 cpl_image_unwrap(center.fit);
02244 center.fit = NULL;
02245 center.coeffs = NULL;
02246
02247 return 1;
02248 }
02249
02250 for (i = 0; i < ns; i++) {
02251
02252 register cxint j = 0;
02253
02254 register cxdouble* _width = cpl_image_get_data_double(width);
02255
02256
02257 for (j = 0; j < nx; j++) {
02258
02259 register cxint k = j * ns + i;
02260
02261 cxdouble width1 =
02262 giraffe_psfdata_get(psfdata, lwidth, i, j);
02263 cxdouble width2 =
02264 giraffe_psfdata_get(psfdata, lexponent, i, j);
02265
02266
02267 _width[k] = 2. * pow(log2 * width1, 1. / width2);
02268
02269 }
02270
02271 }
02272
02273 }
02274 break;
02275
02276 case PROFILE_PSFEXP2:
02277 {
02278
02279 const cxdouble log2 = log(2.);
02280
02281 if (giraffe_psfdata_contains(psfdata, lexponent) == FALSE) {
02282 cpl_image_delete(width);
02283 width = NULL;
02284
02285 cpl_image_unwrap(center.fit);
02286 center.fit = NULL;
02287 center.coeffs = NULL;
02288
02289 return 1;
02290 }
02291
02292 for (i = 0; i < ns; i++) {
02293
02294 register cxint j = 0;
02295
02296 register cxdouble* _width = cpl_image_get_data_double(width);
02297
02298
02299 for (j = 0; j < nx; j++) {
02300
02301 register cxint k = j * ns + i;
02302
02303 cxdouble width1 =
02304 giraffe_psfdata_get(psfdata, lwidth, i, j);
02305 cxdouble width2 =
02306 giraffe_psfdata_get(psfdata, lexponent, i, j);
02307
02308
02309 _width[k] = 2. * pow(log2, 1. / width2) * width1;
02310
02311 }
02312
02313 }
02314
02315 }
02316 break;
02317
02318 case PROFILE_GAUSSIAN:
02319 {
02320
02321 const cxdouble fwhmscale = 4. * sqrt(2. * log(2.));
02322
02323 for (i = 0; i < ns; i++) {
02324
02325 register cxint j = 0;
02326
02327 register cxdouble* _width = cpl_image_get_data_double(width);
02328
02329
02330 for (j = 0; j < nx; j++) {
02331
02332 register cxint k = j * ns + i;
02333
02334 _width[k] = fwhmscale *
02335 giraffe_psfdata_get(psfdata, lwidth, i, j);
02336 }
02337
02338 }
02339
02340 }
02341 break;
02342
02343 default:
02344
02345
02346 cpl_image_delete(width);
02347 width = NULL;
02348
02349 cpl_image_unwrap(center.fit);
02350 center.fit = NULL;
02351 center.coeffs = NULL;
02352
02353 gi_error("Unsupported PSF profile model encountered!");
02354 break;
02355 }
02356
02357
02358 xbin = giraffe_psfdata_get_bins(psfdata);
02359 ybin = giraffe_psfdata_get_data(psfdata, lcenter);
02360
02361
02362 halfwidth.fit = cpl_image_wrap_double(ns, nx,
02363 cpl_matrix_get_data(positions->mw));
02364 halfwidth.coeffs = coeffs->mw;
02365
02366 status = _giraffe_psf_fit_profile2d(&halfwidth, fibers, width, xbin,
02367 ybin, worder, worder, center.fit,
02368 0, ny, setup);
02369
02370 if (status != 0) {
02371 cpl_image_unwrap(halfwidth.fit);
02372 halfwidth.fit = NULL;
02373 halfwidth.coeffs = NULL;
02374
02375 cpl_image_delete(width);
02376 width = NULL;
02377
02378 cpl_image_unwrap(center.fit);
02379 center.fit = NULL;
02380 center.coeffs = NULL;
02381
02382 return 1;
02383 }
02384
02385 cpl_image_unwrap(halfwidth.fit);
02386 halfwidth.fit = NULL;
02387 halfwidth.coeffs = NULL;
02388
02389 cpl_image_delete(width);
02390 width = NULL;
02391
02392 cpl_image_unwrap(center.fit);
02393 center.fit = NULL;
02394 center.coeffs = NULL;
02395
02396 return 0;
02397
02398 }
02399
02400
02401 inline static cpl_image*
02402 _giraffe_psf_simulate_mask(const GiPsfData* psfdata,
02403 const cpl_image* amplitude,
02404 const cpl_image* background,
02405 cxdouble cutoff)
02406 {
02407
02408 const cxchar* model = NULL;
02409
02410 cxint i = 0;
02411 cxint nfibers = 0;
02412 cxint nbins = 0;
02413 cxint _nbins = 0;
02414 cxint nx = 0;
02415 cxint ny = 0;
02416 cxint fiber = 0;
02417
02418 cxdouble bsize = 1.;
02419 cxdouble _bsize = 1.;
02420 cxdouble* _mask = NULL;
02421
02422 const cpl_image* center = NULL;
02423 const cpl_image* width = NULL;
02424 const cpl_image* exponent = NULL;
02425
02426 cpl_image* mask = NULL;
02427
02428 GiModel* profile = NULL;
02429
02430 GiProfileId psfmodel = 0;
02431
02432
02433 cx_assert(psfdata != NULL);
02434
02435 model = giraffe_psfdata_get_model(psfdata);
02436
02437 if (strcmp(model, "psfexp") == 0) {
02438 psfmodel = PROFILE_PSFEXP;
02439 }
02440 else if (strcmp(model, "psfexp2") == 0) {
02441 psfmodel = PROFILE_PSFEXP2;
02442 }
02443 else if (strcmp(model, "gaussian") == 0) {
02444 psfmodel = PROFILE_GAUSSIAN;
02445 }
02446 else {
02447 return NULL;
02448 }
02449
02450 nfibers = giraffe_psfdata_fibers(psfdata);
02451 nbins = giraffe_psfdata_bins(psfdata);
02452 nx = giraffe_psfdata_ysize(psfdata);
02453 ny = giraffe_psfdata_xsize(psfdata);
02454
02455 center = giraffe_psfdata_get_data(psfdata, "Center");
02456 width = giraffe_psfdata_get_data(psfdata, "Width1");
02457 exponent = giraffe_psfdata_get_data(psfdata, "Width2");
02458
02459 if (amplitude == NULL) {
02460 amplitude = giraffe_psfdata_get_data(psfdata, "Amplitude");
02461 }
02462 else {
02463 if ((cpl_image_get_size_x(amplitude) != nfibers) ||
02464 (cpl_image_get_size_y(amplitude) > nbins)) {
02465 return NULL;
02466 }
02467 }
02468
02469 if (background == NULL) {
02470 background = giraffe_psfdata_get_data(psfdata, "Background");
02471 }
02472 else {
02473 if ((cpl_image_get_size_x(background) != nfibers) ||
02474 (cpl_image_get_size_y(background) > nbins)) {
02475 return NULL;
02476 }
02477 }
02478
02479 bsize = (cxdouble)nx / (cxdouble)nbins;
02480
02481 _nbins = cpl_image_get_size_y(amplitude);
02482 _bsize = (cxdouble)nx / (cxdouble)_nbins;
02483
02484 mask = cpl_image_new(ny, nx, CPL_TYPE_DOUBLE);
02485 _mask = cpl_image_get_data_double(mask);
02486
02487 profile = giraffe_model_new(model);
02488
02489 for (fiber = 0; fiber < nfibers; fiber++) {
02490
02491 cxint ylower = 0;
02492 cxint yupper = ny;
02493
02494 const cxdouble* _amplitude =
02495 cpl_image_get_data_double_const(amplitude);
02496 const cxdouble* _center =
02497 cpl_image_get_data_double_const(center);
02498 const cxdouble* _width =
02499 cpl_image_get_data_double_const(width);
02500 const cxdouble* _exponent =
02501 cpl_image_get_data_double_const(exponent);
02502
02503 for (i = 0; i < nx; i++) {
02504
02505 register cxint j = 0;
02506 register cxint k = 0;
02507 register cxint l = 0;
02508 register cxint bin = 0;
02509
02510 register cxdouble a = 1.;
02511 register cxdouble b = 0.;
02512 register cxdouble c = 0.;
02513 register cxdouble s = 0.;
02514 register cxdouble e = 0.;
02515
02516
02517 bin = CX_MAX(0, CX_MIN((cxint)floor(i / bsize), nbins - 1));
02518 k = bin * nfibers + fiber;
02519
02520 bin = CX_MAX(0, CX_MIN((cxint)floor(i / _bsize), _nbins - 1));
02521 l = bin * nfibers + fiber;
02522
02523 a = _amplitude[l];
02524 c = _center[k];
02525 s = _width[k];
02526 e = _exponent[k];
02527
02528 giraffe_model_set_parameter(profile, "Amplitude", a);
02529 giraffe_model_set_parameter(profile, "Background", b);
02530 giraffe_model_set_parameter(profile, "Center", c);
02531 giraffe_model_set_parameter(profile, "Width1", s);
02532 giraffe_model_set_parameter(profile, "Width2", e);
02533
02534 switch (psfmodel) {
02535 case PROFILE_PSFEXP:
02536 {
02537 cxdouble w = pow(s * log(1. / cutoff), 1. / e);
02538
02539 ylower = (cxint) floor(c - w);
02540 yupper = (cxint) ceil(c + w);
02541 }
02542 break;
02543
02544 case PROFILE_PSFEXP2:
02545 {
02546 cxdouble w = s * pow(log(1. / cutoff), 1. / e);
02547
02548 ylower = (cxint) floor(c - w);
02549 yupper = (cxint) ceil(c + w);
02550 }
02551 break;
02552
02553 case PROFILE_GAUSSIAN:
02554 {
02555 cxdouble w = s * sqrt(log(1. / cutoff));
02556 ylower = (cxint) floor(c - w);
02557 yupper = (cxint) ceil(c + w);
02558 }
02559 break;
02560
02561 default:
02562 gi_error("Unsupported PSF profile model encountered!");
02563 break;
02564 }
02565
02566 ylower = CX_MAX(0, ylower);
02567 yupper = CX_MIN(ny, yupper);
02568
02569 for (j = ylower; j < yupper; j++) {
02570
02571 cxint status = 0;
02572
02573 cxdouble value = 0.;
02574
02575
02576
02577
02578
02579 giraffe_model_set_argument(profile, "x", j);
02580 giraffe_model_evaluate(profile, &value, &status);
02581
02582 _mask[i * ny + j] += value;
02583
02584 }
02585
02586 }
02587
02588 }
02589
02590 giraffe_model_delete(profile);
02591 profile = NULL;
02592
02593 return mask;
02594
02595 }
02596
02597
02608 cxint
02609 giraffe_compute_fiber_profiles(GiLocalization* result, GiImage* image,
02610 GiTable* fibers, GiLocalization* master,
02611 GiImage* bpixel, GiPsfConfig* config)
02612 {
02613
02614 const cxchar* const _func = "giraffe_compute_fiber_profiles";
02615
02616 cxint i = 0;
02617 cxint status = 0;
02618 cxint nfibers = 0;
02619 cxint nbins = 0;
02620 cxint nx = 0;
02621 cxint ny = 0;
02622
02623 cxdouble bias_sigma = 0.;
02624 cxdouble dark_value = 0.;
02625
02626 cx_string* s = NULL;
02627
02628 cpl_table* _fibers = NULL;
02629 cpl_table* locc = NULL;
02630
02631 cpl_matrix* my = NULL;
02632
02633 cpl_image* _image = NULL;
02634 cpl_image* _variance = NULL;
02635 cpl_image* _locy = NULL;
02636 cpl_image* _locw = NULL;
02637 cpl_image* _bpixel = NULL;
02638
02639 cpl_propertylist* properties = NULL;
02640
02641 GiModel* psfmodel = NULL;
02642
02643 GiPsfData* psfdata = NULL;
02644 GiPsfData* psffit = NULL;
02645
02646 GiMaskPosition positions = {GIMASK_FITTED_DATA, NULL, NULL};
02647 GiMaskPosition coeffs = {GIMASK_FIT_COEFFS, NULL, NULL};
02648
02649 GiPsfParams psf_setup = {0, 0, 1000., FALSE};
02650
02651
02652 if ((result == NULL) || (image == NULL) || (fibers == NULL) ||
02653 (master == NULL) || (config == NULL)) {
02654 cpl_error_set(_func, CPL_ERROR_NULL_INPUT);
02655 return 1;
02656 }
02657
02658 if ((master->locy == NULL) || (master->locw == NULL)) {
02659 cpl_error_set(_func, CPL_ERROR_NULL_INPUT);
02660 return 1;
02661 }
02662
02663 if ((result->locy != NULL) || (result->locw != NULL) ||
02664 (result->locc != NULL) || (result->psf != NULL)) {
02665 cpl_error_set(_func, CPL_ERROR_ILLEGAL_INPUT);
02666 return 1;
02667 }
02668
02669 _image = giraffe_image_get(image);
02670 _locy = giraffe_image_get(master->locy);
02671 _locw = giraffe_image_get(master->locw);
02672
02673 if (bpixel != NULL) {
02674 _bpixel = giraffe_image_get(bpixel);
02675 }
02676
02677 _fibers = giraffe_table_get(fibers);
02678
02679 if (_fibers == NULL) {
02680 cpl_error_set(_func, CPL_ERROR_DATA_NOT_FOUND);
02681 return 1;
02682 }
02683
02684 nfibers = cpl_table_get_nrow(_fibers);
02685
02686 nx = cpl_image_get_size_y(_image);
02687 ny = cpl_image_get_size_x(_image);
02688
02689 nbins = (cxint) ceil(nx / config->binsize);
02690
02691
02692
02693
02694
02695
02696 properties = giraffe_image_get_properties(image);
02697
02698 if (cpl_propertylist_has(properties, GIALIAS_NFIBERS) == FALSE) {
02699 cpl_propertylist_append_int(properties, GIALIAS_NFIBERS, nfibers);
02700 cpl_propertylist_set_comment(properties, GIALIAS_NFIBERS,
02701 "Number of fibres");
02702 }
02703 else {
02704
02705 cxint _nfibers = cpl_propertylist_get_int(properties,
02706 GIALIAS_NFIBERS);
02707
02708 if (nfibers != _nfibers) {
02709 cpl_error_set(_func, CPL_ERROR_ILLEGAL_INPUT);
02710 return 1;
02711 }
02712
02713 }
02714
02715 if (cpl_propertylist_has(properties, GIALIAS_BIASSIGMA) == FALSE) {
02716 cpl_error_set(_func, CPL_ERROR_DATA_NOT_FOUND);
02717 cpl_msg_error(_func, "Missing bias value property (%s)!",
02718 GIALIAS_BIASVALUE);
02719 return 1;
02720 }
02721 else {
02722 bias_sigma = cpl_propertylist_get_double(properties,
02723 GIALIAS_BIASSIGMA);
02724 }
02725
02726 if (cpl_propertylist_has(properties, GIALIAS_DARKVALUE) == FALSE) {
02727 cpl_msg_warning(_func, "Missing dark value property (%s) will be "
02728 "set to %.2f!", GIALIAS_DARKVALUE, dark_value);
02729 cpl_propertylist_append_double(properties, GIALIAS_DARKVALUE,
02730 dark_value);
02731 }
02732 else {
02733 dark_value = cpl_propertylist_get_double(properties,
02734 GIALIAS_DARKVALUE);
02735 }
02736
02737 if (cpl_propertylist_has(properties, GIALIAS_CONAD) == TRUE) {
02738
02739 cxdouble conad = cpl_propertylist_get_double(properties,
02740 GIALIAS_CONAD);
02741
02742 if (conad > 0.) {
02743 bias_sigma *= conad;
02744 dark_value *= conad;
02745 }
02746
02747 }
02748
02749 giraffe_error_push();
02750
02751 _variance = cpl_image_abs_create(_image);
02752 cpl_image_add_scalar(_variance, pow(bias_sigma, 2.) + dark_value);
02753
02754 if (cpl_error_get_code() != CPL_ERROR_NONE) {
02755 if (_variance != NULL) {
02756 cpl_image_delete(_variance);
02757 _variance = NULL;
02758 }
02759
02760 return 1;
02761 }
02762
02763 giraffe_error_pop();
02764
02765
02766
02767
02768
02769
02770 psfmodel = giraffe_model_new(config->profile);
02771
02772 giraffe_model_thaw(psfmodel);
02773
02774 giraffe_model_set_parameter(psfmodel, "Amplitude", 1.);
02775 giraffe_model_set_parameter(psfmodel, "Background", 0.);
02776 giraffe_model_set_parameter(psfmodel, "Center", 0.);
02777 giraffe_model_set_parameter(psfmodel, "Width1", config->width);
02778
02779 if (cx_strncasecmp(config->profile, "psfexp", 6) == 0) {
02780
02781 cxdouble _exponent = fabs(config->exponent);
02782
02783 giraffe_model_set_parameter(psfmodel, "Width2", _exponent);
02784
02785 if (config->exponent > 0) {
02786 giraffe_model_freeze_parameter(psfmodel, "Width2");
02787 }
02788
02789 }
02790
02791 giraffe_model_set_iterations(psfmodel, config->fit.iterations);
02792 giraffe_model_set_delta(psfmodel, config->fit.delta);
02793 giraffe_model_set_tests(psfmodel, config->fit.tests);
02794
02795
02796
02797
02798
02799
02800
02801 cpl_msg_info(_func, "Fitting fiber profiles ...");
02802
02803 psf_setup.bsize = config->binsize;
02804 psf_setup.mwidth = config->maxwidth;
02805 psf_setup.normalize = config->normalize;
02806
02807 psfdata = giraffe_psfdata_create(nfibers, nbins, ny, nx);
02808
02809 status = _giraffe_psf_compute_profile(psfdata, _image, _variance, _locy,
02810 _locw, _fibers, _bpixel, psfmodel,
02811 &psf_setup);
02812
02813 if (status != 0) {
02814 giraffe_psfdata_delete(psfdata);
02815 psfdata= NULL;
02816
02817 giraffe_model_delete(psfmodel);
02818 psfmodel = NULL;
02819
02820 cpl_image_delete(_variance);
02821 _variance = NULL;
02822
02823 cpl_msg_error(_func, "Fiber profile fit failed!");
02824
02825 return 2;
02826 }
02827
02828
02829
02830
02831
02832
02833
02834 cpl_msg_info(_func, "Fitting PSF profile parameters ...");
02835
02836 if (config->parameter_fit == TRUE) {
02837
02838 const cxchar* parameters[] = {"Center", "Amplitude", "Background",
02839 "Width1", "Width2", NULL};
02840
02841 psffit = _giraffe_psf_fit_parameters(psfdata, _fibers, parameters,
02842 config->yorder, config->worder,
02843 &config->clip);
02844
02845 }
02846 else {
02847
02848 psffit = _giraffe_psf_fit_parameters1d(psfdata, _fibers,
02849 NULL, config->yorder,
02850 &config->clip);
02851
02852 }
02853
02854 if (psffit == NULL) {
02855 giraffe_psfdata_delete(psfdata);
02856 psfdata= NULL;
02857
02858 giraffe_model_delete(psfmodel);
02859 psfmodel = NULL;
02860
02861 cpl_image_delete(_variance);
02862 _variance = NULL;
02863
02864 cpl_msg_error(_func, "PSF parameter fit failed!");
02865 return 3;
02866 }
02867
02868 giraffe_model_delete(psfmodel);
02869 psfmodel = NULL;
02870
02871 cpl_image_delete(_variance);
02872 _variance = NULL;
02873
02874
02875
02876
02877
02878
02879 positions.my = cpl_matrix_new(nx, nfibers);
02880 positions.mw = cpl_matrix_new(nx, nfibers);
02881
02882 coeffs.my = cpl_matrix_new(config->yorder + 1, nfibers);
02883 coeffs.mw = cpl_matrix_new(config->worder + 1, config->worder + 1);
02884
02885 status = _giraffe_psf_compute_mask(&positions, &coeffs, psfdata, _fibers,
02886 config->yorder, config->worder,
02887 &config->clip);
02888
02889 if (status != 0) {
02890
02891 giraffe_psfdata_delete(psffit);
02892 psffit = NULL;
02893
02894 giraffe_psfdata_delete(psfdata);
02895 psfdata= NULL;
02896
02897 cpl_msg_error(_func, "Computation of localization mask from "
02898 "the fiber profile failed!");
02899
02900 return 4;
02901 }
02902
02903 giraffe_psfdata_delete(psfdata);
02904 psfdata= NULL;
02905
02906
02907
02908
02909
02910
02911
02912 properties = giraffe_image_get_properties(image);
02913
02914 cpl_propertylist_update_string(properties, GIALIAS_PSFMODEL,
02915 config->profile);
02916 cpl_propertylist_set_comment(properties, GIALIAS_PSFMODEL,
02917 "PSF profile model identifier");
02918
02919 cpl_propertylist_update_int(properties, GIALIAS_PSFXBINS,
02920 config->binsize);
02921 cpl_propertylist_set_comment(properties, GIALIAS_PSFXBINS,
02922 "Size of bins along the dispersion "
02923 "direction.");
02924
02925 cpl_propertylist_update_int(properties, GIALIAS_PSFYDEG,
02926 config->yorder);
02927 cpl_propertylist_set_comment(properties, GIALIAS_PSFYDEG,
02928 "Order of the fiber center polynomial "
02929 "model.");
02930
02931 cpl_propertylist_update_int(properties, GIALIAS_PSFWDEG,
02932 config->worder);
02933 cpl_propertylist_set_comment(properties, GIALIAS_PSFWDEG,
02934 "Order of the fiber width 2d polynomial "
02935 "model.");
02936
02937 cpl_propertylist_update_int(properties, GIALIAS_PSFWDEG,
02938 config->worder);
02939 cpl_propertylist_set_comment(properties, GIALIAS_PSFWDEG,
02940 "Order of the fiber width 2d polynomial "
02941 "model.");
02942
02943 cpl_propertylist_update_bool(properties, GIALIAS_PSFNORM,
02944 config->normalize);
02945 cpl_propertylist_set_comment(properties, GIALIAS_PSFNORM,
02946 "Pixel value normalization.");
02947
02948 cpl_propertylist_update_int(properties, GIALIAS_PSFNX,
02949 cpl_matrix_get_nrow(positions.my));
02950 cpl_propertylist_set_comment(properties, GIALIAS_PSFNX,
02951 "Number of pixels per spectrum.");
02952
02953 cpl_propertylist_update_int(properties, GIALIAS_PSFNS,
02954 cpl_matrix_get_ncol(positions.my));
02955 cpl_propertylist_set_comment(properties, GIALIAS_PSFNS,
02956 "Number of detected fibers.");
02957
02958 cpl_propertylist_update_double(properties, GIALIAS_PSFSIGMA,
02959 config->clip.level);
02960 cpl_propertylist_set_comment(properties, GIALIAS_PSFSIGMA,
02961 "Sigma multiplier used for the PSF "
02962 "parmeter fit.");
02963
02964 cpl_propertylist_update_double(properties, GIALIAS_PSFSIGMA,
02965 config->clip.level);
02966 cpl_propertylist_set_comment(properties, GIALIAS_PSFSIGMA,
02967 "Sigma multiplier used for the fit of PSF "
02968 "parameters.");
02969
02970 cpl_propertylist_update_int(properties, GIALIAS_PSFNITER,
02971 config->clip.iterations);
02972 cpl_propertylist_set_comment(properties, GIALIAS_PSFNITER,
02973 "Number of iterations used for the fit "
02974 "of PSF parameters.");
02975
02976 cpl_propertylist_update_double(properties, GIALIAS_PSFMFRAC,
02977 config->clip.fraction);
02978 cpl_propertylist_set_comment(properties, GIALIAS_PSFMFRAC,
02979 "Minimum allowed fraction of accepted "
02980 "over total data points used for the "
02981 "fit of PSF parameters.");
02982
02983
02984
02985
02986 result->locy = giraffe_image_create(CPL_TYPE_DOUBLE,
02987 cpl_matrix_get_ncol(positions.my),
02988 cpl_matrix_get_nrow(positions.my));
02989 giraffe_image_copy_matrix(result->locy, positions.my);
02990
02991 cpl_matrix_delete(positions.my);
02992 positions.my = NULL;
02993
02994 giraffe_image_set_properties(result->locy, properties);
02995 properties = giraffe_image_get_properties(result->locy);
02996
02997 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE, "LOCY");
02998 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
02999 "GIRAFFE localization centroid");
03000
03001
03002
03003
03004 result->locw = giraffe_image_create(CPL_TYPE_DOUBLE,
03005 cpl_matrix_get_ncol(positions.mw),
03006 cpl_matrix_get_nrow(positions.mw));
03007 giraffe_image_copy_matrix(result->locw, positions.mw);
03008
03009 cpl_matrix_delete(positions.mw);
03010 positions.mw = NULL;
03011
03012 properties = giraffe_image_get_properties(result->locy);
03013
03014 giraffe_image_set_properties(result->locw, properties);
03015 properties = giraffe_image_get_properties(result->locw);
03016
03017 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE, "LOCWY");
03018 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03019 "GIRAFFE localization half-width");
03020
03021
03022
03023
03024 locc = cpl_table_new(cpl_matrix_get_ncol(coeffs.my));
03025
03026 cpl_table_new_column(locc, "BUTTON", CPL_TYPE_INT);
03027 for (i = 0; i < cpl_table_get_nrow(locc); i++) {
03028 cpl_table_set_int(locc, "BUTTON", i, i);
03029 }
03030
03031 for (i = 0; i < cpl_matrix_get_nrow(coeffs.my); i++) {
03032
03033 cxchar* label = NULL;
03034
03035 cx_asprintf(&label, "YC%d", i);
03036 cpl_table_new_column(locc, label, CPL_TYPE_DOUBLE);
03037 cx_free(label);
03038
03039 }
03040
03041 properties = giraffe_image_get_properties(result->locy);
03042
03043 result->locc = giraffe_table_create(locc, properties);
03044 properties = giraffe_table_get_properties(result->locc);
03045
03046 cpl_table_delete(locc);
03047 locc = NULL;
03048
03049 my = cpl_matrix_transpose_create(coeffs.my);
03050 giraffe_table_copy_matrix(result->locc, "YC0", my);
03051
03052 cpl_matrix_delete(my);
03053 my = NULL;
03054
03055 cpl_matrix_delete(coeffs.my);
03056 coeffs.my = NULL;
03057
03058
03059
03060
03061 s = cx_string_new();
03062
03063 for (i = 0; i < cpl_matrix_get_ncol(coeffs.mw); i++) {
03064 cx_string_sprintf(s, "%s%d", GIALIAS_LOCWIDCOEF, i);
03065 cpl_propertylist_update_double(properties, cx_string_get(s),
03066 cpl_matrix_get(coeffs.mw, 0, i));
03067 }
03068
03069 cx_string_delete(s);
03070 s = NULL;
03071
03072 cpl_matrix_delete(coeffs.mw);
03073 coeffs.mw = NULL;
03074
03075 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
03076 "LOCYWCHEB");
03077 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03078 "GIRAFFE localization fit coefficients");
03079
03080
03081
03082
03083 if (psffit != NULL) {
03084 result->psf = psffit;
03085 }
03086
03087 return 0;
03088
03089 }
03090
03091
03102 GiPsfConfig*
03103 giraffe_psf_config_create(cpl_parameterlist* list)
03104 {
03105
03106 cpl_parameter *p;
03107
03108 GiPsfConfig *self = NULL;
03109
03110
03111 if (list == NULL) {
03112 return NULL;
03113 }
03114
03115 self = cx_calloc(1, sizeof *self);
03116
03117 p = cpl_parameterlist_find(list, "giraffe.psf.model");
03118 self->profile = cx_strdup(cpl_parameter_get_string(p));
03119
03120 if (cx_strncasecmp(self->profile, "psfexp", 6) == 0) {
03121 self->width = 16.;
03122 }
03123 else {
03124 self->width = 4.;
03125 }
03126
03127 p = cpl_parameterlist_find(list, "giraffe.psf.binsize");
03128 self->binsize = cpl_parameter_get_int(p);
03129
03130 if (self->binsize < 1) {
03131 self->binsize = 1;
03132 }
03133
03134 p = cpl_parameterlist_find(list, "giraffe.psf.maxwidth");
03135 self->maxwidth = cpl_parameter_get_double(p);
03136
03137 if (self->width > 0.) {
03138 p = cpl_parameterlist_find(list, "giraffe.psf.width");
03139 self->width = cpl_parameter_get_double(p);
03140 }
03141
03142 if (self->width > self->maxwidth) {
03143 self->width = self->maxwidth;
03144 }
03145
03146 p = cpl_parameterlist_find(list, "giraffe.psf.exponent");
03147 self->exponent = cpl_parameter_get_double(p);
03148
03149 p = cpl_parameterlist_find(list, "giraffe.psf.normalize");
03150 self->normalize = cpl_parameter_get_bool(p);
03151
03152 p = cpl_parameterlist_find(list, "giraffe.psf.profile.iterations");
03153 self->fit.iterations = cpl_parameter_get_int(p);
03154
03155 p = cpl_parameterlist_find(list, "giraffe.psf.profile.tests");
03156 self->fit.tests = cpl_parameter_get_int(p);
03157
03158 p = cpl_parameterlist_find(list, "giraffe.psf.profile.dchisquare");
03159 self->fit.delta = cpl_parameter_get_double(p);
03160
03161 p = cpl_parameterlist_find(list, "giraffe.psf.parameters.fit");
03162 self->parameter_fit = cpl_parameter_get_bool(p);
03163
03164 p = cpl_parameterlist_find(list, "giraffe.psf.parameters.yorder");
03165 self->yorder = cpl_parameter_get_int(p);
03166
03167 if (self->yorder < 0) {
03168 giraffe_psf_config_destroy(self);
03169 self = NULL;
03170 }
03171
03172 p = cpl_parameterlist_find(list, "giraffe.psf.parameters.worder");
03173 self->worder = cpl_parameter_get_int(p);
03174
03175 if (self->worder < 0) {
03176 giraffe_psf_config_destroy(self);
03177 self = NULL;
03178 }
03179
03180 p = cpl_parameterlist_find(list, "giraffe.psf.parameters.sigma");
03181 self->clip.level = cpl_parameter_get_double(p);
03182
03183 p = cpl_parameterlist_find(list, "giraffe.psf.parameters.iterations");
03184 self->clip.iterations = cpl_parameter_get_int(p);
03185
03186 p = cpl_parameterlist_find(list, "giraffe.psf.parameters.fraction");
03187 self->clip.fraction = cpl_parameter_get_double(p);
03188
03189 return self;
03190
03191 }
03192
03193
03206 void
03207 giraffe_psf_config_destroy(GiPsfConfig* self)
03208 {
03209
03210 if (self != NULL) {
03211 if (self->profile != NULL) {
03212 cx_free((cxptr) self->profile);
03213 self->profile = NULL;
03214 }
03215
03216 cx_free(self);
03217 self = NULL;
03218 }
03219
03220 return;
03221
03222 }
03223
03224
03236 void
03237 giraffe_psf_config_add(cpl_parameterlist* list)
03238 {
03239
03240 cpl_parameter* p = NULL;
03241
03242
03243 if (list == NULL) {
03244 return;
03245 }
03246
03247 p = cpl_parameter_new_enum("giraffe.psf.model",
03248 CPL_TYPE_STRING,
03249 "PSF profile model: `psfexp', `psfexp2'",
03250 "giraffe.psf",
03251 "psfexp2", 3, "psfexp", "psfexp2", "gaussian");
03252 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-model");
03253 cpl_parameterlist_append(list, p);
03254
03255 p = cpl_parameter_new_value("giraffe.psf.normalize",
03256 CPL_TYPE_BOOL,
03257 "Use normalized pixel values.",
03258 "giraffe.psf",
03259 FALSE);
03260 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-norm");
03261 cpl_parameterlist_append(list, p);
03262
03263
03264 p = cpl_parameter_new_value("giraffe.psf.binsize",
03265 CPL_TYPE_INT,
03266 "Size of bin along dispersion axis",
03267 "giraffe.psf",
03268 64);
03269 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-binsize");
03270 cpl_parameterlist_append(list, p);
03271
03272
03273 p = cpl_parameter_new_value("giraffe.psf.maxwidth",
03274 CPL_TYPE_DOUBLE,
03275 "Maximum width of the PSF profile.",
03276 "giraffe.psf",
03277 16.);
03278 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-maxwidth");
03279 cpl_parameterlist_append(list, p);
03280
03281
03282 p = cpl_parameter_new_value("giraffe.psf.width",
03283 CPL_TYPE_DOUBLE,
03284 "Initial width of the PSF profile.",
03285 "giraffe.psf",
03286 0.);
03287 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-width");
03288 cpl_parameterlist_append(list, p);
03289
03290
03291 p = cpl_parameter_new_value("giraffe.psf.exponent",
03292 CPL_TYPE_DOUBLE,
03293 "Exponent of the exponential PSF profile "
03294 "(will not be fitted if > 0).",
03295 "giraffe.psf",
03296 -3.);
03297 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-exponent");
03298 cpl_parameterlist_append(list, p);
03299
03300
03301 p = cpl_parameter_new_value("giraffe.psf.profile.iterations",
03302 CPL_TYPE_INT,
03303 "Maximum number of iterations used for "
03304 "the fit of the fiber PSF profile.",
03305 "giraffe.psf",
03306 120);
03307
03308 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-pfniter");
03309 cpl_parameterlist_append(list, p);
03310
03311
03312 p = cpl_parameter_new_value("giraffe.psf.profile.tests",
03313 CPL_TYPE_INT,
03314 "Maximum number of tests used for the fit "
03315 "of the fiber PSF profile",
03316 "giraffe.psf",
03317 7);
03318
03319 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-pfntest");
03320 cpl_parameterlist_append(list, p);
03321
03322
03323 p = cpl_parameter_new_value("giraffe.psf.profile.dchisquare",
03324 CPL_TYPE_DOUBLE,
03325 "Minimum chi-square difference used for the "
03326 "fit of the fiber PSF profile.",
03327 "giraffe.psf",
03328 0.001);
03329
03330 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-pfdchisq");
03331 cpl_parameterlist_append(list, p);
03332
03333
03334 p = cpl_parameter_new_value("giraffe.psf.parameters.fit",
03335 CPL_TYPE_BOOL,
03336 "2D fit of the PSF profile parameters "
03337 "using a Chebyshev polynomial model.",
03338 "giraffe.psf",
03339 FALSE);
03340 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-prmfit");
03341 cpl_parameterlist_append(list, p);
03342
03343
03344 p = cpl_parameter_new_value("giraffe.psf.parameters.yorder",
03345 CPL_TYPE_INT,
03346 "Order of Chebyshev polynomial fit.",
03347 "giraffe.psf",
03348 4);
03349 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-yorder");
03350 cpl_parameterlist_append(list, p);
03351
03352
03353 p = cpl_parameter_new_value("giraffe.psf.parameters.worder",
03354 CPL_TYPE_INT,
03355 "Order of Chebyshev 2D polynomial fit.",
03356 "giraffe.psf",
03357 4);
03358 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-worder");
03359 cpl_parameterlist_append(list, p);
03360
03361
03362 p = cpl_parameter_new_value("giraffe.psf.parameters.sigma",
03363 CPL_TYPE_DOUBLE,
03364 "PSF parameter fitting: sigma threshold "
03365 "factor",
03366 "giraffe.psf",
03367 3.5);
03368 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-sigma");
03369 cpl_parameterlist_append(list, p);
03370
03371
03372 p = cpl_parameter_new_value("giraffe.psf.parameters.iterations",
03373 CPL_TYPE_INT,
03374 "PSF parameter fitting: number of "
03375 "iterations",
03376 "giraffe.psf",
03377 10);
03378 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-niter");
03379 cpl_parameterlist_append(list, p);
03380
03381
03382 p = cpl_parameter_new_range("giraffe.psf.parameters.fraction",
03383 CPL_TYPE_DOUBLE,
03384 "PSF parameter fitting: minimum fraction "
03385 "of points accepted/total.",
03386 "giraffe.psf",
03387 0.8, 0.0, 1.0);
03388 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-mfrac");
03389 cpl_parameterlist_append(list, p);
03390
03391 return;
03392
03393 }