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
00034 #include <cxmemory.h>
00035 #include <cxmessages.h>
00036 #include <cxstrutils.h>
00037
00038 #include <cpl_error.h>
00039 #include <cpl_parameterlist.h>
00040 #include <cpl_propertylist.h>
00041 #include <cpl_matrix.h>
00042 #include <cpl_image.h>
00043 #include <cpl_table.h>
00044
00045 #include "gialias.h"
00046 #include "gierror.h"
00047 #include "gimatrix.h"
00048 #include "gifiberutils.h"
00049 #include "gigrating.h"
00050 #include "gimodel.h"
00051 #include "gilocalization.h"
00052 #include "giextraction.h"
00053 #include "girebinning.h"
00054 #include "gisgcalibration.h"
00055
00056
00065 struct GiMeasurement {
00066 cxdouble value;
00067 cxdouble sigma;
00068 };
00069
00070 typedef struct GiMeasurement GiMeasurement;
00071
00072
00073 struct GiSGSetup {
00074
00075 cxint nx;
00076 cxint nex;
00077
00078 GiRebinScale scale;
00079
00080 cxdouble wlmin;
00081 cxdouble wlmax;
00082 cxdouble wlstep;
00083
00084 cxdouble pixelsize;
00085
00086 };
00087
00088 typedef struct GiSGSetup GiSGSetup;
00089
00090
00091 struct GiCPFitParams {
00092
00093 cxint dnmin;
00094 cxint iterations;
00095
00096 cxdouble step;
00097 cxdouble wfactor;
00098 cxdouble sigma;
00099
00100 GiRebinScale scale;
00101
00102 GiFitSetup fit;
00103
00104 };
00105
00106 typedef struct GiCPFitParams GiCPFitParams;
00107
00108
00109 struct GiCPeakFit {
00110 GiMeasurement amplitude;
00111 GiMeasurement background;
00112 GiMeasurement center;
00113 GiMeasurement width;
00114
00115 cxint status;
00116 };
00117
00118 typedef struct GiCPeakFit GiCPeakFit;
00119
00120
00121 struct GiSGMask {
00122
00123 cxsize size;
00124 cxsize nholes;
00125
00126 GiRebinScale scale;
00127
00128 cxdouble start;
00129 cxdouble step;
00130
00131 cpl_matrix* wavelength;
00132 cpl_matrix* flux;
00133
00134 };
00135
00136 typedef struct GiSGMask GiSGMask;
00137
00138
00139 inline static GiSGMask*
00140 _giraffe_sgmask_new(cxsize size)
00141 {
00142
00143 GiSGMask* self = cx_calloc(1, sizeof *self);
00144
00145 self->wavelength = cpl_matrix_new(1, size);
00146 self->flux = cpl_matrix_new(1, size);
00147
00148 self->size = size;
00149 self->nholes = 0;
00150
00151 self->scale = GIREBIN_SCALE_LINEAR;
00152
00153 self->start = 0.;
00154 self->step = 1.;
00155
00156 return self;
00157
00158 }
00159
00160
00161 inline static void
00162 _giraffe_sgmask_delete(GiSGMask* self)
00163 {
00164
00165 if (self) {
00166
00167 if (self->wavelength != NULL) {
00168 cpl_matrix_delete(self->wavelength);
00169 self->wavelength = NULL;
00170 }
00171
00172 if (self->flux != NULL) {
00173 cpl_matrix_delete(self->flux);
00174 self->flux = NULL;
00175 }
00176
00177 cx_free(self);
00178
00179 }
00180
00181 return;
00182
00183 }
00184
00185
00186 inline static GiSGMask*
00187 _giraffe_sgmask_create(cxsize size, cxdouble start, cxdouble step,
00188 GiRebinScale scale, const GiTable* mask)
00189 {
00190
00191 register cxsize i;
00192
00193 cxdouble wlmin = 0.;
00194 cxdouble wlmax = 0.;
00195 cxdouble wlstep = 0.;
00196
00197 cpl_table* _mask = NULL;
00198
00199 GiSGMask* self = NULL;
00200
00201
00202 cx_assert(mask != NULL);
00203
00204 _mask = giraffe_table_get(mask);
00205 cx_assert(_mask != NULL);
00206
00207 self = _giraffe_sgmask_new(size);
00208
00209 self->start = start;
00210 self->step = step;
00211 self->scale = scale;
00212
00213
00214
00215
00216
00217
00218 for (i = 0; i < self->size; i++) {
00219 cpl_matrix_set(self->wavelength, 0, i, self->start + i * self->step);
00220 }
00221
00222
00223 wlmin = cpl_matrix_get(self->wavelength, 0, 0);
00224 wlmax = cpl_matrix_get(self->wavelength, 0, self->size - 1);
00225 wlstep = self->step;
00226
00227 if (self->scale == GIREBIN_SCALE_LOG) {
00228
00229 wlmin = exp(wlmin);
00230 wlmax = exp(wlmax);
00231 wlstep = exp(wlstep);
00232
00233 }
00234
00235
00236
00237
00238
00239
00240
00241 cpl_table_select_all(_mask);
00242
00243 cpl_table_and_selected_double(_mask, "WLEN1", CPL_GREATER_THAN, wlmin);
00244 cpl_table_and_selected_double(_mask, "WLEN2", CPL_LESS_THAN, wlmax);
00245
00246 _mask = cpl_table_extract_selected(_mask);
00247
00248 if (_mask == NULL || cpl_table_get_nrow(_mask) <= 0) {
00249 _giraffe_sgmask_delete(self);
00250 self = NULL;
00251
00252 return NULL;
00253 }
00254
00255
00256 self->nholes = cpl_table_get_nrow(_mask);
00257
00258 for (i = 0; i < self->nholes; i++) {
00259
00260 register cxsize j;
00261
00262 cxdouble hstart = cpl_table_get(_mask, "WLEN1", i, NULL) - wlmin;
00263 cxdouble hend = cpl_table_get(_mask, "WLEN2", i, NULL) - wlmin;
00264
00265
00266 hstart /= wlstep;
00267 hend /= wlstep;
00268
00269 for (j = (cxsize)(hstart + 0.5); j <= (cxsize)(hend + 0.5); j++) {
00270
00271 cpl_matrix_set(self->flux, 0, j, 1.);
00272
00273 }
00274
00275 }
00276
00277 cpl_table_delete(_mask);
00278
00279 return self;
00280
00281 }
00282
00283
00284 inline static cxsize
00285 _giraffe_sgmask_size(const GiSGMask* self)
00286 {
00287
00288 cx_assert(self != NULL);
00289
00290 return self->size;
00291
00292 }
00293
00294
00295 inline static cxsize
00296 _giraffe_sgmask_holes(const GiSGMask* self)
00297 {
00298
00299 cx_assert(self != NULL);
00300
00301 return self->nholes;
00302
00303 }
00304
00305
00306 inline static cxint
00307 _giraffe_sgmask_set_flux(GiSGMask* self, cxsize position, cxdouble value)
00308 {
00309
00310 cx_assert(self != NULL);
00311
00312 if (position >= (cxsize)cpl_matrix_get_ncol(self->flux)) {
00313 return 1;
00314 }
00315
00316 cpl_matrix_set(self->flux, 0, position, value);
00317
00318 return 0;
00319
00320 }
00321
00322
00323 inline static cxdouble
00324 _giraffe_sgmask_get_flux(GiSGMask* self, cxsize position)
00325 {
00326
00327 const cxchar* const fctid = "_giraffe_sgmask_get_flux";
00328
00329
00330 cx_assert(self != NULL);
00331
00332 if (position >= (cxsize)cpl_matrix_get_ncol(self->flux)) {
00333 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
00334 return 0.;
00335 }
00336
00337 return cpl_matrix_get(self->flux, 0, position);
00338
00339 }
00340
00341
00342 inline static const cpl_matrix*
00343 _giraffe_sgmask_get(GiSGMask* self)
00344 {
00345
00346 cx_assert(self != NULL);
00347
00348 return self->flux;
00349
00350 }
00351
00352
00353 inline static cxint
00354 _giraffe_sgmask_crop(GiSGMask* self, cxsize begin, cxsize end)
00355 {
00356
00357 cxsize size = 0;
00358
00359 cpl_matrix* buffer = NULL;
00360
00361
00362 cx_assert(self != NULL);
00363 cx_assert(end > begin);
00364 cx_assert(cpl_matrix_get_nrow(self->wavelength) == 1);
00365 cx_assert(cpl_matrix_get_nrow(self->flux) == 1);
00366
00367 if (begin >= (cxsize)cpl_matrix_get_ncol(self->flux)) {
00368 return 1;
00369 }
00370
00371 if (end > (cxsize)cpl_matrix_get_ncol(self->flux)) {
00372 end = cpl_matrix_get_ncol(self->flux);
00373 }
00374
00375 if (begin == 0 && end == (cxsize)cpl_matrix_get_ncol(self->flux)) {
00376 return 0;
00377 }
00378
00379 size = end - begin;
00380
00381 buffer = cpl_matrix_extract(self->wavelength, 0, begin, 1, 1, 1, size);
00382 cpl_matrix_delete(self->wavelength);
00383 self->wavelength = buffer;
00384
00385 buffer = cpl_matrix_extract(self->flux, 0, begin, 1, 1, 1, size);
00386 cpl_matrix_delete(self->flux);
00387 self->flux = buffer;
00388
00389 cx_assert(cpl_matrix_get_nrow(self->flux) == 1);
00390 cx_assert((cxsize)cpl_matrix_get_ncol(self->flux) == size);
00391
00392 self->size = size;
00393
00394 return 0;
00395
00396 }
00397
00398
00399 inline static cxdouble
00400 _giraffe_clip_value(cxdouble value, cxdouble low, cxdouble high,
00401 cxbool* flag)
00402 {
00403
00404 cxbool status = FALSE;
00405
00406 if (value < low) {
00407 value = low;
00408 status = TRUE;
00409 }
00410
00411 if (value >= high) {
00412 value = high;
00413 status = TRUE;
00414 }
00415
00416 if (flag != NULL) {
00417 *flag = status;
00418 }
00419
00420 return value;
00421
00422 }
00423
00424
00425
00426
00427
00428
00429
00430
00431 inline static cpl_image*
00432 _giraffe_resample_image(cpl_image* signal, cxdouble step1, cxdouble step2)
00433 {
00434
00435 cxint i;
00436 cxint nx1 = 0;
00437 cxint ny = 0;
00438 cxint nx2 = 0;
00439 cxint step = CX_MAX(1, (cxint)(step1/step2));
00440
00441 cpl_image* _signal = NULL;
00442
00443
00444 cx_assert(signal != NULL);
00445
00446 ny = cpl_image_get_size_x(signal);
00447 nx1 = cpl_image_get_size_y(signal);
00448
00449 nx2 = (nx1 - 1) * step + 1;
00450
00451 _signal = cpl_image_new(ny, nx2, CPL_TYPE_DOUBLE);
00452
00453 for (i = 0; i < ny; i++) {
00454
00455 register cxint j;
00456
00457 register cxdouble* data = cpl_image_get_data(signal);
00458 register cxdouble* _data = cpl_image_get_data(_signal);
00459
00460
00461 for (j = 0; j < nx1 - 1; j++) {
00462
00463 register cxint k;
00464 register cxint l = j * ny + i;
00465 register cxint m = j * ny * step + i;
00466
00467 for (k = 0; k < step; k++) {
00468
00469 cxdouble f = (cxdouble)k / (cxdouble)step;
00470
00471 _data[m + k * ny] = (1. - f) * data[l] + f * data[l + ny];
00472
00473 }
00474
00475 }
00476
00477 _data[nx2 - 1] = data[nx1 - 1];
00478
00479 }
00480
00481 return _signal;
00482
00483 }
00484
00485
00486
00487
00488
00489
00490 inline static cpl_matrix*
00491 _giraffe_compute_cross_correlation(const cpl_matrix* signal,
00492 const cpl_matrix* template,
00493 cxint start, cxint end)
00494 {
00495
00496 const cxchar* const fctid = "_giraffe_compute_cross_correlation";
00497
00498
00499 cxint i;
00500 cxint n = 0;
00501 cxint nmax = 0;
00502 cxint ns = 0;
00503 cxint nccf = 0;
00504
00505 cxdouble sum = 0.;
00506
00507 cpl_matrix* _signal = (cpl_matrix*)signal;
00508 cpl_matrix* _template = (cpl_matrix*)template;
00509 cpl_matrix* ccf = NULL;
00510 cpl_matrix* _ccf = NULL;
00511
00512
00513 cx_assert(_signal != NULL);
00514 cx_assert(cpl_matrix_get_nrow(_signal) == 1);
00515
00516 cx_assert(_template != NULL);
00517 cx_assert(cpl_matrix_get_nrow(_template) == 1);
00518
00519 ns = cpl_matrix_get_ncol(_signal);
00520 cx_assert(ns == cpl_matrix_get_ncol(_template));
00521
00522 cx_assert(start <= end);
00523
00524
00525
00526
00527
00528
00529 nmax = cpl_matrix_get_ncol(_signal) / 2;
00530
00531 start = CX_MAX(CX_MIN(start, nmax), -nmax);
00532 end = CX_MAX(CX_MIN(end, nmax), -nmax);
00533
00534 nccf = end - start;
00535
00536 cpl_msg_debug(fctid, "Cross-correlation function: signal size = %"
00537 CPL_SIZE_FORMAT ", template size = %" CPL_SIZE_FORMAT
00538 ", window start = %d, window end = %d",
00539 cpl_matrix_get_ncol(_signal), cpl_matrix_get_ncol(_template),
00540 start, end);
00541
00542
00543 ccf = cpl_matrix_new(1, nccf);
00544
00545 for (i = start; i < end; i++) {
00546
00547 if (i < 0) {
00548
00549 cxint j;
00550
00551
00552
00553
00554
00555
00556 sum = 0.;
00557
00558 for (j = 0; j < ns + i; j++) {
00559
00560 cxdouble s = cpl_matrix_get(_signal, 0, j);
00561 cxdouble t = cpl_matrix_get(_template, 0, j - i);
00562
00563 sum += t * s;
00564
00565 }
00566
00567 sum /= (cxdouble)(ns + i);
00568
00569 cpl_matrix_set(ccf, 0, i - start, sum);
00570
00571 }
00572 else if (i > 0) {
00573
00574 cxint j;
00575
00576
00577
00578
00579
00580
00581 sum = 0.;
00582
00583 for (j = i; j < ns; j++) {
00584
00585 cxdouble s = cpl_matrix_get(_signal, 0, j);
00586 cxdouble t = cpl_matrix_get(_template, 0, j - i);
00587
00588 sum += t * s;
00589
00590 }
00591
00592 sum /= (cxdouble)(ns - i);
00593
00594 cpl_matrix_set(ccf, 0, i - start, sum);
00595
00596 }
00597 else {
00598
00599 cxint j;
00600
00601
00602
00603
00604
00605
00606 sum = 0.;
00607
00608 for (j = 0; j < ns; j++) {
00609
00610 cxdouble t = cpl_matrix_get(_template, 0, j);
00611 cxdouble s = cpl_matrix_get(_signal, 0, j);
00612
00613 sum += t * s;
00614
00615 }
00616
00617 sum /= (cxdouble)ns;
00618
00619 cpl_matrix_set(ccf, 0, -start, sum);
00620
00621 }
00622
00623
00624 }
00625
00626
00627
00628
00629
00630
00631
00632
00633 n = CX_MAX(1, nccf / 10);
00634
00635 _ccf = cpl_matrix_duplicate(ccf);
00636 giraffe_matrix_sort(_ccf);
00637
00638 sum = 0.;
00639
00640 for (i = nccf - n; i < nccf; i++) {
00641 sum += cpl_matrix_get(_ccf, 0, i);
00642 }
00643
00644 sum /= (cxdouble)n;
00645
00646 cpl_matrix_delete(_ccf);
00647 _ccf = NULL;
00648
00649 if (sum != 0.) {
00650
00651 for (i = 0; i < nccf; i++) {
00652 cpl_matrix_set(ccf, 0, i, cpl_matrix_get(ccf, 0, i) / sum);
00653 }
00654
00655 }
00656
00657 return ccf;
00658
00659 }
00660
00661
00662 inline static cxint
00663 _giraffe_create_setup(GiSGSetup* setup, const GiImage* spectra)
00664 {
00665
00666 cpl_propertylist* properties = NULL;
00667
00668 cpl_image* _spectra = NULL;
00669
00670
00671 cx_assert(setup != NULL);
00672 cx_assert(spectra != NULL);
00673
00674 properties = giraffe_image_get_properties(spectra);
00675 cx_assert(properties != NULL);
00676
00677 _spectra = giraffe_image_get(spectra);
00678 cx_assert(_spectra != NULL);
00679
00680
00681
00682
00683
00684
00685 setup->nx = cpl_image_get_size_y(_spectra);
00686
00687
00688 if (!cpl_propertylist_has(properties, GIALIAS_EXT_NX)) {
00689 return 1;
00690 }
00691 else {
00692
00693 setup->nex = cpl_propertylist_get_int(properties, GIALIAS_EXT_NX);
00694
00695 }
00696
00697 if (!cpl_propertylist_has(properties, GIALIAS_BINSCALE)) {
00698 return 1;
00699 }
00700 else {
00701
00702 const cxchar* s = cpl_propertylist_get_string(properties,
00703 GIALIAS_BINSCALE);
00704
00705
00706 if (cx_strncasecmp(s, "log", 3) == 0) {
00707 setup->scale = GIREBIN_SCALE_LOG;
00708 }
00709 else {
00710 setup->scale = GIREBIN_SCALE_LINEAR;
00711 }
00712
00713 }
00714
00715 if (!cpl_propertylist_has(properties, GIALIAS_BINWLMIN)) {
00716 return 1;
00717 }
00718 else {
00719 setup->wlmin = cpl_propertylist_get_double(properties,
00720 GIALIAS_BINWLMIN);
00721 }
00722
00723 if (!cpl_propertylist_has(properties, GIALIAS_BINSTEP)) {
00724 return 1;
00725 }
00726 else {
00727 setup->wlstep = cpl_propertylist_get_double(properties,
00728 GIALIAS_BINSTEP);
00729 }
00730
00731 setup->wlmax = setup->wlmin + (setup->nx - 1) * setup->wlstep;
00732
00733
00734 if (!cpl_propertylist_has(properties, GIALIAS_PIXSIZY)) {
00735 return 1;
00736 }
00737 else {
00738 setup->pixelsize = cpl_propertylist_get_double(properties,
00739 GIALIAS_PIXSIZY);
00740 }
00741
00742 return 0;
00743
00744 }
00745
00746
00747 inline static cxint
00748 _giraffe_peak_fit(GiCPeakFit* peak, const cpl_matrix* lambda,
00749 const cpl_matrix* ccf, const GiGrating* grating,
00750 const GiCPFitParams* setup)
00751 {
00752
00753 const cxchar* const fctid = "_giraffe_peak_fit";
00754
00755
00756 cxbool stop = FALSE;
00757
00758 cxint i;
00759 cxint dn1 = 0;
00760 cxint dn2 = 0;
00761
00762 cxdouble amplitude = 0.;
00763 cxdouble background = 0.;
00764 cxdouble center = 0.;
00765 cxdouble width = 0.;
00766 cxdouble lower = 0.;
00767 cxdouble upper = 0.;
00768
00769 struct {
00770 cxdouble amplitude;
00771 cxdouble background;
00772 cxdouble center;
00773 cxdouble width;
00774 } initial = {0., 0., 0., 0.};
00775
00776 cpl_size nr = 0;
00777 cpl_size nc = 0;
00778
00779 GiModel* model = giraffe_model_new("gaussian");
00780
00781
00782
00783 cx_assert(model != NULL);
00784 cx_assert(strcmp(giraffe_model_get_name(model), "gaussian") == 0);
00785 cx_assert(lambda != NULL);
00786 cx_assert(ccf != NULL);
00787 cx_assert(grating != NULL);
00788 cx_assert(setup != NULL);
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 background = 0.;
00799
00800 amplitude = cpl_matrix_get_max((cpl_matrix*)ccf) - background;
00801
00802 cpl_matrix_get_maxpos((cpl_matrix*)ccf, &nr, &nc);
00803 cx_assert(nr == 0);
00804
00805 center = cpl_matrix_get((cpl_matrix*)lambda, 0, nc);
00806
00807
00808 if (setup->scale == GIREBIN_SCALE_LOG) {
00809 width = 0.5 / grating->resol;
00810 }
00811 else {
00812 width = 0.5 / grating->resol * grating->wlen0;
00813 }
00814
00815 giraffe_model_set_parameter(model, "Background", background);
00816 giraffe_model_set_parameter(model, "Amplitude", amplitude);
00817 giraffe_model_set_parameter(model, "Center", center);
00818 giraffe_model_set_parameter(model, "Width1", width);
00819
00820 giraffe_model_thaw(model);
00821
00822 giraffe_model_set_iterations(model, setup->fit.iterations);
00823 giraffe_model_set_tests(model, setup->fit.tests);
00824 giraffe_model_set_delta(model, setup->fit.delta);
00825
00826
00827
00828
00829
00830
00831 initial.amplitude = amplitude;
00832 initial.background = background;
00833 initial.center = center;
00834 initial.width = width;
00835
00836 i = 0;
00837
00838 while (i < setup->iterations && !stop) {
00839
00840 cxint j;
00841 cxint _dn1 = 0;
00842 cxint _dn2 = 0;
00843
00844 cxdouble dwc = 0.;
00845 cxdouble dwd = 0.;
00846
00847 cpl_matrix* tlambda = (cpl_matrix*)lambda;
00848 cpl_matrix* tccf = (cpl_matrix*)ccf;
00849
00850
00851
00852
00853
00854
00855
00856
00857 if (i == 1) {
00858
00859 const cxdouble da = 0.2;
00860 const cxdouble dc = 1.;
00861 const cxdouble db = 1.;
00862 const cxdouble dw = 0.2;
00863
00864 cxdouble value = 0.;
00865
00866 value = giraffe_model_get_parameter(model, "Amplitude") * da;
00867 value += (1. - da) * initial.amplitude;
00868
00869 giraffe_model_set_parameter(model, "Amplitude", value);
00870
00871
00872 value = giraffe_model_get_parameter(model, "Center") * dc;
00873 value += (1. - dc) * initial.center;
00874
00875 giraffe_model_set_parameter(model, "Center", value);
00876
00877
00878 value = giraffe_model_get_parameter(model, "Background") * db;
00879 value += (1. - db) * initial.background;
00880
00881 giraffe_model_set_parameter(model, "Background", value);
00882
00883
00884 value = giraffe_model_get_parameter(model, "Width1") * dw;
00885 value += (1. - dw) * initial.width;
00886
00887 giraffe_model_set_parameter(model, "Width1", value);
00888
00889 }
00890
00891
00892
00893
00894
00895
00896
00897 dwd = 2. * giraffe_model_get_parameter(model, "Width1") *
00898 setup->wfactor;
00899 dwc = giraffe_model_get_parameter(model, "Center");
00900
00901 dwd = CX_MAX(setup->dnmin, 2. * dwd / setup->step) * setup->step / 2.;
00902
00903 lower = dwc + 0.5 * setup->step - dwd;
00904 upper = dwc + 0.5 * setup->step + dwd;
00905
00906
00907
00908
00909
00910
00911
00912
00913 for (j = 0; j < cpl_matrix_get_ncol(tlambda); j++) {
00914
00915 if (cpl_matrix_get(tlambda, 0, j) > lower) {
00916 _dn1 = j;
00917 break;
00918 }
00919
00920 }
00921
00922 for (j = cpl_matrix_get_ncol(tlambda) - 1; j >= 0; j--) {
00923
00924 if (cpl_matrix_get(tlambda, 0, j) < upper) {
00925 _dn2 = j + 1;
00926 break;
00927 }
00928
00929 }
00930
00931
00932 if (i > 0 && dn1 == _dn1 && dn2 == _dn2) {
00933
00934 cxdouble _width = giraffe_model_get_parameter(model, "Width1");
00935
00936
00937
00938
00939
00940
00941 dwd = CX_MAX(setup->dnmin, 4. * _width * setup->wfactor /
00942 setup->step) * setup->step / 2.;
00943
00944 lower = dwc + 0.5 * setup->step - dwd;
00945 upper = dwc + 0.5 * setup->step + dwd;
00946
00947 for (j = 0; j < cpl_matrix_get_ncol(tlambda); j++) {
00948
00949 if (cpl_matrix_get(tlambda, 0, j) > lower) {
00950 _dn1 = j;
00951 break;
00952 }
00953
00954 }
00955
00956 for (j = cpl_matrix_get_ncol(tlambda) - 1; j <= 0; j--) {
00957
00958 if (cpl_matrix_get(tlambda, 0, j) < upper) {
00959 _dn2 = j + 1;
00960 break;
00961 }
00962
00963 }
00964
00965 stop = TRUE;
00966
00967 }
00968
00969
00970
00971
00972
00973
00974
00975 if (i <= 1 || dn1 != _dn1 || dn2 != _dn2) {
00976
00977 cxbool flag = FALSE;
00978
00979 const cxint pflag = 1;
00980 cxint status = 0;
00981
00982 cxdouble damplitude = 0.;
00983 cxdouble dbackground = 0.;
00984 cxdouble dcenter = 0.;
00985 cxdouble dwidth = 0.;
00986
00987 cpl_matrix* x = NULL;
00988 cpl_matrix* y = NULL;
00989 cpl_matrix* sigma = NULL;
00990
00991
00992 dn1 = _dn1;
00993 dn2 = _dn2;
00994
00995 x = cpl_matrix_new(dn2 - dn1, 1);
00996 y = cpl_matrix_new(dn2 - dn1, 1);
00997 sigma = cpl_matrix_new(dn2 - dn1, 1);
00998
00999 for (j = 0; j < cpl_matrix_get_nrow(y); j++) {
01000
01001 cpl_matrix_set(x, j, 0, cpl_matrix_get(tlambda, 0, dn1 + j));
01002 cpl_matrix_set(y, j, 0, cpl_matrix_get(tccf, 0, dn1 + j));
01003 cpl_matrix_set(sigma, j, 0, setup->sigma);
01004
01005 }
01006
01007
01008
01009
01010
01011
01012 status = giraffe_model_fit(model, x, y, sigma);
01013
01014 if (status != 0) {
01015
01016 peak->amplitude.value = initial.amplitude;
01017 peak->background.value = initial.background;
01018 peak->center.value = initial.center;
01019 peak->width.value = initial.width;
01020
01021 peak->amplitude.sigma = 1.;
01022 peak->background.sigma = 1.;
01023 peak->center.sigma = 1.;
01024 peak->width.sigma = 1.;
01025
01026 peak->status = -1;
01027
01028 cpl_matrix_delete(x);
01029 cpl_matrix_delete(y);
01030 cpl_matrix_delete(sigma);
01031
01032 giraffe_model_delete(model);
01033
01034 return 1;
01035
01036 }
01037
01038
01039
01040
01041
01042
01043
01044 amplitude = giraffe_model_get_parameter(model, "Amplitude");
01045 damplitude = giraffe_model_get_sigma(model, "Amplitude");
01046
01047 center = giraffe_model_get_parameter(model, "Center");
01048 dcenter = giraffe_model_get_sigma(model, "Center");
01049
01050 background = giraffe_model_get_parameter(model, "Background");
01051 dbackground = giraffe_model_get_sigma(model, "Background");
01052
01053 width = giraffe_model_get_parameter(model, "Width1");
01054 dwidth = giraffe_model_get_sigma(model, "Width1");
01055
01056
01057
01058
01059
01060
01061
01062 lower = -9. * (1 - pflag) + 1.e-5 * pflag;
01063 upper = 9. * pflag - 1.e-5 * (1 - pflag);
01064
01065 peak->amplitude.value = _giraffe_clip_value(amplitude, lower,
01066 upper, &flag);
01067 peak->amplitude.sigma = _giraffe_clip_value(damplitude, 0.,
01068 1., NULL);
01069
01070 stop = stop == FALSE ? flag == TRUE ? TRUE : FALSE : stop;
01071
01072
01073
01074 lower = cpl_matrix_get(x, 1, 0);
01075 upper = cpl_matrix_get(x, cpl_matrix_get_nrow(x) - 2, 0);
01076
01077 peak->center.value = _giraffe_clip_value(center, lower,
01078 upper, &flag);
01079 peak->center.sigma = _giraffe_clip_value(dcenter, 0.,
01080 initial.width, NULL);
01081
01082 stop = stop == FALSE ? flag == TRUE ? TRUE : FALSE : stop;
01083
01084
01085
01086 lower = -2;
01087 upper = 2.;
01088
01089 peak->background.value = _giraffe_clip_value(background, lower,
01090 upper, &flag);
01091 peak->background.sigma = _giraffe_clip_value(dbackground, 0.,
01092 1., NULL);
01093
01094 stop = stop == FALSE ? flag == TRUE ? TRUE : FALSE : stop;
01095
01096
01097
01098 lower = 0.5 * initial.width;
01099 upper = 2. * (cpl_matrix_get(x, cpl_matrix_get_nrow(x) - 2, 0) -
01100 cpl_matrix_get(x, 0, 0));
01101
01102 peak->width.value = _giraffe_clip_value(width, lower,
01103 upper, &flag);
01104 peak->width.sigma = _giraffe_clip_value(dwidth, 0.,
01105 9., NULL);
01106
01107 stop = stop == FALSE ? flag == TRUE ? TRUE : FALSE : stop;
01108
01109 cpl_matrix_delete(x);
01110 cpl_matrix_delete(y);
01111 cpl_matrix_delete(sigma);
01112
01113 if (stop == TRUE) {
01114 cpl_msg_debug(fctid, "Cross-correlation peak fit "
01115 "parameter out of bounds!");
01116
01117 peak->status = 1;
01118 }
01119 else {
01120 peak->status = 0;
01121 }
01122
01123 ++i;
01124
01125 }
01126 else {
01127
01128 stop = TRUE;
01129
01130 }
01131
01132 }
01133
01134 giraffe_model_delete(model);
01135
01136 return 0;
01137
01138 }
01139
01140
01141 inline static cxint
01142 _giraffe_compute_fiber_offsets(cpl_table* offsets,
01143 const GiGrating* grating,
01144 const GiSGSetup* setup)
01145 {
01146
01147 cxint i;
01148
01149 const cxdouble ccdfactor = 1.1;
01150
01151 cxdouble gcamera = 1.;
01152 cxdouble cfactor = 1.;
01153 cxdouble lincorr = 1.;
01154 cxdouble wlen0 = 0.;
01155
01156
01157 cx_assert(offsets != NULL);
01158
01159 if (!cpl_table_has_column(offsets, "WAVELENGTH")) {
01160 return 1;
01161 }
01162
01163 if (!cpl_table_has_column(offsets, "DWF")) {
01164 cpl_table_new_column(offsets, "DWF", CPL_TYPE_DOUBLE);
01165 }
01166
01167 if (!cpl_table_has_column(offsets, "DXF")) {
01168 cpl_table_new_column(offsets, "DXF", CPL_TYPE_DOUBLE);
01169 }
01170
01171
01172
01173
01174
01175
01176
01177 if (setup->scale == GIREBIN_SCALE_LOG) {
01178 wlen0 = 0.5 * (exp(setup->wlmin) + exp(setup->wlmax));
01179 }
01180 else {
01181 wlen0 = 0.5 * (setup->wlmin + setup->wlmax);
01182 }
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193 gcamera = 0.3894 - 5. * (1. / wlen0 - 1. / 550.) -
01194 0.00025 * pow(1. / wlen0 - 1. / 550., 2.);
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204 cfactor = (setup->nex * setup->pixelsize / 1000. * ccdfactor) /
01205 ((grating->wlenmax - grating->wlenmin) * gcamera);
01206
01207
01208
01209
01210
01211
01212 if (setup->scale == GIREBIN_SCALE_LOG) {
01213 lincorr = 1.0;
01214 }
01215 else {
01216 lincorr = 0.5 * (setup->wlmin + setup->wlmax) /
01217 exp(0.5 * (log(setup->wlmin) + log(setup->wlmax)));
01218 }
01219
01220
01221
01222
01223
01224
01225 for (i = 0; i < cpl_table_get_nrow(offsets); i++) {
01226
01227
01228 cxdouble dwf = cpl_table_get_double(offsets, "WAVELENGTH", i, NULL);
01229 cxdouble dxf = 0.;
01230
01231
01232 dwf *= -lincorr;
01233 dxf = dwf * cfactor;
01234
01235 cpl_table_set_double(offsets, "DWF", i, dwf);
01236 cpl_table_set_double(offsets, "DXF", i, dxf);
01237
01238 }
01239
01240 return 0;
01241
01242 }
01243
01244
01245 inline static cpl_table*
01246 _giraffe_compute_offsets(const GiImage* spectra, const GiTable* mask,
01247 const cpl_table* fibers, const GiGrating* grating,
01248 const GiSGSetup* setup, const GiSGCalConfig* config)
01249 {
01250
01251 const cxchar* const fctid = "_giraffe_compute_offsets";
01252
01253 const cxint dnmin = 7;
01254
01255 cxint i;
01256 cxint k;
01257 cxint status = 0;
01258 cxint sampling = 0;
01259 cxint pixel0 = 0;
01260 cxint dn1 = 0;
01261 cxint dn2 = 0;
01262 cxint dnc = 0;
01263 cxint dnd = 0;
01264 cxint xc1 = 0;
01265 cxint xc2 = 0;
01266
01267 const cxdouble clight = 299702.547;
01268
01269 cxdouble cstep = 0.;
01270 cxdouble wlen0 = 0.;
01271 cxdouble nm2km = clight;
01272 cxdouble hpixels = 0.;
01273 cxdouble dv1 = 0.;
01274 cxdouble dv2 = 0.;
01275 cxdouble dw1 = 0.;
01276 cxdouble dw2 = 0.;
01277 cxdouble dwc = 0.;
01278 cxdouble dwd = 0.;
01279
01280 cpl_matrix* spectrum = NULL;
01281
01282 cpl_image* _spectra = NULL;
01283 cpl_image* tspectra = NULL;
01284
01285 cpl_table* peakdata = NULL;
01286
01287 GiSGMask* _mask = NULL;
01288
01289
01290 cx_assert(spectra != NULL);
01291 cx_assert(mask != NULL);
01292 cx_assert(fibers != NULL);
01293 cx_assert(grating != NULL);
01294 cx_assert(setup != NULL);
01295 cx_assert(config != NULL);
01296
01297
01298
01299
01300
01301
01302 if (config->cc_step <= 0.) {
01303 sampling = 1;
01304 }
01305 else {
01306
01307 if (setup->scale == GIREBIN_SCALE_LOG) {
01308
01309 cxdouble wlstep = (exp(setup->wlmax) - exp(setup->wlmin)) /
01310 setup->nx;
01311
01312 sampling = (cxint)(0.5 + wlstep / config->cc_step);
01313
01314 }
01315 else {
01316
01317 sampling = (cxint)(0.5 + setup->wlstep / config->cc_step);
01318
01319 }
01320
01321 }
01322
01323 cstep = setup->wlstep / sampling;
01324
01325
01326
01327
01328
01329
01330 _mask = _giraffe_sgmask_create((setup->nx - 1) * sampling + 1,
01331 setup->wlmin, cstep, setup->scale,
01332 mask);
01333
01334 if (_mask == NULL) {
01335 return NULL;
01336 }
01337
01338
01339
01340
01341
01342
01343 pixel0 = setup->nx / 2;
01344
01345 if (setup->scale == GIREBIN_SCALE_LOG) {
01346
01347
01348
01349
01350
01351 wlen0 = 0.5 * (exp(setup->wlmin) + exp(setup->wlmax));
01352 nm2km = clight;
01353
01354 }
01355 else {
01356
01357
01358
01359
01360
01361 wlen0 = 0.5 * (setup->wlmin + setup->wlmax);
01362 nm2km = clight / wlen0;
01363
01364 }
01365
01366
01367
01368
01369
01370
01371
01372 dv1 = giraffe_range_get_min(config->rv_limits);
01373 dv2 = giraffe_range_get_max(config->rv_limits);
01374
01375 dw1 = dv1 / nm2km;
01376 dw2 = dv2 / nm2km;
01377
01378 cpl_msg_debug(fctid, "Cross-correlation limits: RVlow = %.4f km/s "
01379 "(%.4f nm), RVhigh = %.4f km/s (%.4f nm)", dv1, dw1,
01380 dv2, dw2);
01381
01382 dwd = (dw2 - dw1) / 2.;
01383 dwc = (dw2 + dw1) / 2.;
01384
01385 dnd = CX_MIN(pixel0, CX_MAX(dnmin, (cxint)(dwd / cstep + 0.5)));
01386 dnc = CX_MIN(pixel0, CX_MAX(-pixel0, (cxint)(dwc / cstep + 0.5)));
01387
01388 dn1 = CX_MIN(pixel0 + 1, CX_MAX(-pixel0, dnc - dnd));
01389 dn2 = CX_MIN(pixel0 + 1, CX_MAX(-pixel0, dnc + dnd + 1));
01390
01391 cpl_msg_debug(fctid, "Cross-correlation window: center = %.4f nm "
01392 "(%d pxl) half-width = %.4f nm (%d pxl)", dwc, dnc,
01393 dwd, dnd);
01394
01395
01396
01397
01398
01399
01400
01401 xc1 = (cxint)(giraffe_range_get_min(config->cc_domain) * sampling);
01402 xc2 = (cxint)(giraffe_range_get_max(config->cc_domain) * sampling);
01403
01404 if (xc1 > 0 || xc2 > 0) {
01405 _giraffe_sgmask_crop(_mask, xc1, xc2);
01406 }
01407
01408 for (i = 0; (cxsize)i < _giraffe_sgmask_size(_mask); i++) {
01409
01410 cxdouble value = _giraffe_sgmask_get_flux(_mask, i);
01411
01412 if (value > 0.) {
01413 hpixels += value;
01414 }
01415
01416 }
01417
01418 hpixels /= _giraffe_sgmask_holes(_mask);
01419
01420
01421
01422
01423
01424
01425
01426
01427 i = 0;
01428 k = CX_MAX(0, -dn1);
01429
01430 while (i < k || _giraffe_sgmask_get_flux(_mask, i) > 0.) {
01431
01432 _giraffe_sgmask_set_flux(_mask, i, 0.);
01433 ++i;
01434
01435 }
01436
01437 cpl_msg_debug(fctid, "Mask cleared from 0 to %d", i - 1);
01438
01439 i = _giraffe_sgmask_size(_mask);
01440 k = _giraffe_sgmask_size(_mask) - CX_MAX(0, dn2);
01441
01442 while (i > k || _giraffe_sgmask_get_flux(_mask, i) > 0.) {
01443
01444 _giraffe_sgmask_set_flux(_mask, i, 0.);
01445 --i;
01446
01447 }
01448
01449 cpl_msg_debug(fctid, "Mask cleared from %d to %ld", k,
01450 _giraffe_sgmask_size(_mask) - 1);
01451
01452
01453
01454
01455
01456
01457
01458 _spectra = cpl_image_duplicate(giraffe_image_get(spectra));
01459
01460 if (_spectra == NULL) {
01461
01462 _giraffe_sgmask_delete(_mask);
01463
01464 return NULL;
01465
01466 }
01467
01468
01469 if (config->zmax > 0.) {
01470
01471 cpl_image_threshold(_spectra, CX_MINDOUBLE, config->zmax,
01472 0., config->zmax);
01473
01474 }
01475
01476
01477 tspectra = _giraffe_resample_image(_spectra, setup->wlstep, cstep);
01478
01479 if (tspectra == NULL) {
01480
01481 cpl_image_delete(_spectra);
01482
01483 _giraffe_sgmask_delete(_mask);
01484
01485 return NULL;
01486
01487 }
01488
01489 cpl_image_delete(_spectra);
01490 _spectra = NULL;
01491
01492 if (xc1 > 0 || xc2 > 0) {
01493
01494 _spectra = cpl_image_extract(tspectra, 1, xc1 + 1,
01495 cpl_image_get_size_x(tspectra), xc2 + 1);
01496
01497 if (_spectra == NULL) {
01498
01499 cpl_image_delete(tspectra);
01500
01501 _giraffe_sgmask_delete(_mask);
01502
01503 return NULL;
01504
01505 }
01506
01507 cpl_image_delete(tspectra);
01508 tspectra = NULL;
01509
01510 }
01511 else {
01512
01513 _spectra = tspectra;
01514 tspectra = NULL;
01515
01516 }
01517
01518
01519
01520
01521
01522
01523
01524 peakdata = cpl_table_new(cpl_table_get_nrow(fibers));
01525
01526 cpl_table_duplicate_column(peakdata, "INDEX", (cpl_table*)fibers,
01527 "INDEX");
01528 cpl_table_duplicate_column(peakdata, "FPS", (cpl_table*)fibers,
01529 "FPS");
01530
01531 cpl_table_new_column(peakdata, "WAVELENGTH", CPL_TYPE_DOUBLE);
01532 cpl_table_new_column(peakdata, "FWHM", CPL_TYPE_DOUBLE);
01533 cpl_table_new_column(peakdata, "AMPLITUDE", CPL_TYPE_DOUBLE);
01534 cpl_table_new_column(peakdata, "BACKGROUND", CPL_TYPE_DOUBLE);
01535 cpl_table_new_column(peakdata, "RV", CPL_TYPE_DOUBLE);
01536 cpl_table_new_column(peakdata, "RVERR", CPL_TYPE_DOUBLE);
01537 cpl_table_new_column(peakdata, "RESOLUTION", CPL_TYPE_DOUBLE);
01538 cpl_table_new_column(peakdata, "STATUS", CPL_TYPE_INT);
01539
01540
01541
01542
01543
01544
01545
01546 cpl_msg_debug(fctid, "Computing cross-correlation: central wavelength = "
01547 "%.4f, window = [%.4f, %.4f] [km/s]", wlen0, dv1, dv2);
01548
01549 spectrum = cpl_matrix_new(1, cpl_image_get_size_y(_spectra));
01550
01551 for (i = 0; i < cpl_table_get_nrow(fibers); i++) {
01552
01553 cxint j;
01554 cxint ns = cpl_image_get_size_x(_spectra);
01555 cxint fiber = cpl_table_get_int(fibers, "FPS", i, NULL);
01556 cxint idx = cpl_table_get_int(fibers, "INDEX", i, NULL) - 1;
01557
01558 const cxdouble fwhm_ratio = 2. * sqrt(2. * log(2.));
01559
01560 cxdouble avsigma = 0.;
01561 cxdouble fx = 0.;
01562 cxdouble fxtotal = 0.;
01563 cxdouble fxaverage = 0.;
01564 cxdouble fxmask = 0.;
01565 cxdouble sum = 0.;
01566 cxdouble position = 0.;
01567 cxdouble fwhm = 0.;
01568 cxdouble width = 0.;
01569 cxdouble resolution = 0.;
01570 cxdouble rv = 0.;
01571 cxdouble rverr = 0.;
01572 cxdouble* data = cpl_image_get_data(_spectra);
01573
01574 const cpl_matrix* template = NULL;
01575 cpl_matrix* ccf = NULL;
01576 cpl_matrix* lambda = NULL;
01577
01578 GiCPFitParams peak_setup;
01579 GiCPeakFit peak;
01580
01581
01582
01583
01584
01585
01586
01587
01588 for (j = 0; j < cpl_matrix_get_ncol(spectrum); j++) {
01589
01590 cxdouble flux = data[j * ns + idx];
01591
01592
01593 cpl_matrix_set(spectrum, 0, j, flux);
01594
01595 fxtotal += flux;
01596 fxmask += _giraffe_sgmask_get_flux(_mask, j);
01597 fx += flux * _giraffe_sgmask_get_flux(_mask, j);
01598
01599 }
01600
01601 fx /= sampling;
01602 fxaverage = fxtotal / fxmask;
01603
01604 if (fx > 0.) {
01605 avsigma = 1. / sqrt(fx);
01606 }
01607
01608 cpl_msg_debug(fctid, "Cross-correlation of spectrum %d in window "
01609 "from %d pxl to %d pxl (%.4f nm to %.4f nm)", fiber,
01610 dn1, dn2, dw1, dw2);
01611
01612
01613
01614
01615
01616
01617 lambda = cpl_matrix_new(1, dn2 - dn1);
01618
01619 for (j = dn1; j < dn2; j++) {
01620 cpl_matrix_set(lambda, 0, j - dn1, j * cstep);
01621 }
01622
01623
01624
01625
01626
01627
01628 template = _giraffe_sgmask_get(_mask);
01629
01630 ccf = _giraffe_compute_cross_correlation(spectrum, template, dn1, dn2);
01631
01632 if (ccf == NULL) {
01633
01634 cpl_matrix_delete(lambda);
01635 cpl_matrix_delete(spectrum);
01636
01637 cpl_image_delete(_spectra);
01638
01639 cpl_table_delete(peakdata);
01640
01641 _giraffe_sgmask_delete(_mask);
01642
01643 return NULL;
01644
01645 }
01646
01647 sum = 0.;
01648
01649 for (j = 0; j < cpl_matrix_get_ncol(ccf); j++) {
01650 sum += cpl_matrix_get(ccf, 0, j);
01651 }
01652
01653 if (sum <= 0.) {
01654 cpl_msg_debug(fctid, "Cross-correlation failed: Skipping "
01655 "spectrum %d.", fiber);
01656
01657 cpl_matrix_delete(lambda);
01658 lambda = NULL;
01659
01660 continue;
01661 }
01662
01663
01664
01665
01666
01667
01668 peak_setup.dnmin = dnmin;
01669 peak_setup.iterations = config->rv_niter;
01670 peak_setup.step = cstep;
01671 peak_setup.wfactor = config->rv_wfactor;
01672 peak_setup.sigma = avsigma;
01673 peak_setup.scale = setup->scale;
01674
01675 peak_setup.fit.iterations = config->pf_niter;
01676 peak_setup.fit.tests = config->pf_ntest;
01677 peak_setup.fit.delta = config->pf_dchisq;
01678
01679 status = _giraffe_peak_fit(&peak, lambda, ccf, grating, &peak_setup);
01680
01681 if (status < 0) {
01682
01683 cpl_matrix_delete(ccf);
01684 cpl_matrix_delete(lambda);
01685
01686 cpl_matrix_delete(spectrum);
01687 cpl_image_delete(_spectra);
01688
01689 cpl_table_delete(peakdata);
01690
01691 _giraffe_sgmask_delete(_mask);
01692
01693 return NULL;
01694
01695 }
01696
01697
01698
01699
01700
01701
01702 if (setup->scale == GIREBIN_SCALE_LOG) {
01703 position = peak.center.value * wlen0;
01704 fwhm = (exp(peak.width.value) - 1.) * wlen0;
01705 }
01706 else {
01707 position = peak.center.value;
01708 fwhm = peak.width.value;
01709 }
01710
01711 width = pow(fwhm_ratio * fwhm, 2.) - pow(0.6 * hpixels * cstep, 2.);
01712 resolution = width > 0. ? wlen0 / sqrt(width) : 0.;
01713
01714 fwhm *= 2.;
01715
01716 rv = CX_MAX(dv1, CX_MIN(dv2, peak.center.value * nm2km));
01717 rverr = CX_MIN(dv2 - dv1, peak.center.sigma * nm2km);
01718
01719 cpl_table_set_double(peakdata, "WAVELENGTH", i, position);
01720 cpl_table_set_double(peakdata, "FWHM", i, fwhm);
01721 cpl_table_set_double(peakdata, "AMPLITUDE", i, peak.amplitude.value);
01722 cpl_table_set_double(peakdata, "BACKGROUND", i,
01723 peak.background.value);
01724 cpl_table_set_double(peakdata, "RESOLUTION", i, resolution);
01725 cpl_table_set_double(peakdata, "RV", i, rv);
01726 cpl_table_set_double(peakdata, "RVERR", i, rverr);
01727 cpl_table_set_int(peakdata, "STATUS", i, peak.status);
01728
01729 cpl_matrix_delete(lambda);
01730 cpl_matrix_delete(ccf);
01731
01732 }
01733
01734 cpl_matrix_delete(spectrum);
01735 cpl_image_delete(_spectra);
01736
01737 _giraffe_sgmask_delete(_mask);
01738
01739 return peakdata;
01740
01741 }
01742
01743
01744 inline static cpl_table*
01745 _giraffe_compute_slitgeometry(const GiImage* spectra, const GiTable* mask,
01746 const GiTable* slitgeometry,
01747 const GiGrating* grating,
01748 const GiSGCalConfig* config)
01749 {
01750
01751 cxint status = 0;
01752
01753 cpl_table* _slitgeometry = giraffe_table_get(slitgeometry);
01754 cpl_table* peakdata = NULL;
01755
01756 GiSGSetup setup;
01757
01758
01759
01760
01761
01762
01763 status = _giraffe_create_setup(&setup, spectra);
01764
01765 if (status != 0) {
01766 return NULL;
01767 }
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781 peakdata = _giraffe_compute_offsets(spectra, mask, _slitgeometry,
01782 grating, &setup, config);
01783
01784 if (peakdata == NULL) {
01785 return NULL;
01786 }
01787
01788
01789
01790
01791
01792
01793
01794 status = _giraffe_compute_fiber_offsets(peakdata, grating, &setup);
01795
01796 if (status != 0) {
01797 cpl_table_delete(peakdata);
01798 return NULL;
01799 }
01800
01801
01802
01803
01804
01805
01806 cpl_table_duplicate_column(peakdata, "XF", _slitgeometry, "XF");
01807 cpl_table_add_columns(peakdata, "XF", "DXF");
01808
01809 return peakdata;
01810
01811 }
01812
01813
01814 inline static GiTable*
01815 _giraffe_slitgeometry_table(const cpl_table* offsets,
01816 const GiImage* spectra,
01817 const GiTable* fibers,
01818 const GiTable* slitgeometry,
01819 const GiSGCalConfig* config)
01820 {
01821
01822 const cxchar* idx = NULL;
01823
01824 cxint i;
01825
01826 cpl_propertylist* properties = NULL;
01827 cpl_propertylist* _properties = NULL;
01828
01829 cpl_table* _slit = NULL;
01830 cpl_table* _fibers = NULL;
01831 cpl_table* _slitgeometry = NULL;
01832
01833 GiTable* slit = NULL;
01834
01835
01836 cx_assert(spectra != NULL);
01837 cx_assert(fibers != NULL);
01838
01839 _fibers = giraffe_table_get(fibers);
01840 cx_assert(_fibers != NULL);
01841
01842 _slitgeometry = giraffe_table_get(slitgeometry);
01843 cx_assert(_slitgeometry != NULL);
01844
01845 if (offsets == NULL) {
01846 return NULL;
01847 }
01848
01849
01850 slit = giraffe_table_new();
01851
01852 properties = giraffe_image_get_properties(spectra);
01853 cx_assert(properties != NULL);
01854
01855 giraffe_error_push();
01856
01857 _properties = cpl_propertylist_new();
01858
01859 giraffe_propertylist_copy(_properties, GIALIAS_INSTRUMENT, properties,
01860 GIALIAS_INSTRUMENT);
01861
01862 giraffe_propertylist_copy(_properties, GIALIAS_DATEOBS, properties,
01863 GIALIAS_DATEOBS);
01864
01865 giraffe_propertylist_copy(_properties, GIALIAS_MJDOBS, properties,
01866 GIALIAS_MJDOBS);
01867
01868 giraffe_propertylist_copy(_properties, GIALIAS_INSMODE, properties,
01869 GIALIAS_INSMODE);
01870
01871 giraffe_propertylist_copy(_properties, GIALIAS_INSMODE, properties,
01872 GIALIAS_INSMODE);
01873
01874 giraffe_propertylist_copy(_properties, GIALIAS_SETUPNAME, properties,
01875 GIALIAS_SETUPNAME);
01876
01877 giraffe_propertylist_copy(_properties, GIALIAS_SLITNAME, properties,
01878 GIALIAS_SLITNAME);
01879
01880 giraffe_propertylist_copy(_properties, GIALIAS_FILTNAME, properties,
01881 GIALIAS_FILTNAME);
01882
01883 giraffe_propertylist_copy(_properties, GIALIAS_GRATNAME, properties,
01884 GIALIAS_GRATNAME);
01885
01886 giraffe_propertylist_copy(_properties, GIALIAS_GRATWLEN, properties,
01887 GIALIAS_GRATWLEN);
01888
01889 giraffe_propertylist_copy(_properties, GIALIAS_GRATORDER, properties,
01890 GIALIAS_GRATORDER);
01891
01892 cpl_propertylist_update_double(_properties, GIALIAS_SCAL_CUTOFF,
01893 config->zmax);
01894 cpl_propertylist_set_comment(_properties, GIALIAS_SCAL_CUTOFF,
01895 "Cutoff pixel value.");
01896
01897 cpl_propertylist_update_string(_properties, GIALIAS_GIRFTYPE, "SLITGEOTAB");
01898 cpl_propertylist_set_comment(_properties, GIALIAS_GIRFTYPE,
01899 "Giraffe frame type.");
01900
01901
01902 _slit = cpl_table_new(cpl_table_get_nrow(_fibers));
01903
01904 cpl_table_new_column(_slit, "INDEX", CPL_TYPE_INT);
01905
01906 for (i = 0; i < cpl_table_get_nrow(_slit); i++) {
01907 cpl_table_set_int(_slit, "INDEX", i, i + 1);
01908 }
01909
01910 cpl_table_duplicate_column(_slit, "FPS", (cpl_table*)_fibers, "FPS");
01911 cpl_table_duplicate_column(_slit, "SSN", (cpl_table*)_fibers, "SSN");
01912 cpl_table_duplicate_column(_slit, "XF", (cpl_table*)offsets, "XF");
01913 cpl_table_duplicate_column(_slit, "YF", (cpl_table*)_slitgeometry, "YF");
01914
01915 if (cpl_table_has_column(_slitgeometry, "ZF")) {
01916 cpl_table_duplicate_column(_slit, "ZF",
01917 (cpl_table*)_slitgeometry, "ZF");
01918 }
01919
01920 if (cpl_table_has_column(_slitgeometry, "ZDEFOCUS")) {
01921 cpl_table_duplicate_column(_slit, "ZDEFOCUS",
01922 (cpl_table*)_slitgeometry, "ZDEFOCUS");
01923 }
01924
01925 cpl_table_duplicate_column(_slit, "RV", (cpl_table*)offsets, "RV");
01926 cpl_table_duplicate_column(_slit, "RVERR", (cpl_table*)offsets, "RVERR");
01927 cpl_table_duplicate_column(_slit, "RESOLUTION", (cpl_table*)offsets,
01928 "RESOLUTION");
01929
01930 idx = giraffe_fiberlist_query_index(_fibers);
01931 cpl_table_duplicate_column(_slit, "RINDEX", _fibers, idx);
01932
01933 if (cpl_error_get_code() != CPL_ERROR_NONE) {
01934 cpl_propertylist_delete(_properties);
01935 cpl_table_delete(_slit);
01936
01937 giraffe_table_delete(slit);
01938
01939 return NULL;
01940 }
01941
01942 giraffe_error_pop();
01943
01944 giraffe_table_set_properties(slit, _properties);
01945 cpl_propertylist_delete(_properties);
01946
01947 giraffe_table_set(slit, _slit);
01948 cpl_table_delete(_slit);
01949
01950 return slit;
01951
01952 }
01953
01954
01960 cxint
01961 giraffe_calibrate_slit(GiTable* result, const GiExtraction* extraction,
01962 const GiLocalization* localization,
01963 const GiTable* fibers, const GiTable* wlsolution,
01964 const GiTable* slitgeometry, const GiTable* grating,
01965 const GiTable* mask, const GiSGCalConfig* config)
01966 {
01967
01968 const cxchar* const fctid = "giraffe_calibrate_slit";
01969
01970 cxint i;
01971 cxint status = 0;
01972
01973 cpl_table* _fibers = NULL;
01974 cpl_table* _slitgeometry = NULL;
01975 cpl_table* offsets = NULL;
01976
01977 GiTable* slit = NULL;
01978
01979 GiGrating* setup = NULL;
01980
01981 GiExtraction* _extraction = NULL;
01982
01983
01984 if (result == NULL) {
01985 return 1;
01986 }
01987
01988 if (extraction == NULL) {
01989 return 1;
01990 }
01991
01992 if (extraction->spectra == NULL) {
01993 return 1;
01994 }
01995
01996 if (localization == NULL) {
01997 return 1;
01998 }
01999
02000 if (fibers == NULL) {
02001 return 1;
02002 }
02003
02004 if (wlsolution == NULL) {
02005 return 1;
02006 }
02007
02008 if (slitgeometry == NULL) {
02009 return 1;
02010 }
02011
02012 if (grating == NULL) {
02013 return 1;
02014 }
02015
02016 if (mask == NULL) {
02017 return 1;
02018 }
02019
02020 if (config == NULL) {
02021 return 1;
02022 }
02023
02024
02025 _fibers = giraffe_table_get(fibers);
02026 cx_assert(_fibers != NULL);
02027
02028 _slitgeometry = giraffe_table_get(slitgeometry);
02029 cx_assert(_slitgeometry != NULL);
02030
02031 if (cpl_table_get_nrow(_fibers) != cpl_table_get_nrow(_slitgeometry)) {
02032 return 2;
02033 }
02034
02035
02036
02037
02038
02039
02040 setup = giraffe_grating_create(extraction->spectra, grating);
02041
02042 if (setup == NULL) {
02043 return 3;
02044 }
02045
02046
02047
02048
02049
02050
02051
02052 _extraction = giraffe_extraction_new();
02053
02054 _extraction->spectra = extraction->spectra;
02055 _extraction->error = NULL;
02056
02057
02058 slit = giraffe_table_duplicate(slitgeometry);
02059
02060 for (i = 0; i < config->repeat; i++) {
02061
02062 cxint fps_rvmin = 0;
02063 cxint fps_rvmax = 0;
02064
02065 cxdouble rvmin = 0.;
02066 cxdouble rvmax = 0.;
02067 cxdouble rvmean = 0.;
02068
02069 cpl_size row = 0;
02070
02071 GiRebinning* rebinning = giraffe_rebinning_new();
02072
02073 GiRebinConfig rebin_config = {
02074 GIREBIN_METHOD_LINEAR,
02075 TRUE,
02076 0.005,
02077 GIREBIN_SCALE_LINEAR,
02078 0,
02079 GIREBIN_RANGE_SETUP
02080 };
02081
02082
02083 status = giraffe_rebin_spectra(rebinning, _extraction, fibers,
02084 localization, grating, slit,
02085 wlsolution, &rebin_config);
02086
02087 if (status != 0) {
02088 giraffe_table_delete(slit);
02089
02090 giraffe_extraction_delete(_extraction);
02091 giraffe_rebinning_destroy(rebinning);
02092
02093 giraffe_grating_delete(setup);
02094
02095 return 4;
02096 }
02097
02098 offsets = _giraffe_compute_slitgeometry(rebinning->spectra, mask,
02099 slit, setup, config);
02100
02101 if (offsets == NULL) {
02102 giraffe_table_delete(slit);
02103
02104 giraffe_extraction_delete(_extraction);
02105 giraffe_rebinning_destroy(rebinning);
02106
02107 giraffe_grating_delete(setup);
02108
02109 return 5;
02110 }
02111
02112
02113
02114
02115
02116
02117 cx_assert(cpl_table_get_nrow(offsets) == cpl_table_get_nrow(_fibers));
02118
02119 giraffe_table_delete(slit);
02120 slit = _giraffe_slitgeometry_table(offsets, rebinning->spectra,
02121 fibers, slitgeometry, config);
02122
02123 if (slit == NULL) {
02124
02125 cpl_table_delete(offsets);
02126
02127 giraffe_extraction_delete(_extraction);
02128 giraffe_rebinning_destroy(rebinning);
02129
02130 giraffe_grating_delete(setup);
02131
02132 return 6;
02133 }
02134
02135 cpl_table_delete(offsets);
02136 offsets = NULL;
02137
02138 rvmin = cpl_table_get_column_min(giraffe_table_get(slit), "RV");
02139 cpl_table_get_column_minpos(giraffe_table_get(slit), "RV", &row);
02140 fps_rvmin = cpl_table_get_int(giraffe_table_get(slit), "FPS",
02141 row, NULL);
02142
02143 rvmax = cpl_table_get_column_max(giraffe_table_get(slit), "RV");
02144 cpl_table_get_column_maxpos(giraffe_table_get(slit), "RV", &row);
02145 fps_rvmax = cpl_table_get_int(giraffe_table_get(slit), "FPS",
02146 row, NULL);
02147
02148 rvmean = cpl_table_get_column_mean(giraffe_table_get(slit), "RV");
02149
02150 cpl_msg_info(fctid, "Iteration %d: Fiber offsets [km/s]: minimum = "
02151 "%.6e (fps %d), maximum = %.6e (fps %d), mean = %.6e",
02152 i + 1, rvmin, fps_rvmin, rvmax, fps_rvmax, rvmean);
02153
02154 giraffe_rebinning_destroy(rebinning);
02155 rebinning = NULL;
02156
02157 }
02158
02159 giraffe_extraction_delete(_extraction);
02160 giraffe_grating_delete(setup);
02161
02162 cx_assert(slit != NULL);
02163
02164 giraffe_table_set_properties(result, giraffe_table_get_properties(slit));
02165 giraffe_table_set(result, giraffe_table_get(slit));
02166
02167 giraffe_table_delete(slit);
02168
02169 return 0;
02170
02171 }
02172
02173
02198 cxint
02199 giraffe_compute_offsets(GiTable* fibers, const GiRebinning* rebinning,
02200 const GiTable* grating, const GiTable* mask,
02201 const GiSGCalConfig* config)
02202 {
02203
02204 cxint status = 0;
02205 cxint nfibers = 0;
02206 cxint fiber = 0;
02207 cxint peak = 0;
02208 cxint fps = 0;
02209 cxint fps0 = 0;
02210 cxint fps1 = 0;
02211
02212 cxdouble dwf0 = 0.;
02213
02214 cpl_table* _fibers = NULL;
02215 cpl_table* peakdata = NULL;
02216
02217 GiGrating* _grating = NULL;
02218
02219 GiSGSetup setup;
02220
02221
02222 if ((rebinning == NULL) || (rebinning->spectra == NULL)) {
02223 return -1;
02224 }
02225
02226 if (fibers == NULL) {
02227 return -2;
02228 }
02229
02230 if (grating == NULL) {
02231 return -3;
02232 }
02233
02234 if (mask == NULL) {
02235 return -4;
02236 }
02237
02238 if (config == NULL) {
02239 return -5;
02240 }
02241
02242
02243 _fibers = giraffe_table_get(fibers);
02244 cx_assert(_fibers != NULL);
02245
02246
02247
02248
02249
02250
02251
02252 cpl_table_unselect_all(_fibers);
02253 cpl_table_or_selected_int(_fibers, "RP", CPL_EQUAL_TO, -1);
02254
02255 _fibers = cpl_table_extract_selected(_fibers);
02256
02257 if (_fibers == NULL) {
02258 return 1;
02259 }
02260
02261
02262
02263
02264
02265
02266 _grating = giraffe_grating_create(rebinning->spectra, grating);
02267
02268 if (_grating == NULL) {
02269 cpl_table_delete(_fibers);
02270 return 2;
02271 }
02272
02273
02274
02275
02276
02277 status = _giraffe_create_setup(&setup, rebinning->spectra);
02278
02279 if (status != 0) {
02280 cpl_table_delete(_fibers);
02281 return 3;
02282 }
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297 peakdata = _giraffe_compute_offsets(rebinning->spectra, mask, _fibers,
02298 _grating, &setup, config);
02299
02300 if (peakdata == NULL) {
02301 cpl_table_delete(_fibers);
02302 return 4;
02303 }
02304
02305
02306
02307
02308
02309
02310
02311 status = _giraffe_compute_fiber_offsets(peakdata, _grating, &setup);
02312
02313 if (status != 0) {
02314 cpl_table_delete(peakdata);
02315 cpl_table_delete(_fibers);
02316
02317 return 5;
02318 }
02319
02320 cpl_table_delete(_fibers);
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333 _fibers = giraffe_table_get(fibers);
02334
02335 giraffe_error_push();
02336
02337 cpl_table_new_column(_fibers, "WLRES", CPL_TYPE_DOUBLE);
02338 cpl_table_set_column_unit(_fibers, "WLRES", "nm");
02339
02340 if (cpl_error_get_code() != CPL_ERROR_NONE) {
02341 cpl_table_delete(peakdata);
02342 return 6;
02343 }
02344
02345 giraffe_error_pop();
02346
02347
02348 giraffe_error_push();
02349
02350 fps0 = cpl_table_get_int(peakdata, "FPS", 0, NULL);
02351 dwf0 = cpl_table_get_double(peakdata, "DWF", 0, NULL);
02352
02353 nfibers = cpl_table_get_nrow(_fibers);
02354
02355 fps = cpl_table_get_int(_fibers, "FPS", 0, NULL);
02356
02357 while (fps != fps0) {
02358
02359 cpl_table_set_double(_fibers, "WLRES", fiber, dwf0);
02360
02361 ++fiber;
02362 fps = cpl_table_get_int(_fibers, "FPS", fiber, NULL);
02363
02364 }
02365
02366 for (peak = 1; peak < cpl_table_get_nrow(peakdata); ++peak) {
02367
02368 cxdouble dwf1 = cpl_table_get_double(peakdata, "DWF", peak, NULL);
02369 cxdouble slope = 0.;
02370
02371
02372 fps1 = cpl_table_get_int(peakdata, "FPS", peak, NULL);
02373
02374 slope = (dwf1 - dwf0) / ((cxdouble)(fps1 - fps0));
02375
02376 while (fps != fps1) {
02377
02378 cpl_table_set_double(_fibers, "WLRES", fiber,
02379 slope * (fps - fps0) + dwf0);
02380
02381 ++fiber;
02382 fps = cpl_table_get_int(_fibers, "FPS", fiber, NULL);
02383 }
02384
02385 fps0 = fps1;
02386 dwf0 = dwf1;
02387
02388 }
02389
02390 fps1 = cpl_table_get_int(_fibers, "FPS", nfibers - 1, NULL);
02391
02392 while (fps != fps1) {
02393
02394 cpl_table_set_double(_fibers, "WLRES", fiber, dwf0);
02395
02396 ++fiber;
02397 fps = cpl_table_get_int(_fibers, "FPS", fiber, NULL);
02398
02399 }
02400
02401 cpl_table_set_double(_fibers, "WLRES", fiber, dwf0);
02402
02403 cx_assert(fiber == nfibers - 1);
02404
02405 if (cpl_error_get_code() != CPL_ERROR_NONE) {
02406 cpl_table_delete(peakdata);
02407 return 7;
02408 }
02409
02410 giraffe_error_pop();
02411
02412 return 0;
02413
02414 }
02415
02416
02429 GiSGCalConfig*
02430 giraffe_sgcalibration_config_create(cpl_parameterlist* list)
02431 {
02432
02433 const cxchar* s = NULL;
02434
02435 cpl_parameter* p = NULL;
02436
02437 GiSGCalConfig* config = NULL;
02438
02439
02440 if (!list) {
02441 return NULL;
02442 }
02443
02444 config = cx_calloc(1, sizeof *config);
02445
02446 config->cc_wdomain = FALSE;
02447
02448 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.iterations");
02449 config->repeat = cpl_parameter_get_int(p);
02450
02451 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.zmax");
02452 config->zmax = cpl_parameter_get_double(p);
02453
02454 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.cc.step");
02455 config->cc_step = cpl_parameter_get_double(p);
02456
02457 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.cc.domain");
02458 s = cpl_parameter_get_string(p);
02459
02460 if (s) {
02461
02462 cxchar** values = cx_strsplit(s, ",", 3);
02463
02464 if (values == NULL) {
02465
02466 giraffe_sgcalibration_config_destroy(config);
02467 return NULL;
02468
02469 }
02470 else {
02471
02472 cxchar* last;
02473
02474 cxdouble lower = 0.;
02475 cxdouble upper = 0.;
02476
02477
02478 lower = strtod(values[0], &last);
02479
02480 if (*last != '\0') {
02481
02482 cx_strfreev(values);
02483 giraffe_sgcalibration_config_destroy(config);
02484
02485 return NULL;
02486
02487 }
02488
02489 lower = lower >= 0. ? lower : 0.;
02490
02491
02492 if (values[1] != NULL) {
02493
02494 upper = strtod(values[1], &last);
02495
02496 if (*last != '\0') {
02497
02498 cx_strfreev(values);
02499 giraffe_sgcalibration_config_destroy(config);
02500
02501 return NULL;
02502
02503 }
02504
02505 upper = upper > lower ? upper : 0.;
02506
02507 }
02508
02509 config->cc_domain = giraffe_range_create(lower, upper);
02510 cx_assert(config->cc_domain != NULL);
02511
02512 }
02513
02514 cx_strfreev(values);
02515 values = NULL;
02516
02517 }
02518
02519
02520 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.rv.limits");
02521 s = cpl_parameter_get_string(p);
02522
02523 if (s) {
02524
02525 cxchar** values = cx_strsplit(s, ",", 3);
02526
02527 if (values == NULL) {
02528
02529 giraffe_sgcalibration_config_destroy(config);
02530 return NULL;
02531
02532 }
02533 else {
02534
02535 cxchar* last;
02536
02537 cxdouble lower = 0.;
02538 cxdouble upper = 0.;
02539
02540
02541 lower = strtod(values[0], &last);
02542
02543 if (*last != '\0') {
02544
02545 cx_strfreev(values);
02546 giraffe_sgcalibration_config_destroy(config);
02547
02548 return NULL;
02549
02550 }
02551
02552 if (values[1] != NULL) {
02553
02554 upper = strtod(values[1], &last);
02555
02556 if (*last != '\0') {
02557
02558 cx_strfreev(values);
02559 giraffe_sgcalibration_config_destroy(config);
02560
02561 return NULL;
02562
02563 }
02564
02565 if (lower > 0 || upper < lower) {
02566
02567 cx_strfreev(values);
02568 giraffe_sgcalibration_config_destroy(config);
02569
02570 return NULL;
02571
02572 }
02573
02574 }
02575 else {
02576
02577 if (lower > 0.) {
02578
02579 upper = lower;
02580 lower = -upper;
02581
02582 }
02583 else {
02584
02585 upper = -lower;
02586
02587 }
02588
02589 }
02590
02591 cx_assert(lower <= 0);
02592 cx_assert(lower < upper);
02593
02594 config->rv_limits = giraffe_range_create(lower, upper);
02595 cx_assert(config->rv_limits != NULL);
02596
02597 }
02598
02599 cx_strfreev(values);
02600 values = NULL;
02601
02602 }
02603
02604
02605 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.rv.iterations");
02606 config->rv_niter = cpl_parameter_get_int(p);
02607
02608 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.rv.wfactor");
02609 config->rv_wfactor = cpl_parameter_get_double(p);
02610
02611 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.peak.iterations");
02612 config->pf_niter = cpl_parameter_get_int(p);
02613
02614 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.peak.tests");
02615 config->pf_ntest = cpl_parameter_get_int(p);
02616
02617 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.peak.dchisquare");
02618 config->pf_dchisq = cpl_parameter_get_double(p);
02619
02620 return config;
02621
02622 }
02623
02624
02639 void
02640 giraffe_sgcalibration_config_destroy(GiSGCalConfig* config)
02641 {
02642
02643 if (config) {
02644 if (config->cc_domain) {
02645 giraffe_range_delete(config->cc_domain);
02646 }
02647
02648 if (config->rv_limits) {
02649 giraffe_range_delete(config->rv_limits);
02650 }
02651
02652 cx_free(config);
02653 }
02654
02655 return;
02656 }
02657
02658
02670 void
02671 giraffe_sgcalibration_config_add(cpl_parameterlist* list)
02672 {
02673
02674 cpl_parameter* p;
02675
02676
02677 if (!list) {
02678 return;
02679 }
02680
02681 p = cpl_parameter_new_value("giraffe.sgcalibration.iterations",
02682 CPL_TYPE_INT,
02683 "Slit geometry calibration maximum number "
02684 "of iterations.",
02685 "giraffe.sgcalibration",
02686 1);
02687 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-cniter");
02688 cpl_parameterlist_append(list, p);
02689
02690
02691 p = cpl_parameter_new_value("giraffe.sgcalibration.zmax",
02692 CPL_TYPE_DOUBLE,
02693 "Maximum allowed pixel value. To be "
02694 "effective it must be larger than 0.",
02695 "giraffe.sgcalibration",
02696 10000.);
02697 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-zmax");
02698 cpl_parameterlist_append(list, p);
02699
02700
02701 p = cpl_parameter_new_value("giraffe.sgcalibration.cc.step",
02702 CPL_TYPE_DOUBLE,
02703 "Cross-correlation step.",
02704 "giraffe.sgcalibration",
02705 -0.005);
02706 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-cstep");
02707 cpl_parameterlist_append(list, p);
02708
02709
02710 p = cpl_parameter_new_value("giraffe.sgcalibration.cc.domain",
02711 CPL_TYPE_STRING,
02712 "Restricts the cross-correlation to the "
02713 "given domain.",
02714 "giraffe.sgcalibration",
02715 "0.,0.");
02716 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-cdomain");
02717 cpl_parameterlist_append(list, p);
02718
02719
02720 p = cpl_parameter_new_value("giraffe.sgcalibration.rv.limits",
02721 CPL_TYPE_STRING,
02722 "Delta RV limits of the cross-correlation "
02723 "window in km/s.",
02724 "giraffe.sgcalibration",
02725 "-200.,200.");
02726 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-rvlimits");
02727 cpl_parameterlist_append(list, p);
02728
02729
02730 p = cpl_parameter_new_value("giraffe.sgcalibration.rv.iterations",
02731 CPL_TYPE_INT,
02732 "Maximum number of iterations used for the "
02733 "RV determination.",
02734 "giraffe.sgcalibration",
02735 3);
02736 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-rvniter");
02737 cpl_parameterlist_append(list, p);
02738
02739
02740 p = cpl_parameter_new_value("giraffe.sgcalibration.rv.wfactor",
02741 CPL_TYPE_DOUBLE,
02742 "Data window width factor. The FWHM times "
02743 "this value determines the window width.",
02744 "giraffe.sgcalibration",
02745 1.5);
02746 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-rvwfactor");
02747 cpl_parameterlist_append(list, p);
02748
02749
02750 p = cpl_parameter_new_value("giraffe.sgcalibration.peak.iterations",
02751 CPL_TYPE_INT,
02752 "Peak model fit maximum number of "
02753 "iterations.",
02754 "giraffe.sgcalibration",
02755 50);
02756
02757 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-pfniter");
02758 cpl_parameterlist_append(list, p);
02759
02760
02761 p = cpl_parameter_new_value("giraffe.sgcalibration.peak.tests",
02762 CPL_TYPE_INT,
02763 "Cross-correlation peak fit maximum number "
02764 "of tests",
02765 "giraffe.sgcalibration",
02766 7);
02767
02768 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-pfntest");
02769 cpl_parameterlist_append(list, p);
02770
02771
02772 p = cpl_parameter_new_value("giraffe.sgcalibration.peak.dchisquare",
02773 CPL_TYPE_DOUBLE,
02774 "Cross-correlation peak fit minimum "
02775 "chi-square difference.",
02776 "giraffe.sgcalibration",
02777 0.0001);
02778
02779 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-pfdchisq");
02780 cpl_parameterlist_append(list, p);
02781
02782 return;
02783
02784 }