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