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
02423
02424
02425
02426
02427 cpl_image_power(mse, 0.5);
02428
02429 _giraffe_optimal_workspace_delete(workspace);
02430 workspace = NULL;
02431
02432 _giraffe_extraction_psflimits_delete(limits);
02433 limits = NULL;
02434
02435 _giraffe_extractionslice_delete(slice);
02436 slice = NULL;
02437
02438 cpl_matrix_delete(weights);
02439 weights = NULL;
02440
02441 cpl_matrix_delete(mask);
02442 mask = NULL;
02443
02444 cpl_matrix_delete(variance);
02445 variance = NULL;
02446
02447 cpl_matrix_delete(signal);
02448 signal = NULL;
02449
02450 cpl_matrix_delete(profiles);
02451 profiles = NULL;
02452
02453 giraffe_model_delete(psfmodel);
02454 psfmodel = NULL;
02455
02456 return 0;
02457
02458 }
02459
02460
02485 cxint
02486 giraffe_extract_spectra(GiExtraction* result, GiImage* image,
02487 GiTable* fibers, GiLocalization* sloc,
02488 GiImage* bpixel, GiImage* slight,
02489 GiExtractConfig* config)
02490 {
02491
02492 const cxchar *fctid = "giraffe_extract_spectra";
02493
02494
02495 cxint ns = 0;
02496 cxint nx = 0;
02497 cxint ny = 0;
02498 cxint status = 0;
02499
02500 cxdouble bias_sigma = 0.;
02501 cxdouble dark_value = 0;
02502 cxdouble exptime = 0;
02503
02504 cpl_propertylist *properties;
02505
02506 cpl_image* _image = NULL;
02507 cpl_image* _locy = NULL;
02508 cpl_image* _locw = NULL;
02509 cpl_image* _spectra = NULL;
02510 cpl_image* _error = NULL;
02511 cpl_image* _npixels = NULL;
02512 cpl_image* _centroid = NULL;
02513 cpl_image* _model = NULL;
02514
02515 cpl_table* _fibers = NULL;
02516
02517
02518
02519
02520
02521
02522 if (!result || !image || !fibers || !sloc || !config) {
02523 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
02524 return 1;
02525 }
02526
02527
02528 if ((sloc->locy == NULL) || (sloc->locw == NULL)) {
02529 cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
02530 return 1;
02531 }
02532
02533 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 _fibers = giraffe_table_get(fibers);
02541
02542 if (_fibers == NULL) {
02543 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
02544 return 1;
02545 }
02546
02547 properties = giraffe_image_get_properties(image);
02548
02549 if (properties == NULL) {
02550 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
02551 return 1;
02552 }
02553
02554 if ((config->emethod == GIEXTRACT_OPTIMAL) && (sloc->psf == NULL)) {
02555 cpl_msg_error(fctid, "Missing data: PSF profile data is required "
02556 "for optimal spectrum extraction!");
02557 return 1;
02558 }
02559
02560 if (config->ron > 0.) {
02561
02562 cpl_msg_info(fctid, "Setting bias sigma value property (%s) to %.4g",
02563 GIALIAS_BIASSIGMA, config->ron);
02564
02565 cpl_propertylist_update_double(properties, GIALIAS_BIASSIGMA,
02566 config->ron);
02567 }
02568 else {
02569 if (!cpl_propertylist_has(properties, GIALIAS_BIASSIGMA)) {
02570 cpl_msg_error(fctid, "Missing bias value property (%s)!",
02571 GIALIAS_BIASSIGMA);
02572 return 1;
02573 }
02574 }
02575
02576 bias_sigma = cpl_propertylist_get_double(properties, GIALIAS_BIASSIGMA);
02577
02578
02579 if (!cpl_propertylist_has(properties, GIALIAS_DARKVALUE)) {
02580
02581 dark_value = 0.;
02582
02583 cpl_msg_warning(fctid, "Missing dark value property (%s), will be "
02584 "set to 0.!", GIALIAS_DARKVALUE);
02585 cpl_propertylist_append_double(properties, GIALIAS_DARKVALUE,
02586 dark_value);
02587
02588 }
02589 else {
02590 dark_value = cpl_propertylist_get_double(properties,
02591 GIALIAS_DARKVALUE);
02592 }
02593
02594
02595 if (!cpl_propertylist_has(properties, GIALIAS_EXPTIME)) {
02596 cpl_msg_error(fctid, "Missing exposure time property (%s)!",
02597 GIALIAS_EXPTIME);
02598 return 1;
02599 }
02600 else {
02601 exptime = cpl_propertylist_get_double(properties, GIALIAS_EXPTIME);
02602 }
02603
02604 if (cpl_propertylist_has(properties, GIALIAS_CONAD)) {
02605
02606 cxdouble conad = cpl_propertylist_get_double(properties,
02607 GIALIAS_CONAD);
02608
02609 bias_sigma *= conad;
02610 dark_value *= conad;
02611
02612 }
02613
02614
02615
02616
02617
02618
02619 _image = giraffe_image_get(image);
02620 _locy = giraffe_image_get(sloc->locy);
02621 _locw = giraffe_image_get(sloc->locw);
02622
02623 ny = cpl_image_get_size_x(_image);
02624 nx = cpl_image_get_size_y(_locw);
02625 ns = cpl_table_get_nrow(_fibers);
02626
02627
02628 switch (config->emethod) {
02629 case GIEXTRACT_SUM:
02630 {
02631
02632 cxint xsize = cpl_image_get_size_x(_image);
02633 cxint ysize = cpl_image_get_size_y(_image);
02634
02635 cxdouble bias_variance = bias_sigma * bias_sigma;
02636
02637 cpl_image* bpixmap = NULL;
02638 cpl_image* variance = NULL;
02639
02640
02641 result->spectra = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02642 result->error = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02643 result->npixels = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02644 result->centroid = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02645 result->model = NULL;
02646
02647 _spectra = giraffe_image_get(result->spectra);
02648 _error = giraffe_image_get(result->error);
02649 _npixels = giraffe_image_get(result->npixels);
02650 _centroid = giraffe_image_get(result->centroid);
02651
02652 if (bpixel != NULL) {
02653
02654 bpixmap = giraffe_image_get(bpixel);
02655
02656 if (cpl_image_get_size_x(bpixmap) != xsize ||
02657 cpl_image_get_size_y(bpixmap) != ysize) {
02658
02659 cxbool crop = FALSE;
02660
02661 cpl_propertylist *p =
02662 giraffe_image_get_properties(bpixel);
02663
02664 GiWindow w = {1, 1, 0, 0};
02665
02666
02667 w.x1 = cpl_image_get_size_x(bpixmap);
02668 w.y1 = cpl_image_get_size_y(bpixmap);
02669
02670 if (cpl_propertylist_has(p, GIALIAS_PRSCX)) {
02671 w.x0 += cpl_propertylist_get_int(p, GIALIAS_PRSCX);
02672 crop = TRUE;
02673 }
02674
02675 if (cpl_propertylist_has(p, GIALIAS_OVSCX)) {
02676 w.x1 -= cpl_propertylist_get_int(p, GIALIAS_OVSCX);
02677 crop = TRUE;
02678 }
02679
02680 if (cpl_propertylist_has(p, GIALIAS_PRSCY)) {
02681 w.y0 += cpl_propertylist_get_int(p, GIALIAS_PRSCY);
02682 crop = TRUE;
02683 }
02684
02685 if (cpl_propertylist_has(p, GIALIAS_OVSCY)) {
02686 w.y1 -= cpl_propertylist_get_int(p, GIALIAS_OVSCY);
02687 crop = TRUE;
02688 }
02689
02690 if ((w.x1 - w.x0 + 1) != xsize ||
02691 (w.y1 - w.y0 + 1) != ysize) {
02692 cpl_msg_error(fctid, "Invalid bad pixel map! Image "
02693 "sizes do not match!");
02694
02695 giraffe_image_delete(result->spectra);
02696 result->spectra = NULL;
02697
02698 giraffe_image_delete(result->error);
02699 result->error = NULL;
02700
02701 giraffe_image_delete(result->npixels);
02702 result->npixels = NULL;
02703
02704 giraffe_image_delete(result->centroid);
02705 result->centroid = NULL;
02706
02707 giraffe_image_delete(result->model);
02708 result->model = NULL;
02709
02710 return 1;
02711 }
02712
02713 if (crop == TRUE) {
02714 bpixmap = cpl_image_extract(bpixmap, w.x0, w.y0,
02715 w.x1, w.y1);
02716 }
02717
02718 }
02719
02720 }
02721
02722 if (slight != NULL) {
02723 cpl_msg_warning(fctid, "Scattered light model will be "
02724 "ignored for extraction method `SUM'");
02725 }
02726
02727 variance = cpl_image_abs_create(_image);
02728 cpl_image_add_scalar(variance,
02729 bias_variance + dark_value * exptime);
02730
02731 status = _giraffe_extract_summation(_image, variance, _fibers,
02732 _locy, _locw, bpixmap,
02733 _spectra, _error, _npixels,
02734 _centroid);
02735
02736 cpl_image_delete(variance);
02737 if (bpixmap != giraffe_image_get(bpixel)) {
02738 cpl_image_delete(bpixmap);
02739 }
02740 bpixmap = NULL;
02741
02742 break;
02743
02744 }
02745
02746 case GIEXTRACT_OPTIMAL:
02747 {
02748
02749 cxint xsize = cpl_image_get_size_x(_image);
02750 cxint ysize = cpl_image_get_size_y(_image);
02751
02752 cxdouble v0 = 0.;
02753
02754 cpl_image* variance = NULL;
02755 cpl_image* bpixmap = NULL;
02756
02757 GiExtractOptimalConfig setup;
02758
02759
02760 result->spectra = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02761 result->error = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02762 result->npixels = NULL;
02763 result->model = giraffe_image_create(CPL_TYPE_DOUBLE, ny, nx);
02764 result->centroid = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02765
02766 _spectra = giraffe_image_get(result->spectra);
02767 _error = giraffe_image_get(result->error);
02768 _model = giraffe_image_get(result->model);
02769 _centroid = giraffe_image_get(result->centroid);
02770
02771 setup.clip.iterations = config->psf.iterations;
02772 setup.clip.level = config->psf.sigma;
02773 setup.clip.fraction = config->optimal.fraction;
02774 setup.limits = config->optimal.wfactor < 0. ? FALSE : TRUE;
02775 setup.ewidth = CX_MAX(1., fabs(config->optimal.wfactor));
02776 setup.bkgorder = config->optimal.bkgorder;
02777 setup.exptime = exptime;
02778 setup.ron = bias_sigma;
02779 setup.dark = dark_value;
02780
02781
02782 if (bpixel != NULL) {
02783
02784 bpixmap = giraffe_image_get(bpixel);
02785
02786 if (cpl_image_get_size_x(bpixmap) != xsize ||
02787 cpl_image_get_size_y(bpixmap) != ysize) {
02788
02789 cxbool crop = FALSE;
02790
02791 cpl_propertylist *p =
02792 giraffe_image_get_properties(bpixel);
02793
02794 GiWindow w = {1, 1, 0, 0};
02795
02796
02797 w.x1 = cpl_image_get_size_x(bpixmap);
02798 w.y1 = cpl_image_get_size_y(bpixmap);
02799
02800 if (cpl_propertylist_has(p, GIALIAS_PRSCX)) {
02801 w.x0 += cpl_propertylist_get_int(p, GIALIAS_PRSCX);
02802 crop = TRUE;
02803 }
02804
02805 if (cpl_propertylist_has(p, GIALIAS_OVSCX)) {
02806 w.x1 -= cpl_propertylist_get_int(p, GIALIAS_OVSCX);
02807 crop = TRUE;
02808 }
02809
02810 if (cpl_propertylist_has(p, GIALIAS_PRSCY)) {
02811 w.y0 += cpl_propertylist_get_int(p, GIALIAS_PRSCY);
02812 crop = TRUE;
02813 }
02814
02815 if (cpl_propertylist_has(p, GIALIAS_OVSCY)) {
02816 w.y1 -= cpl_propertylist_get_int(p, GIALIAS_OVSCY);
02817 crop = TRUE;
02818 }
02819
02820 if ((w.x1 - w.x0 + 1) != xsize ||
02821 (w.y1 - w.y0 + 1) != ysize) {
02822
02823 cpl_msg_error(fctid, "Invalid bad pixel map! "
02824 "Image sizes do not match!");
02825
02826 giraffe_image_delete(result->spectra);
02827 result->spectra = NULL;
02828
02829 giraffe_image_delete(result->error);
02830 result->error = NULL;
02831
02832 giraffe_image_delete(result->npixels);
02833 result->npixels = NULL;
02834
02835 giraffe_image_delete(result->centroid);
02836 result->centroid = NULL;
02837
02838 giraffe_image_delete(result->model);
02839 result->model = NULL;
02840
02841 return 1;
02842
02843 }
02844
02845 if (crop == TRUE) {
02846 bpixmap = cpl_image_extract(bpixmap, w.x0, w.y0,
02847 w.x1, w.y1);
02848 }
02849
02850 }
02851
02852 }
02853
02854 variance = cpl_image_new(xsize, ysize, CPL_TYPE_DOUBLE);
02855 v0 = bias_sigma * bias_sigma + dark_value * exptime;
02856
02857
02858 if (slight != NULL) {
02859
02860 register cxsize i = 0;
02861 register cxsize npixels = xsize * ysize;
02862
02863 const cxdouble* _slight =
02864 cpl_image_get_data_double(giraffe_image_get(slight));
02865
02866 cxdouble* _variance = cpl_image_get_data_double(variance);
02867
02868 for (i = 0; i < npixels; i++) {
02869 _variance[i] = v0 + fabs(_slight[i]);
02870 }
02871
02872 }
02873 else {
02874
02875 register cxsize i = 0;
02876 register cxsize npixels = xsize * ysize;
02877
02878 cxdouble* _variance = cpl_image_get_data_double(variance);
02879
02880 for (i = 0; i < npixels; i++) {
02881 _variance[i] = v0;
02882 }
02883
02884 }
02885
02886
02887 status = _giraffe_extract_optimal(_image, variance, _fibers,
02888 _locy, _locw, sloc->psf,
02889 bpixmap, _spectra, _error,
02890 _model, _centroid, &setup);
02891
02892 cpl_image_delete(variance);
02893 variance = NULL;
02894
02895 if (bpixmap != giraffe_image_get(bpixel)) {
02896 cpl_image_delete(bpixmap);
02897 }
02898 bpixmap = NULL;
02899
02900 break;
02901
02902 }
02903
02904 case GIEXTRACT_HORNE:
02905 {
02906
02907 cxint xsize = cpl_image_get_size_x(_image);
02908 cxint ysize = cpl_image_get_size_y(_image);
02909
02910 cxdouble v0 = 0.;
02911
02912 cpl_image* variance = NULL;
02913 cpl_image* bpixmap = NULL;
02914
02915 GiExtractHorneConfig setup;
02916
02917
02918 result->spectra = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02919 result->error = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02920 result->npixels = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02921 result->centroid = giraffe_image_create(CPL_TYPE_DOUBLE, ns, nx);
02922 result->model = NULL;
02923
02924 _spectra = giraffe_image_get(result->spectra);
02925 _error = giraffe_image_get(result->error);
02926 _npixels = giraffe_image_get(result->npixels);
02927 _centroid = giraffe_image_get(result->centroid);
02928
02929 setup.clip.iterations = config->psf.iterations;
02930 setup.clip.level = config->psf.sigma;
02931 setup.clip.fraction = config->horne.mingood;
02932 setup.ewidth = config->horne.ewidth;
02933 setup.exptime = exptime;
02934 setup.ron = bias_sigma;
02935 setup.dark = dark_value;
02936
02937 if (bpixel != NULL) {
02938
02939 bpixmap = giraffe_image_get(bpixel);
02940
02941 if (cpl_image_get_size_x(bpixmap) != xsize ||
02942 cpl_image_get_size_y(bpixmap) != ysize) {
02943
02944 cxbool crop = FALSE;
02945
02946 cpl_propertylist *p =
02947 giraffe_image_get_properties(bpixel);
02948
02949 GiWindow w = {1, 1, 0, 0};
02950
02951
02952 w.x1 = cpl_image_get_size_x(bpixmap);
02953 w.y1 = cpl_image_get_size_y(bpixmap);
02954
02955 if (cpl_propertylist_has(p, GIALIAS_PRSCX)) {
02956 w.x0 += cpl_propertylist_get_int(p, GIALIAS_PRSCX);
02957 crop = TRUE;
02958 }
02959
02960 if (cpl_propertylist_has(p, GIALIAS_OVSCX)) {
02961 w.x1 -= cpl_propertylist_get_int(p, GIALIAS_OVSCX);
02962 crop = TRUE;
02963 }
02964
02965 if (cpl_propertylist_has(p, GIALIAS_PRSCY)) {
02966 w.y0 += cpl_propertylist_get_int(p, GIALIAS_PRSCY);
02967 crop = TRUE;
02968 }
02969
02970 if (cpl_propertylist_has(p, GIALIAS_OVSCY)) {
02971 w.y1 -= cpl_propertylist_get_int(p, GIALIAS_OVSCY);
02972 crop = TRUE;
02973 }
02974
02975 if ((w.x1 - w.x0 + 1) != xsize ||
02976 (w.y1 - w.y0 + 1) != ysize) {
02977
02978 cpl_msg_error(fctid, "Invalid bad pixel map! "
02979 "Image sizes do not match!");
02980
02981 giraffe_image_delete(result->spectra);
02982 result->spectra = NULL;
02983
02984 giraffe_image_delete(result->error);
02985 result->error = NULL;
02986
02987 giraffe_image_delete(result->npixels);
02988 result->npixels = NULL;
02989
02990 giraffe_image_delete(result->centroid);
02991 result->centroid = NULL;
02992
02993 giraffe_image_delete(result->model);
02994 result->model = NULL;
02995
02996 return 1;
02997
02998 }
02999
03000 if (crop == TRUE) {
03001 bpixmap = cpl_image_extract(bpixmap, w.x0, w.y0,
03002 w.x1, w.y1);
03003 }
03004
03005 }
03006
03007 }
03008
03009 variance = cpl_image_new(xsize, ysize, CPL_TYPE_DOUBLE);
03010 v0 = bias_sigma * bias_sigma + dark_value * exptime;
03011
03012
03013 if (slight != NULL) {
03014
03015 register cxsize i = 0;
03016 register cxsize npixels = xsize * ysize;
03017
03018 const cxdouble* _slight =
03019 cpl_image_get_data_double(giraffe_image_get(slight));
03020
03021 cxdouble* _variance = cpl_image_get_data_double(variance);
03022
03023 for (i = 0; i < npixels; i++) {
03024 _variance[i] = v0 + fabs(_slight[i]);
03025 }
03026
03027 }
03028 else {
03029
03030 register cxsize i = 0;
03031 register cxsize npixels = xsize * ysize;
03032
03033 cxdouble* _variance = cpl_image_get_data_double(variance);
03034
03035 for (i = 0; i < npixels; i++) {
03036 _variance[i] = v0;
03037 }
03038
03039 }
03040
03041
03042 status = _giraffe_extract_horne(_image, variance, _fibers,
03043 _locy, _locw, sloc->psf,
03044 bpixmap, _spectra, _error,
03045 _npixels, _centroid, &setup);
03046
03047 cpl_image_delete(variance);
03048 variance = NULL;
03049
03050 if (bpixmap != giraffe_image_get(bpixel)) {
03051 cpl_image_delete(bpixmap);
03052 }
03053 bpixmap = NULL;
03054
03055 break;
03056
03057 }
03058
03059 default:
03060 gi_message("%s: Method %d selected for spectrum extraction.",
03061 fctid, config->emethod);
03062 cpl_msg_error(fctid, "Invalid extraction method!");
03063
03064 status = 1;
03065 break;
03066 }
03067
03068
03069 if (status) {
03070
03071 giraffe_image_delete(result->spectra);
03072 result->spectra = NULL;
03073
03074 giraffe_image_delete(result->error);
03075 result->error = NULL;
03076
03077 giraffe_image_delete(result->npixels);
03078 result->npixels = NULL;
03079
03080 giraffe_image_delete(result->centroid);
03081 result->centroid = NULL;
03082
03083 giraffe_image_delete(result->model);
03084 result->model = NULL;
03085
03086 cpl_msg_error(fctid, "Spectrum extraction (method %d) failed!",
03087 config->emethod);
03088
03089 return 1;
03090
03091 }
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102 properties = giraffe_image_get_properties(image);
03103 giraffe_image_set_properties(result->spectra, properties);
03104
03105 properties = giraffe_image_get_properties(result->spectra);
03106
03107
03108
03109
03110
03111
03112
03113 giraffe_propertylist_update(properties,
03114 giraffe_image_get_properties(sloc->locy),
03115 "^ESO PRO LOC.*");
03116
03117 cpl_propertylist_set_int(properties, GIALIAS_NAXIS1,
03118 cpl_image_get_size_x(_spectra));
03119 cpl_propertylist_set_int(properties, GIALIAS_NAXIS2,
03120 cpl_image_get_size_y(_spectra));
03121
03122 cpl_propertylist_set_int(properties, GIALIAS_BITPIX, -32);
03123 cpl_propertylist_set_double(properties, GIALIAS_BZERO, 0.);
03124 cpl_propertylist_set_double(properties, GIALIAS_BSCALE, 1.);
03125
03126 cpl_propertylist_update_int(properties, GIALIAS_NFIBERS,
03127 cpl_image_get_size_x(_spectra));
03128
03129 cpl_propertylist_append_int(properties, GIALIAS_EXT_NX,
03130 cpl_image_get_size_y(_spectra));
03131 cpl_propertylist_append_int(properties, GIALIAS_EXT_NS,
03132 cpl_image_get_size_x(_spectra));
03133
03134 switch (config->emethod) {
03135 case GIEXTRACT_SUM:
03136 cpl_propertylist_append_string(properties, GIALIAS_EXT_METHOD,
03137 "SUM");
03138 cpl_propertylist_set_comment(properties, GIALIAS_EXT_METHOD,
03139 "Spectrum extraction method");
03140 break;
03141
03142 case GIEXTRACT_HORNE:
03143 {
03144
03145 cpl_propertylist_append_string(properties, GIALIAS_EXT_METHOD,
03146 "HORNE");
03147 cpl_propertylist_set_comment(properties, GIALIAS_EXT_METHOD,
03148 "Spectrum extraction method");
03149
03150 cpl_propertylist_append_string(properties, GIALIAS_EXTPSF_MODEL,
03151 config->psf.model);
03152 cpl_propertylist_set_comment(properties, GIALIAS_EXTPSF_MODEL,
03153 "PSF model used");
03154 cpl_propertylist_append_double(properties, GIALIAS_EXTPSF_SIGMA,
03155 config->psf.sigma);
03156 cpl_propertylist_set_comment(properties, GIALIAS_EXTPSF_SIGMA,
03157 "PSF fit sigma clipping threshold");
03158 cpl_propertylist_append_int(properties, GIALIAS_EXTPSF_NITER,
03159 config->psf.iterations);
03160 cpl_propertylist_set_comment(properties, GIALIAS_EXTPSF_NITER,
03161 "PSF fit maximum number of "
03162 "iterations");
03163
03164 cpl_propertylist_append_int(properties, GIALIAS_EXTHRN_EWIDTH,
03165 config->horne.ewidth);
03166 cpl_propertylist_set_comment(properties, GIALIAS_EXTHRN_EWIDTH,
03167 "Number of extra pixels used");
03168 cpl_propertylist_append_int(properties, GIALIAS_EXTHRN_MINGOOD,
03169 config->horne.mingood);
03170 cpl_propertylist_set_comment(properties, GIALIAS_EXTHRN_MINGOOD,
03171 "Minimum number of pixels to keep");
03172
03173
03174 break;
03175 }
03176
03177 case GIEXTRACT_OPTIMAL:
03178 cpl_propertylist_append_string(properties, GIALIAS_EXT_METHOD,
03179 "OPTIMAL");
03180 cpl_propertylist_set_comment(properties, GIALIAS_EXT_METHOD,
03181 "Spectrum extraction method");
03182
03183 cpl_propertylist_append_string(properties, GIALIAS_EXTPSF_MODEL,
03184 config->psf.model);
03185 cpl_propertylist_set_comment(properties, GIALIAS_EXTPSF_MODEL,
03186 "PSF model used");
03187 cpl_propertylist_append_double(properties, GIALIAS_EXTPSF_SIGMA,
03188 config->psf.sigma);
03189 cpl_propertylist_set_comment(properties, GIALIAS_EXTPSF_SIGMA,
03190 "PSF fit sigma clipping threshold");
03191 cpl_propertylist_append_int(properties, GIALIAS_EXTPSF_NITER,
03192 config->psf.iterations);
03193 cpl_propertylist_set_comment(properties, GIALIAS_EXTPSF_NITER,
03194 "PSF fit maximum number of "
03195 "iterations");
03196
03197 cpl_propertylist_append_double(properties, GIALIAS_EXTOPT_FRACTION,
03198 config->optimal.fraction);
03199 cpl_propertylist_set_comment(properties, GIALIAS_EXTOPT_FRACTION,
03200 "Minimum fraction of pixels used.");
03201 cpl_propertylist_append_double(properties, GIALIAS_EXTOPT_WFACTOR,
03202 config->optimal.wfactor);
03203 cpl_propertylist_set_comment(properties, GIALIAS_EXTOPT_WFACTOR,
03204 "Multiple of the fiber PSF half "
03205 "width used for spectrum "
03206 "extraction.");
03207 cpl_propertylist_append_int(properties, GIALIAS_EXTOPT_BGORDER,
03208 config->optimal.bkgorder);
03209 cpl_propertylist_set_comment(properties, GIALIAS_EXTOPT_BGORDER,
03210 "Order of the background polynomial "
03211 "model along the spatial direction.");
03212
03213 break;
03214
03215 default:
03216 break;
03217 }
03218
03219 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE, "EXTSP");
03220 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03221 "Extracted spectra");
03222
03223
03224
03225
03226
03227
03228 giraffe_image_set_properties(result->error, properties);
03229 properties = giraffe_image_get_properties(result->error);
03230
03231 cpl_propertylist_set_string(properties, GIALIAS_GIRFTYPE, "EXTERRS");
03232 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03233 "Extracted spectra errors");
03234
03235
03236
03237
03238
03239
03240 giraffe_image_set_properties(result->centroid, properties);
03241 properties = giraffe_image_get_properties(result->centroid);
03242
03243 cpl_propertylist_set_string(properties, GIALIAS_GIRFTYPE, "EXTYCEN");
03244 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03245 "Extracted spectra centroids");
03246
03247
03248
03249
03250
03251
03252 if (result->npixels != NULL) {
03253 giraffe_image_set_properties(result->npixels, properties);
03254 properties = giraffe_image_get_properties(result->npixels);
03255
03256 cpl_propertylist_set_string(properties, GIALIAS_GIRFTYPE, "EXTNPIX");
03257 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03258 "Extracted spectra npixels");
03259 }
03260
03261
03262
03263
03264
03265
03266 if (result->model != NULL) {
03267 giraffe_image_set_properties(result->model, properties);
03268 properties = giraffe_image_get_properties(result->model);
03269
03270 cpl_propertylist_set_string(properties, GIALIAS_GIRFTYPE, "EXTMODEL");
03271 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
03272 "Model spectra used for extraction");
03273 }
03274
03275 return 0;
03276
03277 }
03278
03279
03290 GiExtractConfig*
03291 giraffe_extract_config_create(cpl_parameterlist* list)
03292 {
03293
03294 const cxchar* s;
03295 cpl_parameter* p;
03296
03297 GiExtractConfig* config = NULL;
03298
03299
03300 if (!list) {
03301 return NULL;
03302 }
03303
03304 config = cx_calloc(1, sizeof *config);
03305
03306 p = cpl_parameterlist_find(list, "giraffe.extraction.method");
03307 s = cpl_parameter_get_string(p);
03308 if (!strcmp(s, "OPTIMAL")) {
03309 config->emethod = GIEXTRACT_OPTIMAL;
03310 }
03311 else if (!strcmp(s, "HORNE")) {
03312 config->emethod = GIEXTRACT_HORNE;
03313 }
03314 else {
03315 config->emethod = GIEXTRACT_SUM;
03316 }
03317
03318 p = cpl_parameterlist_find(list, "giraffe.extraction.ron");
03319 config->ron = cpl_parameter_get_double(p);
03320
03321 p = cpl_parameterlist_find(list, "giraffe.extraction.psf.model");
03322 config->psf.model = cx_strdup(cpl_parameter_get_string(p));
03323
03324 p = cpl_parameterlist_find(list, "giraffe.extraction.psf.sigma");
03325 config->psf.sigma = cpl_parameter_get_double(p);
03326
03327 p = cpl_parameterlist_find(list, "giraffe.extraction.psf.iterations");
03328 config->psf.iterations = cpl_parameter_get_int(p);
03329
03330
03331 p = cpl_parameterlist_find(list, "giraffe.extraction.horne.extrawidth");
03332 config->horne.ewidth = cpl_parameter_get_int(p);
03333
03334 p = cpl_parameterlist_find(list, "giraffe.extraction.horne.mingood");
03335 config->horne.mingood = cpl_parameter_get_double(p);
03336
03337
03338 p = cpl_parameterlist_find(list, "giraffe.extraction.optimal.fraction");
03339 config->optimal.fraction = cpl_parameter_get_double(p);
03340
03341 p = cpl_parameterlist_find(list, "giraffe.extraction.optimal.wfactor");
03342 config->optimal.wfactor = cpl_parameter_get_double(p);
03343
03344 p = cpl_parameterlist_find(list, "giraffe.extraction.optimal.bkgorder");
03345 config->optimal.bkgorder = cpl_parameter_get_int(p);
03346
03347 return config;
03348
03349 }
03350
03351
03364 void
03365 giraffe_extract_config_destroy(GiExtractConfig* config)
03366 {
03367
03368 if (config) {
03369
03370 if (config->psf.model) {
03371 cx_free(config->psf.model);
03372 }
03373
03374 cx_free(config);
03375
03376 }
03377
03378 return;
03379
03380 }
03381
03382
03394 void
03395 giraffe_extract_config_add(cpl_parameterlist* list)
03396 {
03397
03398 cpl_parameter* p = NULL;
03399
03400
03401 if (list == NULL) {
03402 return;
03403 }
03404
03405 p = cpl_parameter_new_enum("giraffe.extraction.method",
03406 CPL_TYPE_STRING,
03407 "Extraction method: 'SUM', 'HORNE' or "
03408 "'OPTIMAL'",
03409 "giraffe.extraction",
03410 "SUM", 3, "SUM", "OPTIMAL", "HORNE");
03411 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-method");
03412 cpl_parameterlist_append(list, p);
03413
03414
03415 p = cpl_parameter_new_value("giraffe.extraction.ron",
03416 CPL_TYPE_DOUBLE,
03417 "New bias sigma (RON) value for "
03418 "bias and dark "
03419 "corrected image",
03420 "giraffe.extraction",
03421 -1.);
03422 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-ron");
03423 cpl_parameterlist_append(list, p);
03424
03425
03426 p = cpl_parameter_new_enum("giraffe.extraction.psf.model",
03427 CPL_TYPE_STRING,
03428 "PSF profile model: `psfexp', `psfexp2'",
03429 "giraffe.extraction.psf",
03430 "psfexp2", 2, "psfexp", "psfexp2");
03431 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-psfmodel");
03432 cpl_parameterlist_append(list, p);
03433
03434
03435 p = cpl_parameter_new_value("giraffe.extraction.psf.sigma",
03436 CPL_TYPE_DOUBLE,
03437 "Sigma clippging threshold used for "
03438 "rejecting data points during PSF fitting "
03439 "(Horne's sigma). It is used to reject bad "
03440 "pixels and cosmics.",
03441 "giraffe.extraction.psf",
03442 7.);
03443 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-psfsigma");
03444 cpl_parameterlist_append(list, p);
03445
03446
03447 p = cpl_parameter_new_value("giraffe.extraction.psf.iterations",
03448 CPL_TYPE_INT,
03449 "Maximum number of iterations used for "
03450 "fitting the PSF profile.",
03451 "giraffe.extraction.psf",
03452 2);
03453 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-psfniter");
03454 cpl_parameterlist_append(list, p);
03455
03456
03457 p = cpl_parameter_new_value("giraffe.extraction.horne.extrawidth",
03458 CPL_TYPE_INT,
03459 "Horne extraction method: Number of "
03460 "extra pixels added to the fiber "
03461 "half-width.",
03462 "giraffe.extraction.horne",
03463 2);
03464 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-hewidth");
03465 cpl_parameterlist_append(list, p);
03466
03467
03468 p = cpl_parameter_new_value("giraffe.extraction.horne.mingood",
03469 CPL_TYPE_INT,
03470 "Horne extraction method: Minimum number of "
03471 "points used for the profile fit. It sets "
03472 "the lower limit of data points for the "
03473 "pixel rejection.",
03474 "giraffe.extraction.horne",
03475 3);
03476 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-hmingood");
03477 cpl_parameterlist_append(list, p);
03478
03479
03480 p = cpl_parameter_new_range("giraffe.extraction.optimal.fraction",
03481 CPL_TYPE_DOUBLE,
03482 "Optimal extraction method: Minimum fraction "
03483 "of the data points used for fitting the "
03484 "fiber profiles. It sets the lower limit "
03485 "for the pixel rejection.",
03486 "giraffe.extraction.optimal",
03487 0.9, 0.0, 1.0);
03488 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-omfrac");
03489 cpl_parameterlist_append(list, p);
03490
03491
03492 p = cpl_parameter_new_value("giraffe.extraction.optimal.wfactor",
03493 CPL_TYPE_DOUBLE,
03494 "Optimal extraction method: Factor by which "
03495 "the fiber PSF half width is multiplied. "
03496 "Adjacent spectra within this area are "
03497 "assumed to affect the spectrum being "
03498 "extracted.",
03499 "giraffe.extraction.optimal",
03500 3.);
03501 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-owfactor");
03502 cpl_parameterlist_append(list, p);
03503
03504
03505 p = cpl_parameter_new_value("giraffe.extraction.optimal.bkgorder",
03506 CPL_TYPE_INT,
03507 "Optimal extraction method: Order of the "
03508 "polynomial background model, which is "
03509 "fitted for each wavelength bin along the "
03510 "spatial direction.",
03511 "giraffe.extraction.optimal",
03512 2);
03513 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extr-obkgorder");
03514 cpl_parameterlist_append(list, p);
03515
03516
03517 return;
03518
03519 }