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 nframes = 1;
02620 cxint nbins = 0;
02621 cxint nx = 0;
02622 cxint ny = 0;
02623
02624 cxdouble conad = 1.;
02625 cxdouble bias_ron = 0.;
02626 cxdouble bias_sigma = 0.;
02627 cxdouble dark_value = 0.;
02628
02629 cx_string* s = NULL;
02630
02631 cpl_table* _fibers = NULL;
02632 cpl_table* locc = NULL;
02633
02634 cpl_matrix* my = NULL;
02635
02636 cpl_image* _image = NULL;
02637 cpl_image* _variance = NULL;
02638 cpl_image* _locy = NULL;
02639 cpl_image* _locw = NULL;
02640 cpl_image* _bpixel = NULL;
02641
02642 cpl_propertylist* properties = NULL;
02643
02644 GiModel* psfmodel = NULL;
02645
02646 GiPsfData* psfdata = NULL;
02647 GiPsfData* psffit = NULL;
02648
02649 GiMaskPosition positions = {GIMASK_FITTED_DATA, NULL, NULL};
02650 GiMaskPosition coeffs = {GIMASK_FIT_COEFFS, NULL, NULL};
02651
02652 GiPsfParams psf_setup = {0, 0, 1000., FALSE};
02653
02654
02655 if ((result == NULL) || (image == NULL) || (fibers == NULL) ||
02656 (master == NULL) || (config == NULL)) {
02657 cpl_error_set(_func, CPL_ERROR_NULL_INPUT);
02658 return 1;
02659 }
02660
02661 if ((master->locy == NULL) || (master->locw == NULL)) {
02662 cpl_error_set(_func, CPL_ERROR_NULL_INPUT);
02663 return 1;
02664 }
02665
02666 if ((result->locy != NULL) || (result->locw != NULL) ||
02667 (result->locc != NULL) || (result->psf != NULL)) {
02668 cpl_error_set(_func, CPL_ERROR_ILLEGAL_INPUT);
02669 return 1;
02670 }
02671
02672 _image = giraffe_image_get(image);
02673 _locy = giraffe_image_get(master->locy);
02674 _locw = giraffe_image_get(master->locw);
02675
02676 if (bpixel != NULL) {
02677 _bpixel = giraffe_image_get(bpixel);
02678 }
02679
02680 _fibers = giraffe_table_get(fibers);
02681
02682 if (_fibers == NULL) {
02683 cpl_error_set(_func, CPL_ERROR_DATA_NOT_FOUND);
02684 return 1;
02685 }
02686
02687 nfibers = cpl_table_get_nrow(_fibers);
02688
02689 nx = cpl_image_get_size_y(_image);
02690 ny = cpl_image_get_size_x(_image);
02691
02692 nbins = (cxint) ceil(nx / config->binsize);
02693
02694
02695
02696
02697
02698
02699 properties = giraffe_image_get_properties(image);
02700
02701 if (cpl_propertylist_has(properties, GIALIAS_NFIBERS) == FALSE) {
02702 cpl_propertylist_append_int(properties, GIALIAS_NFIBERS, nfibers);
02703 cpl_propertylist_set_comment(properties, GIALIAS_NFIBERS,
02704 "Number of fibres");
02705 }
02706 else {
02707
02708 cxint _nfibers = cpl_propertylist_get_int(properties,
02709 GIALIAS_NFIBERS);
02710
02711 if (nfibers != _nfibers) {
02712 cpl_error_set(_func, CPL_ERROR_ILLEGAL_INPUT);
02713 return 1;
02714 }
02715
02716 }
02717
02718
02719 if (!cpl_propertylist_has(properties, GIALIAS_CONAD)) {
02720 cpl_msg_error(_func, "Missing detector gain property (%s)! ",
02721 GIALIAS_CONAD);
02722 return 1;
02723 }
02724 else {
02725 conad = cpl_propertylist_get_double(properties, GIALIAS_CONAD);
02726 }
02727
02728
02729 if (!cpl_propertylist_has(properties, GIALIAS_BIASERROR)) {
02730 cpl_msg_warning(_func, "Missing bias error property (%s)! Setting "
02731 "bias error to 0.", GIALIAS_BIASERROR);
02732 bias_sigma = 0.;
02733 }
02734 else {
02735 bias_sigma = cpl_propertylist_get_double(properties, GIALIAS_BIASERROR);
02736 }
02737
02738
02739 giraffe_error_push();
02740
02741 bias_ron = giraffe_propertylist_get_ron(properties);
02742
02743 if (cpl_error_get_code() != CPL_ERROR_NONE) {
02744 return 1;
02745 }
02746
02747 giraffe_error_pop();
02748
02749
02750 if (cpl_propertylist_has(properties, GIALIAS_DARKVALUE) == FALSE) {
02751 cpl_msg_warning(_func, "Missing dark value property (%s) will be "
02752 "set to %.2f!", GIALIAS_DARKVALUE, dark_value);
02753 cpl_propertylist_append_double(properties, GIALIAS_DARKVALUE,
02754 dark_value);
02755 }
02756 else {
02757 dark_value = cpl_propertylist_get_double(properties,
02758 GIALIAS_DARKVALUE);
02759 }
02760
02761
02762 if (cpl_propertylist_has(properties, GIALIAS_DATANCOM)) {
02763 nframes = cpl_propertylist_get_int(properties, GIALIAS_DATANCOM);
02764 }
02765
02766
02767
02768
02769
02770
02771 bias_sigma *= conad;
02772 dark_value *= conad;
02773
02774
02775
02776
02777
02778
02779 giraffe_error_push();
02780
02781 _image = cpl_image_multiply_scalar_create(_image, nframes * conad);
02782 _variance = cpl_image_abs_create(_image);
02783
02784 cpl_image_add_scalar(_variance,
02785 nframes * (bias_ron * bias_ron + nframes *
02786 (bias_sigma * bias_sigma + dark_value * dark_value)));
02787
02788 if (cpl_error_get_code() != CPL_ERROR_NONE) {
02789 if (_variance != NULL) {
02790 cpl_image_delete(_variance);
02791 _variance = NULL;
02792 }
02793
02794 cpl_image_delete(_image);
02795 _image = NULL;
02796
02797 return 1;
02798 }
02799
02800 giraffe_error_pop();
02801
02802
02803
02804
02805
02806
02807 psfmodel = giraffe_model_new(config->profile);
02808
02809 giraffe_model_thaw(psfmodel);
02810
02811 giraffe_model_set_parameter(psfmodel, "Amplitude", 1.);
02812 giraffe_model_set_parameter(psfmodel, "Background", 0.);
02813 giraffe_model_set_parameter(psfmodel, "Center", 0.);
02814 giraffe_model_set_parameter(psfmodel, "Width1", config->width);
02815
02816 if (cx_strncasecmp(config->profile, "psfexp", 6) == 0) {
02817
02818 cxdouble _exponent = fabs(config->exponent);
02819
02820 giraffe_model_set_parameter(psfmodel, "Width2", _exponent);
02821
02822 if (config->exponent > 0) {
02823 giraffe_model_freeze_parameter(psfmodel, "Width2");
02824 }
02825
02826 }
02827
02828 giraffe_model_set_iterations(psfmodel, config->fit.iterations);
02829 giraffe_model_set_delta(psfmodel, config->fit.delta);
02830 giraffe_model_set_tests(psfmodel, config->fit.tests);
02831
02832
02833
02834
02835
02836
02837
02838 cpl_msg_info(_func, "Fitting fiber profiles ...");
02839
02840 psf_setup.bsize = config->binsize;
02841 psf_setup.mwidth = config->maxwidth;
02842 psf_setup.normalize = config->normalize;
02843
02844 psfdata = giraffe_psfdata_create(nfibers, nbins, ny, nx);
02845
02846 status = _giraffe_psf_compute_profile(psfdata, _image, _variance, _locy,
02847 _locw, _fibers, _bpixel, psfmodel,
02848 &psf_setup);
02849
02850 cpl_image_delete(_image);
02851 _image = NULL;
02852
02853 if (status != 0) {
02854 giraffe_psfdata_delete(psfdata);
02855 psfdata= NULL;
02856
02857 giraffe_model_delete(psfmodel);
02858 psfmodel = NULL;
02859
02860 cpl_image_delete(_variance);
02861 _variance = NULL;
02862
02863 cpl_msg_error(_func, "Fiber profile fit failed!");
02864
02865 return 2;
02866 }
02867
02868
02869
02870
02871
02872
02873
02874 _image = (cpl_image*) giraffe_psfdata_get_data(psfdata, "Amplitude");
02875 cpl_image_divide_scalar(_image, nframes * conad);
02876
02877 _image = (cpl_image*) giraffe_psfdata_get_data(psfdata, "Background");
02878 cpl_image_divide_scalar(_image, nframes * conad);
02879
02880 _image = NULL;
02881
02882
02883
02884
02885
02886
02887
02888 cpl_msg_info(_func, "Fitting PSF profile parameters ...");
02889
02890 if (config->parameter_fit == TRUE) {
02891
02892 const cxchar* parameters[] = {"Center", "Amplitude", "Background",
02893 "Width1", "Width2", NULL};
02894
02895 psffit = _giraffe_psf_fit_parameters(psfdata, _fibers, parameters,
02896 config->yorder, config->worder,
02897 &config->clip);
02898
02899 }
02900 else {
02901
02902 psffit = _giraffe_psf_fit_parameters1d(psfdata, _fibers,
02903 NULL, config->yorder,
02904 &config->clip);
02905
02906 }
02907
02908 if (psffit == NULL) {
02909 giraffe_psfdata_delete(psfdata);
02910 psfdata= NULL;
02911
02912 giraffe_model_delete(psfmodel);
02913 psfmodel = NULL;
02914
02915 cpl_image_delete(_variance);
02916 _variance = NULL;
02917
02918 cpl_msg_error(_func, "PSF parameter fit failed!");
02919 return 3;
02920 }
02921
02922 giraffe_model_delete(psfmodel);
02923 psfmodel = NULL;
02924
02925 cpl_image_delete(_variance);
02926 _variance = NULL;
02927
02928
02929
02930
02931
02932
02933 positions.my = cpl_matrix_new(nx, nfibers);
02934 positions.mw = cpl_matrix_new(nx, nfibers);
02935
02936 coeffs.my = cpl_matrix_new(config->yorder + 1, nfibers);
02937 coeffs.mw = cpl_matrix_new(config->worder + 1, config->worder + 1);
02938
02939 status = _giraffe_psf_compute_mask(&positions, &coeffs, psfdata, _fibers,
02940 config->yorder, config->worder,
02941 &config->clip);
02942
02943 if (status != 0) {
02944
02945 giraffe_psfdata_delete(psffit);
02946 psffit = NULL;
02947
02948 giraffe_psfdata_delete(psfdata);
02949 psfdata= NULL;
02950
02951 cpl_msg_error(_func, "Computation of localization mask from "
02952 "the fiber profile failed!");
02953
02954 return 4;
02955 }
02956
02957 giraffe_psfdata_delete(psfdata);
02958 psfdata= NULL;
02959
02960
02961
02962
02963
02964
02965
02966 properties = giraffe_image_get_properties(image);
02967
02968 cpl_propertylist_update_string(properties, GIALIAS_PSFMODEL,
02969 config->profile);
02970 cpl_propertylist_set_comment(properties, GIALIAS_PSFMODEL,
02971 "PSF profile model identifier");
02972
02973 cpl_propertylist_update_int(properties, GIALIAS_PSFXBINS,
02974 config->binsize);
02975 cpl_propertylist_set_comment(properties, GIALIAS_PSFXBINS,
02976 "Size of bins along the dispersion "
02977 "direction.");
02978
02979 cpl_propertylist_update_int(properties, GIALIAS_PSFYDEG,
02980 config->yorder);
02981 cpl_propertylist_set_comment(properties, GIALIAS_PSFYDEG,
02982 "Order of the fiber center polynomial "
02983 "model.");
02984
02985 cpl_propertylist_update_int(properties, GIALIAS_PSFWDEG,
02986 config->worder);
02987 cpl_propertylist_set_comment(properties, GIALIAS_PSFWDEG,
02988 "Order of the fiber width 2d polynomial "
02989 "model.");
02990
02991 cpl_propertylist_update_int(properties, GIALIAS_PSFWDEG,
02992 config->worder);
02993 cpl_propertylist_set_comment(properties, GIALIAS_PSFWDEG,
02994 "Order of the fiber width 2d polynomial "
02995 "model.");
02996
02997 cpl_propertylist_update_bool(properties, GIALIAS_PSFNORM,
02998 config->normalize);
02999 cpl_propertylist_set_comment(properties, GIALIAS_PSFNORM,
03000 "Pixel value normalization.");
03001
03002 cpl_propertylist_update_int(properties, GIALIAS_PSFNX,
03003 cpl_matrix_get_nrow(positions.my));
03004 cpl_propertylist_set_comment(properties, GIALIAS_PSFNX,
03005 "Number of pixels per spectrum.");
03006
03007 cpl_propertylist_update_int(properties, GIALIAS_PSFNS,
03008 cpl_matrix_get_ncol(positions.my));
03009 cpl_propertylist_set_comment(properties, GIALIAS_PSFNS,
03010 "Number of detected fibers.");
03011
03012 cpl_propertylist_update_double(properties, GIALIAS_PSFSIGMA,
03013 config->clip.level);
03014 cpl_propertylist_set_comment(properties, GIALIAS_PSFSIGMA,
03015 "Sigma multiplier used for the PSF "
03016 "parmeter fit.");
03017
03018 cpl_propertylist_update_double(properties, GIALIAS_PSFSIGMA,
03019 config->clip.level);
03020 cpl_propertylist_set_comment(properties, GIALIAS_PSFSIGMA,
03021 "Sigma multiplier used for the fit of PSF "
03022 "parameters.");
03023
03024 cpl_propertylist_update_int(properties, GIALIAS_PSFNITER,
03025 config->clip.iterations);
03026 cpl_propertylist_set_comment(properties, GIALIAS_PSFNITER,
03027 "Number of iterations used for the fit "
03028 "of PSF parameters.");
03029
03030 cpl_propertylist_update_double(properties, GIALIAS_PSFMFRAC,
03031 config->clip.fraction);
03032 cpl_propertylist_set_comment(properties, GIALIAS_PSFMFRAC,
03033 "Minimum allowed fraction of accepted "
03034 "over total data points used for the "
03035 "fit of PSF parameters.");
03036
03037
03038
03039
03040 result->locy = giraffe_image_create(CPL_TYPE_DOUBLE,
03041 cpl_matrix_get_ncol(positions.my),
03042 cpl_matrix_get_nrow(positions.my));
03043 giraffe_image_copy_matrix(result->locy, positions.my);
03044
03045 cpl_matrix_delete(positions.my);
03046 positions.my = NULL;
03047
03048 giraffe_image_set_properties(result->locy, properties);
03049 properties = giraffe_image_get_properties(result->locy);
03050
03051 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE, "LOCY");
03052 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03053 "GIRAFFE localization centroid");
03054
03055
03056
03057
03058 result->locw = giraffe_image_create(CPL_TYPE_DOUBLE,
03059 cpl_matrix_get_ncol(positions.mw),
03060 cpl_matrix_get_nrow(positions.mw));
03061 giraffe_image_copy_matrix(result->locw, positions.mw);
03062
03063 cpl_matrix_delete(positions.mw);
03064 positions.mw = NULL;
03065
03066 properties = giraffe_image_get_properties(result->locy);
03067
03068 giraffe_image_set_properties(result->locw, properties);
03069 properties = giraffe_image_get_properties(result->locw);
03070
03071 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE, "LOCWY");
03072 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03073 "GIRAFFE localization half-width");
03074
03075
03076
03077
03078 locc = cpl_table_new(cpl_matrix_get_ncol(coeffs.my));
03079
03080 cpl_table_new_column(locc, "BUTTON", CPL_TYPE_INT);
03081 for (i = 0; i < cpl_table_get_nrow(locc); i++) {
03082 cpl_table_set_int(locc, "BUTTON", i, i);
03083 }
03084
03085 for (i = 0; i < cpl_matrix_get_nrow(coeffs.my); i++) {
03086
03087 cxchar* label = NULL;
03088
03089 cx_asprintf(&label, "YC%d", i);
03090 cpl_table_new_column(locc, label, CPL_TYPE_DOUBLE);
03091 cx_free(label);
03092
03093 }
03094
03095 properties = giraffe_image_get_properties(result->locy);
03096
03097 result->locc = giraffe_table_create(locc, properties);
03098 properties = giraffe_table_get_properties(result->locc);
03099
03100 cpl_table_delete(locc);
03101 locc = NULL;
03102
03103 my = cpl_matrix_transpose_create(coeffs.my);
03104 giraffe_table_copy_matrix(result->locc, "YC0", my);
03105
03106 cpl_matrix_delete(my);
03107 my = NULL;
03108
03109 cpl_matrix_delete(coeffs.my);
03110 coeffs.my = NULL;
03111
03112
03113
03114
03115 s = cx_string_new();
03116
03117 for (i = 0; i < cpl_matrix_get_ncol(coeffs.mw); i++) {
03118 cx_string_sprintf(s, "%s%d", GIALIAS_LOCWIDCOEF, i);
03119 cpl_propertylist_update_double(properties, cx_string_get(s),
03120 cpl_matrix_get(coeffs.mw, 0, i));
03121 }
03122
03123 cx_string_delete(s);
03124 s = NULL;
03125
03126 cpl_matrix_delete(coeffs.mw);
03127 coeffs.mw = NULL;
03128
03129 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
03130 "LOCYWCHEB");
03131 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03132 "GIRAFFE localization fit coefficients");
03133
03134
03135
03136
03137 if (psffit != NULL) {
03138 result->psf = psffit;
03139 }
03140
03141 return 0;
03142
03143 }
03144
03145
03156 GiPsfConfig*
03157 giraffe_psf_config_create(cpl_parameterlist* list)
03158 {
03159
03160 cpl_parameter *p;
03161
03162 GiPsfConfig *self = NULL;
03163
03164
03165 if (list == NULL) {
03166 return NULL;
03167 }
03168
03169 self = cx_calloc(1, sizeof *self);
03170
03171 p = cpl_parameterlist_find(list, "giraffe.psf.model");
03172 self->profile = cx_strdup(cpl_parameter_get_string(p));
03173
03174 if (cx_strncasecmp(self->profile, "psfexp", 6) == 0) {
03175 self->width = 16.;
03176 }
03177 else {
03178 self->width = 4.;
03179 }
03180
03181 p = cpl_parameterlist_find(list, "giraffe.psf.binsize");
03182 self->binsize = cpl_parameter_get_int(p);
03183
03184 if (self->binsize < 1) {
03185 self->binsize = 1;
03186 }
03187
03188 p = cpl_parameterlist_find(list, "giraffe.psf.maxwidth");
03189 self->maxwidth = cpl_parameter_get_double(p);
03190
03191 if (self->width > 0.) {
03192 p = cpl_parameterlist_find(list, "giraffe.psf.width");
03193 self->width = cpl_parameter_get_double(p);
03194 }
03195
03196 if (self->width > self->maxwidth) {
03197 self->width = self->maxwidth;
03198 }
03199
03200 p = cpl_parameterlist_find(list, "giraffe.psf.exponent");
03201 self->exponent = cpl_parameter_get_double(p);
03202
03203 p = cpl_parameterlist_find(list, "giraffe.psf.normalize");
03204 self->normalize = cpl_parameter_get_bool(p);
03205
03206 p = cpl_parameterlist_find(list, "giraffe.psf.profile.iterations");
03207 self->fit.iterations = cpl_parameter_get_int(p);
03208
03209 p = cpl_parameterlist_find(list, "giraffe.psf.profile.tests");
03210 self->fit.tests = cpl_parameter_get_int(p);
03211
03212 p = cpl_parameterlist_find(list, "giraffe.psf.profile.dchisquare");
03213 self->fit.delta = cpl_parameter_get_double(p);
03214
03215 p = cpl_parameterlist_find(list, "giraffe.psf.parameters.fit");
03216 self->parameter_fit = cpl_parameter_get_bool(p);
03217
03218 p = cpl_parameterlist_find(list, "giraffe.psf.parameters.yorder");
03219 self->yorder = cpl_parameter_get_int(p);
03220
03221 if (self->yorder < 0) {
03222 giraffe_psf_config_destroy(self);
03223 self = NULL;
03224 }
03225
03226 p = cpl_parameterlist_find(list, "giraffe.psf.parameters.worder");
03227 self->worder = cpl_parameter_get_int(p);
03228
03229 if (self->worder < 0) {
03230 giraffe_psf_config_destroy(self);
03231 self = NULL;
03232 }
03233
03234 p = cpl_parameterlist_find(list, "giraffe.psf.parameters.sigma");
03235 self->clip.level = cpl_parameter_get_double(p);
03236
03237 p = cpl_parameterlist_find(list, "giraffe.psf.parameters.iterations");
03238 self->clip.iterations = cpl_parameter_get_int(p);
03239
03240 p = cpl_parameterlist_find(list, "giraffe.psf.parameters.fraction");
03241 self->clip.fraction = cpl_parameter_get_double(p);
03242
03243 return self;
03244
03245 }
03246
03247
03260 void
03261 giraffe_psf_config_destroy(GiPsfConfig* self)
03262 {
03263
03264 if (self != NULL) {
03265 if (self->profile != NULL) {
03266 cx_free((cxptr) self->profile);
03267 self->profile = NULL;
03268 }
03269
03270 cx_free(self);
03271 self = NULL;
03272 }
03273
03274 return;
03275
03276 }
03277
03278
03290 void
03291 giraffe_psf_config_add(cpl_parameterlist* list)
03292 {
03293
03294 cpl_parameter* p = NULL;
03295
03296
03297 if (list == NULL) {
03298 return;
03299 }
03300
03301 p = cpl_parameter_new_enum("giraffe.psf.model",
03302 CPL_TYPE_STRING,
03303 "PSF profile model: `psfexp', `psfexp2'",
03304 "giraffe.psf",
03305 "psfexp2", 3, "psfexp", "psfexp2", "gaussian");
03306 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-model");
03307 cpl_parameterlist_append(list, p);
03308
03309 p = cpl_parameter_new_value("giraffe.psf.normalize",
03310 CPL_TYPE_BOOL,
03311 "Use normalized pixel values.",
03312 "giraffe.psf",
03313 FALSE);
03314 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-norm");
03315 cpl_parameterlist_append(list, p);
03316
03317
03318 p = cpl_parameter_new_value("giraffe.psf.binsize",
03319 CPL_TYPE_INT,
03320 "Size of bin along dispersion axis",
03321 "giraffe.psf",
03322 64);
03323 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-binsize");
03324 cpl_parameterlist_append(list, p);
03325
03326
03327 p = cpl_parameter_new_value("giraffe.psf.maxwidth",
03328 CPL_TYPE_DOUBLE,
03329 "Maximum width of the PSF profile.",
03330 "giraffe.psf",
03331 16.);
03332 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-maxwidth");
03333 cpl_parameterlist_append(list, p);
03334
03335
03336 p = cpl_parameter_new_value("giraffe.psf.width",
03337 CPL_TYPE_DOUBLE,
03338 "Initial width of the PSF profile.",
03339 "giraffe.psf",
03340 0.);
03341 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-width");
03342 cpl_parameterlist_append(list, p);
03343
03344
03345 p = cpl_parameter_new_value("giraffe.psf.exponent",
03346 CPL_TYPE_DOUBLE,
03347 "Exponent of the exponential PSF profile "
03348 "(will not be fitted if > 0).",
03349 "giraffe.psf",
03350 -3.);
03351 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-exponent");
03352 cpl_parameterlist_append(list, p);
03353
03354
03355 p = cpl_parameter_new_value("giraffe.psf.profile.iterations",
03356 CPL_TYPE_INT,
03357 "Maximum number of iterations used for "
03358 "the fit of the fiber PSF profile.",
03359 "giraffe.psf",
03360 120);
03361
03362 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-pfniter");
03363 cpl_parameterlist_append(list, p);
03364
03365
03366 p = cpl_parameter_new_value("giraffe.psf.profile.tests",
03367 CPL_TYPE_INT,
03368 "Maximum number of tests used for the fit "
03369 "of the fiber PSF profile",
03370 "giraffe.psf",
03371 7);
03372
03373 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-pfntest");
03374 cpl_parameterlist_append(list, p);
03375
03376
03377 p = cpl_parameter_new_value("giraffe.psf.profile.dchisquare",
03378 CPL_TYPE_DOUBLE,
03379 "Minimum chi-square difference used for the "
03380 "fit of the fiber PSF profile.",
03381 "giraffe.psf",
03382 0.001);
03383
03384 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-pfdchisq");
03385 cpl_parameterlist_append(list, p);
03386
03387
03388 p = cpl_parameter_new_value("giraffe.psf.parameters.fit",
03389 CPL_TYPE_BOOL,
03390 "2D fit of the PSF profile parameters "
03391 "using a Chebyshev polynomial model.",
03392 "giraffe.psf",
03393 FALSE);
03394 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-prmfit");
03395 cpl_parameterlist_append(list, p);
03396
03397
03398 p = cpl_parameter_new_value("giraffe.psf.parameters.yorder",
03399 CPL_TYPE_INT,
03400 "Order of Chebyshev polynomial fit.",
03401 "giraffe.psf",
03402 4);
03403 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-yorder");
03404 cpl_parameterlist_append(list, p);
03405
03406
03407 p = cpl_parameter_new_value("giraffe.psf.parameters.worder",
03408 CPL_TYPE_INT,
03409 "Order of Chebyshev 2D polynomial fit.",
03410 "giraffe.psf",
03411 4);
03412 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-worder");
03413 cpl_parameterlist_append(list, p);
03414
03415
03416 p = cpl_parameter_new_value("giraffe.psf.parameters.sigma",
03417 CPL_TYPE_DOUBLE,
03418 "PSF parameter fitting: sigma threshold "
03419 "factor",
03420 "giraffe.psf",
03421 3.5);
03422 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-sigma");
03423 cpl_parameterlist_append(list, p);
03424
03425
03426 p = cpl_parameter_new_value("giraffe.psf.parameters.iterations",
03427 CPL_TYPE_INT,
03428 "PSF parameter fitting: number of "
03429 "iterations",
03430 "giraffe.psf",
03431 10);
03432 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-niter");
03433 cpl_parameterlist_append(list, p);
03434
03435
03436 p = cpl_parameter_new_range("giraffe.psf.parameters.fraction",
03437 CPL_TYPE_DOUBLE,
03438 "PSF parameter fitting: minimum fraction "
03439 "of points accepted/total.",
03440 "giraffe.psf",
03441 0.8, 0.0, 1.0);
03442 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "psf-mfrac");
03443 cpl_parameterlist_append(list, p);
03444
03445 return;
03446
03447 }