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
02197 cxint
02198 giraffe_compute_offsets(GiTable* fibers, const GiRebinning* rebinning,
02199 const GiTable* grating, const GiTable* mask,
02200 const GiSGCalConfig* config)
02201 {
02202
02203 cxint status = 0;
02204 cxint nfibers = 0;
02205 cxint fiber = 0;
02206 cxint peak = 0;
02207 cxint fps = 0;
02208 cxint fps0 = 0;
02209 cxint fps1 = 0;
02210
02211 cxdouble dwf0 = 0.;
02212
02213 cpl_table* _fibers = NULL;
02214 cpl_table* peakdata = NULL;
02215
02216 GiGrating* _grating = NULL;
02217
02218 GiSGSetup setup;
02219
02220
02221 if ((rebinning == NULL) || (rebinning->spectra == NULL)) {
02222 return -1;
02223 }
02224
02225 if (fibers == NULL) {
02226 return -2;
02227 }
02228
02229 if (grating == NULL) {
02230 return -3;
02231 }
02232
02233 if (mask == NULL) {
02234 return -4;
02235 }
02236
02237 if (config == NULL) {
02238 return -5;
02239 }
02240
02241
02242 _fibers = giraffe_table_get(fibers);
02243 cx_assert(_fibers != NULL);
02244
02245
02246
02247
02248
02249
02250
02251 cpl_table_unselect_all(_fibers);
02252 cpl_table_or_selected_int(_fibers, "RP", CPL_EQUAL_TO, -1);
02253
02254 _fibers = cpl_table_extract_selected(_fibers);
02255
02256 if (_fibers == NULL) {
02257 return 1;
02258 }
02259
02260
02261
02262
02263
02264
02265 _grating = giraffe_grating_create(rebinning->spectra, grating);
02266
02267 if (_grating == NULL) {
02268 cpl_table_delete(_fibers);
02269 return 2;
02270 }
02271
02272
02273
02274
02275
02276 status = _giraffe_create_setup(&setup, rebinning->spectra);
02277
02278 if (status != 0) {
02279 cpl_table_delete(_fibers);
02280 return 3;
02281 }
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296 peakdata = _giraffe_compute_offsets(rebinning->spectra, mask, _fibers,
02297 _grating, &setup, config);
02298
02299 if (peakdata == NULL) {
02300 cpl_table_delete(_fibers);
02301 return 4;
02302 }
02303
02304
02305
02306
02307
02308
02309
02310 status = _giraffe_compute_fiber_offsets(peakdata, _grating, &setup);
02311
02312 if (status != 0) {
02313 cpl_table_delete(peakdata);
02314 cpl_table_delete(_fibers);
02315
02316 return 5;
02317 }
02318
02319 cpl_table_delete(_fibers);
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332 _fibers = giraffe_table_get(fibers);
02333
02334 giraffe_error_push();
02335
02336 cpl_table_new_column(_fibers, "WLRES", CPL_TYPE_DOUBLE);
02337 cpl_table_set_column_unit(_fibers, "WLRES", "nm");
02338
02339 if (cpl_error_get_code() != CPL_ERROR_NONE) {
02340 cpl_table_delete(peakdata);
02341 return 6;
02342 }
02343
02344 giraffe_error_pop();
02345
02346
02347 giraffe_error_push();
02348
02349 fps0 = cpl_table_get_int(peakdata, "FPS", 0, NULL);
02350 dwf0 = cpl_table_get_double(peakdata, "DWF", 0, NULL);
02351
02352 nfibers = cpl_table_get_nrow(_fibers);
02353
02354 fps = cpl_table_get_int(_fibers, "FPS", 0, NULL);
02355
02356 while (fps != fps0) {
02357
02358 cpl_table_set_double(_fibers, "WLRES", fiber, dwf0);
02359
02360 ++fiber;
02361 fps = cpl_table_get_int(_fibers, "FPS", fiber, NULL);
02362
02363 }
02364
02365 for (peak = 1; peak < cpl_table_get_nrow(peakdata); ++peak) {
02366
02367 cxdouble dwf1 = cpl_table_get_double(peakdata, "DWF", peak, NULL);
02368 cxdouble slope = 0.;
02369
02370
02371 fps1 = cpl_table_get_int(peakdata, "FPS", peak, NULL);
02372
02373 slope = (dwf1 - dwf0) / ((cxdouble)(fps1 - fps0));
02374
02375 while (fps != fps1) {
02376
02377 cpl_table_set_double(_fibers, "WLRES", fiber,
02378 slope * (fps - fps0) + dwf0);
02379
02380 ++fiber;
02381 fps = cpl_table_get_int(_fibers, "FPS", fiber, NULL);
02382 }
02383
02384 fps0 = fps1;
02385 dwf0 = dwf1;
02386
02387 }
02388
02389 fps1 = cpl_table_get_int(_fibers, "FPS", nfibers - 1, NULL);
02390
02391 while (fps != fps1) {
02392
02393 cpl_table_set_double(_fibers, "WLRES", fiber, dwf0);
02394
02395 ++fiber;
02396 fps = cpl_table_get_int(_fibers, "FPS", fiber, NULL);
02397
02398 }
02399
02400 cpl_table_set_double(_fibers, "WLRES", fiber, dwf0);
02401
02402 cx_assert(fiber == nfibers - 1);
02403
02404 if (cpl_error_get_code() != CPL_ERROR_NONE) {
02405 cpl_table_delete(peakdata);
02406 return 7;
02407 }
02408
02409 giraffe_error_pop();
02410
02411 return 0;
02412
02413 }
02414
02415
02428 GiSGCalConfig*
02429 giraffe_sgcalibration_config_create(cpl_parameterlist* list)
02430 {
02431
02432 const cxchar* s = NULL;
02433
02434 cpl_parameter* p = NULL;
02435
02436 GiSGCalConfig* config = NULL;
02437
02438
02439 if (!list) {
02440 return NULL;
02441 }
02442
02443 config = cx_calloc(1, sizeof *config);
02444
02445 config->cc_wdomain = FALSE;
02446
02447 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.iterations");
02448 config->repeat = cpl_parameter_get_int(p);
02449
02450 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.zmax");
02451 config->zmax = cpl_parameter_get_double(p);
02452
02453 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.cc.step");
02454 config->cc_step = cpl_parameter_get_double(p);
02455
02456 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.cc.domain");
02457 s = cpl_parameter_get_string(p);
02458
02459 if (s) {
02460
02461 cxchar** values = cx_strsplit(s, ",", 3);
02462
02463 if (values == NULL) {
02464
02465 giraffe_sgcalibration_config_destroy(config);
02466 return NULL;
02467
02468 }
02469 else {
02470
02471 cxchar* last;
02472
02473 cxdouble lower = 0.;
02474 cxdouble upper = 0.;
02475
02476
02477 lower = strtod(values[0], &last);
02478
02479 if (*last != '\0') {
02480
02481 cx_strfreev(values);
02482 giraffe_sgcalibration_config_destroy(config);
02483
02484 return NULL;
02485
02486 }
02487
02488 lower = lower >= 0. ? lower : 0.;
02489
02490
02491 if (values[1] != NULL) {
02492
02493 upper = strtod(values[1], &last);
02494
02495 if (*last != '\0') {
02496
02497 cx_strfreev(values);
02498 giraffe_sgcalibration_config_destroy(config);
02499
02500 return NULL;
02501
02502 }
02503
02504 upper = upper > lower ? upper : 0.;
02505
02506 }
02507
02508 config->cc_domain = giraffe_range_create(lower, upper);
02509 cx_assert(config->cc_domain != NULL);
02510
02511 }
02512
02513 cx_strfreev(values);
02514 values = NULL;
02515
02516 }
02517
02518
02519 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.rv.limits");
02520 s = cpl_parameter_get_string(p);
02521
02522 if (s) {
02523
02524 cxchar** values = cx_strsplit(s, ",", 3);
02525
02526 if (values == NULL) {
02527
02528 giraffe_sgcalibration_config_destroy(config);
02529 return NULL;
02530
02531 }
02532 else {
02533
02534 cxchar* last;
02535
02536 cxdouble lower = 0.;
02537 cxdouble upper = 0.;
02538
02539
02540 lower = strtod(values[0], &last);
02541
02542 if (*last != '\0') {
02543
02544 cx_strfreev(values);
02545 giraffe_sgcalibration_config_destroy(config);
02546
02547 return NULL;
02548
02549 }
02550
02551 if (values[1] != NULL) {
02552
02553 upper = strtod(values[1], &last);
02554
02555 if (*last != '\0') {
02556
02557 cx_strfreev(values);
02558 giraffe_sgcalibration_config_destroy(config);
02559
02560 return NULL;
02561
02562 }
02563
02564 if (lower > 0 || upper < lower) {
02565
02566 cx_strfreev(values);
02567 giraffe_sgcalibration_config_destroy(config);
02568
02569 return NULL;
02570
02571 }
02572
02573 }
02574 else {
02575
02576 if (lower > 0.) {
02577
02578 upper = lower;
02579 lower = -upper;
02580
02581 }
02582 else {
02583
02584 upper = -lower;
02585
02586 }
02587
02588 }
02589
02590 cx_assert(lower <= 0);
02591 cx_assert(lower < upper);
02592
02593 config->rv_limits = giraffe_range_create(lower, upper);
02594 cx_assert(config->rv_limits != NULL);
02595
02596 }
02597
02598 cx_strfreev(values);
02599 values = NULL;
02600
02601 }
02602
02603
02604 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.rv.iterations");
02605 config->rv_niter = cpl_parameter_get_int(p);
02606
02607 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.rv.wfactor");
02608 config->rv_wfactor = cpl_parameter_get_double(p);
02609
02610 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.peak.iterations");
02611 config->pf_niter = cpl_parameter_get_int(p);
02612
02613 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.peak.tests");
02614 config->pf_ntest = cpl_parameter_get_int(p);
02615
02616 p = cpl_parameterlist_find(list, "giraffe.sgcalibration.peak.dchisquare");
02617 config->pf_dchisq = cpl_parameter_get_double(p);
02618
02619 return config;
02620
02621 }
02622
02623
02638 void
02639 giraffe_sgcalibration_config_destroy(GiSGCalConfig* config)
02640 {
02641
02642 if (config) {
02643 if (config->cc_domain) {
02644 giraffe_range_delete(config->cc_domain);
02645 }
02646
02647 if (config->rv_limits) {
02648 giraffe_range_delete(config->rv_limits);
02649 }
02650
02651 cx_free(config);
02652 }
02653
02654 return;
02655 }
02656
02657
02669 void
02670 giraffe_sgcalibration_config_add(cpl_parameterlist* list)
02671 {
02672
02673 cpl_parameter* p;
02674
02675
02676 if (!list) {
02677 return;
02678 }
02679
02680 p = cpl_parameter_new_value("giraffe.sgcalibration.iterations",
02681 CPL_TYPE_INT,
02682 "Slit geometry calibration maximum number "
02683 "of iterations.",
02684 "giraffe.sgcalibration",
02685 1);
02686 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-cniter");
02687 cpl_parameterlist_append(list, p);
02688
02689
02690 p = cpl_parameter_new_value("giraffe.sgcalibration.zmax",
02691 CPL_TYPE_DOUBLE,
02692 "Maximum allowed pixel value. To be "
02693 "effective it must be larger than 0.",
02694 "giraffe.sgcalibration",
02695 10000.);
02696 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-zmax");
02697 cpl_parameterlist_append(list, p);
02698
02699
02700 p = cpl_parameter_new_value("giraffe.sgcalibration.cc.step",
02701 CPL_TYPE_DOUBLE,
02702 "Cross-correlation step.",
02703 "giraffe.sgcalibration",
02704 -0.005);
02705 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-cstep");
02706 cpl_parameterlist_append(list, p);
02707
02708
02709 p = cpl_parameter_new_value("giraffe.sgcalibration.cc.domain",
02710 CPL_TYPE_STRING,
02711 "Restricts the cross-correlation to the "
02712 "given domain.",
02713 "giraffe.sgcalibration",
02714 "0.,0.");
02715 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-cdomain");
02716 cpl_parameterlist_append(list, p);
02717
02718
02719 p = cpl_parameter_new_value("giraffe.sgcalibration.rv.limits",
02720 CPL_TYPE_STRING,
02721 "Delta RV limits of the cross-correlation "
02722 "window in km/s.",
02723 "giraffe.sgcalibration",
02724 "-200.,200.");
02725 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-rvlimits");
02726 cpl_parameterlist_append(list, p);
02727
02728
02729 p = cpl_parameter_new_value("giraffe.sgcalibration.rv.iterations",
02730 CPL_TYPE_INT,
02731 "Maximum number of iteration used for the "
02732 "RV determination.",
02733 "giraffe.sgcalibration",
02734 3);
02735 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-rvniter");
02736 cpl_parameterlist_append(list, p);
02737
02738
02739 p = cpl_parameter_new_value("giraffe.sgcalibration.rv.wfactor",
02740 CPL_TYPE_DOUBLE,
02741 "Data window width factor. The FWHM times "
02742 "this value determines the window width.",
02743 "giraffe.sgcalibration",
02744 1.5);
02745 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-rvwfactor");
02746 cpl_parameterlist_append(list, p);
02747
02748
02749 p = cpl_parameter_new_value("giraffe.sgcalibration.peak.iterations",
02750 CPL_TYPE_INT,
02751 "Peak model fit maximum number of "
02752 "iterations.",
02753 "giraffe.sgcalibration",
02754 50);
02755
02756 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-pfniter");
02757 cpl_parameterlist_append(list, p);
02758
02759
02760 p = cpl_parameter_new_value("giraffe.sgcalibration.peak.tests",
02761 CPL_TYPE_INT,
02762 "Cross-correlation peak fit maximum number "
02763 "of tests",
02764 "giraffe.sgcalibration",
02765 7);
02766
02767 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-pfntest");
02768 cpl_parameterlist_append(list, p);
02769
02770
02771 p = cpl_parameter_new_value("giraffe.sgcalibration.peak.dchisquare",
02772 CPL_TYPE_DOUBLE,
02773 "Cross-correlation peak fit minimum "
02774 "chi-square difference.",
02775 "giraffe.sgcalibration",
02776 0.0001);
02777
02778 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scal-pfdchisq");
02779 cpl_parameterlist_append(list, p);
02780
02781 return;
02782
02783 }