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