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 #include <string.h>
00033 #include <math.h>
00034
00035 #include <cxstring.h>
00036 #include <cxmemory.h>
00037
00038 #include <cpl_image.h>
00039 #include <cpl_vector.h>
00040 #include <cpl_matrix.h>
00041 #include <cpl_mask.h>
00042 #include <cpl_parameterlist.h>
00043 #include <cpl_msg.h>
00044
00045 #include "gimacros.h"
00046 #include "gialias.h"
00047 #include "giarray.h"
00048 #include "giimage.h"
00049 #include "gitable.h"
00050 #include "gimatrix.h"
00051 #include "giarray.h"
00052 #include "gimask.h"
00053 #include "gimath.h"
00054 #include "gimessages.h"
00055 #include "giutils.h"
00056 #include "gilocalize.h"
00057 #include "gidebug.h"
00058
00059
00060
00069
00070
00071 enum GiLocalizeMethod {
00072 GILOCALIZE_HALF_WIDTH,
00073 GILOCALIZE_BARYCENTER
00074 };
00075
00076 typedef enum GiLocalizeMethod GiLocalizeMethod;
00077
00078
00079
00080
00081
00082
00083 static const cxchar *_task = "giraffe_localize_spectra";
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 inline static cxbool
00119 _giraffe_validate_pixel(cxint *pixels, cxint xsize, cxint ysize,
00120 cxint xpos, cxint ypos, cxint xwidth, cxint ywidth,
00121 cxsize count)
00122 {
00123
00124 cxint i;
00125 cxint xstart = xpos - xwidth;
00126 cxint ystart = ypos - ywidth;
00127 cxint xend = xpos + xwidth;
00128 cxint yend = ypos + ywidth;
00129
00130 cxsize _count = 0;
00131
00132
00133
00134
00135
00136
00137
00138 xstart = CX_MAX(0, xstart);
00139 ystart = CX_MAX(0, ystart);
00140
00141 xend = CX_MIN(xsize - 1, xend);
00142 yend = CX_MIN(ysize - 1, yend);
00143
00144 xwidth = CX_MAX(xwidth,1 );
00145 ywidth = CX_MAX(ywidth,1 );
00146
00147
00148
00149
00150
00151
00152
00153 for (i = ystart; i <= yend; i++) {
00154
00155 cxint j;
00156 cxint row;
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 if (i == ypos) {
00167 continue;
00168 }
00169
00170 row = i * xsize;
00171
00172 for (j = xstart; j <= xend; j++) {
00173 if (pixels[row + j]) {
00174 ++_count;
00175 }
00176
00177 if (_count >= count) {
00178 return 1;
00179 }
00180 }
00181
00182 }
00183
00184 return 0;
00185
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 inline static cpl_matrix*
00217 _giraffe_fit_border(cpl_matrix* mborder, cpl_matrix* mbase,
00218 cpl_matrix* mxok, cxint nspectra, cxdouble sigma,
00219 cxint niter, cxdouble mfrac, cpl_matrix* mcoeff)
00220 {
00221
00222 const cxchar* const fctid = "_giraffe_fit_border";
00223
00224 register cxint x = 0;
00225 register cxint naccept = 0;
00226 register cxint ntotal = 0;
00227 register cxint iteration = 0;
00228 register cxint nx = cpl_matrix_get_ncol(mbase);
00229 register cxint yorder = cpl_matrix_get_nrow(mbase);
00230 register cxint nxok = cpl_matrix_get_nrow(mxok);
00231
00232 register cxdouble ratio = 1.0;
00233
00234 cpl_matrix* mtmp = NULL;
00235 cpl_matrix* yraw = NULL;
00236 cpl_matrix* ydiff = NULL;
00237 cpl_matrix* mfit = NULL;
00238 cpl_matrix* coeffs = NULL;
00239
00240
00241
00242 if (nxok < yorder) {
00243 cpl_error_set(fctid, CPL_ERROR_INCOMPATIBLE_INPUT);
00244
00245 GIDEBUG(gi_warning("%s: not enough points mxok[%d] for %d order fit",
00246 fctid, nxok, yorder));
00247
00248 return NULL;
00249 }
00250
00251
00252
00253
00254
00255
00256 yraw = cpl_matrix_new(1, nxok);
00257 ydiff = cpl_matrix_new(nxok, 1);
00258
00259 mtmp = cpl_matrix_duplicate(mxok);
00260
00261
00262
00263
00264
00265 for (x = 0; x < nxok; x++) {
00266 cxdouble data = cpl_matrix_get(mborder, x, nspectra);
00267 cpl_matrix_set(yraw, 0, x, data);
00268 }
00269
00270
00271
00272
00273
00274
00275 ntotal = nxok;
00276 naccept = ntotal;
00277
00278 while (naccept > 0 && iteration < niter && ratio > mfrac) {
00279
00280 register cxint k = 0;
00281 register cxint l = 0;
00282
00283 register cxdouble ysigma = 0.;
00284
00285 cpl_matrix* rawbase = giraffe_chebyshev_base1d(0., nx, yorder, mtmp);
00286 cx_assert(rawbase != NULL);
00287
00288 if (coeffs != NULL) {
00289 cpl_matrix_delete(coeffs);
00290 }
00291
00292 coeffs = giraffe_matrix_leastsq(rawbase, yraw);
00293 if (coeffs == NULL) {
00294 gi_warning("%s: error in giraffe_matrix_leastsq(), spectrum %d",
00295 fctid, nspectra);
00296 break;
00297 }
00298
00299 cpl_matrix_delete(rawbase);
00300 rawbase = NULL;
00301
00302 if (mfit != NULL) {
00303 cpl_matrix_delete(mfit);
00304 }
00305
00306 mfit = cpl_matrix_product_create(coeffs, mbase);
00307
00308 for (x = 0; x < cpl_matrix_get_nrow(ydiff); x++) {
00309
00310 cxint xok = (cxint) cpl_matrix_get(mtmp, x, 0);
00311
00312 cxdouble diff =
00313 cpl_matrix_get(yraw, 0, x) - cpl_matrix_get(mfit, 0, xok);
00314
00315
00316 cpl_matrix_set(ydiff, x , 0, diff);
00317
00318 }
00319
00320 ysigma = sigma * giraffe_matrix_sigma_mean(ydiff, 0.);
00321
00322
00323
00324
00325
00326
00327 k = 0;
00328 for (l = 0; l < cpl_matrix_get_nrow(ydiff); l++) {
00329
00330 if (fabs(cpl_matrix_get(ydiff, l, 0)) <= ysigma) {
00331
00332 cxint xok = cpl_matrix_get(mtmp, l, 0);
00333 cxdouble data = cpl_matrix_get(yraw, 0, l);
00334
00335 cpl_matrix_set(mtmp, k, 0, xok);
00336 cpl_matrix_set(yraw, 0, k, data);
00337
00338 ++k;
00339 }
00340
00341 }
00342
00343
00344
00345
00346
00347
00348 if (k == naccept) {
00349 break;
00350 }
00351
00352
00353
00354
00355
00356
00357 naccept = k;
00358 ratio = (cxdouble) naccept / (cxdouble) ntotal;
00359
00360 GIDEBUG(gi_message("Iteration %d: Sigma %f, accepted bins: %d, "
00361 "rejected %d\n", iteration, ysigma, naccept,
00362 ntotal - naccept));
00363
00364
00365
00366
00367
00368 cpl_matrix_resize(mtmp, 0,
00369 naccept - cpl_matrix_get_nrow(mtmp), 0, 0);
00370 cpl_matrix_resize(yraw, 0,
00371 0, 0, naccept - cpl_matrix_get_ncol(yraw));
00372 cpl_matrix_resize(ydiff, 0,
00373 naccept - cpl_matrix_get_nrow(ydiff), 0, 0);
00374
00375 iteration++;
00376 }
00377
00378 if (coeffs != NULL) {
00379 register cxint l;
00380
00381 for (l = 0; l < cpl_matrix_get_nrow(mcoeff); l++) {
00382 cpl_matrix_set(mcoeff, l, 0, cpl_matrix_get(coeffs, 0, l));
00383 }
00384 }
00385
00386
00387
00388
00389
00390
00391 cpl_matrix_delete(coeffs);
00392 cpl_matrix_delete(ydiff);
00393 cpl_matrix_delete(yraw);
00394 cpl_matrix_delete(mtmp);
00395
00396 return mfit;
00397
00398 }
00399
00400
00401
00402
00403
00404
00405
00406
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 inline static cxint
00436 _giraffe_build_raw_mask(cpl_image *raw, cpl_image *bpixel, cxint nspectra,
00437 cxdouble noise, GiMaskParameters *config,
00438 cxint *ndetect, cpl_matrix *mxok, cpl_matrix *myup,
00439 cpl_matrix *mylo)
00440 {
00441
00442 register cxint x = 0;
00443 register cxint y = 0;
00444 register cxint xretry = 0;
00445 register cxint xok = 0;
00446
00447 cxint ny = 0;
00448 cxint nrows = 0;
00449 cxint ncols = 0;
00450 cxint *yabove = NULL;
00451 cxint *ybelow = NULL;
00452 cxint *good_pixels = NULL;
00453 cxint ywidth = config->ywidth > 1 ? config->ywidth : 2;
00454 cxint ckwidth = config->ckdata.width;
00455 cxint ckheight = config->ckdata.height;
00456 cxint ckcount = config->ckdata.count;
00457
00458
00459 cxdouble *pixels = NULL;
00460
00461 cpl_mask* med = NULL;
00462
00463 cpl_image *img = NULL;
00464
00465
00466 med = cpl_mask_new(1, 9);
00467 if (med != NULL) {
00468
00469 cxint i = 0;
00470
00471 for (i = 0; i < cpl_mask_get_size_x(med); ++i) {
00472 cpl_mask_set(med, 1, i + 1, CPL_BINARY_1);
00473 }
00474
00475 img = cpl_image_new(cpl_image_get_size_x(raw),
00476 cpl_image_get_size_y(raw),
00477 cpl_image_get_type(raw));
00478 cpl_image_filter_mask(img, raw, med, CPL_FILTER_MEDIAN,
00479 CPL_BORDER_FILTER);
00480 }
00481 else {
00482 img = raw;
00483 }
00484
00485 cpl_mask_delete(med);
00486
00487
00488
00489 *ndetect = 0;
00490
00491 cpl_msg_info(_task, "Generating mask (%d spectra expected) ...",
00492 nspectra);
00493
00494 GIDEBUG(gi_message("noise = %g start = %d tries = %d xbin = %d "
00495 "ywidth = %d", noise, config->start, config->retry,
00496 config->xbin, ywidth));
00497
00498 pixels = cpl_image_get_data_double(img);
00499
00500 nrows = cpl_image_get_size_y(img);
00501 ncols = cpl_image_get_size_x(img);
00502
00503
00504 #if 0
00505 cxdouble sigma = 2.;
00506 cxdouble ssqr = sigma * sigma;
00507
00508 cxint xr = 2;
00509 cxint yr = 2;
00510
00511 cpl_matrix* kern = cpl_matrix_new(2 * xr + 1, 2 * yr + 1);
00512
00513 for (i = -xr; i <= xr; ++i) {
00514
00515 cxint j = 0;
00516
00517 for (j = -yr; j <= yr; ++j) {
00518
00519 cxdouble rsqr = i * i + j * j;
00520 cxdouble h = (rsqr / ssqr - 1.) * exp(-rsqr / (2. * ssqr));
00521
00522 cpl_matrix_set(kern, i + xr, j + yr, h);
00523 }
00524
00525 }
00526
00527 cpl_image* lod = cpl_image_filter_linear(raw, kern);
00528 cpl_image_save(lod, "lod.fits", -32, 0, CPL_IO_DEFAULT);
00529 cpl_image_delete(lod);
00530 cpl_matrix_delete(kern);
00531 #endif
00532
00533 #if 0
00534
00535 cpl_matrix* h1 = cpl_matrix_new(3, 3);
00536 cpl_matrix* h3 = cpl_matrix_new(3, 3);
00537
00538 cpl_matrix_set(h1, 0, 0, 1);
00539 cpl_matrix_set(h1, 0, 1, 2);
00540 cpl_matrix_set(h1, 0, 2, 1);
00541
00542 cpl_matrix_set(h1, 2, 0, -1);
00543 cpl_matrix_set(h1, 2, 1, -2);
00544 cpl_matrix_set(h1, 2, 2, -1);
00545
00546 cpl_matrix_set(h3, 0, 0, -1);
00547 cpl_matrix_set(h3, 1, 0, -2);
00548 cpl_matrix_set(h3, 2, 0, -1);
00549
00550 cpl_matrix_set(h3, 0, 2, 1);
00551 cpl_matrix_set(h3, 1, 2, 2);
00552 cpl_matrix_set(h3, 2, 2, 1);
00553
00554 cpl_matrix* med = cpl_matrix_new(9, 1);
00555 cpl_matrix_fill(med, 1.);
00556
00557 cpl_image* sraw = cpl_image_filter_median(raw, med);
00558 cpl_image* hz = cpl_image_filter_linear(sraw, h1);
00559 cpl_image* vt = cpl_image_filter_linear(sraw, h3);
00560 cpl_image* vt2 = cpl_image_filter_linear(vt, h3);
00561
00562 cpl_image_save(sraw, "master_flat_smooth.fits", -32, 0, CPL_IO_DEFAULT);
00563 cpl_image_save(hz, "horizontal.fits", -32, 0, CPL_IO_DEFAULT);
00564 cpl_image_save(vt, "vertical.fits", -32, 0, CPL_IO_DEFAULT);
00565 cpl_image_save(vt2, "vertical2.fits", -32, 0, CPL_IO_DEFAULT);
00566
00567
00568 const cxdouble* _vt2 = cpl_image_get_data_double_const(vt2);
00569
00570 cpl_image* center = cpl_image_new(ncols, nrows, CPL_TYPE_INT);
00571
00572 cxint* _center = cpl_image_get_data_int(center);
00573 cxdouble* _buffer = cx_calloc(ncols, sizeof(cxdouble));
00574
00575 cxint m = 0;
00576 cxint pos = 0;
00577
00578 for (m = 0; m < nrows; ++m) {
00579
00580 cxint n = 0;
00581 cxint k = 0;
00582 cxint iteration = 0;
00583
00584 cxdouble low = -1;
00585 cxdouble avg = 0.;
00586 cxdouble rms = 0.;
00587
00588
00589 memcpy(_buffer, &_vt2[m * ncols], ncols * sizeof(cxdouble));
00590
00591 avg = giraffe_array_mean(_buffer, ncols);
00592
00593 for (n = 0; n < ncols; ++n) {
00594 rms += (_buffer[n] - avg) * (_buffer[n] - avg);
00595 }
00596 rms = sqrt(rms / (ncols - 1.) / ncols);
00597
00598
00599 avg -= 5. * rms;
00600
00601 while (iteration < ncols && low < 0.) {
00602
00603 cxdouble d2x = (avg < 0.) ? avg : 0.;
00604
00605 for (n = 0; n < ncols; ++n) {
00606
00607 if (_buffer[n] < d2x) {
00608 d2x = _buffer[n];
00609 pos = n;
00610 }
00611
00612 }
00613
00614 _center[m * ncols + pos] = 1;
00615 low = d2x;
00616
00617 k = pos - 1;
00618
00619 while (_buffer[k] > _buffer[k + 1] && k >= 0) {
00620 _buffer[k] = 0.;
00621 _center[m * ncols + pos] += 1;
00622 --k;
00623 }
00624
00625 k = pos + 1;
00626
00627 while (_buffer[k] > _buffer[k - 1] && k < ncols) {
00628 _buffer[k] = 0.;
00629 _center[m * ncols + pos] += 1;
00630 ++k;
00631 }
00632
00633 _buffer[pos] = 0.;
00634
00635 ++iteration;
00636
00637 }
00638
00639 }
00640
00641 cx_free(_buffer);
00642
00643 cpl_image_save(center, "mask.fits", -32, 0, CPL_IO_DEFAULT);
00644
00645 cpl_image_delete(center);
00646 cpl_image_delete(vt2);
00647 cpl_image_delete(vt);
00648 cpl_image_delete(hz);
00649 #endif
00650
00651
00652 if (config->xbin > 1) {
00653
00654 cxint nx = nrows;
00655
00656 cxdouble* _pixels = NULL;
00657
00658
00659 nrows = (cxint) ceil(nrows / config->xbin);
00660 config->start = (cxint) ceil(config->start / config->xbin);
00661
00662 _pixels = cx_calloc(ncols * nrows, sizeof(cxdouble));
00663
00664 for (y = 0; y < ncols; ++y) {
00665
00666 for (x = 0; x < nrows; ++x) {
00667
00668 register cxint xx = 0;
00669 register cxint zx = x * ncols;
00670 register cxint xr = x * config->xbin;
00671 register cxint zr = xr * ncols;
00672
00673
00674 _pixels[zx + y] = 0.;
00675
00676 for (xx = 0; xx < config->xbin && xr < nx; ++xx) {
00677 _pixels[zx + y] += pixels[zr + y];
00678 }
00679
00680 _pixels[zx + y] /= config->xbin;
00681
00682 }
00683
00684 }
00685
00686 pixels = _pixels;
00687
00688 }
00689
00690 good_pixels = cx_calloc(nrows * ncols, sizeof(cxint));
00691
00692 if (config->local) {
00693
00694 cxint ywidth2 = ywidth / 2;
00695 cxint sz = 2 * ywidth2 + 1;
00696
00697 cpl_vector *ymins = cpl_vector_new(sz);
00698
00699
00700
00701
00702
00703
00704
00705
00706 for (x = 0; x < nrows; x++) {
00707
00708 cpl_vector_fill(ymins, 0.);
00709
00710 for (y = 0; y < ncols; y++) {
00711
00712 register cxint k, kk;
00713
00714 cxdouble value = 0.;
00715 cxdouble bkg = 0.;
00716 cxdouble threshold = 0.;
00717
00718
00719 for (kk = 0, k = -ywidth2; k <= ywidth2; k++) {
00720
00721 register cxint ky = y + k;
00722
00723 if (ky < 0 || ky >= ncols) {
00724 continue;
00725 }
00726
00727 cpl_vector_set(ymins, kk, pixels[x * ncols + ky]);
00728 ++kk;
00729 }
00730
00731 if (kk == 0) {
00732 continue;
00733 }
00734
00735 if (config->threshold > 0.) {
00736
00737 const cxint count = 2;
00738
00739 cxint i = 0;
00740
00741
00742
00743
00744
00745
00746
00747 giraffe_array_sort(cpl_vector_get_data(ymins), kk);
00748
00749 bkg = 0.;
00750
00751 for (i = 0; i < count; i++) {
00752 bkg += cpl_vector_get(ymins, i);
00753 }
00754 bkg /= (cxdouble)count;
00755 threshold = sqrt((noise * noise +
00756 fabs(pixels[x * ncols + y])) / config->xbin);
00757
00758 }
00759 else {
00760
00761 register cxint i;
00762 register cxdouble mean = 0.;
00763
00764
00765 for (i = 0; i < kk; i++) {
00766 mean += cpl_vector_get(ymins, i);
00767 }
00768 mean /= kk;
00769
00770 giraffe_array_sort(cpl_vector_get_data(ymins), kk);
00771
00772 bkg = (cpl_vector_get(ymins, 0) +
00773 cpl_vector_get(ymins, 1)) / 2.0;
00774 threshold = mean - bkg;
00775
00776 }
00777
00778
00779
00780
00781
00782
00783 value = pixels[x * ncols + y] - bkg;
00784
00785 if (value < 0.) {
00786 continue;
00787 }
00788
00789 if (value > fabs(config->threshold) * threshold) {
00790 good_pixels[x * ncols + y] = 1;
00791 }
00792 }
00793 }
00794
00795 cpl_vector_delete(ymins);
00796 ymins = NULL;
00797
00798 }
00799 else {
00800
00801 cxdouble threshold = 0.;
00802
00803
00804
00805
00806
00807
00808 if (config->threshold > 0.) {
00809 threshold = config->threshold * noise;
00810 }
00811 else {
00812 cxdouble mean = cpl_image_get_mean(raw);
00813
00814 threshold = -config->threshold * mean * nspectra *
00815 config->wavg / ncols;
00816 }
00817
00818 for (x = 0; x < nrows; x++) {
00819 for (y = 0; y < ncols; y++) {
00820
00821 if (pixels[x * ncols + y] > threshold) {
00822 good_pixels[x * ncols + y] = 1;
00823 }
00824
00825 }
00826 }
00827
00828 }
00829
00830 GIDEBUG(cxint *data = cx_calloc(nrows * ncols, sizeof(cxint));
00831
00832 memcpy(data, good_pixels, nrows * ncols * sizeof(cxint));
00833 cpl_image *gp = cpl_image_wrap_int(ncols, nrows, data);
00834 cpl_image_save(gp, "locmask.fits", 32, NULL, CPL_IO_DEFAULT);
00835 cpl_image_unwrap(gp);
00836 cx_free(data));
00837
00838
00839
00840
00841
00842
00843 yabove = cx_calloc(nspectra + 1, sizeof(cxint));
00844 ybelow = cx_calloc(nspectra + 1, sizeof(cxint));
00845
00846
00847
00848
00849
00850
00851 ny = ncols - 1;
00852
00853 xretry = 0;
00854 xok = 0;
00855
00856 for (x = config->start; (x >= 0) && (xretry <= config->retry); x--) {
00857
00858 register cxint zx = x * ncols;
00859 register cxint nborders = 0;
00860 register cxint nbelow = 0;
00861 register cxint nabove = 0;
00862 register cxint in_spectrum = 0;
00863
00864
00865 for (y = 1; y < ny; y++) {
00866
00867 register cxint tmp = 2 * good_pixels[zx + y];
00868
00869
00870
00871
00872
00873 nborders = CX_MAX(CX_MAX(nborders, nbelow), nabove);
00874
00875 if (nborders > nspectra) {
00876 break;
00877 }
00878
00879
00880
00881
00882
00883
00884
00885 if (good_pixels[zx + y + 1]) {
00886
00887
00888
00889
00890
00891
00892 if ((tmp - good_pixels[zx + y - 1]) == 2) {
00893
00894
00895
00896
00897
00898
00899 if (!in_spectrum) {
00900
00901
00902
00903
00904
00905
00906 ybelow[nbelow++] = y;
00907 in_spectrum = 1;
00908
00909 }
00910
00911 }
00912
00913 }
00914
00915 if (good_pixels[zx + y - 1]) {
00916
00917
00918
00919
00920
00921
00922 if ((tmp - good_pixels[zx + y + 1]) == 2) {
00923
00924
00925
00926
00927
00928
00929 if (in_spectrum) {
00930
00931
00932
00933
00934
00935
00936 yabove[nabove++] = y;
00937 in_spectrum = 0;
00938
00939 }
00940
00941 }
00942
00943 }
00944
00945
00946
00947 if (tmp &&
00948 !good_pixels[zx + y - 1] && !good_pixels[zx + y + 1]) {
00949
00950 if (_giraffe_validate_pixel(good_pixels, ncols, nrows, y, x,
00951 ckwidth, ckheight, ckcount)) {
00952
00953 yabove[nabove++] = y;
00954 ybelow[nbelow++] = y;
00955 }
00956
00957 }
00958
00959 }
00960
00961 if (in_spectrum) {
00962 nborders--;
00963 nbelow--;
00964 in_spectrum = 0;
00965 }
00966
00967 *ndetect = nborders;
00968
00969 if (!in_spectrum && (nbelow == nspectra) && (nbelow == nabove)) {
00970
00971
00972
00973
00974
00975
00976
00977
00978 for (y = 0; y < nspectra; y++) {
00979 cpl_matrix_set(mylo, xok, y, (cxdouble) ybelow[y]);
00980 cpl_matrix_set(myup, xok, y, (cxdouble) yabove[y]);
00981 cpl_matrix_set(mxok, xok, 0, (config->xbin > 1) ?
00982 (cxdouble) (x + 0.5) * config->xbin :
00983 (cxdouble) x);
00984 }
00985 xok++;
00986 xretry = 0;
00987 }
00988 else if (xretry++ < config->retry) {
00989
00990
00991
00992
00993
00994
00995 continue;
00996 }
00997 else {
00998
00999
01000
01001
01002
01003 break;
01004 }
01005 }
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016 xretry = 0;
01017
01018 for (x = config->start + 1; (x < nrows) &&
01019 (xretry <= config->retry); x++) {
01020
01021 register cxint zx = x * ncols;
01022 register cxint nborders = 0;
01023 register cxint nbelow = 0;
01024 register cxint nabove = 0;
01025 register cxint in_spectrum = 0;
01026
01027
01028 for (y = 1; y < ny; y++) {
01029
01030 register cxint tmp = 2 * good_pixels[zx + y];
01031
01032 nborders = CX_MAX(CX_MAX(nborders, nbelow), nabove);
01033
01034 if (nborders > nspectra) {
01035 break;
01036 }
01037
01038 if (good_pixels[zx + y + 1]) {
01039 if ((tmp - good_pixels[zx + y - 1]) == 2) {
01040 if (!in_spectrum) {
01041 ybelow[nbelow++] = y;
01042 in_spectrum = 1;
01043 }
01044 }
01045 }
01046
01047 if (good_pixels[zx + y - 1]) {
01048 if ((tmp - good_pixels[zx + y + 1]) == 2) {
01049 if (in_spectrum) {
01050 yabove[nabove++] = y;
01051 in_spectrum = 0;
01052 }
01053 }
01054 }
01055
01056
01057
01058 if (tmp &&
01059 !good_pixels[zx + y - 1] && !good_pixels[zx + y + 1]) {
01060
01061 if (_giraffe_validate_pixel(good_pixels, ncols, nrows, y, x,
01062 ckwidth, ckheight, ckcount)) {
01063
01064 yabove[nabove++] = y;
01065 ybelow[nbelow++] = y;
01066 }
01067
01068 }
01069
01070 }
01071
01072 if (in_spectrum) {
01073 nborders--;
01074 nbelow--;
01075 in_spectrum = 0;
01076 }
01077
01078 *ndetect = nborders;
01079
01080 if (!in_spectrum && (nbelow == nspectra) && (nbelow == nabove)) {
01081
01082 for (y = 0; y < nspectra; y++) {
01083 cpl_matrix_set(mylo, xok, y, (cxdouble) ybelow[y]);
01084 cpl_matrix_set(myup, xok, y, (cxdouble) yabove[y]);
01085 cpl_matrix_set(mxok, xok, 0, (config->xbin > 1) ?
01086 (cxdouble) (x + 0.5) * config->xbin :
01087 (cxdouble) x);
01088 }
01089 xok++;
01090 xretry = 0;
01091 }
01092 else if (xretry++ < config->retry) {
01093 continue;
01094 }
01095 else {
01096 break;
01097 }
01098
01099 }
01100
01101 cx_free(ybelow);
01102 cx_free(yabove);
01103 cx_free(good_pixels);
01104
01105 if (pixels != cpl_image_get_data_double(img)) {
01106 cx_free(pixels);
01107 pixels = NULL;
01108 }
01109
01110 if (img != raw) {
01111 cpl_image_delete(img);
01112 img = NULL;
01113 }
01114
01115 if (xok == 0) {
01116 if (*ndetect < nspectra) {
01117 return -1;
01118 }
01119 else if (*ndetect > nspectra) {
01120 return -1;
01121 }
01122 else {
01123 return -2;
01124 }
01125 }
01126 else {
01127 *ndetect = nspectra;
01128 cpl_msg_info(_task, "%d spectra detected in %d wavelength bins",
01129 *ndetect, xok);
01130 }
01131
01132 return xok;
01133
01134 }
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162 inline static void
01163 _giraffe_fit_raw_mask(cpl_matrix *mxok, cpl_matrix *myup, cpl_matrix *mylo,
01164 cpl_table *fibers, GiMaskParameters *config,
01165 GiMaskPosition *position)
01166 {
01167
01168 register cxint nn, x, nspectra;
01169 register cxint nx = cpl_matrix_get_nrow(position->my);
01170 register cxint ns = cpl_table_get_nrow(fibers);
01171
01172 cpl_matrix *mxraw;
01173 cpl_matrix *base;
01174 cpl_matrix *mcoeff;
01175
01176
01177
01178 mxraw = cpl_matrix_new(nx, 1);
01179 mcoeff = cpl_matrix_new(config->ydeg + 1, 1);
01180
01181
01182
01183
01184
01185
01186 for (x = 0; x < nx; x++) {
01187 cpl_matrix_set(mxraw, x, 0, x);
01188 }
01189
01190
01191
01192
01193
01194 base = giraffe_chebyshev_base1d(0., nx, config->ydeg + 1, mxraw);
01195 cpl_matrix_delete(mxraw);
01196
01197 nspectra = 0;
01198 for (nn = 0; nn < ns; nn++) {
01199 cpl_matrix *ylofit = NULL;
01200 cpl_matrix *yupfit = NULL;
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213 ylofit = _giraffe_fit_border(mylo, base, mxok, nspectra,
01214 config->sigma, config->niter,
01215 config->mfrac, mcoeff);
01216 if (ylofit == NULL) {
01217 cpl_msg_warning(_task, "Could not compute low border for "
01218 "spectrum %d", nn);
01219 nspectra++;
01220 continue;
01221 }
01222
01223
01224 yupfit = _giraffe_fit_border(myup, base, mxok, nspectra,
01225 config->sigma, config->niter,
01226 config->mfrac, mcoeff);
01227 if (yupfit == NULL) {
01228 cpl_msg_warning(_task, "Could not compute up border for "
01229 "spectrum %d", nn);
01230 nspectra++;
01231 continue;
01232 }
01233
01234
01235
01236
01237
01238
01239
01240 for (x = 0; x < nx; x++) {
01241
01242 cpl_matrix_set(position->my, x, nn, 0.5 *
01243 (cpl_matrix_get(yupfit, x, 0) +
01244 cpl_matrix_get(ylofit, x, 0)));
01245
01246 cpl_matrix_set(position->my, x, nn, 0.5 *
01247 (cpl_matrix_get(yupfit, x, 0) -
01248 cpl_matrix_get(ylofit, x, 0)) + config->ewid);
01249
01250 }
01251 cpl_matrix_delete(ylofit);
01252 cpl_matrix_delete(yupfit);
01253 nspectra++;
01254
01255 }
01256
01257 cpl_msg_info(_task, "%03d spectrum positions fitted", nspectra);
01258
01259 cpl_matrix_delete(base);
01260 cpl_matrix_delete(mcoeff);
01261
01262 if (nspectra == 0) {
01263 cpl_msg_warning(_task, "could not fit any spectra, check number "
01264 "of good wavelength bins");
01265 return;
01266 }
01267
01268 return;
01269
01270 }
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307 inline static void
01308 _giraffe_fit_raw_centroid(cpl_image* mz, cpl_matrix* mxok, cpl_matrix* myup,
01309 cpl_matrix* mylo, cpl_table* fibers,
01310 GiMaskParameters* config, GiMaskPosition* position,
01311 GiMaskPosition* coeffs)
01312 {
01313
01314 const cxchar* const fctid = "_giraffe_fit_raw_centroid";
01315
01316 register cxint nn = 0;
01317 register cxint x = 0;
01318 register cxint y = 0;
01319 register cxint nspectra = 0;
01320 register cxint nx = cpl_image_get_size_y(mz);
01321 register cxint ny = cpl_image_get_size_x(mz);
01322 register cxint ns = cpl_table_get_nrow(fibers);
01323
01324 cxint yorder = config->ydeg + 1;
01325 cxint worder = config->wdeg + 1;
01326
01327 cpl_matrix* mxraw = NULL;
01328 cpl_matrix* base = NULL;
01329 cpl_matrix* mycenter = NULL;
01330 cpl_matrix* mywidth = NULL;
01331 cpl_matrix* mx = NULL;
01332 cpl_matrix* my = NULL;
01333 cpl_matrix* mw = NULL;
01334 cpl_matrix* chebcoeff = NULL;
01335 cpl_matrix* mfitlocw = NULL;
01336 cpl_matrix* ycenfit = NULL;
01337 cpl_matrix* ycencoeff = NULL;
01338
01339
01340
01341 if (cpl_matrix_get_nrow(position->my) != nx ||
01342 cpl_matrix_get_ncol(position->my) != ns) {
01343 gi_error("%s: invalid size for position->my[%d,%d], expected "
01344 "[%d,%d]", fctid, cpl_matrix_get_nrow(position->my),
01345 cpl_matrix_get_ncol(position->my), nx, ns);
01346 return;
01347 }
01348
01349 if (cpl_matrix_get_nrow(position->mw) != nx ||
01350 cpl_matrix_get_ncol(position->mw) != ns) {
01351 gi_error("%s: invalid size for position->mw[%d,%d], expected "
01352 "[%d,%d]", fctid, cpl_matrix_get_nrow(position->my),
01353 cpl_matrix_get_ncol(position->my), nx, ns);
01354 return;
01355 }
01356
01357
01358
01359
01360
01361
01362 mxraw = cpl_matrix_new(nx, 1);
01363
01364 for (x = 0; x < nx; x++) {
01365 cpl_matrix_set(mxraw, x, 0, x);
01366 }
01367
01368
01369
01370
01371
01372
01373 base = giraffe_chebyshev_base1d(0., nx, yorder, mxraw);
01374 cpl_matrix_delete(mxraw);
01375
01376 mycenter = cpl_matrix_new(cpl_matrix_get_nrow(mxok), ns);
01377 mywidth = cpl_matrix_new(1, cpl_matrix_get_nrow(mxok) * ns);
01378
01379 ycencoeff = cpl_matrix_new(yorder, 1);
01380
01381 for (nn = 0; nn < ns; nn++) {
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398 cxdouble* pixels = cpl_image_get_data_double(mz);
01399
01400 for (x = 0; x < cpl_matrix_get_nrow(mxok); x++) {
01401
01402 register cxint zx = (cxint) cpl_matrix_get(mxok, x, 0);
01403
01404 register cxdouble zz = 0.;
01405 register cxdouble yy = 0.;
01406
01407 cxdouble lower = cpl_matrix_get(mylo, x, nspectra);
01408 cxdouble upper = cpl_matrix_get(myup, x, nspectra);
01409
01410
01411 for (y = (cxint) lower; y <= (cxint) upper; y++) {
01412 yy += pixels[zx * ny + y] * y;
01413 zz += pixels[zx * ny + y];
01414 }
01415
01416 cpl_matrix_set(mycenter, x, nspectra, yy / zz);
01417 cpl_matrix_set(mywidth, 0, x * ns + nspectra, config->ewid +
01418 (upper - lower) / 2.0);
01419
01420 }
01421
01422
01423
01424
01425
01426 cpl_matrix_fill(ycencoeff, 0.);
01427 ycenfit = _giraffe_fit_border(mycenter, base, mxok, nspectra,
01428 config->sigma, config->niter,
01429 config->mfrac, ycencoeff);
01430 if (ycenfit == NULL) {
01431 cpl_msg_warning(_task, "Could not fit centroid for spectrum %d",
01432 nn);
01433 nspectra++;
01434 continue;
01435 }
01436
01437
01438
01439
01440
01441 for (x = 0; x < yorder; x++) {
01442 cpl_matrix_set(coeffs->my, x, nn,
01443 cpl_matrix_get(ycencoeff, x, 0));
01444 }
01445
01446
01447
01448
01449
01450
01451 for (x = 0; x < nx; x++) {
01452 cpl_matrix_set(position->my, x, nn,
01453 cpl_matrix_get(ycenfit, 0, x));
01454 }
01455
01456 cpl_matrix_delete(ycenfit);
01457 nspectra++;
01458
01459 }
01460
01461 GIDEBUG(cpl_image *lycenter = giraffe_matrix_create_image(mycenter);
01462 cpl_image_save(lycenter, "lycenter.fits", -32, NULL,
01463 CPL_IO_DEFAULT);
01464 cpl_image_delete(lycenter);
01465
01466 lycenter = giraffe_matrix_create_image(position->my);
01467 cpl_image_save(lycenter, "lycenterfit.fits", -32, NULL,
01468 CPL_IO_DEFAULT);
01469 cpl_image_delete(lycenter);
01470
01471 cpl_image *lyxok = giraffe_matrix_create_image(mxok);
01472 cpl_image_save(lyxok, "lyxok.fits", -32, NULL,
01473 CPL_IO_DEFAULT);
01474 cpl_image_delete(lyxok));
01475
01476
01477 cpl_msg_info(_task, "%03d spectrum positions fitted", nspectra);
01478
01479 cpl_matrix_delete(base);
01480 cpl_matrix_delete(mycenter);
01481 cpl_matrix_delete(ycencoeff);
01482
01483 if (nspectra == 0) {
01484 cpl_msg_warning(_task, "Could not fit any spectra, check number of "
01485 "good wavelength bins");
01486
01487 cpl_matrix_delete(mywidth);
01488 return;
01489 }
01490
01491
01492
01493
01494
01495 cpl_msg_info(_task, "2D fit (order %dx%d) of mask width", worder,
01496 worder);
01497
01498
01499
01500
01501
01502 mx = cpl_matrix_new(cpl_matrix_get_nrow(mxok) * nspectra, 1);
01503 my = cpl_matrix_new(cpl_matrix_get_nrow(mxok) * nspectra, 1);
01504 mw = cpl_matrix_new(1, cpl_matrix_get_nrow(mxok) * nspectra);
01505
01506 for (y = 0, nn = 0; nn < nspectra; nn++) {
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518 for (x = 0; x < cpl_matrix_get_nrow(mxok); x++) {
01519
01520 register cxint zx = (cxint) cpl_matrix_get(mxok, x, 0);
01521 register cxint lx = x * nspectra + y;
01522
01523
01524 cpl_matrix_set(mx, lx, 0, cpl_matrix_get(mxok, x, 0));
01525 cpl_matrix_set(my, lx, 0, cpl_matrix_get(position->my, zx, nn));
01526 cpl_matrix_set(mw, 0, lx, cpl_matrix_get(mywidth, 0, x * ns + y));
01527 }
01528 y++;
01529 }
01530
01531 base = giraffe_chebyshev_base2d(0., 0., nx, ny, worder, worder, mx, my);
01532
01533 cpl_matrix_delete(my);
01534 cpl_matrix_delete(mx);
01535
01536 chebcoeff = giraffe_matrix_leastsq(base, mw);
01537 cpl_matrix_delete(base);
01538 cpl_matrix_delete(mw);
01539
01540 cpl_matrix_delete(mywidth);
01541
01542 if (chebcoeff == NULL) {
01543 gi_warning("%s: error in giraffe_matrix_leastsq() for width 2D fit",
01544 fctid);
01545 return;
01546 }
01547
01548
01549
01550
01551
01552 for (nn = 0; nn < cpl_matrix_get_ncol(chebcoeff); nn++) {
01553 cpl_matrix_set(coeffs->mw, 0, nn, cpl_matrix_get(chebcoeff, 0, nn));
01554 }
01555
01556
01557
01558
01559
01560 mx = cpl_matrix_new(nx * nspectra, 1);
01561 my = cpl_matrix_new(nx * nspectra, 1);
01562
01563 for (y = 0, nn = 0; nn < nspectra; nn++) {
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575 for (x = 0; x < nx; x++) {
01576
01577 register cxint lx = x * nspectra + y;
01578
01579 cpl_matrix_set(mx, lx, 0, x);
01580 cpl_matrix_set(my, lx, 0, cpl_matrix_get(position->my, x, nn));
01581
01582 }
01583 y++;
01584 }
01585
01586 cpl_matrix_set_size(chebcoeff, worder, worder);
01587
01588 mfitlocw = giraffe_chebyshev_fit2d(0., 0., nx, ny, chebcoeff, mx, my);
01589 cpl_matrix_delete(chebcoeff);
01590
01591 cpl_matrix_delete(my);
01592 cpl_matrix_delete(mx);
01593
01594 for (y = 0, nn = 0; nn < nspectra; nn++) {
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606 for (x = 0; x < nx; x++) {
01607
01608 register cxint lx = x * nspectra + y;
01609
01610 cpl_matrix_set(position->mw, x, nn,
01611 cpl_matrix_get(mfitlocw, lx, 0));
01612
01613 }
01614 y++;
01615 }
01616
01617 cpl_matrix_delete(mfitlocw);
01618
01619 return;
01620
01621 }
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649 inline static cxint
01650 _giraffe_localize_spectra(cpl_image *mzraw, cpl_image *bpixel,
01651 cpl_table *fibers, GiLocalizeMethod method,
01652 cxbool normalize, cxdouble noise,
01653 GiMaskParameters *config, GiMaskPosition *position,
01654 GiMaskPosition *coeffs)
01655 {
01656
01657 cxint n, nn;
01658 cxint nx, ny, nxok;
01659 cxint ndetect, nspectra;
01660 cxint x, y;
01661
01662 cxdouble uplost = 0.;
01663 cxdouble lolost = 0.;
01664 cxdouble avglost = 0.;
01665 cxdouble avgmask = 0.;
01666 cxdouble sigmask = 0.;
01667 cxdouble sigmean = 0.;
01668 cxdouble avgborders = 0.;
01669
01670 cxdouble *_mzraw;
01671
01672 cpl_matrix *mxok;
01673 cpl_matrix *myup;
01674 cpl_matrix *mylo;
01675 cpl_matrix *mwid;
01676
01677 cpl_image *mz = NULL;
01678 cpl_image *mznorm = NULL;
01679
01680
01681
01682 nx = cpl_image_get_size_y(mzraw);
01683 ny = cpl_image_get_size_x(mzraw);
01684 _mzraw = cpl_image_get_data_double(mzraw);
01685
01686
01687 if (normalize == TRUE) {
01688
01689 cxdouble zxmax = 0.0;
01690 cxdouble *_mzx = NULL;
01691 cxdouble *_mznorm = NULL;
01692
01693 cpl_image *mzx = NULL;
01694
01695
01696 cpl_msg_info(_task, "Using normalized spectra for localization");
01697
01698
01699
01700
01701
01702
01703
01704
01705 mznorm = cpl_image_new(ny, nx, CPL_TYPE_DOUBLE);
01706 _mznorm = cpl_image_get_data_double(mznorm);
01707
01708 mzx = cpl_image_new(1, nx, CPL_TYPE_DOUBLE);
01709 _mzx = cpl_image_get_data_double(mzx);
01710
01711
01712
01713
01714
01715
01716 for (x = 0 ; x < nx; x++) {
01717 for (y = 0 ; y < ny; y++) {
01718 _mzx[x] += _mzraw[x * ny + y];
01719 }
01720
01721
01722
01723
01724
01725 if (_mzx[x] > zxmax) {
01726 zxmax = _mzx[x];
01727 }
01728 }
01729
01730 GIDEBUG(cpl_image_save(mzx, "mzx.fits", -32, NULL, CPL_IO_DEFAULT));
01731
01732 for (x = 0 ; x < nx; x++) {
01733
01734 register cxdouble zxnorm = zxmax / _mzx[x];
01735
01736 for (y = 0 ; y < ny; y++) {
01737 _mznorm[x * ny + y] = _mzraw[x * ny + y] * zxnorm;
01738 }
01739
01740 }
01741
01742 cpl_image_delete(mzx);
01743 mz = mznorm;
01744 }
01745 else {
01746
01747
01748
01749
01750
01751 cpl_msg_info(_task, "Using raw spectra for localization");
01752 mz = mzraw;
01753 }
01754
01755
01756
01757
01758
01759
01760 nspectra = cpl_table_get_nrow(fibers);
01761
01762 mxok = cpl_matrix_new(nx, 1);
01763 myup = cpl_matrix_new(nx, nspectra);
01764 mylo = cpl_matrix_new(nx, nspectra);
01765
01766
01767
01768
01769
01770
01771 config->xbin = (config->xbin > 1) ? 2 * (config->xbin / 2) : 1;
01772
01773 GIDEBUG(cpl_image_save(mz, "mz.fits", -32, NULL, CPL_IO_DEFAULT));
01774
01775 nxok = _giraffe_build_raw_mask(mz, bpixel, nspectra, noise, config,
01776 &ndetect, mxok, myup, mylo);
01777
01778 if (nxok < 0) {
01779 switch (nxok) {
01780 case -1:
01781 cpl_msg_warning(_task, "Invalid number of spectra detected: "
01782 "%d != %d", ndetect, nspectra);
01783 break;
01784
01785 case -2:
01786 cpl_msg_warning(_task, "No abcissa with good number "
01787 "of spectra");
01788 break;
01789
01790 default:
01791 cpl_msg_warning(_task, "Error while searching for spectra");
01792 }
01793
01794 return nxok;
01795 }
01796
01797
01798
01799
01800
01801
01802 cpl_matrix_resize(mxok, 0, nxok - cpl_matrix_get_nrow(mxok), 0, 0);
01803 cpl_matrix_resize(myup, 0, nxok - cpl_matrix_get_nrow(myup), 0, 0);
01804 cpl_matrix_resize(mylo, 0, nxok - cpl_matrix_get_nrow(mylo), 0, 0);
01805
01806 GIDEBUG(gi_message("%s: mxok[0-%d]=[%g-%g]", __func__,
01807 cpl_matrix_get_nrow(mxok) - 1,
01808 cpl_matrix_get_min(mxok),
01809 cpl_matrix_get_max(mxok)));
01810
01811
01812 cpl_msg_info(_task, "Computing spectrum positions and widths in "
01813 "pixel range [%g,%g]", cpl_matrix_get_min(mxok),
01814 cpl_matrix_get_max(mxok));
01815
01816 if (cpl_matrix_get_nrow(mxok) <= config->ydeg) {
01817 cpl_msg_info(_task, "Not enough data points %d for %d order fit",
01818 cpl_matrix_get_nrow(mxok), config->ydeg);
01819
01820 return -1;
01821 }
01822
01823 switch (method) {
01824 case GILOCALIZE_HALF_WIDTH:
01825 cpl_msg_info(_task, "Using half-width for localization");
01826 _giraffe_fit_raw_mask(mxok, myup, mylo, fibers, config,
01827 position);
01828 break;
01829
01830 case GILOCALIZE_BARYCENTER:
01831 default:
01832 cpl_msg_info(_task, "Using barycenter for localization");
01833 _giraffe_fit_raw_centroid(mz, mxok, myup, mylo, fibers, config,
01834 position, coeffs);
01835 break;
01836 }
01837
01838 if (normalize == 1) {
01839 cpl_image_delete(mznorm);
01840 }
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852 mwid = cpl_matrix_new(nxok, nspectra);
01853
01854 for (n = 0, nn = 0; nn < cpl_table_get_nrow(fibers); nn++) {
01855
01856 for (x = 0; x < nxok; x++) {
01857 register cxint lx = (cxint) cpl_matrix_get(mxok, x, 0);
01858
01859 cxdouble lower = cpl_matrix_get(mylo, x, n);
01860 cxdouble upper = cpl_matrix_get(myup, x, n);
01861 cxdouble width = cpl_matrix_get(position->mw, lx, nn);
01862
01863 uplost += cpl_matrix_get(position->my, lx, nn) + width - upper;
01864 lolost += cpl_matrix_get(position->my, lx, nn) - width - lower;
01865
01866 avgborders += upper - lower;
01867 avgmask += width;
01868
01869 cpl_matrix_set(mwid, x, n, 2. * width);
01870 }
01871 n++;
01872 }
01873
01874 sigmean = cpl_matrix_get_mean(mwid);
01875 sigmask = giraffe_matrix_sigma_mean(mwid, sigmean);
01876 avglost = (lolost + uplost) / (nspectra * nxok);
01877 avgmask = 2.0 * avgmask / nspectra;
01878
01879 cpl_msg_info(_task, "Mask was computed using %d of %d wavelength bins",
01880 nxok, nx);
01881 cpl_msg_info(_task, "Average # of pixels per spectra: %.4g",
01882 avgmask);
01883 cpl_msg_info(_task, "Average # of in-borders pixels per spectra: %.4g",
01884 avgborders / nspectra);
01885 cpl_msg_info(_task, "Average lost pixels per spectra: %.4g",
01886 avglost);
01887 cpl_msg_info(_task, "Average lost pixels at upper border: %.4g",
01888 uplost / (nspectra * nxok));
01889 cpl_msg_info(_task, "Average lost pixels at lower border: %.4g",
01890 lolost / (nspectra * nxok));
01891 cpl_msg_info(_task, "Average spectrum width: %.4g +/- %.4g, "
01892 "(min, max) = (%.4g, %.4g)", sigmean, sigmask,
01893 cpl_matrix_get_min(mwid), cpl_matrix_get_max(mwid));
01894
01895 cpl_matrix_delete(mwid);
01896
01897 cpl_matrix_delete(mylo);
01898 cpl_matrix_delete(myup);
01899 cpl_matrix_delete(mxok);
01900
01901 return 0;
01902
01903 }
01904
01905
01906 inline static cxint
01907 _giraffe_finalize_fibers(cpl_table *fibers, cpl_matrix *locy, GiImage *mlocy,
01908 cxdouble maxoffset, cxdouble* maxshift)
01909 {
01910
01911 cxint i = 0;
01912 cxint j = 0;
01913 cxint nx = 0;
01914 cxint ny = 0;
01915 cxint _nx = 0;
01916 cxint _ny = 0;
01917 cxint nfibers = 0;
01918 cxint irow = 0;
01919
01920 cxdouble max_shift = 0.;
01921 cxdouble *positions = NULL;
01922
01923 cpl_image *_mlocy = NULL;
01924
01925
01926 if (fibers == NULL || locy == NULL || mlocy == NULL) {
01927 return -1;
01928 }
01929
01930 if (cpl_table_has_column(fibers, "RINDEX") == FALSE) {
01931 return -1;
01932 }
01933
01934 nx = cpl_matrix_get_ncol(locy);
01935 ny = cpl_matrix_get_nrow(locy);
01936
01937 nfibers = cpl_table_get_nrow(fibers);
01938
01939 _mlocy = giraffe_image_get(mlocy);
01940 _nx = cpl_image_get_size_x(_mlocy);
01941 _ny = cpl_image_get_size_y(_mlocy);
01942
01943 if (ny != _ny) {
01944 return -2;
01945 }
01946
01947 if (nfibers > _nx) {
01948 return -3;
01949 }
01950
01951 cpl_table_select_all(fibers);
01952
01953
01954
01955
01956
01957
01958 irow = (_ny - 1) / 2;
01959 positions = (cxdouble *)cpl_image_get_data(_mlocy) + irow * _nx;
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970 for (i = 0; i < nfibers; i++) {
01971
01972 if (j < nx) {
01973
01974 cxint pos = cpl_table_get_int(fibers, "RINDEX", i, NULL) - 1;
01975
01976 cxdouble yc = cpl_matrix_get(locy, irow, j);
01977 cxdouble shift = fabs(yc - positions[pos]);
01978
01979 if (shift <= maxoffset) {
01980 cpl_table_unselect_row(fibers, i);
01981 ++j;
01982 }
01983 else {
01984 max_shift = CX_MAX(max_shift, shift);
01985 }
01986
01987 }
01988 }
01989
01990 cpl_table_erase_selected(fibers);
01991
01992 if (maxshift != NULL) {
01993 *maxshift = max_shift;
01994 }
01995
01996 return 0;
01997
01998 }
01999
02000
02029 cxint
02030 giraffe_localize_spectra(GiLocalization *result, GiImage *image,
02031 GiTable *fibers, GiLocalization *master,
02032 GiImage *badpixels, GiLocalizeConfig *config)
02033 {
02034
02035 const cxchar *fctid = "giraffe_localize_spectra";
02036
02037 cxint i;
02038 cxint status;
02039 cxint nrows;
02040 cxint nfibers;
02041 cxint ckwidth;
02042 cxint ckheight;
02043 cxint ckcount;
02044
02045 cxdouble mwidth;
02046 cxdouble sigma;
02047
02048 cx_string *pname;
02049
02050 cpl_propertylist *properties;
02051
02052 cpl_image *_image = giraffe_image_get(image);
02053 cpl_image *_bpixel = giraffe_image_get(badpixels);
02054 cpl_image *_result = NULL;
02055
02056 cpl_matrix *_my;
02057
02058 cpl_table *_fibers = NULL;
02059 cpl_table *fiber_setup = NULL;
02060 cpl_table *locc;
02061
02062 GiLocalizeMethod method;
02063
02064 GiInstrumentMode mode;
02065
02066 GiMaskParameters mask_config;
02067
02068 GiMaskPosition mask_position;
02069 GiMaskPosition mask_coeffs;
02070
02071
02072
02073
02074
02075
02076
02077 if (result == NULL || image == NULL || fibers == NULL || config == NULL) {
02078 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
02079 return 1;
02080 }
02081
02082 if (badpixels != NULL) {
02083 #if 1
02084 cpl_msg_debug(fctid,"Bad pixel correction is not available. Bad "
02085 "pixel map will be ignored.");
02086 #else
02087 gi_warning("%s: Bad pixel correction is not available. Bad "
02088 "pixel map at %p will be ignored.", fctid, badpixels);
02089 #endif
02090 }
02091
02092 _fibers = giraffe_table_get(fibers);
02093
02094 if (_fibers == NULL) {
02095 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
02096 return 1;
02097 }
02098 else {
02099 fiber_setup = _fibers;
02100 }
02101
02102 properties = giraffe_image_get_properties(image);
02103
02104
02105
02106
02107
02108
02109 nfibers = cpl_table_get_nrow(_fibers);
02110
02111 cpl_msg_info(fctid, "Setting number of fibers (%s) to %d",
02112 GIALIAS_NFIBERS, nfibers);
02113
02114 cpl_propertylist_update_int(properties, GIALIAS_NFIBERS, nfibers);
02115 cpl_propertylist_set_comment(properties, GIALIAS_NFIBERS,
02116 "Number of fibres");
02117
02118
02119
02120
02121
02122
02123 if (config->ron > 0.) {
02124 cpl_msg_info(fctid, "Setting bias sigma value (%s) to %.5g",
02125 GIALIAS_BIASSIGMA, config->ron);
02126 cpl_propertylist_update_double(properties, GIALIAS_BIASSIGMA,
02127 config->ron);
02128 }
02129
02130
02131 sigma = cpl_propertylist_get_double(properties, GIALIAS_BIASSIGMA);
02132
02133 if (cpl_propertylist_has(properties, GIALIAS_CONAD)) {
02134
02135 cxdouble conad = cpl_propertylist_get_double(properties,
02136 GIALIAS_CONAD);
02137
02138
02139 if (conad > 0.) {
02140 sigma *= conad;
02141 }
02142 else {
02143 cpl_msg_error(fctid, "Invalid conversion factor "
02144 "(ADU to e-): %.2g", conad);
02145 return 1;
02146 }
02147
02148 }
02149
02150 cpl_msg_info(fctid, "Bias sigma value: %.3g e-", sigma);
02151
02152 if (config->noise > 0.) {
02153 cpl_msg_info(fctid, "Noise multiplier: %.3g",
02154 config->noise);
02155 }
02156 else {
02157 cpl_msg_info(fctid, "Threshold multiplier: %.3g",
02158 fabs(config->noise));
02159 }
02160
02161
02162
02163
02164
02165
02166 nrows = cpl_image_get_size_y(_image);
02167
02168 if (config->start < 0) {
02169 config->start = nrows / 2;
02170 }
02171
02172
02173
02174
02175
02176
02177 mode = giraffe_get_mode(properties);
02178
02179 if (config->ywidth < 1) {
02180
02181 cpl_msg_info(fctid, "Configuring equilizing filter width from "
02182 "instrument mode");
02183
02184 switch (mode) {
02185 case GIMODE_MEDUSA:
02186 config->ywidth = 16;
02187 break;
02188
02189 case GIMODE_IFU:
02190 config->ywidth = 6;
02191 break;
02192
02193 case GIMODE_ARGUS:
02194 config->ywidth = 6;
02195 break;
02196
02197 default:
02198 cpl_msg_error(fctid, "Invalid instrument mode!");
02199 return 1;
02200 break;
02201 }
02202
02203
02204 if (!cpl_propertylist_has(properties, GIALIAS_SLITNAME)) {
02205 cpl_msg_error(fctid, "Property (%s) not found in raw image",
02206 GIALIAS_SLITNAME);
02207 return 1;
02208 }
02209 else {
02210 const cxchar *slit =
02211 cpl_propertylist_get_string(properties, GIALIAS_SLITNAME);
02212
02213 cpl_msg_info(fctid, "Setting equilizing filter to %d [pxl] "
02214 "for slit configuration `%s'", config->ywidth,
02215 slit);
02216 }
02217
02218 }
02219
02220
02221
02222
02223
02224
02225 switch (mode) {
02226 case GIMODE_MEDUSA:
02227 mwidth = GISPECTRUM_MWIDTH_MEDUSA;
02228
02229 ckwidth = 1;
02230 ckheight = 3;
02231 ckcount = 8;
02232
02233 break;
02234
02235 case GIMODE_IFU:
02236 mwidth = GISPECTRUM_MWIDTH_IFU;
02237
02238 ckwidth = 0;
02239 ckheight = 3;
02240 ckcount = 4;
02241
02242 break;
02243
02244 case GIMODE_ARGUS:
02245 mwidth = GISPECTRUM_MWIDTH_IFU;
02246
02247 ckwidth = 0;
02248 ckheight = 3;
02249 ckcount = 4;
02250
02251 break;
02252
02253 default:
02254 cpl_msg_error(fctid, "Invalid instrument mode!");
02255 return 1;
02256 break;
02257 }
02258
02259
02260
02261
02262
02263
02264 if (config->centroid == TRUE) {
02265 method = GILOCALIZE_BARYCENTER;
02266 }
02267 else {
02268 method = GILOCALIZE_HALF_WIDTH;
02269 }
02270
02271
02272
02273
02274
02275
02276
02277 mask_config.ywidth = config->ywidth;
02278 mask_config.local = config->local;
02279 mask_config.threshold = config->noise;
02280 mask_config.ydeg = config->yorder;
02281 mask_config.wdeg = config->worder;
02282 mask_config.ewid = config->ewidth;
02283 mask_config.wavg = mwidth;
02284 mask_config.ckdata.width = ckwidth;
02285 mask_config.ckdata.height = ckheight;
02286 mask_config.ckdata.count = ckcount;
02287 mask_config.sigma = config->sigma;
02288 mask_config.niter = config->iterations;
02289 mask_config.mfrac = config->fraction;
02290 mask_config.start = config->start;
02291 mask_config.retry = config->retries;
02292 mask_config.xbin = config->binsize;
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305 if (config->full != TRUE) {
02306
02307 cpl_msg_info(fctid, "Computing spectrum localization using SIWC "
02308 "spectra");
02309
02310 if (!master || !master->locy || !master->locy) {
02311 cpl_msg_error(fctid, "Required full master localization is "
02312 "missing!");
02313 return 1;
02314 }
02315
02316
02317
02318
02319
02320
02321
02322 cpl_table_unselect_all(_fibers);
02323 cpl_table_or_selected_int(_fibers, "RP", CPL_EQUAL_TO, -1);
02324
02325 fiber_setup = cpl_table_extract_selected(_fibers);
02326 nfibers = cpl_table_get_nrow(fiber_setup);
02327
02328 }
02329
02330
02331
02332
02333
02334
02335
02336 mask_position.type = GIMASK_FITTED_DATA;
02337 mask_position.my = cpl_matrix_new(nrows, nfibers);
02338 mask_position.mw = cpl_matrix_new(nrows, nfibers);
02339
02340 mask_coeffs.type = GIMASK_FIT_COEFFS;
02341 mask_coeffs.my = cpl_matrix_new(mask_config.ydeg + 1, nfibers);
02342 mask_coeffs.mw = cpl_matrix_new(1, (mask_config.wdeg + 1) *
02343 (mask_config.wdeg + 1));
02344
02345
02346
02347
02348
02349
02350 status = _giraffe_localize_spectra(_image, _bpixel, fiber_setup,
02351 method, config->normalize, sigma,
02352 &mask_config, &mask_position,
02353 &mask_coeffs);
02354
02355 if (status) {
02356 result->locy = NULL;
02357 result->locw = NULL;
02358 result->locc = NULL;
02359 result->psf = NULL;
02360
02361 cpl_matrix_delete(mask_position.my);
02362 cpl_matrix_delete(mask_position.mw);
02363
02364 cpl_matrix_delete(mask_coeffs.my);
02365 cpl_matrix_delete(mask_coeffs.mw);
02366
02367 if (config->full != TRUE) {
02368 cpl_table_delete(fiber_setup);
02369 }
02370
02371 cpl_msg_error(fctid, "Spectrum localization computation failed!");
02372
02373 return 1;
02374 }
02375
02376
02377
02378
02379
02380
02381 if (config->full != TRUE) {
02382
02383
02384
02385
02386
02387
02388 cpl_table_delete(fiber_setup);
02389
02390 }
02391 else {
02392
02393 if (master != NULL && master->locy != NULL) {
02394
02395 cxint nf = cpl_table_get_nrow(_fibers);
02396
02397 cxdouble maxoffset = 0.5 * mask_config.wavg;
02398 cxdouble maxshift = 0.;
02399
02400
02401 cpl_msg_info(fctid, "Comparing detected and expected fiber "
02402 "positions.");
02403
02404 status = _giraffe_finalize_fibers(_fibers, mask_position.my,
02405 master->locy, maxoffset,
02406 &maxshift);
02407
02408 if (status != 0) {
02409
02410 if (status == -3) {
02411
02412 const cpl_image* mlocy = giraffe_image_get(master->locy);
02413 cxint _nf = cpl_image_get_size_x(mlocy);
02414
02415 cpl_msg_error(fctid, "More fibers (%d) than expected "
02416 "(%d) were found!", nf, _nf);
02417
02418 }
02419
02420 result->locy = NULL;
02421 result->locw = NULL;
02422 result->locc = NULL;
02423 result->psf = NULL;
02424
02425 cpl_matrix_delete(mask_position.my);
02426 cpl_matrix_delete(mask_position.mw);
02427
02428 cpl_matrix_delete(mask_coeffs.my);
02429 cpl_matrix_delete(mask_coeffs.mw);
02430
02431 if (config->full != TRUE) {
02432 cpl_table_delete(fiber_setup);
02433 }
02434
02435 cpl_msg_error(fctid, "Comparison of fiber positions "
02436 "failed!");
02437
02438 return 1;
02439 }
02440
02441 cx_assert(cpl_table_get_nrow(_fibers) <= nf);
02442
02443 cpl_msg_info(fctid, "%d of %d expected fibers were detected.",
02444 cpl_table_get_nrow(_fibers), nf);
02445
02446 if (cpl_table_get_nrow(_fibers) < nf) {
02447 cpl_msg_debug(fctid, "Maximum offset from the expected "
02448 "position is %.2f, maximum allowed offset is %.2f",
02449 maxshift, maxoffset);
02450 cpl_msg_warning(fctid, "%d fibers are missing!",
02451 nf - cpl_table_get_nrow(_fibers));
02452 }
02453
02454 }
02455
02456 }
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466 result->locy =
02467 giraffe_image_create(CPL_TYPE_DOUBLE,
02468 cpl_matrix_get_ncol(mask_position.my),
02469 cpl_matrix_get_nrow(mask_position.my));
02470
02471 giraffe_image_copy_matrix(result->locy, mask_position.my);
02472 cpl_matrix_delete(mask_position.my);
02473
02474 giraffe_image_set_properties(result->locy, properties);
02475 properties = giraffe_image_get_properties(result->locy);
02476
02477 _result = giraffe_image_get(result->locy);
02478
02479 cpl_propertylist_set_int(properties, GIALIAS_NAXIS1,
02480 cpl_image_get_size_x(_result));
02481 cpl_propertylist_set_int(properties, GIALIAS_NAXIS2,
02482 cpl_image_get_size_y(_result));
02483 cpl_propertylist_set_int(properties, GIALIAS_BITPIX, -32);
02484 cpl_propertylist_set_double(properties, GIALIAS_BZERO, 0.);
02485 cpl_propertylist_set_double(properties, GIALIAS_BSCALE, 1.);
02486
02487 cpl_propertylist_append_int(properties, GIALIAS_LOCNX,
02488 cpl_image_get_size_y(_result));
02489 cpl_propertylist_append_int(properties, GIALIAS_LOCNS,
02490 cpl_image_get_size_x(_result));
02491
02492 if (config->centroid) {
02493 cpl_propertylist_append_string(properties, GIALIAS_LMETHOD,
02494 "BARYCENTER");
02495 }
02496 else {
02497 cpl_propertylist_append_string(properties, GIALIAS_LMETHOD,
02498 "HALF_WIDTH");
02499 }
02500
02501 if (config->normalize) {
02502 cpl_propertylist_append_int(properties, GIALIAS_LNORMALIZE,
02503 config->ywidth);
02504 }
02505 else {
02506 cpl_propertylist_append_int(properties, GIALIAS_LNORMALIZE,
02507 -config->ywidth);
02508 }
02509
02510 cpl_propertylist_append_bool(properties, GIALIAS_LFULLLOC, config->full);
02511 cpl_propertylist_append_int(properties, GIALIAS_LOCYDEG, config->yorder);
02512 cpl_propertylist_append_int(properties, GIALIAS_LOCWDEG, config->worder);
02513 cpl_propertylist_append_double(properties, GIALIAS_LEXTRAWID,
02514 config->ewidth);
02515 cpl_propertylist_append_double(properties, GIALIAS_LNOISEMULT,
02516 config->noise);
02517
02518 cpl_propertylist_append_double(properties, GIALIAS_LCLIPSIGMA,
02519 config->sigma);
02520 cpl_propertylist_append_int(properties, GIALIAS_LCLIPNITER,
02521 config->iterations);
02522 cpl_propertylist_append_double(properties, GIALIAS_LCLIPMFRAC,
02523 config->fraction);
02524
02525
02526 if (cpl_propertylist_has(properties, GIALIAS_GIRFTYPE)) {
02527 cpl_propertylist_set_string(properties, GIALIAS_GIRFTYPE, "LOCY");
02528 }
02529 else {
02530 cpl_propertylist_append_string(properties, GIALIAS_GIRFTYPE, "LOCY");
02531 }
02532 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE, "GIRAFFE "
02533 "localization centroid");
02534
02535
02536
02537
02538 result->locw =
02539 giraffe_image_create(CPL_TYPE_DOUBLE,
02540 cpl_matrix_get_ncol(mask_position.mw),
02541 cpl_matrix_get_nrow(mask_position.mw));
02542
02543 giraffe_image_copy_matrix(result->locw, mask_position.mw);
02544 cpl_matrix_delete(mask_position.mw);
02545
02546 giraffe_image_set_properties(result->locw, properties);
02547 properties = giraffe_image_get_properties(result->locw);
02548
02549 _result = giraffe_image_get(result->locw);
02550
02551 cpl_propertylist_set_int(properties, GIALIAS_NAXIS1,
02552 cpl_image_get_size_x(_result));
02553 cpl_propertylist_set_int(properties, GIALIAS_NAXIS2,
02554 cpl_image_get_size_y(_result));
02555
02556 if (cpl_propertylist_has(properties, GIALIAS_GIRFTYPE)) {
02557 cpl_propertylist_set_string(properties, GIALIAS_GIRFTYPE,
02558 "LOCWY");
02559 }
02560 else {
02561 cpl_propertylist_append_string(properties, GIALIAS_GIRFTYPE,
02562 "LOCWY");
02563 }
02564 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE, "GIRAFFE "
02565 "localization half-width");
02566
02567
02568
02569
02570 locc = cpl_table_new(cpl_matrix_get_ncol(mask_coeffs.my));
02571
02572 cpl_table_new_column(locc, "BUTTON", CPL_TYPE_INT);
02573 for (i = 0; i < cpl_table_get_nrow(locc); i++) {
02574 cpl_table_set_int(locc, "BUTTON", i, i);
02575 }
02576
02577 for (i = 0; i < cpl_matrix_get_nrow(mask_coeffs.my); i++) {
02578 cxchar *label = NULL;
02579
02580 cx_asprintf(&label, "YC%d", i);
02581 cpl_table_new_column(locc, label, CPL_TYPE_DOUBLE);
02582 cx_free(label);
02583 }
02584
02585
02586 result->locc = giraffe_table_create(locc, properties);
02587 cpl_table_delete(locc);
02588
02589 _my = cpl_matrix_transpose_create(mask_coeffs.my);
02590 giraffe_table_copy_matrix(result->locc, "YC0", _my);
02591 cpl_matrix_delete(_my);
02592 cpl_matrix_delete(mask_coeffs.my);
02593
02594 properties = giraffe_table_get_properties(result->locc);
02595
02596
02597
02598
02599 pname = cx_string_new();
02600
02601 for (i = 0; i < cpl_matrix_get_ncol(mask_coeffs.mw); i++) {
02602 cx_string_sprintf(pname, "%s%d", GIALIAS_LOCWIDCOEF, i);
02603 cpl_propertylist_append_double(properties, cx_string_get(pname),
02604 cpl_matrix_get(mask_coeffs.mw, 0, i));
02605 }
02606
02607 cx_string_delete(pname);
02608 cpl_matrix_delete(mask_coeffs.mw);
02609
02610 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
02611 "LOCYWCHEB");
02612 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE, "GIRAFFE "
02613 "localization fit coefficients");
02614
02615
02616
02617
02618 result->psf = NULL;
02619
02620 return 0;
02621
02622 }
02623
02624
02635 GiLocalizeConfig *
02636 giraffe_localize_config_create(cpl_parameterlist *list)
02637 {
02638
02639 const cxchar *s;
02640 cpl_parameter *p;
02641
02642 GiLocalizeConfig *config = NULL;
02643
02644
02645 if (list == NULL) {
02646 return NULL;
02647 }
02648
02649 config = cx_calloc(1, sizeof *config);
02650
02651
02652
02653
02654
02655
02656 config->full = TRUE;
02657 config->centroid = TRUE;
02658 config->local = TRUE;
02659
02660
02661 p = cpl_parameterlist_find(list, "giraffe.localization.mode");
02662 s = cpl_parameter_get_string(p);
02663 if (strcmp(s, "siwc") == 0) {
02664 config->full = FALSE;
02665 }
02666
02667 p = cpl_parameterlist_find(list, "giraffe.localization.start");
02668 config->start = cpl_parameter_get_int(p);
02669
02670 p = cpl_parameterlist_find(list, "giraffe.localization.retries");
02671 config->retries = cpl_parameter_get_int(p);
02672
02673 p = cpl_parameterlist_find(list, "giraffe.localization.binsize");
02674 config->binsize = cpl_parameter_get_int(p);
02675
02676 p = cpl_parameterlist_find(list, "giraffe.localization.ewidth");
02677 config->ewidth = cpl_parameter_get_double(p);
02678
02679 p = cpl_parameterlist_find(list, "giraffe.localization.ywidth");
02680 config->ywidth = cpl_parameter_get_int(p);
02681
02682 p = cpl_parameterlist_find(list, "giraffe.localization.center");
02683 s = cpl_parameter_get_string(p);
02684 if (!strcmp(s, "hwidth")) {
02685 config->centroid = FALSE;
02686 }
02687
02688 p = cpl_parameterlist_find(list, "giraffe.localization.normalize");
02689 config->normalize = cpl_parameter_get_bool(p);
02690
02691 p = cpl_parameterlist_find(list, "giraffe.localization.threshold");
02692 s = cpl_parameter_get_string(p);
02693 if (!strcmp(s, "global")) {
02694 config->local = FALSE;
02695 }
02696
02697 p = cpl_parameterlist_find(list, "giraffe.localization.noise");
02698 config->noise = cpl_parameter_get_double(p);
02699
02700 p = cpl_parameterlist_find(list, "giraffe.localization.ron");
02701 config->ron = cpl_parameter_get_double(p);
02702
02703 p = cpl_parameterlist_find(list, "giraffe.localization.yorder");
02704 config->yorder = cpl_parameter_get_int(p);
02705
02706 p = cpl_parameterlist_find(list, "giraffe.localization.worder");
02707 config->worder = cpl_parameter_get_int(p);
02708
02709 p = cpl_parameterlist_find(list, "giraffe.localization.sigma");
02710 config->sigma = cpl_parameter_get_double(p);
02711
02712 p = cpl_parameterlist_find(list, "giraffe.localization.iterations");
02713 config->iterations = cpl_parameter_get_int(p);
02714
02715 p = cpl_parameterlist_find(list, "giraffe.localization.fraction");
02716 config->fraction = cpl_parameter_get_double(p);
02717
02718 return config;
02719
02720 }
02721
02722
02735 void
02736 giraffe_localize_config_destroy(GiLocalizeConfig *config)
02737 {
02738
02739 if (config) {
02740 cx_free(config);
02741 }
02742
02743 return;
02744
02745 }
02746
02747
02759 void
02760 giraffe_localize_config_add(cpl_parameterlist *list)
02761 {
02762
02763 cpl_parameter *p;
02764
02765
02766 if (list == NULL) {
02767 return;
02768 }
02769
02770 p = cpl_parameter_new_enum("giraffe.localization.mode",
02771 CPL_TYPE_STRING,
02772 "Localization mode: Use all spectra "
02773 "or the 5 SIWC spectra",
02774 "giraffe.localization",
02775 "all", 2, "all", "siwc");
02776 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-mode");
02777 cpl_parameterlist_append(list, p);
02778
02779
02780 p = cpl_parameter_new_value("giraffe.localization.start",
02781 CPL_TYPE_INT,
02782 "Bin along x-axis",
02783 "giraffe.localization",
02784 -1);
02785 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-start");
02786 cpl_parameterlist_append(list, p);
02787
02788
02789 p = cpl_parameter_new_value("giraffe.localization.retries",
02790 CPL_TYPE_INT,
02791 "Initial localization detection "
02792 "xbin retries.",
02793 "giraffe.localization",
02794 10);
02795 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-retries");
02796 cpl_parameterlist_append(list, p);
02797
02798
02799 p = cpl_parameter_new_value("giraffe.localization.binsize",
02800 CPL_TYPE_INT,
02801 "Initial localization detection "
02802 "xbin size.",
02803 "giraffe.localization",
02804 -1);
02805 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-binsize");
02806 cpl_parameterlist_append(list, p);
02807
02808
02809 p = cpl_parameter_new_value("giraffe.localization.ewidth",
02810 CPL_TYPE_DOUBLE,
02811 "Localization detection extra width.",
02812 "giraffe.localization",
02813 1.0);
02814 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-ewidth");
02815 cpl_parameterlist_append(list, p);
02816
02817
02818 p = cpl_parameter_new_value("giraffe.localization.ywidth",
02819 CPL_TYPE_INT,
02820 "Full width [pxl] of the equilizing "
02821 "filter (distance between two "
02822 "adjacent fibers).",
02823 "giraffe.localization",
02824 -1);
02825 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-ywidth");
02826 cpl_parameterlist_append(list, p);
02827
02828
02829 p = cpl_parameter_new_enum("giraffe.localization.center",
02830 CPL_TYPE_STRING,
02831 "Method used for mask center "
02832 "computation.",
02833 "giraffe.localization",
02834 "centroid", 2, "centroid",
02835 "hwidth");
02836 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-center");
02837 cpl_parameterlist_append(list, p);
02838
02839
02840 p = cpl_parameter_new_value("giraffe.localization.normalize",
02841 CPL_TYPE_BOOL,
02842 "Enable spectrum normalization along "
02843 "the dispersion axis.",
02844 "giraffe.localization",
02845 FALSE);
02846 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-norm");
02847 cpl_parameterlist_append(list, p);
02848
02849
02850 p = cpl_parameter_new_value("giraffe.localization.noise",
02851 CPL_TYPE_DOUBLE,
02852 "Threshold multiplier.",
02853 "giraffe.localization",
02854 7.0);
02855 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-noise");
02856 cpl_parameterlist_append(list, p);
02857
02858
02859 p = cpl_parameter_new_enum("giraffe.localization.threshold",
02860 CPL_TYPE_STRING,
02861 "Selects thresholding algorithm: local or "
02862 "global",
02863 "giraffe.localization",
02864 "local", 2, "local", "global");
02865 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-threshold");
02866 cpl_parameterlist_append(list, p);
02867
02868
02869 p = cpl_parameter_new_value("giraffe.localization.ron",
02870 CPL_TYPE_DOUBLE,
02871 "New bias sigma (RON) value for dark "
02872 "subtraction",
02873 "giraffe.localization",
02874 -1.);
02875 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-ron");
02876 cpl_parameterlist_append(list, p);
02877
02878
02879 p = cpl_parameter_new_value("giraffe.localization.yorder",
02880 CPL_TYPE_INT,
02881 "Order of Chebyshev polynomial fit.",
02882 "giraffe.localization",
02883 4);
02884 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-yorder");
02885 cpl_parameterlist_append(list, p);
02886
02887
02888 p = cpl_parameter_new_value("giraffe.localization.worder",
02889 CPL_TYPE_INT,
02890 "Order of Chebyshev 2D polynomial fit.",
02891 "giraffe.localization",
02892 2);
02893 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-worder");
02894 cpl_parameterlist_append(list, p);
02895
02896
02897 p = cpl_parameter_new_value("giraffe.localization.sigma",
02898 CPL_TYPE_DOUBLE,
02899 "Localization clipping: sigma threshold "
02900 "factor",
02901 "giraffe.localization",
02902 2.5);
02903 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-sigma");
02904 cpl_parameterlist_append(list, p);
02905
02906
02907 p = cpl_parameter_new_value("giraffe.localization.iterations",
02908 CPL_TYPE_INT,
02909 "Localization clipping: number of "
02910 "iterations",
02911 "giraffe.localization",
02912 5);
02913 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-niter");
02914 cpl_parameterlist_append(list, p);
02915
02916
02917 p = cpl_parameter_new_range("giraffe.localization.fraction",
02918 CPL_TYPE_DOUBLE,
02919 "Localization clipping: minimum fraction "
02920 "of points accepted/total.",
02921 "giraffe.localization",
02922 0.9, 0.0, 1.0);
02923 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sloc-mfrac");
02924 cpl_parameterlist_append(list, p);
02925
02926 return;
02927
02928 }