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 <math.h>
00033 #include <float.h>
00034
00035 #include <cxmemory.h>
00036 #include <cxstring.h>
00037 #include <cxstrutils.h>
00038
00039 #include <cpl_parameterlist.h>
00040 #include <cpl_matrix.h>
00041 #include <cpl_table.h>
00042 #include <cpl_msg.h>
00043
00044 #include "gimacros.h"
00045 #include "gialias.h"
00046 #include "giclip.h"
00047 #include "giarray.h"
00048 #include "giimage.h"
00049 #include "gimatrix.h"
00050 #include "giwindow.h"
00051 #include "gipsfdata.h"
00052 #include "gimodel.h"
00053 #include "gimath.h"
00054 #include "gilocalization.h"
00055 #include "gimessages.h"
00056 #include "gifiberutils.h"
00057 #include "giutils.h"
00058 #include "giextract.h"
00059
00060
00069 enum GiProfileId {
00070 PROFILE_PSFEXP = 1 << 1,
00071 PROFILE_PSFEXP2 = 1 << 2,
00072 PROFILE_GAUSSIAN = 1 << 3
00073 };
00074
00075 typedef enum GiProfileId GiProfileId;
00076
00077
00078
00079
00080
00081
00082 struct GiExtractOptimalConfig {
00083
00084 GiClipParams clip;
00085
00086 cxbool limits;
00087
00088 cxint bkgorder;
00089
00090 cxdouble exptime;
00091 cxdouble ron;
00092 cxdouble dark;
00093 cxdouble ewidth;
00094 };
00095
00096 typedef struct GiExtractOptimalConfig GiExtractOptimalConfig;
00097
00098
00099
00100
00101
00102
00103 struct GiExtractHorneConfig {
00104 GiClipParams clip;
00105
00106 cxdouble exptime;
00107 cxdouble ron;
00108 cxdouble dark;
00109 cxdouble ewidth;
00110 };
00111
00112 typedef struct GiExtractHorneConfig GiExtractHorneConfig;
00113
00114
00115 struct GiExtractionData {
00116 cxdouble value;
00117 cxdouble error;
00118 cxdouble position;
00119 cxdouble npixels;
00120 };
00121
00122 typedef struct GiExtractionData GiExtractionData;
00123
00124
00125 struct GiExtractionSlice {
00126 cxint fsize;
00127 cxint msize;
00128
00129 cxint nflx;
00130 cxint nbkg;
00131
00132 cpl_matrix* flux;
00133 cpl_matrix* variance;
00134 cpl_matrix* model;
00135 };
00136
00137 typedef struct GiExtractionSlice GiExtractionSlice;
00138
00139
00140 struct GiExtractionPsfLimits {
00141 cxint size;
00142
00143 cxint* ymin;
00144 cxint* ymax;
00145 };
00146
00147 typedef struct GiExtractionPsfLimits GiExtractionPsfLimits;
00148
00149
00150 struct GiExtractionWorkspace {
00151 cpl_matrix* atw;
00152 cpl_matrix* atwa;
00153 cpl_matrix* atws;
00154 cpl_matrix* c;
00155 cpl_matrix* tmp;
00156 };
00157
00158 typedef struct GiExtractionWorkspace GiExtractionWorkspace;
00159
00160
00161 struct GiVirtualSlit {
00162 cxint width;
00163
00164 cxdouble center;
00165 cxdouble extra_width;
00166
00167 cxdouble* position;
00168 cxdouble* signal;
00169 cxdouble* variance;
00170 cxdouble* fraction;
00171
00172 cxint* mask;
00173 cxint* offset;
00174 };
00175
00176 typedef struct GiVirtualSlit GiVirtualSlit;
00177
00178
00179
00180
00181
00182
00183 inline static GiExtractionSlice*
00184 _giraffe_extractionslice_new(cxint nflx, cxint ndata, cxint nbkg)
00185 {
00186
00187 GiExtractionSlice* self = cx_malloc(sizeof *self);
00188
00189 self->nflx = nflx;
00190 self->nbkg = nbkg;
00191
00192 self->fsize = nflx + nbkg;
00193 self->msize = ndata;
00194
00195 self->flux = cpl_matrix_new(self->fsize, 1);
00196 self->variance = cpl_matrix_new(self->fsize, 1);
00197 self->model = cpl_matrix_new(self->msize, 1);
00198
00199 return self;
00200
00201 }
00202
00203
00204 inline static void
00205 _giraffe_extractionslice_delete(GiExtractionSlice* self)
00206 {
00207
00208 if (self != NULL) {
00209 if (self->model != NULL) {
00210 cpl_matrix_delete(self->model);
00211 self->model = NULL;
00212 }
00213
00214 if (self->variance != NULL) {
00215 cpl_matrix_delete(self->variance);
00216 self->variance = NULL;
00217 }
00218
00219 if (self->flux != NULL) {
00220 cpl_matrix_delete(self->flux);
00221 self->flux = NULL;
00222 }
00223
00224 cx_free(self);
00225 }
00226
00227 return;
00228
00229 }
00230
00231
00232 inline static GiExtractionPsfLimits*
00233 _giraffe_extraction_psflimits_new(cxint size)
00234 {
00235
00236 GiExtractionPsfLimits* self = cx_malloc(sizeof *self);
00237
00238 self->size = size;
00239
00240 self->ymin = cx_calloc(self->size, sizeof(cxint));
00241 self->ymax = cx_calloc(self->size, sizeof(cxint));
00242
00243 return self;
00244
00245 }
00246
00247
00248 inline static void
00249 _giraffe_extraction_psflimits_delete(GiExtractionPsfLimits* self)
00250 {
00251
00252 if (self != NULL) {
00253 if (self->ymin != NULL) {
00254 cx_free(self->ymin);
00255 }
00256
00257 if (self->ymax != NULL) {
00258 cx_free(self->ymax);
00259 }
00260
00261 cx_free(self);
00262 }
00263
00264 return;
00265
00266 }
00267
00268
00269 inline static GiExtractionWorkspace*
00270 _giraffe_optimal_workspace_new(cxint m, cxint n)
00271 {
00272
00273 GiExtractionWorkspace* self = cx_malloc(sizeof *self);
00274
00275
00276 self->atw = cpl_matrix_new(m, n);
00277 self->atwa = cpl_matrix_new(m, m);
00278 self->c = cpl_matrix_new(m, m);
00279 self->atws = cpl_matrix_new(m, 1);
00280
00281 self->tmp = cpl_matrix_new(m, m);
00282
00283 return self;
00284
00285 }
00286
00287
00288 inline static void
00289 _giraffe_optimal_workspace_delete(GiExtractionWorkspace* self)
00290 {
00291
00292 if (self != NULL) {
00293 if (self->atws != NULL) {
00294 cpl_matrix_delete(self->atws);
00295 }
00296
00297 if (self->atwa != NULL) {
00298 cpl_matrix_delete(self->atwa);
00299 }
00300
00301 if (self->c != NULL) {
00302 cpl_matrix_delete(self->c);
00303 }
00304
00305 if (self->atw != NULL) {
00306 cpl_matrix_delete(self->atw);
00307 }
00308
00309 if (self->tmp != NULL) {
00310 cpl_matrix_delete(self->tmp);
00311 }
00312
00313 cx_free(self);
00314
00315 }
00316
00317 return;
00318
00319 }
00320
00321
00322
00323
00324
00325
00326 inline static void
00327 _giraffe_virtualslit_allocate(GiVirtualSlit* self)
00328 {
00329
00330 if ((self != NULL) && (self->width > 0)) {
00331
00332 self->position = cx_calloc(self->width, sizeof(cxdouble));
00333 self->signal = cx_calloc(self->width, sizeof(cxdouble));
00334 self->variance = cx_calloc(self->width, sizeof(cxdouble));
00335 self->fraction = cx_calloc(self->width, sizeof(cxdouble));
00336
00337 self->mask = cx_calloc(self->width, sizeof(cxdouble));
00338 self->offset = cx_calloc(self->width, sizeof(cxdouble));
00339
00340 }
00341
00342 return;
00343
00344 }
00345
00346
00347 inline static GiVirtualSlit*
00348 _giraffe_virtualslit_new(cxdouble extra_width)
00349 {
00350
00351 GiVirtualSlit* self = cx_calloc(1, sizeof *self);
00352
00353 self->width = 0;
00354 self->center = 0.;
00355 self->extra_width = extra_width;
00356
00357 self->position = NULL;
00358 self->signal = NULL;
00359 self->variance = NULL;
00360 self->fraction = NULL;
00361 self->mask = NULL;
00362 self->offset = NULL;
00363
00364 return self;
00365
00366 }
00367
00368
00369 inline static void
00370 _giraffe_virtualslit_clear(GiVirtualSlit* self)
00371 {
00372
00373 if (self != NULL) {
00374
00375 if (self->position != NULL) {
00376 cx_free(self->position);
00377 self->position = NULL;
00378 }
00379
00380 if (self->signal != NULL) {
00381 cx_free(self->signal);
00382 self->signal = NULL;
00383 }
00384
00385 if (self->variance != NULL) {
00386 cx_free(self->variance);
00387 self->variance = NULL;
00388 }
00389
00390 if (self->fraction != NULL) {
00391 cx_free(self->fraction);
00392 self->fraction = NULL;
00393 }
00394
00395 if (self->mask != NULL) {
00396 cx_free(self->mask);
00397 self->mask = NULL;
00398 }
00399
00400 if (self->offset != NULL) {
00401 cx_free(self->offset);
00402 self->offset = NULL;
00403 }
00404
00405 self->extra_width = 0.;
00406 self->center = 0.;
00407 self->width = 0;
00408
00409 }
00410
00411 return;
00412
00413 }
00414
00415
00416 inline static void
00417 _giraffe_virtualslit_delete(GiVirtualSlit* self)
00418 {
00419
00420 if (self != NULL) {
00421 _giraffe_virtualslit_clear(self);
00422
00423 cx_free(self);
00424 self = NULL;
00425 }
00426
00427 return;
00428
00429 }
00430
00431
00432 inline static cxint
00433 _giraffe_virtualslit_setup(GiVirtualSlit* self, cxint bin,
00434 cxdouble center, cxdouble width,
00435 const cpl_image* signal, const cpl_image* variance,
00436 const cpl_image* bpixel)
00437 {
00438
00439 register cxint ny = cpl_image_get_size_x(signal);
00440 register cxint offset = bin * cpl_image_get_size_x(signal);
00441
00442 register cxdouble lower = center - (width + self->extra_width);
00443 register cxdouble upper = center + (width + self->extra_width);
00444
00445 register cxint first = (cxint) floor(lower);
00446 register cxint last = (cxint) ceil(upper);
00447
00448 const cxdouble* s = cpl_image_get_data_double_const(signal);
00449 const cxdouble* v = cpl_image_get_data_double_const(variance);
00450
00451
00452
00453
00454
00455
00456 lower = CX_MAX(0., lower);
00457 upper = CX_MIN(ny, upper);
00458
00459 first = CX_MAX(0, first);
00460 last = CX_MIN(ny, last);
00461
00462 self->center = center;
00463 self->width = last - first + 1;
00464
00465
00466
00467
00468
00469
00470 _giraffe_virtualslit_allocate(self);
00471
00472 if (bpixel != NULL) {
00473
00474 register cxint k = 0;
00475 register cxint y = 0;
00476
00477 const cxint* _bpixel = cpl_image_get_data_int_const(bpixel);
00478
00479
00480 for (y = first; y <= last; y++) {
00481
00482 register cxint ypos = offset + y;
00483
00484 cxint ok = (_bpixel[ypos] & GIR_M_PIX_SET) == 0 ? 1 : 0;
00485
00486
00487 self->position[k] = y - center;
00488 self->fraction[k] = 1.;
00489
00490 self->signal[k] = s[ypos];
00491 self->variance[k] = v[ypos];
00492
00493 self->mask[k] = ok;
00494 self->offset[k] = ypos;
00495 ++k;
00496
00497 }
00498
00499 }
00500 else {
00501
00502 register cxint k = 0;
00503 register cxint y = 0;
00504
00505
00506 for (y = first; y <= last; y++) {
00507
00508 register cxint ypos = offset + y;
00509
00510 cxint ok = 1;
00511
00512
00513 self->position[k] = y - center;
00514 self->fraction[k] = 1.;
00515
00516 self->signal[k] = s[ypos];
00517 self->variance[k] = v[ypos];
00518
00519 self->mask[k] = ok;
00520 self->offset[k] = ypos;
00521 ++k;
00522
00523 }
00524
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534 self->fraction[0] = ((cxdouble)first + 1.) - lower;
00535 self->fraction[self->width - 1] = upper - ((cxdouble)last - 1.);
00536
00537 return self->width;
00538
00539 }
00540
00541
00542
00543
00544
00545
00546 inline static cxint
00547 _giraffe_matrix_invert(cpl_matrix* m_inv, const cpl_matrix* m, cpl_matrix* lu)
00548 {
00549
00550 cxint i = 0;
00551 cxint status = 0;
00552 cxint n = cpl_matrix_get_ncol(m);
00553
00554 register cxint sz = n * n * sizeof(cxdouble);
00555
00556 const cxdouble* _m = cpl_matrix_get_data_const(m);
00557
00558 cxdouble* _m_inv = cpl_matrix_get_data(m_inv);
00559 cxdouble* _m_lu = cpl_matrix_get_data(lu);
00560
00561 cpl_array* perm = cpl_array_new(n, CPL_TYPE_INT);
00562
00563 register cxint* perm_data = cpl_array_get_data_int(perm);
00564
00565
00566 memset(_m_inv, 0, sz);
00567 memcpy(_m_lu, _m, sz);
00568
00569 if (cpl_matrix_decomp_lu(lu, perm, &i) != 0) {
00570 cpl_array_delete(perm);
00571 return 1;
00572 }
00573
00574
00575
00576
00577
00578
00579 for (i = 0; i < n; ++i) {
00580 _m_inv[i * n + perm_data[i]] = 1.;
00581 }
00582
00583 cpl_array_delete(perm);
00584
00585
00586 status = cpl_matrix_solve_lu(lu, m_inv, NULL);
00587
00588 if (status != 0) {
00589 cpl_matrix_delete(m_inv);
00590 return 2;
00591 }
00592
00593 return 0;
00594
00595 }
00596
00597
00598
00599
00600
00601
00602 inline static cpl_matrix*
00603 _giraffe_compute_psf(GiModel* psf, const cpl_matrix* x)
00604 {
00605
00606 register cxint i = 0;
00607 register cxint n = 0;
00608
00609 cxint status = 0;
00610
00611 const cxdouble* _x = NULL;
00612
00613 cxdouble* _y = NULL;
00614
00615 cpl_matrix* y = NULL;
00616
00617 cx_assert(psf != NULL);
00618 cx_assert(x != NULL);
00619 cx_assert(cpl_matrix_get_ncol(x) == 1);
00620
00621 n = cpl_matrix_get_nrow(x);
00622
00623 y = cpl_matrix_new(n, 1);
00624
00625 _x = cpl_matrix_get_data_const(x);
00626 _y = cpl_matrix_get_data(y);
00627
00628 for (i = 0; i < n; i++) {
00629 giraffe_model_set_argument(psf, "x", _x[i]);
00630 giraffe_model_evaluate(psf, &_y[i], &status);
00631
00632 if (status != 0) {
00633 cpl_matrix_delete(y);
00634 return NULL;
00635 }
00636 }
00637
00638 return y;
00639
00640 }
00641
00642
00643
00644
00645
00646
00647
00648 inline static cxint
00649 _giraffe_horne_extract_slit(GiExtractionData* result,
00650 const GiVirtualSlit* vslit, GiModel* psf,
00651 const GiExtractHorneConfig* config)
00652 {
00653
00654 cxint i = 0;
00655 cxint ngood = 0;
00656
00657 cxdouble var = 0.;
00658 cxdouble bkg = 0.;
00659 cxdouble flx = 0.;
00660 cxdouble norm = 0.;
00661 cxdouble* tdata = NULL;
00662 cxdouble* _mnpsf = NULL;
00663
00664 cpl_matrix* mnpsf = NULL;
00665 cpl_matrix* mvslit = NULL;
00666
00667
00668
00669
00670
00671
00672
00673 mvslit = cpl_matrix_wrap(vslit->width, 1, vslit->position);
00674 mnpsf = _giraffe_compute_psf(psf, mvslit);
00675
00676 cpl_matrix_unwrap(mvslit);
00677 mvslit = NULL;
00678
00679 if (mnpsf == NULL) {
00680 return -1;
00681 }
00682
00683
00684
00685
00686
00687
00688 _mnpsf = cpl_matrix_get_data(mnpsf);
00689
00690 norm = 0.;
00691
00692 for (i = 0; i < vslit->width; ++i) {
00693 _mnpsf[i] = CX_MAX(_mnpsf[i], 0.);
00694 norm += _mnpsf[i];
00695 }
00696
00697 for (i = 0; i < vslit->width; ++i) {
00698 _mnpsf[i] /= norm;
00699 }
00700
00701
00702
00703
00704
00705
00706 tdata = cx_malloc(vslit->width * sizeof(cxdouble));
00707
00708 i = 0;
00709 ngood = 0;
00710
00711 while (i < vslit->width) {
00712 if (vslit->mask[i] > 0) {
00713 tdata[ngood] = CX_MAX(vslit->signal[i], 0.);
00714 ++ngood;
00715 }
00716 ++i;
00717 }
00718
00719 if (ngood > 1) {
00720 giraffe_array_sort(tdata, ngood);
00721 bkg = 0.5 * (tdata[0] + tdata[1]);
00722 }
00723
00724 cx_free(tdata);
00725 tdata = NULL;
00726
00727
00728
00729
00730
00731
00732
00733
00734 if (ngood > 0) {
00735
00736 cxint iteration = 0;
00737 cxint nreject = -1;
00738 cxint niter = config->clip.iterations;
00739 cxint nmin = (cxint)config->clip.fraction;
00740
00741 cxdouble sigma = config->clip.level * config->clip.level;
00742 cxdouble* variance = NULL;
00743
00744
00745
00746
00747
00748
00749
00750 norm = 0.;
00751 flx = 0.;
00752
00753 for (i = 0; i < vslit->width; ++i) {
00754 if (vslit->mask[i] != 0) {
00755 flx += (vslit->signal[i] - bkg) * vslit->fraction[i];
00756 norm += vslit->fraction[i] * _mnpsf[i];
00757 }
00758 }
00759
00760 flx /= norm;
00761
00762
00763
00764
00765
00766
00767
00768 variance = cx_calloc(vslit->width, sizeof(cxdouble));
00769
00770 for (i = 0; i < vslit->width; ++i) {
00771
00772 register cxdouble ve = flx * _mnpsf[i] + bkg;
00773
00774 variance[i] = vslit->variance[i] + fabs(vslit->fraction[i] * ve);
00775
00776 }
00777
00778
00779
00780
00781
00782
00783 nreject = -1;
00784
00785 while ((iteration < niter) && (ngood > nmin) && (nreject != 0)) {
00786
00787 cxint imax = 0;
00788
00789 cxdouble _flx = 0.;
00790 cxdouble mmax = 0.;
00791
00792
00793 norm = 0.;
00794 var = 0.;
00795 nreject = 0;
00796
00797
00798
00799
00800
00801
00802 for (i = 0; i < vslit->width; ++i) {
00803
00804 if (vslit->mask[i] != 0) {
00805
00806 cxdouble m = vslit->signal[i] - bkg - flx * _mnpsf[i];
00807
00808 m *= vslit->fraction[i];
00809 m *= m / variance[i] ;
00810
00811 if (m > mmax) {
00812 mmax = m;
00813 imax = i;
00814 }
00815
00816 }
00817
00818 }
00819
00820 if ((sigma > 0.) && (mmax > sigma)) {
00821 vslit->mask[imax] = 0;
00822 ++nreject;
00823 --ngood;
00824 }
00825
00826
00827
00828
00829
00830
00831 for (i = 0; i < vslit->width; ++i) {
00832
00833 if (vslit->mask[i] != 0) {
00834
00835 register cxdouble data = vslit->signal[i] - bkg;
00836 register cxdouble p = _mnpsf[i];
00837
00838 data *= vslit->fraction[i];
00839 p *= vslit->fraction[i];
00840
00841 norm += p * p / variance[i];
00842 _flx += p * data / variance[i];
00843 var += p;
00844
00845 }
00846
00847 }
00848
00849 flx = _flx / norm;
00850 var /= norm;
00851
00852
00853
00854
00855
00856
00857 for (i = 0; i < vslit->width; ++i) {
00858
00859 register cxdouble ve = flx * _mnpsf[i] + bkg;
00860
00861 variance[i] = vslit->variance[i] + fabs(vslit->fraction[i] * ve);
00862
00863 }
00864
00865 ++iteration;
00866
00867 }
00868
00869 cx_free(variance);
00870 variance = NULL;
00871
00872 }
00873
00874 cpl_matrix_delete(mnpsf);
00875 mnpsf = NULL;
00876
00877 result->value = flx;
00878 result->error = sqrt(var);
00879 result->position = vslit->center;
00880 result->npixels = ngood;
00881
00882 return ngood == 0 ? 1 : 0;
00883
00884 }
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930 inline static cxint
00931 _giraffe_optimal_extract_slice(GiExtractionSlice* slice,
00932 const cpl_matrix* AT,
00933 const cpl_matrix* S,
00934 const cpl_matrix* W,
00935 GiExtractionPsfLimits* limits,
00936 GiExtractionWorkspace* ws)
00937 {
00938
00939 register cxint i = 0;
00940 register cxint n = cpl_matrix_get_ncol(AT);
00941 register cxint m = cpl_matrix_get_nrow(AT);
00942
00943 cxint status = 0;
00944
00945 const cxdouble* at = cpl_matrix_get_data_const(AT);
00946 const cxdouble* w = cpl_matrix_get_data_const(W);
00947 const cxdouble* s = cpl_matrix_get_data_const(S);
00948 const cxdouble* c = cpl_matrix_get_data_const(ws->c);
00949
00950 cxdouble* atw = cpl_matrix_get_data(ws->atw);
00951 cxdouble* atwa = cpl_matrix_get_data(ws->atwa);
00952 cxdouble* atws = cpl_matrix_get_data(ws->atws);
00953 cxdouble* sf = cpl_matrix_get_data(slice->flux);
00954 cxdouble* sv = cpl_matrix_get_data(slice->variance);
00955 cxdouble* sm = cpl_matrix_get_data(slice->model);
00956
00957
00958 for (i = 0; i < m; ++i) {
00959
00960 register cxint j = 0;
00961 register cxint im = i * m;
00962 register cxint in = i * n;
00963 register cxint ymin = limits->ymin[i];
00964 register cxint ymax = limits->ymax[i];
00965
00966
00967 atws[i] = 0.;
00968
00969 for (j = 0; j < n; ++j) {
00970
00971 register cxint k = in + j;
00972
00973
00974 atw[k] = w[j] * at[k];
00975 atws[i] += atw[k] * s[j];
00976
00977 }
00978
00979 for (j = 0; j < i; ++j) {
00980
00981 register cxint k = 0;
00982 register cxint l = im + j;
00983
00984 atwa[l] = 0.;
00985 for (k = ymin; k < ymax; ++k) {
00986 atwa[l] += atw[in + k] * at[j * n + k];
00987 }
00988
00989 atwa[j * m + i] = atwa[l];
00990
00991 }
00992
00993 atwa[im + i] = 0.;
00994
00995 for (j = ymin; j < ymax; ++j) {
00996 atwa[im + i] += atw[in + j] * at[in + j];
00997 }
00998
00999 }
01000
01001
01002 status = _giraffe_matrix_invert(ws->c, ws->atwa, ws->tmp);
01003
01004 if (status != 0) {
01005 return 1;
01006 }
01007
01008 for (i = 0; i < m; ++i) {
01009
01010 register cxint j = 0;
01011 register cxint im = i * m;
01012
01013
01014 sf[i] = 0.;
01015 sv[i] = c[im + i];
01016
01017 for (j = 0; j < m; ++j) {
01018 sf[i] += c[im + j] * atws[j];
01019 }
01020
01021 }
01022
01023 for (i = 0; i < n; ++i) {
01024
01025 register cxint j = 0;
01026
01027
01028 sm[i] = 0.;
01029
01030 for (j = 0; j < m; ++j) {
01031 sm[i] += at[j * n + i] * sf[j];
01032 }
01033
01034 }
01035
01036 return 0;
01037
01038 }
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064 inline static cxint
01065 _giraffe_extract_summation(const cpl_image* mz, const cpl_image* mvarz,
01066 const cpl_table* fibers, const cpl_image* my,
01067 const cpl_image* mw, cpl_image* mbpx,
01068 cpl_image* ms, cpl_image* mse,
01069 cpl_image* msn, cpl_image* msy)
01070 {
01071
01072 register cxint nn;
01073
01074 const cxchar* idx = NULL;
01075
01076 cxint ny = cpl_image_get_size_x(mz);
01077 cxint nfibers = cpl_table_get_nrow(fibers);
01078 cxint nspectra = cpl_image_get_size_x(my);
01079 cxint nbins = cpl_image_get_size_y(my);
01080
01081 const cxdouble* pixels = cpl_image_get_data_double_const(mz);
01082 const cxdouble* variances = cpl_image_get_data_double_const(mvarz);
01083 const cxdouble* locy = cpl_image_get_data_double_const(my);
01084 const cxdouble* locw = cpl_image_get_data_double_const(mw);
01085
01086 cxdouble* flux = cpl_image_get_data_double(ms);
01087 cxdouble* flux_error = cpl_image_get_data_double(mse);
01088 cxdouble* flux_npixels = cpl_image_get_data_double(msn);
01089 cxdouble* flux_ypos = cpl_image_get_data_double(msy);
01090
01091
01092
01093
01094
01095
01096
01097 cx_assert(nfibers <= nspectra);
01098
01099 idx = giraffe_fiberlist_query_index(fibers);
01100
01101 cx_assert(cpl_table_has_column(fibers, idx) != 0);
01102
01103 if (mbpx != NULL) {
01104
01105 const cxint* bpx = cpl_image_get_data_int(mbpx);
01106
01107 for (nn = 0; nn < nfibers; nn++) {
01108
01109 register cxint x;
01110 register cxint ns = cpl_table_get_int(fibers, idx, nn, NULL) - 1;
01111
01112
01113 for (x = 0; x < cpl_image_get_size_y(mz) && x < nbins; x++) {
01114
01115 cxint y;
01116 cxint yup, ylo;
01117 cxint lx = x * nspectra + ns;
01118 cxint sx = x * nfibers + nn;
01119
01120 cxdouble ylower = locy[lx] - locw[lx];
01121 cxdouble yupper = locy[lx] + locw[lx];
01122 cxdouble zsum = 0.;
01123 cxdouble ysum = 0.;
01124 cxdouble error2 = 0.;
01125
01126
01127 flux[sx] = 0.;
01128 flux_npixels[sx] = 0.;
01129 flux_error[sx] = 0.;
01130 flux_ypos[sx] = 0.;
01131
01132
01133
01134
01135
01136
01137 if (locw[lx] <= 0.0) {
01138 continue;
01139 }
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149 ylo = (cxint) ceil(ylower);
01150 yup = (cxint) floor(yupper);
01151
01152
01153 if (yup < 0. || ylo - 1 >= ny) {
01154 continue;
01155 }
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169 y = ylo - 1;
01170
01171 if (y >= 0) {
01172
01173 if (!(bpx[x * ny + y] & GIR_M_PIX_SET)) {
01174
01175 cxdouble extcoeff = (cxdouble)ylo - ylower;
01176 cxdouble extcoeff2 = extcoeff * extcoeff;
01177 cxdouble px = CX_MAX(pixels[x * ny + y], 0.);
01178
01179 flux[sx] = pixels[x * ny + y] * extcoeff;
01180 flux_npixels[sx] = extcoeff;
01181 error2 = variances[x * ny + y] * extcoeff2;
01182
01183 zsum = px * extcoeff;
01184 ysum = y * px * extcoeff;
01185
01186 }
01187
01188 }
01189
01190
01191
01192
01193
01194
01195 for (y = CX_MAX(ylo, 0); y < yup && y < ny; y++) {
01196
01197 if (!(bpx[x * ny + y] & GIR_M_PIX_SET)) {
01198
01199 cxdouble px = CX_MAX(pixels[x * ny + y], 0.);
01200
01201 flux[sx] += pixels[x * ny + y];
01202 flux_npixels[sx] += 1.0;
01203 error2 += variances[x * ny + y];
01204
01205 zsum += px;
01206 ysum += y * px;
01207
01208 }
01209
01210 }
01211
01212
01213
01214
01215
01216
01217 y = yup;
01218
01219 if (y < ny) {
01220
01221 if (!(bpx[x * ny + y] & GIR_M_PIX_SET)) {
01222
01223 cxdouble extcoeff = yupper - (cxdouble)yup;
01224 cxdouble extcoeff2 = extcoeff * extcoeff;
01225 cxdouble px = CX_MAX(pixels[x * ny + y], 0.);
01226
01227 flux[sx] += pixels[x * ny + y] * extcoeff;
01228 flux_npixels[sx] += extcoeff;
01229 error2 += variances[x * ny + y] * extcoeff2;
01230
01231 zsum += px * extcoeff;
01232 ysum += y * px * extcoeff;
01233
01234 }
01235
01236 }
01237
01238 flux_error[sx] = sqrt(error2);
01239
01240
01241
01242
01243 if (fabs(ysum) < DBL_EPSILON || fabs(zsum) < DBL_EPSILON) {
01244 flux_ypos[sx] = 0.5 * (yupper + ylower);
01245 }
01246 else {
01247 flux_ypos[sx] = ysum / zsum;
01248 }
01249
01250 }
01251
01252 }
01253
01254 }
01255 else {
01256
01257 for (nn = 0; nn < nfibers; nn++) {
01258
01259 register cxint x;
01260 register cxint ns = cpl_table_get_int(fibers, idx,
01261 nn, NULL) - 1;
01262
01263
01264 for (x = 0; x < cpl_image_get_size_y(mz) && x < nbins; x++) {
01265
01266 cxint y;
01267 cxint yup, ylo;
01268 cxint lx = x * nspectra + ns;
01269 cxint sx = x * nfibers + nn;
01270
01271 cxdouble yupper, ylower;
01272 cxdouble zsum = 0.;
01273 cxdouble ysum = 0.;
01274 cxdouble error2 = 0.;
01275
01276
01277 flux[sx] = 0.;
01278 flux_npixels[sx] = 0.;
01279 flux_error[sx] = 0.;
01280 flux_ypos[sx] = 0.;
01281
01282
01283
01284
01285
01286
01287 if (locw[lx] <= 0.0) {
01288 continue;
01289 }
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299 yupper = locy[lx] + locw[lx];
01300 ylower = locy[lx] - locw[lx];
01301
01302 ylo = (cxint) ceil(ylower);
01303 yup = (cxint) floor(yupper);
01304
01305
01306 if (yup < 0. || ylo - 1 >= ny) {
01307 continue;
01308 }
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322 y = ylo - 1;
01323
01324 if (y >= 0) {
01325
01326 cxdouble extcoeff = (cxdouble)ylo - ylower;
01327 cxdouble extcoeff2 = extcoeff * extcoeff;
01328 cxdouble px = CX_MAX(pixels[x * ny + y], 0.);
01329
01330 flux[sx] = pixels[x * ny + y] * extcoeff;
01331 flux_npixels[sx] = extcoeff;
01332 error2 = variances[x * ny + y] * extcoeff2;
01333
01334 zsum = px * extcoeff;
01335 ysum = y * px * extcoeff;
01336
01337 }
01338
01339
01340
01341
01342
01343
01344 for (y = CX_MAX(ylo, 0); y < yup && y < ny; y++) {
01345
01346 cxdouble px = CX_MAX(pixels[x * ny + y], 0.);
01347
01348 flux[sx] += pixels[x * ny + y];
01349 flux_npixels[sx] += 1.0;
01350 error2 += variances[x * ny + y];
01351
01352 zsum += px;
01353 ysum += y * px;
01354 }
01355
01356
01357
01358
01359
01360
01361 y = yup;
01362
01363 if (y < ny) {
01364
01365 cxdouble extcoeff = yupper - (cxdouble)yup;
01366 cxdouble extcoeff2 = extcoeff * extcoeff;
01367 cxdouble px = CX_MAX(pixels[x * ny + y], 0.);
01368
01369 flux[sx] += pixels[x * ny + y] * extcoeff;
01370 flux_npixels[sx] += extcoeff;
01371 error2 += variances[x * ny + y] * extcoeff2;
01372
01373 zsum += px * extcoeff;
01374 ysum += y * px * extcoeff;
01375
01376 }
01377
01378 flux_error[sx] = sqrt(error2);
01379
01380
01381
01382
01383 if (fabs(ysum) < DBL_EPSILON || fabs(zsum) < DBL_EPSILON) {
01384 flux_ypos[sx] = 0.5 * (yupper + ylower);
01385 }
01386 else {
01387 flux_ypos[sx] = ysum / zsum;
01388 }
01389
01390 }
01391
01392 }
01393
01394 }
01395
01396 return 0;
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
01422 inline static cxint
01423 _giraffe_extract_horne(const cpl_image* mz, const cpl_image* mzvar,
01424 const cpl_table* fibers, const cpl_image* my,
01425 const cpl_image* mw, const GiPsfData* psfdata,
01426 cpl_image* mbpx, cpl_image* ms, cpl_image* mse,
01427 cpl_image* msn, cpl_image* msy,
01428 const GiExtractHorneConfig* config)
01429 {
01430
01431 const cxchar* idx = NULL;
01432
01433 cxint nx = 0;
01434 cxint ny = 0;
01435 cxint fiber = 0;
01436 cxint nfibers = 0;
01437
01438 const cxdouble* locy = NULL;
01439 const cxdouble* locw = NULL;
01440 const cxdouble* width = NULL;
01441 const cxdouble* exponent = NULL;
01442
01443 GiModel* psfmodel = NULL;
01444
01445
01446 cx_assert(mz != NULL);
01447 cx_assert(mzvar != NULL);
01448
01449 cx_assert(fibers != NULL);
01450
01451 cx_assert(my != NULL);
01452 cx_assert(mw != NULL);
01453
01454 cx_assert(psfdata != NULL);
01455
01456 cx_assert(ms != NULL);
01457 cx_assert(mse != NULL);
01458 cx_assert(msn != NULL);
01459 cx_assert(msy != NULL);
01460
01461 cx_assert(config != NULL);
01462
01463 ny = cpl_image_get_size_x(mz);
01464 nx = cpl_image_get_size_y(mz);
01465 nfibers = cpl_table_get_nrow(fibers);
01466
01467 locy = cpl_image_get_data_double_const(my);
01468 locw = cpl_image_get_data_double_const(mw);
01469
01470 cx_assert((ny == cpl_image_get_size_x(mzvar)) &&
01471 (nx == cpl_image_get_size_y(mzvar)));
01472
01473 cx_assert(cpl_image_get_size_x(my) == cpl_image_get_size_x(mw));
01474 cx_assert(cpl_image_get_size_y(my) == cpl_image_get_size_y(mw));
01475
01476 cx_assert(giraffe_psfdata_fibers(psfdata) ==
01477 (cxsize)cpl_image_get_size_x(my));
01478 cx_assert(giraffe_psfdata_bins(psfdata) ==
01479 (cxsize)cpl_image_get_size_y(my));
01480
01481 cx_assert((nfibers == cpl_image_get_size_x(ms)) &&
01482 (nx == cpl_image_get_size_y(ms)));
01483 cx_assert((nfibers == cpl_image_get_size_x(mse)) &&
01484 (nx == cpl_image_get_size_y(mse)));
01485 cx_assert((nfibers == cpl_image_get_size_x(msn)) &&
01486 (nx == cpl_image_get_size_y(msn)));
01487 cx_assert((nfibers == cpl_image_get_size_x(msy)) &&
01488 (nx == cpl_image_get_size_y(msy)));
01489
01490 cx_assert((mbpx == NULL) || ((ny == cpl_image_get_size_x(mbpx)) &&
01491 (nx == cpl_image_get_size_y(mbpx))));
01492
01493
01494
01495
01496
01497
01498
01499 idx = giraffe_fiberlist_query_index(fibers);
01500
01501 cx_assert(cpl_table_has_column(fibers, idx) != 0);
01502
01503
01504
01505
01506
01507
01508
01509 if (giraffe_psfdata_contains(psfdata, "Center") == FALSE) {
01510 return -1;
01511 }
01512
01513 if (giraffe_psfdata_contains(psfdata, "Width2") == TRUE) {
01514 exponent = cpl_image_get_data_const(giraffe_psfdata_get_data(psfdata,
01515 "Width2"));
01516 }
01517
01518 width = cpl_image_get_data_const(giraffe_psfdata_get_data(psfdata,
01519 "Width1"));
01520
01521
01522
01523
01524
01525
01526 psfmodel = giraffe_model_new(giraffe_psfdata_get_model(psfdata));
01527
01528 if (psfmodel == NULL) {
01529 return -2;
01530 }
01531
01532 giraffe_model_set_parameter(psfmodel, "Center", 0.);
01533 giraffe_model_set_parameter(psfmodel, "Amplitude", 1.);
01534 giraffe_model_set_parameter(psfmodel, "Background", 0.);
01535
01536
01537
01538
01539
01540
01541 for (fiber = 0; fiber < nfibers; ++fiber) {
01542
01543 register cxint bin = 0;
01544 register cxint fidx = cpl_table_get_int(fibers, idx, fiber, NULL) - 1;
01545
01546 cxint nbins = CX_MIN(nx, cpl_image_get_size_y(my));
01547
01548 cxdouble* _ms = cpl_image_get_data_double(ms);
01549 cxdouble* _mse = cpl_image_get_data_double(mse);
01550 cxdouble* _msy = cpl_image_get_data_double(msy);
01551 cxdouble* _msn = cpl_image_get_data_double(msn);
01552
01553
01554 for (bin = 0; bin < nbins; bin++) {
01555
01556 register cxint lpos = bin * cpl_image_get_size_x(my) + fidx;
01557 register cxint spos = bin * nfibers + fiber;
01558
01559 cxint status = 0;
01560 cxint vwidth = 0;
01561
01562 register cxdouble lcenter = locy[lpos];
01563 register cxdouble lwidth = locw[lpos];
01564
01565 register cxdouble ylower = lcenter - lwidth;
01566 register cxdouble yupper = lcenter + lwidth;
01567
01568 GiVirtualSlit* vslit = NULL;
01569
01570 GiExtractionData result = {0., 0., 0., 0.};
01571
01572
01573
01574
01575
01576
01577 if ((lwidth <= 0.) || (yupper < 0.) || (ylower > ny)) {
01578 continue;
01579 }
01580
01581
01582
01583
01584
01585 vslit = _giraffe_virtualslit_new(config->ewidth);
01586
01587 vwidth = _giraffe_virtualslit_setup(vslit, bin, lcenter, lwidth,
01588 mz, mzvar, mbpx);
01589
01590 if (vwidth == 0) {
01591 _giraffe_virtualslit_delete(vslit);
01592 vslit = NULL;
01593
01594 continue;
01595 }
01596
01597
01598
01599
01600
01601
01602 giraffe_model_set_parameter(psfmodel, "Width1", width[lpos]);
01603
01604 if (exponent != NULL) {
01605 giraffe_model_set_parameter(psfmodel, "Width2",
01606 exponent[lpos]);
01607 }
01608
01609
01610
01611
01612
01613
01614
01615 status = _giraffe_horne_extract_slit(&result, vslit, psfmodel,
01616 config);
01617
01618 _giraffe_virtualslit_delete(vslit);
01619 vslit = NULL;
01620
01621 if (status < 0) {
01622
01623 giraffe_model_delete(psfmodel);
01624 psfmodel = NULL;
01625
01626 return 1;
01627 }
01628
01629 _ms[spos] = result.value;
01630 _mse[spos] = result.error;
01631 _msy[spos] = result.position;
01632 _msn[spos] = result.npixels;
01633
01634 }
01635
01636 }
01637
01638
01639 giraffe_model_delete(psfmodel);
01640 psfmodel = NULL;
01641
01642 return 0;
01643
01644 }
01645
01646
01647
01648
01649
01650
01651
01652 inline static cxint
01653 _giraffe_optimal_build_profiles(cpl_matrix* profiles,
01654 GiExtractionPsfLimits* limits,
01655 const cpl_image* my, const cpl_image* mw,
01656 const cpl_table* fibers, cxint bin,
01657 GiModel* psf, const cxdouble* width,
01658 const cxdouble* exponent, cxdouble wfactor)
01659 {
01660
01661 const cxchar* idx = giraffe_fiberlist_query_index(fibers);
01662
01663 cxint fiber = 0;
01664 cxint nfibers = cpl_table_get_nrow(fibers);
01665 cxint ny = cpl_matrix_get_ncol(profiles);
01666
01667 const cxdouble* locy = cpl_image_get_data_double_const(my);
01668 const cxdouble* locw = cpl_image_get_data_double_const(mw);
01669
01670 cxdouble* _profiles = cpl_matrix_get_data(profiles);
01671
01672 cxdouble* ypos = NULL;
01673
01674
01675 cx_assert(cpl_table_has_column(fibers, idx) != 0);
01676 cx_assert((limits == NULL) ||
01677 (cpl_matrix_get_nrow(profiles) == limits->size));
01678
01679 ypos = cx_calloc(ny, sizeof(cxdouble));
01680
01681 for (fiber = 0; fiber < nfibers; ++fiber) {
01682
01683 register cxint i = 0;
01684 register cxint y = 0;
01685 register cxint k = 0;
01686
01687 cxint fidx = cpl_table_get_int(fibers, idx, fiber, NULL) - 1;
01688 cxint lpos = bin * cpl_image_get_size_x(my) + fidx;
01689
01690 register cxdouble lcenter = locy[lpos];
01691 register cxdouble lwidth = locw[lpos];
01692
01693 register cxdouble ylower = lcenter - fabs(wfactor) * lwidth;
01694 register cxdouble yupper = lcenter + fabs(wfactor) * lwidth;
01695
01696 register cxint first = (cxint) floor(ylower);
01697 register cxint last = (cxint) ceil(yupper);
01698
01699 register cxint vwidth = 0;
01700
01701 cxdouble norm = 0.;
01702 cxdouble* _mnpsf = NULL;
01703
01704 cpl_matrix* positions = NULL;
01705 cpl_matrix* mnpsf = NULL;
01706
01707
01708
01709
01710
01711
01712 ylower = CX_MAX(0., ylower);
01713 yupper = CX_MIN(ny - 1., yupper);
01714
01715 first = CX_MAX(0, first);
01716 last = CX_MIN(ny - 1, last);
01717
01718 vwidth = last - first + 1;
01719
01720 if (limits != NULL) {
01721 limits->ymin[fiber] = first;
01722 limits->ymax[fiber] = last + 1;
01723 }
01724
01725
01726
01727
01728
01729
01730 giraffe_model_set_parameter(psf, "Width1", width[lpos]);
01731
01732 if (exponent != NULL) {
01733 giraffe_model_set_parameter(psf, "Width2", exponent[lpos]);
01734 }
01735
01736
01737
01738
01739
01740
01741 k = 0;
01742 for (y = first; y <= last; ++y) {
01743 ypos[k] = y - lcenter;
01744 ++k;
01745 }
01746
01747 positions = cpl_matrix_wrap(vwidth, 1, ypos);
01748 mnpsf = _giraffe_compute_psf(psf, positions);
01749
01750 cpl_matrix_unwrap(positions);
01751 positions = NULL;
01752
01753 if (mnpsf == NULL) {
01754 cx_free(ypos);
01755 ypos = NULL;
01756
01757 return 1;
01758 }
01759
01760 _mnpsf = cpl_matrix_get_data(mnpsf);
01761
01762 for (i = 0; i < vwidth; ++i) {
01763 _mnpsf[i] = CX_MAX(_mnpsf[i], 0.);
01764 norm += _mnpsf[i];
01765 }
01766
01767 for (i = 0; i < vwidth; ++i) {
01768 _mnpsf[i] /= norm;
01769 }
01770
01771 k = fiber * ny + first;
01772 for (y = 0; y < vwidth; ++y) {
01773 _profiles[k + y] = _mnpsf[y];
01774 }
01775
01776 cpl_matrix_delete(mnpsf);
01777 mnpsf = NULL;
01778
01779 }
01780
01781 cx_free(ypos);
01782 ypos = NULL;
01783
01784 return 0;
01785
01786 }
01787
01788
01789 inline static cxint
01790 _giraffe_extract_optimal(const cpl_image* mz, const cpl_image* mzvar,
01791 const cpl_table* fibers, const cpl_image* my,
01792 const cpl_image* mw, const GiPsfData* psfdata,
01793 cpl_image* mbpx, cpl_image* ms, cpl_image* mse,
01794 cpl_image* msm, cpl_image* msy,
01795 const GiExtractOptimalConfig* config)
01796 {
01797
01798 const cxbool nolimits = (config->limits == TRUE) ? FALSE : TRUE;
01799
01800 const cxint bkg_nc = config->bkgorder + 1;
01801 const cxint niter = config->clip.iterations;
01802
01803 register cxint i = 0;
01804
01805 cxint nx = 0;
01806 cxint ny = 0;
01807 cxint bin = 0;
01808 cxint nbins = 0;
01809 cxint nfibers = 0;
01810
01811 const cxdouble wfactor = config->ewidth;
01812 const cxdouble sigma = config->clip.level * config->clip.level;
01813 const cxdouble fraction = config->clip.fraction;
01814
01815 const cxdouble* width = NULL;
01816 const cxdouble* exponent = NULL;
01817
01818 cxdouble* _ypos = NULL;
01819 cxdouble* _bkg_base = NULL;
01820 cxdouble* _profiles = NULL;
01821 cxdouble* _signal = NULL;
01822 cxdouble* _variance = NULL;
01823 cxdouble* _mask = NULL;
01824 cxdouble* _weights = NULL;
01825
01826 cpl_matrix* ypos = NULL;
01827 cpl_matrix* bkg_base = NULL;
01828 cpl_matrix* profiles = NULL;
01829 cpl_matrix* weights = NULL;
01830 cpl_matrix* signal = NULL;
01831 cpl_matrix* variance = NULL;
01832 cpl_matrix* mask = NULL;
01833
01834 GiModel* psfmodel = NULL;
01835
01836 GiExtractionPsfLimits* limits = NULL;
01837
01838 GiExtractionSlice* slice = NULL;
01839
01840 GiExtractionWorkspace* workspace;
01841
01842
01843 cx_assert(mz != NULL);
01844 cx_assert(mzvar != NULL);
01845
01846 cx_assert(fibers != NULL);
01847
01848 cx_assert(my != NULL);
01849 cx_assert(mw != NULL);
01850
01851 cx_assert(psfdata != NULL);
01852
01853 cx_assert(ms != NULL);
01854 cx_assert(mse != NULL);
01855 cx_assert(msm != NULL);
01856 cx_assert(msy != NULL);
01857
01858 ny = cpl_image_get_size_x(mz);
01859 nx = cpl_image_get_size_y(mz);
01860
01861 nfibers = cpl_table_get_nrow(fibers);
01862 nbins = CX_MIN(nx, cpl_image_get_size_y(my));
01863
01864 cx_assert((ny == cpl_image_get_size_x(mzvar)) &&
01865 (nx == cpl_image_get_size_y(mzvar)));
01866
01867 cx_assert(cpl_image_get_size_x(my) == cpl_image_get_size_x(mw));
01868 cx_assert(cpl_image_get_size_y(my) == cpl_image_get_size_y(mw));
01869
01870 cx_assert(giraffe_psfdata_fibers(psfdata) ==
01871 (cxsize)cpl_image_get_size_x(my));
01872 cx_assert(giraffe_psfdata_bins(psfdata) ==
01873 (cxsize)cpl_image_get_size_y(my));
01874
01875 cx_assert((nfibers == cpl_image_get_size_x(ms)) &&
01876 (nx == cpl_image_get_size_y(ms)));
01877 cx_assert((nfibers == cpl_image_get_size_x(mse)) &&
01878 (nx == cpl_image_get_size_y(mse)));
01879 cx_assert((nfibers == cpl_image_get_size_x(msy)) &&
01880 (nx == cpl_image_get_size_y(msy)));
01881 cx_assert((ny == cpl_image_get_size_x(msm)) &&
01882 (nx == cpl_image_get_size_y(msm)));
01883
01884 cx_assert((mbpx == NULL) || ((ny == cpl_image_get_size_x(mbpx)) &&
01885 (nx == cpl_image_get_size_y(mbpx))));
01886
01887
01888
01889
01890
01891
01892
01893 if (giraffe_psfdata_contains(psfdata, "Center") == FALSE) {
01894 return -1;
01895 }
01896
01897 if (giraffe_psfdata_contains(psfdata, "Width2") == TRUE) {
01898 exponent = cpl_image_get_data_const(giraffe_psfdata_get_data(psfdata,
01899 "Width2"));
01900 }
01901
01902 width = cpl_image_get_data_const(giraffe_psfdata_get_data(psfdata,
01903 "Width1"));
01904
01905
01906
01907
01908
01909
01910 psfmodel = giraffe_model_new(giraffe_psfdata_get_model(psfdata));
01911
01912 if (psfmodel == NULL) {
01913 return -2;
01914 }
01915
01916 giraffe_model_set_parameter(psfmodel, "Amplitude", 1.);
01917 giraffe_model_set_parameter(psfmodel, "Background", 0.);
01918 giraffe_model_set_parameter(psfmodel, "Center", 0.);
01919
01920
01921
01922
01923
01924
01925 ypos = cpl_matrix_new(ny, 1);
01926
01927 if (ypos == NULL) {
01928 giraffe_model_delete(psfmodel);
01929 psfmodel = NULL;
01930
01931 return -3;
01932 }
01933
01934 _ypos = cpl_matrix_get_data(ypos);
01935
01936 for (i = 0; i < ny; ++i) {
01937 _ypos[i] = i;
01938 }
01939
01940
01941
01942
01943
01944
01945
01946 profiles = cpl_matrix_new(nfibers + bkg_nc, ny);
01947
01948 if (profiles == NULL) {
01949 cpl_matrix_delete(ypos);
01950 ypos = NULL;
01951
01952 giraffe_model_delete(psfmodel);
01953 psfmodel = NULL;
01954
01955 return -3;
01956 }
01957
01958 _profiles = cpl_matrix_get_data(profiles);
01959
01960
01961 signal = cpl_matrix_new(ny, 1);
01962
01963 if (signal == NULL) {
01964 cpl_matrix_delete(profiles);
01965 profiles = NULL;
01966
01967 cpl_matrix_delete(ypos);
01968 ypos = NULL;
01969
01970 giraffe_model_delete(psfmodel);
01971 psfmodel = NULL;
01972
01973 return -3;
01974 }
01975
01976 _signal = cpl_matrix_get_data(signal);
01977
01978
01979 variance = cpl_matrix_new(ny, 1);
01980
01981 if (variance == NULL) {
01982 cpl_matrix_delete(signal);
01983 signal = NULL;
01984
01985 cpl_matrix_delete(profiles);
01986 profiles = NULL;
01987
01988 cpl_matrix_delete(ypos);
01989 ypos = NULL;
01990
01991 giraffe_model_delete(psfmodel);
01992 psfmodel = NULL;
01993
01994 return -3;
01995 }
01996
01997 _variance = cpl_matrix_get_data(variance);
01998
01999
02000 mask = cpl_matrix_new(ny, 1);
02001
02002 if (mask == NULL) {
02003 cpl_matrix_delete(variance);
02004 variance = NULL;
02005
02006 cpl_matrix_delete(signal);
02007 signal = NULL;
02008
02009 cpl_matrix_delete(profiles);
02010 profiles = NULL;
02011
02012 cpl_matrix_delete(ypos);
02013 ypos = NULL;
02014
02015 giraffe_model_delete(psfmodel);
02016 psfmodel = NULL;
02017
02018 return -3;
02019 }
02020
02021 _mask = cpl_matrix_get_data(mask);
02022
02023
02024 weights = cpl_matrix_new(ny, 1);
02025
02026 if (mask == NULL) {
02027 cpl_matrix_delete(mask);
02028 mask = NULL;
02029
02030 cpl_matrix_delete(variance);
02031 variance = NULL;
02032
02033 cpl_matrix_delete(signal);
02034 signal = NULL;
02035
02036 cpl_matrix_delete(profiles);
02037 profiles = NULL;
02038
02039 cpl_matrix_delete(ypos);
02040 ypos = NULL;
02041
02042 giraffe_model_delete(psfmodel);
02043 psfmodel = NULL;
02044
02045 return -3;
02046 }
02047
02048 _weights = cpl_matrix_get_data(weights);
02049
02050
02051
02052
02053
02054
02055
02056 bkg_base = giraffe_chebyshev_base1d(0., ny, bkg_nc, ypos);
02057
02058 cpl_matrix_delete(ypos);
02059 ypos = NULL;
02060
02061 if (bkg_base == NULL) {
02062 cpl_matrix_delete(weights);
02063 weights = NULL;
02064
02065 cpl_matrix_delete(mask);
02066 mask = NULL;
02067
02068 cpl_matrix_delete(variance);
02069 variance = NULL;
02070
02071 cpl_matrix_delete(signal);
02072 signal = NULL;
02073
02074 cpl_matrix_delete(profiles);
02075 profiles = NULL;
02076
02077 cpl_matrix_delete(ypos);
02078 ypos = NULL;
02079
02080 giraffe_model_delete(psfmodel);
02081 psfmodel = NULL;
02082
02083 return -3;
02084 }
02085
02086 _bkg_base = cpl_matrix_get_data(bkg_base);
02087
02088 for (i = 0; i < bkg_nc; ++i) {
02089
02090 register cxint j = 0;
02091 register cxint offset = nfibers * ny;
02092
02093 for (j = 0; j < ny; ++j) {
02094 _profiles[i * ny + j + offset] = _bkg_base[i * ny + j];
02095 }
02096
02097 }
02098
02099 _bkg_base = NULL;
02100
02101 cpl_matrix_delete(bkg_base);
02102 bkg_base = NULL;
02103
02104
02105
02106
02107
02108
02109 slice = _giraffe_extractionslice_new(nfibers, ny, bkg_nc);
02110
02111 if (slice == NULL) {
02112 cpl_matrix_delete(weights);
02113 weights = NULL;
02114
02115 cpl_matrix_delete(mask);
02116 mask = NULL;
02117
02118 cpl_matrix_delete(variance);
02119 variance = NULL;
02120
02121 cpl_matrix_delete(signal);
02122 signal = NULL;
02123
02124 cpl_matrix_delete(profiles);
02125 profiles = NULL;
02126
02127 cpl_matrix_delete(ypos);
02128 ypos = NULL;
02129
02130 giraffe_model_delete(psfmodel);
02131 psfmodel = NULL;
02132
02133 return -3;
02134 }
02135
02136
02137 limits = _giraffe_extraction_psflimits_new(nfibers + bkg_nc);
02138
02139 if (limits == NULL) {
02140
02141 _giraffe_extractionslice_delete(slice);
02142 slice = NULL;
02143
02144 cpl_matrix_delete(weights);
02145 weights = NULL;
02146
02147 cpl_matrix_delete(mask);
02148 mask = NULL;
02149
02150 cpl_matrix_delete(variance);
02151 variance = NULL;
02152
02153 cpl_matrix_delete(signal);
02154 signal = NULL;
02155
02156 cpl_matrix_delete(profiles);
02157 profiles = NULL;
02158
02159 cpl_matrix_delete(ypos);
02160 ypos = NULL;
02161
02162 giraffe_model_delete(psfmodel);
02163 psfmodel = NULL;
02164
02165 return -3;
02166
02167 }
02168
02169 for (i = 0; i < limits->size; ++i) {
02170 limits->ymin[i] = 0;
02171 limits->ymax[i] = ny;
02172 }
02173
02174
02175
02176
02177
02178
02179 workspace = _giraffe_optimal_workspace_new(nfibers + bkg_nc, ny);
02180
02181 for (bin = 0; bin < nbins; ++bin) {
02182
02183 cxbool stop = FALSE;
02184
02185 cxint iter = 0;
02186 cxint nmin = 0;
02187 cxint ngood = ny;
02188
02189 const cxdouble* _my = cpl_image_get_data_double_const(my);
02190 const cxdouble* _mz = cpl_image_get_data_double_const(mz);
02191 const cxdouble* _mzvar = cpl_image_get_data_double_const(mzvar);
02192
02193 cxdouble* _ms = cpl_image_get_data_double(ms);
02194 cxdouble* _mse = cpl_image_get_data_double(mse);
02195 cxdouble* _msy = cpl_image_get_data_double(msy);
02196 cxdouble* _msm = cpl_image_get_data_double(msm);
02197
02198 cxint status = 0;
02199
02200 GiExtractionPsfLimits* _limits = (nolimits == FALSE) ? limits : NULL;
02201
02202 cx_assert(_mz != NULL);
02203 cx_assert(_mzvar != NULL);
02204
02205
02206
02207
02208
02209
02210
02211 status = _giraffe_optimal_build_profiles(profiles, _limits, my, mw,
02212 fibers, bin, psfmodel, width,
02213 exponent, wfactor);
02214
02215 if (status != 0) {
02216 _giraffe_optimal_workspace_delete(workspace);
02217 workspace = NULL;
02218
02219 _giraffe_extraction_psflimits_delete(limits);
02220 limits = NULL;
02221
02222 _giraffe_extractionslice_delete(slice);
02223 slice = NULL;
02224
02225 cpl_matrix_delete(weights);
02226 weights = NULL;
02227
02228 cpl_matrix_delete(mask);
02229 mask = NULL;
02230
02231 cpl_matrix_delete(variance);
02232 variance = NULL;
02233
02234 cpl_matrix_delete(signal);
02235 signal = NULL;
02236
02237 cpl_matrix_delete(profiles);
02238 profiles = NULL;
02239
02240 cpl_matrix_delete(ypos);
02241 ypos = NULL;
02242
02243 giraffe_model_delete(psfmodel);
02244 psfmodel = NULL;
02245
02246 return -4;
02247 }
02248
02249
02250
02251
02252
02253
02254
02255 if (mbpx != NULL) {
02256
02257 const cxint* _mbpx = cpl_image_get_data_int_const(mbpx);
02258
02259
02260 cx_assert(_mbpx != NULL);
02261
02262 for (i = 0; i < ny; ++i) {
02263
02264 cxbool bad = (_mbpx[bin * ny + i] & GIR_M_PIX_SET) ||
02265 (_mz[bin * ny + i] < 0.);
02266
02267 _signal[i] = _mz[bin * ny + i];
02268 _variance[i] = _signal[i] + _mzvar[bin * ny + i];
02269 _mask[i] = 1.;
02270
02271 if (bad == TRUE) {
02272 _mask[i] = 0.;
02273 --ngood;
02274 }
02275
02276 _weights[i] = _mask[i] / _variance[i];
02277
02278 }
02279
02280 }
02281 else {
02282
02283 for (i = 0; i < ny; ++i) {
02284
02285 cxbool bad = (_mz[bin * ny + i] < 0.);
02286
02287 _signal[i] = _mz[bin * ny + i];
02288 _variance[i] = _signal[i] + _mzvar[bin * ny + i];
02289 _mask[i] = 1.;
02290
02291 if (bad == TRUE) {
02292 _mask[i] = 0.;
02293 --ngood;
02294 }
02295
02296 _weights[i] = _mask[i] / _variance[i];
02297
02298 }
02299
02300 }
02301
02302
02303
02304
02305
02306
02307
02308 nmin = (cxint)(fraction * ngood);
02309
02310 while ((iter < niter) && (stop == FALSE)) {
02311
02312 cxint nreject = 0;
02313
02314 const cxdouble* _model = NULL;
02315
02316
02317 status = _giraffe_optimal_extract_slice(slice, profiles,
02318 signal, weights, limits, workspace);
02319
02320 if (status != 0) {
02321 _giraffe_optimal_workspace_delete(workspace);
02322 workspace = NULL;
02323
02324 _giraffe_extraction_psflimits_delete(limits);
02325 limits = NULL;
02326
02327 _giraffe_extractionslice_delete(slice);
02328 slice = NULL;
02329
02330 cpl_matrix_delete(weights);
02331 weights = NULL;
02332
02333 cpl_matrix_delete(mask);
02334 mask = NULL;
02335
02336 cpl_matrix_delete(variance);
02337 variance = NULL;
02338
02339 cpl_matrix_delete(signal);
02340 signal = NULL;
02341
02342 cpl_matrix_delete(profiles);
02343 profiles = NULL;
02344
02345 cpl_matrix_delete(ypos);
02346 ypos = NULL;
02347
02348 giraffe_model_delete(psfmodel);
02349 psfmodel = NULL;
02350
02351 return -5;
02352 }
02353
02354
02355
02356
02357
02358
02359 _model = cpl_matrix_get_data(slice->model);
02360
02361 for (i = 0; i < ny; ++i) {
02362
02363 if (_mask[i] > 0.) {
02364
02365 cxbool bad = FALSE;
02366 cxdouble residual = _signal[i] - _model[i];
02367
02368
02369 _variance[i] = _model[i] + _mzvar[bin * ny + i];
02370
02371 bad = (residual * residual) > (sigma * _variance[i]) ?
02372 TRUE : FALSE;
02373
02374 if (bad == TRUE) {
02375 _mask[i] = 0.;
02376 ++nreject;
02377 --ngood;
02378 }
02379
02380 _weights[i] = _mask[i] / _variance[i];
02381
02382 }
02383
02384 }
02385
02386 if ((nreject == 0) || (ngood <= nmin)) {
02387 stop = TRUE;
02388 }
02389
02390 ++iter;
02391
02392 }
02393
02394
02395
02396
02397
02398
02399
02400 memcpy(&_ms[bin * nfibers], cpl_matrix_get_data(slice->flux),
02401 slice->nflx * sizeof(cxdouble));
02402 memcpy(&_mse[bin * nfibers], cpl_matrix_get_data(slice->variance),
02403 slice->nflx * sizeof(cxdouble));
02404 memcpy(&_msm[bin * ny], cpl_matrix_get_data(slice->model),
02405 slice->msize * sizeof(cxdouble));
02406
02407 memcpy(&_msy[bin * nfibers], &_my[bin * nfibers],
02408 nfibers * sizeof(cxdouble));
02409
02410
02411
02412
02413
02414
02415 cpl_matrix_fill_window(profiles, 0., 0, 0, nfibers, ny);
02416
02417 }
02418
02419
02420
02421
02422
02423
02424 cpl_image_power(mse, 0.5);
02425
02426 _giraffe_optimal_workspace_delete(workspace);
02427 workspace = NULL;
02428
02429 _giraffe_extraction_psflimits_delete(limits);
02430 limits = NULL;
02431
02432 _giraffe_extractionslice_delete(slice);
02433 slice = NULL;
02434
02435 cpl_matrix_delete(weights);
02436 weights = NULL;
02437
02438 cpl_matrix_delete(mask);
02439 mask = NULL;
02440
02441 cpl_matrix_delete(variance);
02442 variance = NULL;
02443
02444 cpl_matrix_delete(signal);
02445 signal = NULL;
02446
02447 cpl_matrix_delete(profiles);
02448 profiles = NULL;
02449
02450 giraffe_model_delete(psfmodel);
02451 psfmodel = NULL;
02452
02453 return 0;
02454
02455 }
02456
02457
02482 cxint
02483 giraffe_extract_spectra(GiExtraction* result, GiImage* image,
02484 GiTable* fibers, GiLocalization* sloc,
02485 GiImage* bpixel, GiImage* slight,
02486 GiExtractConfig* config)
02487 {
02488
02489 const cxchar *fctid = "giraffe_extract_spectra";
02490
02491
02492 cxint ns = 0;
02493 cxint nx = 0;
02494 cxint ny = 0;
02495 cxint status = 0;
02496 cxint nframes = 1;
02497
02498 cxdouble bias_ron = 0.;
02499 cxdouble bias_sigma = 0.;
02500 cxdouble dark_value = 0.;
02501 cxdouble exptime = 0.;
02502 cxdouble conad = 1.;
02503
02504 cpl_propertylist *properties;
02505
02506 cpl_image* _image = NULL;
02507 cpl_image* _locy = NULL;
02508 cpl_image* _locw = NULL;
02509 cpl_image* _spectra = NULL;
02510 cpl_image* _error = NULL;
02511 cpl_image* _npixels = NULL;
02512 cpl_image* _centroid = NULL;
02513 cpl_image* _model = NULL;
02514
02515 cpl_table* _fibers = NULL;
02516
02517
02518
02519
02520
02521
02522 if (!result || !image || !fibers || !sloc || !config) {
02523 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
02524 return 1;
02525 }
02526
02527
02528 if ((sloc->locy == NULL) || (sloc->locw == NULL)) {
02529 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
02530 return 1;
02531 }
02532
02533
02534 if (result->spectra != NULL || result->error != NULL ||
02535 result->npixels != NULL || result->centroid != NULL ||
02536 result->model != NULL) {
02537 gi_warning("%s: Results structure at %p is not empty! Contents "
02538 "might be lost.", fctid, result);
02539 }
02540
02541
02542 _fibers = giraffe_table_get(fibers);
02543
02544 if (_fibers == NULL) {
02545 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
02546 return 1;
02547 }
02548
02549
02550 if ((config->emethod == GIEXTRACT_OPTIMAL) && (sloc->psf == NULL)) {
02551 cpl_msg_error(fctid, "Missing data: PSF profile data is required "
02552 "for optimal spectrum extraction!");
02553 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
02554
02555 return 1;
02556 }
02557
02558
02559 properties = giraffe_image_get_properties(image);
02560
02561 if (properties == NULL) {
02562 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
02563 return 1;
02564 }
02565
02566
02567 if (!cpl_propertylist_has(properties, GIALIAS_CONAD)) {
02568 cpl_msg_error(fctid, "Missing detector gain property (%s)! ",
02569 GIALIAS_CONAD);
02570 return 1;
02571 }
02572 else {
02573 conad = cpl_propertylist_get_double(properties, GIALIAS_CONAD);
02574 }
02575
02576
02577 if (!cpl_propertylist_has(properties, GIALIAS_BIASERROR)) {
02578 cpl_msg_warning(fctid, "Missing bias error property (%s)! Setting "
02579 "bias error to 0.", GIALIAS_BIASERROR);
02580 bias_sigma = 0.;
02581 }
02582 else {
02583 bias_sigma = cpl_propertylist_get_double(properties, GIALIAS_BIASERROR);
02584 }
02585
02586
02587 if (config->ron > 0.) {
02588
02589 cpl_msg_info(fctid, "Setting bias RMS property (%s) to %.4g ADU",
02590 GIALIAS_BIASSIGMA, config->ron);
02591
02592 cpl_propertylist_update_double(properties, GIALIAS_BIASSIGMA,
02593 config->ron);
02594 }
02595
02596 bias_ron = giraffe_propertylist_get_ron(properties);
02597
02598
02599 if (!cpl_propertylist_has(properties, GIALIAS_DARKVALUE)) {
02600
02601 dark_value = 0.;
02602
02603 cpl_msg_warning(fctid, "Missing dark value property (%s), will be "
02604 "set to 0.!", GIALIAS_DARKVALUE);
02605 cpl_propertylist_append_double(properties, GIALIAS_DARKVALUE,
02606 dark_value);
02607
02608 }
02609 else {
02610 dark_value = cpl_propertylist_get_double(properties,
02611 GIALIAS_DARKVALUE);
02612 }
02613
02614
02615 if (!cpl_propertylist_has(properties, GIALIAS_EXPTIME)) {
02616 cpl_msg_error(fctid, "Missing exposure time property (%s)!",
02617 GIALIAS_EXPTIME);
02618 return 1;
02619 }
02620 else {
02621 exptime = cpl_propertylist_get_double(properties, GIALIAS_EXPTIME);
02622 }
02623
02624
02625 if (cpl_propertylist_has(properties, GIALIAS_DATANCOM)) {
02626 nframes = cpl_propertylist_get_int(properties, GIALIAS_DATANCOM);
02627 }
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638 bias_sigma *= conad;
02639 dark_value *= conad;
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653 _image = cpl_image_multiply_scalar_create(giraffe_image_get(image),
02654 nframes * conad);
02655
02656 _locy = giraffe_image_get(sloc->locy);
02657 _locw = giraffe_image_get(sloc->locw);
02658
02659 ny = cpl_image_get_size_x(_image);
02660 nx = cpl_image_get_size_y(_locw);
02661 ns = cpl_table_get_nrow(_fibers);
02662
02663
02664 switch (config->emethod) {
02665 case GIEXTRACT_SUM:
02666 {
02667
02668 cxint xsize = cpl_image_get_size_x(_image);
02669 cxint ysize = cpl_image_get_size_y(_image);
02670
02671 cxdouble ron_variance = bias_ron * bias_ron;
02672 cxdouble bias_variance = bias_sigma * bias_sigma;
02673 cxdouble dark_variance = dark_value * exptime;
02674
02675 cpl_image* bpixmap = NULL;
02676 cpl_image* variance = NULL;
02677
02678
02679 result->spectra = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02680 result->error = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02681 result->npixels = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02682 result->centroid = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02683 result->model = NULL;
02684
02685 _spectra = giraffe_image_get(result->spectra);
02686 _error = giraffe_image_get(result->error);
02687 _npixels = giraffe_image_get(result->npixels);
02688 _centroid = giraffe_image_get(result->centroid);
02689
02690 if (bpixel != NULL) {
02691
02692 bpixmap = giraffe_image_get(bpixel);
02693
02694 if (cpl_image_get_size_x(bpixmap) != xsize ||
02695 cpl_image_get_size_y(bpixmap) != ysize) {
02696
02697 cxbool crop = FALSE;
02698
02699 cpl_propertylist *p =
02700 giraffe_image_get_properties(bpixel);
02701
02702 GiWindow w = {1, 1, 0, 0};
02703
02704
02705 w.x1 = cpl_image_get_size_x(bpixmap);
02706 w.y1 = cpl_image_get_size_y(bpixmap);
02707
02708 if (cpl_propertylist_has(p, GIALIAS_PRSCX)) {
02709 w.x0 += cpl_propertylist_get_int(p, GIALIAS_PRSCX);
02710 crop = TRUE;
02711 }
02712
02713 if (cpl_propertylist_has(p, GIALIAS_OVSCX)) {
02714 w.x1 -= cpl_propertylist_get_int(p, GIALIAS_OVSCX);
02715 crop = TRUE;
02716 }
02717
02718 if (cpl_propertylist_has(p, GIALIAS_PRSCY)) {
02719 w.y0 += cpl_propertylist_get_int(p, GIALIAS_PRSCY);
02720 crop = TRUE;
02721 }
02722
02723 if (cpl_propertylist_has(p, GIALIAS_OVSCY)) {
02724 w.y1 -= cpl_propertylist_get_int(p, GIALIAS_OVSCY);
02725 crop = TRUE;
02726 }
02727
02728 if ((w.x1 - w.x0 + 1) != xsize ||
02729 (w.y1 - w.y0 + 1) != ysize) {
02730 cpl_msg_error(fctid, "Invalid bad pixel map! Image "
02731 "sizes do not match!");
02732
02733 giraffe_image_delete(result->spectra);
02734 result->spectra = NULL;
02735
02736 giraffe_image_delete(result->error);
02737 result->error = NULL;
02738
02739 giraffe_image_delete(result->npixels);
02740 result->npixels = NULL;
02741
02742 giraffe_image_delete(result->centroid);
02743 result->centroid = NULL;
02744
02745 giraffe_image_delete(result->model);
02746 result->model = NULL;
02747
02748 cpl_image_delete(_image);
02749 _image = NULL;
02750
02751 return 1;
02752 }
02753
02754 if (crop == TRUE) {
02755 bpixmap = cpl_image_extract(bpixmap, w.x0, w.y0,
02756 w.x1, w.y1);
02757 }
02758
02759 }
02760
02761 }
02762
02763 if (slight != NULL) {
02764 cpl_msg_warning(fctid, "Scattered light model will be "
02765 "ignored for extraction method `SUM'");
02766 }
02767
02768 variance = cpl_image_abs_create(_image);
02769
02770
02771
02772
02773
02774
02775
02776 cpl_image_add_scalar(variance, nframes * (ron_variance + nframes *
02777 (bias_variance + dark_variance)));
02778
02779 status = _giraffe_extract_summation(_image, variance, _fibers,
02780 _locy, _locw, bpixmap,
02781 _spectra, _error, _npixels,
02782 _centroid);
02783
02784 cpl_image_delete(variance);
02785 if (bpixmap != giraffe_image_get(bpixel)) {
02786 cpl_image_delete(bpixmap);
02787 }
02788 bpixmap = NULL;
02789
02790 break;
02791
02792 }
02793
02794 case GIEXTRACT_OPTIMAL:
02795 {
02796
02797 cxint xsize = cpl_image_get_size_x(_image);
02798 cxint ysize = cpl_image_get_size_y(_image);
02799
02800 cxdouble v0 = 0.;
02801 cxdouble ron_variance = bias_ron * bias_ron;
02802 cxdouble bias_variance = bias_sigma * bias_sigma;
02803 cxdouble dark_variance = dark_value * exptime;
02804
02805 cpl_image* variance = NULL;
02806 cpl_image* bpixmap = NULL;
02807
02808 GiExtractOptimalConfig setup;
02809
02810
02811 result->spectra = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02812 result->error = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02813 result->npixels = NULL;
02814 result->model = giraffe_image_create(CPL_TYPE_DOUBLE, ny, nx);
02815 result->centroid = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02816
02817 _spectra = giraffe_image_get(result->spectra);
02818 _error = giraffe_image_get(result->error);
02819 _model = giraffe_image_get(result->model);
02820 _centroid = giraffe_image_get(result->centroid);
02821
02822 setup.clip.iterations = config->psf.iterations;
02823 setup.clip.level = config->psf.sigma;
02824 setup.clip.fraction = config->optimal.fraction;
02825 setup.limits = config->optimal.wfactor < 0. ? FALSE : TRUE;
02826 setup.ewidth = CX_MAX(1., fabs(config->optimal.wfactor));
02827 setup.bkgorder = config->optimal.bkgorder;
02828 setup.exptime = exptime;
02829 setup.ron = bias_sigma;
02830 setup.dark = dark_value;
02831
02832
02833 if (bpixel != NULL) {
02834
02835 bpixmap = giraffe_image_get(bpixel);
02836
02837 if (cpl_image_get_size_x(bpixmap) != xsize ||
02838 cpl_image_get_size_y(bpixmap) != ysize) {
02839
02840 cxbool crop = FALSE;
02841
02842 cpl_propertylist *p =
02843 giraffe_image_get_properties(bpixel);
02844
02845 GiWindow w = {1, 1, 0, 0};
02846
02847
02848 w.x1 = cpl_image_get_size_x(bpixmap);
02849 w.y1 = cpl_image_get_size_y(bpixmap);
02850
02851 if (cpl_propertylist_has(p, GIALIAS_PRSCX)) {
02852 w.x0 += cpl_propertylist_get_int(p, GIALIAS_PRSCX);
02853 crop = TRUE;
02854 }
02855
02856 if (cpl_propertylist_has(p, GIALIAS_OVSCX)) {
02857 w.x1 -= cpl_propertylist_get_int(p, GIALIAS_OVSCX);
02858 crop = TRUE;
02859 }
02860
02861 if (cpl_propertylist_has(p, GIALIAS_PRSCY)) {
02862 w.y0 += cpl_propertylist_get_int(p, GIALIAS_PRSCY);
02863 crop = TRUE;
02864 }
02865
02866 if (cpl_propertylist_has(p, GIALIAS_OVSCY)) {
02867 w.y1 -= cpl_propertylist_get_int(p, GIALIAS_OVSCY);
02868 crop = TRUE;
02869 }
02870
02871 if ((w.x1 - w.x0 + 1) != xsize ||
02872 (w.y1 - w.y0 + 1) != ysize) {
02873
02874 cpl_msg_error(fctid, "Invalid bad pixel map! "
02875 "Image sizes do not match!");
02876
02877 giraffe_image_delete(result->spectra);
02878 result->spectra = NULL;
02879
02880 giraffe_image_delete(result->error);
02881 result->error = NULL;
02882
02883 giraffe_image_delete(result->npixels);
02884 result->npixels = NULL;
02885
02886 giraffe_image_delete(result->centroid);
02887 result->centroid = NULL;
02888
02889 giraffe_image_delete(result->model);
02890 result->model = NULL;
02891
02892 cpl_image_delete(_image);
02893 _image = NULL;
02894
02895 return 1;
02896
02897 }
02898
02899 if (crop == TRUE) {
02900 bpixmap = cpl_image_extract(bpixmap, w.x0, w.y0,
02901 w.x1, w.y1);
02902 }
02903
02904 }
02905
02906 }
02907
02908 variance = cpl_image_new(xsize, ysize, CPL_TYPE_DOUBLE);
02909
02910
02911
02912
02913
02914
02915
02916 v0 = nframes * (ron_variance + nframes *
02917 (bias_variance + dark_variance));
02918
02919
02920
02921
02922
02923
02924
02925
02926 if (slight != NULL) {
02927
02928 register cxsize i = 0;
02929 register cxsize npixels = xsize * ysize;
02930
02931 const cxdouble* _slight =
02932 cpl_image_get_data_double(giraffe_image_get(slight));
02933
02934 cxdouble* _variance = cpl_image_get_data_double(variance);
02935
02936 for (i = 0; i < npixels; i++) {
02937 _variance[i] = v0 + fabs(_slight[i]) * conad * nframes;
02938 }
02939
02940 }
02941 else {
02942
02943 register cxsize i = 0;
02944 register cxsize npixels = xsize * ysize;
02945
02946 cxdouble* _variance = cpl_image_get_data_double(variance);
02947
02948 for (i = 0; i < npixels; i++) {
02949 _variance[i] = v0;
02950 }
02951
02952 }
02953
02954
02955 status = _giraffe_extract_optimal(_image, variance, _fibers,
02956 _locy, _locw, sloc->psf,
02957 bpixmap, _spectra, _error,
02958 _model, _centroid, &setup);
02959
02960 cpl_image_delete(variance);
02961 variance = NULL;
02962
02963 if (bpixmap != giraffe_image_get(bpixel)) {
02964 cpl_image_delete(bpixmap);
02965 }
02966 bpixmap = NULL;
02967
02968 break;
02969
02970 }
02971
02972 case GIEXTRACT_HORNE:
02973 {
02974
02975 cxint xsize = cpl_image_get_size_x(_image);
02976 cxint ysize = cpl_image_get_size_y(_image);
02977
02978 cxdouble v0 = 0.;
02979 cxdouble ron_variance = bias_ron * bias_ron;
02980 cxdouble bias_variance = bias_sigma * bias_sigma;
02981 cxdouble dark_variance = dark_value * exptime;
02982
02983 cpl_image* variance = NULL;
02984 cpl_image* bpixmap = NULL;
02985
02986 GiExtractHorneConfig setup;
02987
02988
02989 result->spectra = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02990 result->error = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02991 result->npixels = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02992 result->centroid = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02993 result->model = NULL;
02994
02995 _spectra = giraffe_image_get(result->spectra);
02996 _error = giraffe_image_get(result->error);
02997 _npixels = giraffe_image_get(result->npixels);
02998 _centroid = giraffe_image_get(result->centroid);
02999
03000 setup.clip.iterations = config->psf.iterations;
03001 setup.clip.level = config->psf.sigma;
03002 setup.clip.fraction = config->horne.mingood;
03003 setup.ewidth = config->horne.ewidth;
03004 setup.exptime = exptime;
03005 setup.ron = bias_sigma;
03006 setup.dark = dark_value;
03007
03008 if (bpixel != NULL) {
03009
03010 bpixmap = giraffe_image_get(bpixel);
03011
03012 if (cpl_image_get_size_x(bpixmap) != xsize ||
03013 cpl_image_get_size_y(bpixmap) != ysize) {
03014
03015 cxbool crop = FALSE;
03016
03017 cpl_propertylist *p =
03018 giraffe_image_get_properties(bpixel);
03019
03020 GiWindow w = {1, 1, 0, 0};
03021
03022
03023 w.x1 = cpl_image_get_size_x(bpixmap);
03024 w.y1 = cpl_image_get_size_y(bpixmap);
03025
03026 if (cpl_propertylist_has(p, GIALIAS_PRSCX)) {
03027 w.x0 += cpl_propertylist_get_int(p, GIALIAS_PRSCX);
03028 crop = TRUE;
03029 }
03030
03031 if (cpl_propertylist_has(p, GIALIAS_OVSCX)) {
03032 w.x1 -= cpl_propertylist_get_int(p, GIALIAS_OVSCX);
03033 crop = TRUE;
03034 }
03035
03036 if (cpl_propertylist_has(p, GIALIAS_PRSCY)) {
03037 w.y0 += cpl_propertylist_get_int(p, GIALIAS_PRSCY);
03038 crop = TRUE;
03039 }
03040
03041 if (cpl_propertylist_has(p, GIALIAS_OVSCY)) {
03042 w.y1 -= cpl_propertylist_get_int(p, GIALIAS_OVSCY);
03043 crop = TRUE;
03044 }
03045
03046 if ((w.x1 - w.x0 + 1) != xsize ||
03047 (w.y1 - w.y0 + 1) != ysize) {
03048
03049 cpl_msg_error(fctid, "Invalid bad pixel map! "
03050 "Image sizes do not match!");
03051
03052 giraffe_image_delete(result->spectra);
03053 result->spectra = NULL;
03054
03055 giraffe_image_delete(result->error);
03056 result->error = NULL;
03057
03058 giraffe_image_delete(result->npixels);
03059 result->npixels = NULL;
03060
03061 giraffe_image_delete(result->centroid);
03062 result->centroid = NULL;
03063
03064 giraffe_image_delete(result->model);
03065 result->model = NULL;
03066
03067 cpl_image_delete(_image);
03068 _image = NULL;
03069
03070 return 1;
03071
03072 }
03073
03074 if (crop == TRUE) {
03075 bpixmap = cpl_image_extract(bpixmap, w.x0, w.y0,
03076 w.x1, w.y1);
03077 }
03078
03079 }
03080
03081 }
03082
03083 variance = cpl_image_new(xsize, ysize, CPL_TYPE_DOUBLE);
03084
03085
03086
03087
03088
03089
03090
03091 v0 = nframes * (ron_variance + nframes *
03092 (bias_variance + dark_variance));
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102 if (slight != NULL) {
03103
03104 register cxsize i = 0;
03105 register cxsize npixels = xsize * ysize;
03106
03107 const cxdouble* _slight =
03108 cpl_image_get_data_double(giraffe_image_get(slight));
03109
03110 cxdouble* _variance = cpl_image_get_data_double(variance);
03111
03112 for (i = 0; i < npixels; i++) {
03113 _variance[i] = v0 + fabs(_slight[i]) * nframes * conad;
03114 }
03115
03116 }
03117 else {
03118
03119 register cxsize i = 0;
03120 register cxsize npixels = xsize * ysize;
03121
03122 cxdouble* _variance = cpl_image_get_data_double(variance);
03123
03124 for (i = 0; i < npixels; i++) {
03125 _variance[i] = v0;
03126 }
03127
03128 }
03129
03130
03131 status = _giraffe_extract_horne(_image, variance, _fibers,
03132 _locy, _locw, sloc->psf,
03133 bpixmap, _spectra, _error,
03134 _npixels, _centroid, &setup);
03135
03136 cpl_image_delete(variance);
03137 variance = NULL;
03138
03139 if (bpixmap != giraffe_image_get(bpixel)) {
03140 cpl_image_delete(bpixmap);
03141 }
03142 bpixmap = NULL;
03143
03144 break;
03145
03146 }
03147
03148 default:
03149 gi_message("%s: Method %d selected for spectrum extraction.",
03150 fctid, config->emethod);
03151 cpl_msg_error(fctid, "Invalid extraction method!");
03152
03153 status = 1;
03154 break;
03155 }
03156
03157 cpl_image_delete(_image);
03158 _image = NULL;
03159
03160 if (status) {
03161
03162 giraffe_image_delete(result->spectra);
03163 result->spectra = NULL;
03164
03165 giraffe_image_delete(result->error);
03166 result->error = NULL;
03167
03168 giraffe_image_delete(result->npixels);
03169 result->npixels = NULL;
03170
03171 giraffe_image_delete(result->centroid);
03172 result->centroid = NULL;
03173
03174 giraffe_image_delete(result->model);
03175 result->model = NULL;
03176
03177 cpl_msg_error(fctid, "Spectrum extraction (method %d) failed!",
03178 config->emethod);
03179
03180 cpl_image_delete(_image);
03181 _image = NULL;
03182
03183 return 1;
03184
03185 }
03186
03187
03188
03189
03190
03191
03192
03193
03194
03195
03196
03197
03198 if (result->spectra) {
03199 cpl_image_divide_scalar(giraffe_image_get(result->spectra),
03200 nframes * conad);
03201 }
03202
03203 if (result->model) {
03204 cpl_image_divide_scalar(giraffe_image_get(result->model),
03205 nframes * conad);
03206 }
03207
03208 if (result->error) {
03209 cpl_image_divide_scalar(giraffe_image_get(result->error),
03210 nframes * conad);
03211 }
03212
03213
03214
03215
03216
03217
03218 properties = giraffe_image_get_properties(image);
03219 giraffe_image_set_properties(result->spectra, properties);
03220
03221 properties = giraffe_image_get_properties(result->spectra);
03222
03223
03224
03225
03226
03227
03228
03229 giraffe_propertylist_update(properties,
03230 giraffe_image_get_properties(sloc->locy),
03231 "^ESO PRO LOC.*");
03232
03233 cpl_propertylist_set_int(properties, GIALIAS_NAXIS1,
03234 cpl_image_get_size_x(_spectra));
03235 cpl_propertylist_set_int(properties, GIALIAS_NAXIS2,
03236 cpl_image_get_size_y(_spectra));
03237
03238 cpl_propertylist_set_int(properties, GIALIAS_BITPIX, -32);
03239 cpl_propertylist_set_double(properties, GIALIAS_BZERO, 0.);
03240 cpl_propertylist_set_double(properties, GIALIAS_BSCALE, 1.);
03241
03242 cpl_propertylist_update_int(properties, GIALIAS_NFIBERS,
03243 cpl_image_get_size_x(_spectra));
03244
03245 cpl_propertylist_append_int(properties, GIALIAS_EXT_NX,
03246 cpl_image_get_size_y(_spectra));
03247 cpl_propertylist_append_int(properties, GIALIAS_EXT_NS,
03248 cpl_image_get_size_x(_spectra));
03249
03250 switch (config->emethod) {
03251 case GIEXTRACT_SUM:
03252 cpl_propertylist_append_string(properties, GIALIAS_EXT_METHOD,
03253 "SUM");
03254 cpl_propertylist_set_comment(properties, GIALIAS_EXT_METHOD,
03255 "Spectrum extraction method");
03256 break;
03257
03258 case GIEXTRACT_HORNE:
03259 {
03260
03261 cpl_propertylist_append_string(properties, GIALIAS_EXT_METHOD,
03262 "HORNE");
03263 cpl_propertylist_set_comment(properties, GIALIAS_EXT_METHOD,
03264 "Spectrum extraction method");
03265
03266 cpl_propertylist_append_string(properties, GIALIAS_EXTPSF_MODEL,
03267 config->psf.model);
03268 cpl_propertylist_set_comment(properties, GIALIAS_EXTPSF_MODEL,
03269 "PSF model used");
03270 cpl_propertylist_append_double(properties, GIALIAS_EXTPSF_SIGMA,
03271 config->psf.sigma);
03272 cpl_propertylist_set_comment(properties, GIALIAS_EXTPSF_SIGMA,
03273 "PSF fit sigma clipping threshold");
03274 cpl_propertylist_append_int(properties, GIALIAS_EXTPSF_NITER,
03275 config->psf.iterations);
03276 cpl_propertylist_set_comment(properties, GIALIAS_EXTPSF_NITER,
03277 "PSF fit maximum number of "
03278 "iterations");
03279
03280 cpl_propertylist_append_int(properties, GIALIAS_EXTHRN_EWIDTH,
03281 config->horne.ewidth);
03282 cpl_propertylist_set_comment(properties, GIALIAS_EXTHRN_EWIDTH,
03283 "Number of extra pixels used");
03284 cpl_propertylist_append_int(properties, GIALIAS_EXTHRN_MINGOOD,
03285 config->horne.mingood);
03286 cpl_propertylist_set_comment(properties, GIALIAS_EXTHRN_MINGOOD,
03287 "Minimum number of pixels to keep");
03288
03289
03290 break;
03291 }
03292
03293 case GIEXTRACT_OPTIMAL:
03294 cpl_propertylist_append_string(properties, GIALIAS_EXT_METHOD,
03295 "OPTIMAL");
03296 cpl_propertylist_set_comment(properties, GIALIAS_EXT_METHOD,
03297 "Spectrum extraction method");
03298
03299 cpl_propertylist_append_string(properties, GIALIAS_EXTPSF_MODEL,
03300 config->psf.model);
03301 cpl_propertylist_set_comment(properties, GIALIAS_EXTPSF_MODEL,
03302 "PSF model used");
03303 cpl_propertylist_append_double(properties, GIALIAS_EXTPSF_SIGMA,
03304 config->psf.sigma);
03305 cpl_propertylist_set_comment(properties, GIALIAS_EXTPSF_SIGMA,
03306 "PSF fit sigma clipping threshold");
03307 cpl_propertylist_append_int(properties, GIALIAS_EXTPSF_NITER,
03308 config->psf.iterations);
03309 cpl_propertylist_set_comment(properties, GIALIAS_EXTPSF_NITER,
03310 "PSF fit maximum number of "
03311 "iterations");
03312
03313 cpl_propertylist_append_double(properties, GIALIAS_EXTOPT_FRACTION,
03314 config->optimal.fraction);
03315 cpl_propertylist_set_comment(properties, GIALIAS_EXTOPT_FRACTION,
03316 "Minimum fraction of pixels used.");
03317 cpl_propertylist_append_double(properties, GIALIAS_EXTOPT_WFACTOR,
03318 config->optimal.wfactor);
03319 cpl_propertylist_set_comment(properties, GIALIAS_EXTOPT_WFACTOR,
03320 "Multiple of the fiber PSF half "
03321 "width used for spectrum "
03322 "extraction.");
03323 cpl_propertylist_append_int(properties, GIALIAS_EXTOPT_BGORDER,
03324 config->optimal.bkgorder);
03325 cpl_propertylist_set_comment(properties, GIALIAS_EXTOPT_BGORDER,
03326 "Order of the background polynomial "
03327 "model along the spatial direction.");
03328
03329 break;
03330
03331 default:
03332 break;
03333 }
03334
03335 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE, "EXTSP");
03336 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03337 "Extracted spectra");
03338
03339
03340
03341
03342
03343
03344 giraffe_image_set_properties(result->error, properties);
03345 properties = giraffe_image_get_properties(result->error);
03346
03347 cpl_propertylist_set_string(properties, GIALIAS_GIRFTYPE, "EXTERRS");
03348 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03349 "Extracted spectra errors");
03350
03351
03352
03353
03354
03355
03356 giraffe_image_set_properties(result->centroid, properties);
03357 properties = giraffe_image_get_properties(result->centroid);
03358
03359 cpl_propertylist_set_string(properties, GIALIAS_GIRFTYPE, "EXTYCEN");
03360 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03361 "Extracted spectra centroids");
03362
03363
03364
03365
03366
03367
03368 if (result->npixels != NULL) {
03369 giraffe_image_set_properties(result->npixels, properties);
03370 properties = giraffe_image_get_properties(result->npixels);
03371
03372 cpl_propertylist_set_string(properties, GIALIAS_GIRFTYPE, "EXTNPIX");
03373 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03374 "Extracted spectra npixels");
03375 }
03376
03377
03378
03379
03380
03381
03382 if (result->model != NULL) {
03383 giraffe_image_set_properties(result->model, properties);
03384 properties = giraffe_image_get_properties(result->model);
03385
03386 cpl_propertylist_set_string(properties, GIALIAS_GIRFTYPE, "EXTMODEL");
03387 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03388 "Model spectra used for extraction");
03389 }
03390
03391 return 0;
03392
03393 }
03394
03395
03406 GiExtractConfig*
03407 giraffe_extract_config_create(cpl_parameterlist* list)
03408 {
03409
03410 const cxchar* s;
03411 cpl_parameter* p;
03412
03413 GiExtractConfig* config = NULL;
03414
03415
03416 if (!list) {
03417 return NULL;
03418 }
03419
03420 config = cx_calloc(1, sizeof *config);
03421
03422 p = cpl_parameterlist_find(list, "giraffe.extraction.method");
03423 s = cpl_parameter_get_string(p);
03424 if (!strcmp(s, "OPTIMAL")) {
03425 config->emethod = GIEXTRACT_OPTIMAL;
03426 }
03427 else if (!strcmp(s, "HORNE")) {
03428 config->emethod = GIEXTRACT_HORNE;
03429 }
03430 else {
03431 config->emethod = GIEXTRACT_SUM;
03432 }
03433
03434 p = cpl_parameterlist_find(list, "giraffe.extraction.ron");
03435 config->ron = cpl_parameter_get_double(p);
03436
03437 p = cpl_parameterlist_find(list, "giraffe.extraction.psf.model");
03438 config->psf.model = cx_strdup(cpl_parameter_get_string(p));
03439
03440 p = cpl_parameterlist_find(list, "giraffe.extraction.psf.sigma");
03441 config->psf.sigma = cpl_parameter_get_double(p);
03442
03443 p = cpl_parameterlist_find(list, "giraffe.extraction.psf.iterations");
03444 config->psf.iterations = cpl_parameter_get_int(p);
03445
03446
03447 p = cpl_parameterlist_find(list, "giraffe.extraction.horne.extrawidth");
03448 config->horne.ewidth = cpl_parameter_get_int(p);
03449
03450 p = cpl_parameterlist_find(list, "giraffe.extraction.horne.mingood");
03451 config->horne.mingood = cpl_parameter_get_double(p);
03452
03453
03454 p = cpl_parameterlist_find(list, "giraffe.extraction.optimal.fraction");
03455 config->optimal.fraction = cpl_parameter_get_double(p);
03456
03457 p = cpl_parameterlist_find(list, "giraffe.extraction.optimal.wfactor");
03458 config->optimal.wfactor = cpl_parameter_get_double(p);
03459
03460 p = cpl_parameterlist_find(list, "giraffe.extraction.optimal.bkgorder");
03461 config->optimal.bkgorder = cpl_parameter_get_int(p);
03462
03463 return config;
03464
03465 }
03466
03467
03480 void
03481 giraffe_extract_config_destroy(GiExtractConfig* config)
03482 {
03483
03484 if (config) {
03485
03486 if (config->psf.model) {
03487 cx_free(config->psf.model);
03488 }
03489
03490 cx_free(config);
03491
03492 }
03493
03494 return;
03495
03496 }
03497
03498
03510 void
03511 giraffe_extract_config_add(cpl_parameterlist* list)
03512 {
03513
03514 cpl_parameter* p = NULL;
03515
03516
03517 if (list == NULL) {
03518 return;
03519 }
03520
03521 p = cpl_parameter_new_enum("giraffe.extraction.method",
03522 CPL_TYPE_STRING,
03523 "Extraction method: 'SUM', 'HORNE' or "
03524 "'OPTIMAL'",
03525 "giraffe.extraction",
03526 "SUM", 3, "SUM", "OPTIMAL", "HORNE");
03527 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-method");
03528 cpl_parameterlist_append(list, p);
03529
03530
03531 p = cpl_parameter_new_value("giraffe.extraction.ron",
03532 CPL_TYPE_DOUBLE,
03533 "New bias sigma (RON) value for "
03534 "bias and dark "
03535 "corrected image",
03536 "giraffe.extraction",
03537 -1.);
03538 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-ron");
03539 cpl_parameterlist_append(list, p);
03540
03541
03542 p = cpl_parameter_new_enum("giraffe.extraction.psf.model",
03543 CPL_TYPE_STRING,
03544 "PSF profile model: `psfexp', `psfexp2'",
03545 "giraffe.extraction.psf",
03546 "psfexp2", 2, "psfexp", "psfexp2");
03547 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-psfmodel");
03548 cpl_parameterlist_append(list, p);
03549
03550
03551 p = cpl_parameter_new_value("giraffe.extraction.psf.sigma",
03552 CPL_TYPE_DOUBLE,
03553 "Sigma clippging threshold used for "
03554 "rejecting data points during PSF fitting "
03555 "(Horne's sigma). It is used to reject bad "
03556 "pixels and cosmics.",
03557 "giraffe.extraction.psf",
03558 7.);
03559 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-psfsigma");
03560 cpl_parameterlist_append(list, p);
03561
03562
03563 p = cpl_parameter_new_value("giraffe.extraction.psf.iterations",
03564 CPL_TYPE_INT,
03565 "Maximum number of iterations used for "
03566 "fitting the PSF profile.",
03567 "giraffe.extraction.psf",
03568 2);
03569 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-psfniter");
03570 cpl_parameterlist_append(list, p);
03571
03572
03573 p = cpl_parameter_new_value("giraffe.extraction.horne.extrawidth",
03574 CPL_TYPE_INT,
03575 "Horne extraction method: Number of "
03576 "extra pixels added to the fiber "
03577 "half-width.",
03578 "giraffe.extraction.horne",
03579 2);
03580 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-hewidth");
03581 cpl_parameterlist_append(list, p);
03582
03583
03584 p = cpl_parameter_new_value("giraffe.extraction.horne.mingood",
03585 CPL_TYPE_INT,
03586 "Horne extraction method: Minimum number of "
03587 "points used for the profile fit. It sets "
03588 "the lower limit of data points for the "
03589 "pixel rejection.",
03590 "giraffe.extraction.horne",
03591 3);
03592 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-hmingood");
03593 cpl_parameterlist_append(list, p);
03594
03595
03596 p = cpl_parameter_new_range("giraffe.extraction.optimal.fraction",
03597 CPL_TYPE_DOUBLE,
03598 "Optimal extraction method: Minimum fraction "
03599 "of the data points used for fitting the "
03600 "fiber profiles. It sets the lower limit "
03601 "for the pixel rejection.",
03602 "giraffe.extraction.optimal",
03603 0.9, 0.0, 1.0);
03604 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-omfrac");
03605 cpl_parameterlist_append(list, p);
03606
03607
03608 p = cpl_parameter_new_value("giraffe.extraction.optimal.wfactor",
03609 CPL_TYPE_DOUBLE,
03610 "Optimal extraction method: Factor by which "
03611 "the fiber PSF half width is multiplied. "
03612 "Adjacent spectra within this area are "
03613 "assumed to affect the spectrum being "
03614 "extracted.",
03615 "giraffe.extraction.optimal",
03616 3.);
03617 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-owfactor");
03618 cpl_parameterlist_append(list, p);
03619
03620
03621 p = cpl_parameter_new_value("giraffe.extraction.optimal.bkgorder",
03622 CPL_TYPE_INT,
03623 "Optimal extraction method: Order of the "
03624 "polynomial background model, which is "
03625 "fitted for each wavelength bin along the "
03626 "spatial direction.",
03627 "giraffe.extraction.optimal",
03628 2);
03629 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-obkgorder");
03630 cpl_parameterlist_append(list, p);
03631
03632
03633 return;
03634
03635 }