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