35 #include <cxmessages.h>
36 #include <cxstrutils.h>
38 #include <cpl_error.h>
39 #include <cpl_parameterlist.h>
40 #include <cpl_propertylist.h>
41 #include <cpl_matrix.h>
42 #include <cpl_image.h>
43 #include <cpl_table.h>
48 #include "gifiberutils.h"
49 #include "gigrating.h"
51 #include "gilocalization.h"
52 #include "giextraction.h"
53 #include "girebinning.h"
54 #include "gisgcalibration.h"
65 struct GiMeasurement {
70 typedef struct GiMeasurement GiMeasurement;
88 typedef struct GiSGSetup GiSGSetup;
91 struct GiCPFitParams {
106 typedef struct GiCPFitParams GiCPFitParams;
110 GiMeasurement amplitude;
111 GiMeasurement background;
112 GiMeasurement center;
118 typedef struct GiCPeakFit GiCPeakFit;
131 cpl_matrix* wavelength;
136 typedef struct GiSGMask GiSGMask;
139 inline static GiSGMask*
140 _giraffe_sgmask_new(cxsize size)
143 GiSGMask*
self = cx_calloc(1,
sizeof *
self);
145 self->wavelength = cpl_matrix_new(1, size);
146 self->flux = cpl_matrix_new(1, size);
151 self->scale = GIREBIN_SCALE_LINEAR;
162 _giraffe_sgmask_delete(GiSGMask*
self)
167 if (self->wavelength != NULL) {
168 cpl_matrix_delete(self->wavelength);
169 self->wavelength = NULL;
172 if (self->flux != NULL) {
173 cpl_matrix_delete(self->flux);
186 inline static GiSGMask*
187 _giraffe_sgmask_create(cxsize size, cxdouble start, cxdouble step,
188 GiRebinScale scale,
const GiTable* mask)
195 cxdouble wlstep = 0.;
197 cpl_table* _mask = NULL;
199 GiSGMask*
self = NULL;
202 cx_assert(mask != NULL);
205 cx_assert(_mask != NULL);
207 self = _giraffe_sgmask_new(size);
218 for (i = 0; i <
self->size; i++) {
219 cpl_matrix_set(self->wavelength, 0, i, self->start + i * self->step);
223 wlmin = cpl_matrix_get(self->wavelength, 0, 0);
224 wlmax = cpl_matrix_get(self->wavelength, 0, self->size - 1);
227 if (self->scale == GIREBIN_SCALE_LOG) {
231 wlstep = exp(wlstep);
241 cpl_table_select_all(_mask);
243 cpl_table_and_selected_double(_mask,
"WLEN1", CPL_GREATER_THAN, wlmin);
244 cpl_table_and_selected_double(_mask,
"WLEN2", CPL_LESS_THAN, wlmax);
246 _mask = cpl_table_extract_selected(_mask);
248 if (_mask == NULL || cpl_table_get_nrow(_mask) <= 0) {
249 _giraffe_sgmask_delete(
self);
256 self->nholes = cpl_table_get_nrow(_mask);
258 for (i = 0; i <
self->nholes; i++) {
262 cxdouble hstart = cpl_table_get(_mask,
"WLEN1", i, NULL) - wlmin;
263 cxdouble hend = cpl_table_get(_mask,
"WLEN2", i, NULL) - wlmin;
269 for (j = (cxsize)(hstart + 0.5); j <= (cxsize)(hend + 0.5); j++) {
271 cpl_matrix_set(self->flux, 0, j, 1.);
277 cpl_table_delete(_mask);
285 _giraffe_sgmask_size(
const GiSGMask*
self)
288 cx_assert(
self != NULL);
296 _giraffe_sgmask_holes(
const GiSGMask*
self)
299 cx_assert(
self != NULL);
307 _giraffe_sgmask_set_flux(GiSGMask*
self, cxsize position, cxdouble value)
310 cx_assert(
self != NULL);
312 if (position >= (cxsize)cpl_matrix_get_ncol(self->flux)) {
316 cpl_matrix_set(self->flux, 0, position, value);
323 inline static cxdouble
324 _giraffe_sgmask_get_flux(GiSGMask*
self, cxsize position)
327 const cxchar*
const fctid =
"_giraffe_sgmask_get_flux";
330 cx_assert(
self != NULL);
332 if (position >= (cxsize)cpl_matrix_get_ncol(self->flux)) {
333 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
337 return cpl_matrix_get(self->flux, 0, position);
342 inline static const cpl_matrix*
343 _giraffe_sgmask_get(GiSGMask*
self)
346 cx_assert(
self != NULL);
354 _giraffe_sgmask_crop(GiSGMask*
self, cxsize begin, cxsize end)
359 cpl_matrix* buffer = NULL;
362 cx_assert(
self != NULL);
363 cx_assert(end > begin);
364 cx_assert(cpl_matrix_get_nrow(self->wavelength) == 1);
365 cx_assert(cpl_matrix_get_nrow(self->flux) == 1);
367 if (begin >= (cxsize)cpl_matrix_get_ncol(self->flux)) {
371 if (end > (cxsize)cpl_matrix_get_ncol(self->flux)) {
372 end = cpl_matrix_get_ncol(self->flux);
375 if (begin == 0 && end == (cxsize)cpl_matrix_get_ncol(self->flux)) {
381 buffer = cpl_matrix_extract(self->wavelength, 0, begin, 1, 1, 1, size);
382 cpl_matrix_delete(self->wavelength);
383 self->wavelength = buffer;
385 buffer = cpl_matrix_extract(self->flux, 0, begin, 1, 1, 1, size);
386 cpl_matrix_delete(self->flux);
389 cx_assert(cpl_matrix_get_nrow(self->flux) == 1);
390 cx_assert((cxsize)cpl_matrix_get_ncol(self->flux) == size);
399 inline static cxdouble
400 _giraffe_clip_value(cxdouble value, cxdouble low, cxdouble high,
404 cxbool status = FALSE;
431 inline static cpl_image*
432 _giraffe_resample_image(cpl_image* signal, cxdouble step1, cxdouble step2)
439 cxint step = CX_MAX(1, (cxint)(step1/step2));
441 cpl_image* _signal = NULL;
444 cx_assert(signal != NULL);
446 ny = cpl_image_get_size_x(signal);
447 nx1 = cpl_image_get_size_y(signal);
449 nx2 = (nx1 - 1) * step + 1;
451 _signal = cpl_image_new(ny, nx2, CPL_TYPE_DOUBLE);
453 for (i = 0; i < ny; i++) {
457 register cxdouble* data = cpl_image_get_data(signal);
458 register cxdouble* _data = cpl_image_get_data(_signal);
461 for (j = 0; j < nx1 - 1; j++) {
464 register cxint l = j * ny + i;
465 register cxint m = j * ny * step + i;
467 for (k = 0; k < step; k++) {
469 cxdouble f = (cxdouble)k / (cxdouble)step;
471 _data[m + k * ny] = (1. - f) * data[l] + f * data[l + ny];
477 _data[nx2 - 1] = data[nx1 - 1];
490 inline static cpl_matrix*
491 _giraffe_compute_cross_correlation(
const cpl_matrix* signal,
492 const cpl_matrix*
template,
493 cxint start, cxint end)
496 const cxchar*
const fctid =
"_giraffe_compute_cross_correlation";
507 cpl_matrix* _signal = (cpl_matrix*)signal;
508 cpl_matrix* _template = (cpl_matrix*)
template;
509 cpl_matrix* ccf = NULL;
510 cpl_matrix* _ccf = NULL;
513 cx_assert(_signal != NULL);
514 cx_assert(cpl_matrix_get_nrow(_signal) == 1);
516 cx_assert(_template != NULL);
517 cx_assert(cpl_matrix_get_nrow(_template) == 1);
519 ns = cpl_matrix_get_ncol(_signal);
520 cx_assert(ns == cpl_matrix_get_ncol(_template));
522 cx_assert(start <= end);
529 nmax = cpl_matrix_get_ncol(_signal) / 2;
531 start = CX_MAX(CX_MIN(start, nmax), -nmax);
532 end = CX_MAX(CX_MIN(end, nmax), -nmax);
536 cpl_msg_debug(fctid,
"Cross-correlation function: signal size = %"
537 CPL_SIZE_FORMAT
", template size = %" CPL_SIZE_FORMAT
538 ", window start = %d, window end = %d",
539 cpl_matrix_get_ncol(_signal), cpl_matrix_get_ncol(_template),
543 ccf = cpl_matrix_new(1, nccf);
545 for (i = start; i < end; i++) {
558 for (j = 0; j < ns + i; j++) {
560 cxdouble s = cpl_matrix_get(_signal, 0, j);
561 cxdouble t = cpl_matrix_get(_template, 0, j - i);
567 sum /= (cxdouble)(ns + i);
569 cpl_matrix_set(ccf, 0, i - start, sum);
583 for (j = i; j < ns; j++) {
585 cxdouble s = cpl_matrix_get(_signal, 0, j);
586 cxdouble t = cpl_matrix_get(_template, 0, j - i);
592 sum /= (cxdouble)(ns - i);
594 cpl_matrix_set(ccf, 0, i - start, sum);
608 for (j = 0; j < ns; j++) {
610 cxdouble t = cpl_matrix_get(_template, 0, j);
611 cxdouble s = cpl_matrix_get(_signal, 0, j);
619 cpl_matrix_set(ccf, 0, -start, sum);
633 n = CX_MAX(1, nccf / 10);
635 _ccf = cpl_matrix_duplicate(ccf);
640 for (i = nccf - n; i < nccf; i++) {
641 sum += cpl_matrix_get(_ccf, 0, i);
646 cpl_matrix_delete(_ccf);
651 for (i = 0; i < nccf; i++) {
652 cpl_matrix_set(ccf, 0, i, cpl_matrix_get(ccf, 0, i) / sum);
663 _giraffe_create_setup(GiSGSetup* setup,
const GiImage* spectra)
666 cpl_propertylist* properties = NULL;
668 cpl_image* _spectra = NULL;
671 cx_assert(setup != NULL);
672 cx_assert(spectra != NULL);
675 cx_assert(properties != NULL);
678 cx_assert(_spectra != NULL);
685 setup->nx = cpl_image_get_size_y(_spectra);
688 if (!cpl_propertylist_has(properties, GIALIAS_EXT_NX)) {
693 setup->nex = cpl_propertylist_get_int(properties, GIALIAS_EXT_NX);
697 if (!cpl_propertylist_has(properties, GIALIAS_BINSCALE)) {
702 const cxchar* s = cpl_propertylist_get_string(properties,
706 if (cx_strncasecmp(s,
"log", 3) == 0) {
707 setup->scale = GIREBIN_SCALE_LOG;
710 setup->scale = GIREBIN_SCALE_LINEAR;
715 if (!cpl_propertylist_has(properties, GIALIAS_BINWLMIN)) {
719 setup->wlmin = cpl_propertylist_get_double(properties,
723 if (!cpl_propertylist_has(properties, GIALIAS_BINSTEP)) {
727 setup->wlstep = cpl_propertylist_get_double(properties,
731 setup->wlmax = setup->wlmin + (setup->nx - 1) * setup->wlstep;
734 if (!cpl_propertylist_has(properties, GIALIAS_PIXSIZY)) {
738 setup->pixelsize = cpl_propertylist_get_double(properties,
748 _giraffe_peak_fit(GiCPeakFit* peak,
const cpl_matrix* lambda,
749 const cpl_matrix* ccf,
const GiGrating* grating,
750 const GiCPFitParams* setup)
753 const cxchar*
const fctid =
"_giraffe_peak_fit";
762 cxdouble amplitude = 0.;
763 cxdouble background = 0.;
764 cxdouble center = 0.;
774 } initial = {0., 0., 0., 0.};
779 GiModel* model = giraffe_model_new(
"gaussian");
783 cx_assert(model != NULL);
784 cx_assert(strcmp(giraffe_model_get_name(model),
"gaussian") == 0);
785 cx_assert(lambda != NULL);
786 cx_assert(ccf != NULL);
787 cx_assert(grating != NULL);
788 cx_assert(setup != NULL);
800 amplitude = cpl_matrix_get_max((cpl_matrix*)ccf) - background;
802 cpl_matrix_get_maxpos((cpl_matrix*)ccf, &nr, &nc);
805 center = cpl_matrix_get((cpl_matrix*)lambda, 0, nc);
808 if (setup->scale == GIREBIN_SCALE_LOG) {
809 width = 0.5 / grating->
resol;
812 width = 0.5 / grating->
resol * grating->
wlen0;
815 giraffe_model_set_parameter(model,
"Background", background);
816 giraffe_model_set_parameter(model,
"Amplitude", amplitude);
817 giraffe_model_set_parameter(model,
"Center", center);
818 giraffe_model_set_parameter(model,
"Width1", width);
820 giraffe_model_thaw(model);
822 giraffe_model_set_iterations(model, setup->fit.iterations);
823 giraffe_model_set_tests(model, setup->fit.tests);
824 giraffe_model_set_delta(model, setup->fit.delta);
831 initial.amplitude = amplitude;
832 initial.background = background;
833 initial.center = center;
834 initial.width = width;
838 while (i < setup->iterations && !stop) {
847 cpl_matrix* tlambda = (cpl_matrix*)lambda;
848 cpl_matrix* tccf = (cpl_matrix*)ccf;
859 const cxdouble da = 0.2;
860 const cxdouble dc = 1.;
861 const cxdouble db = 1.;
862 const cxdouble dw = 0.2;
866 value = giraffe_model_get_parameter(model,
"Amplitude") * da;
867 value += (1. - da) * initial.amplitude;
869 giraffe_model_set_parameter(model,
"Amplitude", value);
872 value = giraffe_model_get_parameter(model,
"Center") * dc;
873 value += (1. - dc) * initial.center;
875 giraffe_model_set_parameter(model,
"Center", value);
878 value = giraffe_model_get_parameter(model,
"Background") * db;
879 value += (1. - db) * initial.background;
881 giraffe_model_set_parameter(model,
"Background", value);
884 value = giraffe_model_get_parameter(model,
"Width1") * dw;
885 value += (1. - dw) * initial.width;
887 giraffe_model_set_parameter(model,
"Width1", value);
897 dwd = 2. * giraffe_model_get_parameter(model,
"Width1") *
899 dwc = giraffe_model_get_parameter(model,
"Center");
901 dwd = CX_MAX(setup->dnmin, 2. * dwd / setup->step) * setup->step / 2.;
903 lower = dwc + 0.5 * setup->step - dwd;
904 upper = dwc + 0.5 * setup->step + dwd;
913 for (j = 0; j < cpl_matrix_get_ncol(tlambda); j++) {
915 if (cpl_matrix_get(tlambda, 0, j) > lower) {
922 for (j = cpl_matrix_get_ncol(tlambda) - 1; j >= 0; j--) {
924 if (cpl_matrix_get(tlambda, 0, j) < upper) {
932 if (i > 0 && dn1 == _dn1 && dn2 == _dn2) {
934 cxdouble _width = giraffe_model_get_parameter(model,
"Width1");
941 dwd = CX_MAX(setup->dnmin, 4. * _width * setup->wfactor /
942 setup->step) * setup->step / 2.;
944 lower = dwc + 0.5 * setup->step - dwd;
945 upper = dwc + 0.5 * setup->step + dwd;
947 for (j = 0; j < cpl_matrix_get_ncol(tlambda); j++) {
949 if (cpl_matrix_get(tlambda, 0, j) > lower) {
956 for (j = cpl_matrix_get_ncol(tlambda) - 1; j <= 0; j--) {
958 if (cpl_matrix_get(tlambda, 0, j) < upper) {
975 if (i <= 1 || dn1 != _dn1 || dn2 != _dn2) {
979 const cxint pflag = 1;
982 cxdouble damplitude = 0.;
983 cxdouble dbackground = 0.;
984 cxdouble dcenter = 0.;
985 cxdouble dwidth = 0.;
987 cpl_matrix* x = NULL;
988 cpl_matrix* y = NULL;
989 cpl_matrix* sigma = NULL;
995 x = cpl_matrix_new(dn2 - dn1, 1);
996 y = cpl_matrix_new(dn2 - dn1, 1);
997 sigma = cpl_matrix_new(dn2 - dn1, 1);
999 for (j = 0; j < cpl_matrix_get_nrow(y); j++) {
1001 cpl_matrix_set(x, j, 0, cpl_matrix_get(tlambda, 0, dn1 + j));
1002 cpl_matrix_set(y, j, 0, cpl_matrix_get(tccf, 0, dn1 + j));
1003 cpl_matrix_set(sigma, j, 0, setup->sigma);
1012 status = giraffe_model_fit(model, x, y, sigma);
1016 peak->amplitude.value = initial.amplitude;
1017 peak->background.value = initial.background;
1018 peak->center.value = initial.center;
1019 peak->width.value = initial.width;
1021 peak->amplitude.sigma = 1.;
1022 peak->background.sigma = 1.;
1023 peak->center.sigma = 1.;
1024 peak->width.sigma = 1.;
1028 cpl_matrix_delete(x);
1029 cpl_matrix_delete(y);
1030 cpl_matrix_delete(sigma);
1032 giraffe_model_delete(model);
1044 amplitude = giraffe_model_get_parameter(model,
"Amplitude");
1045 damplitude = giraffe_model_get_sigma(model,
"Amplitude");
1047 center = giraffe_model_get_parameter(model,
"Center");
1048 dcenter = giraffe_model_get_sigma(model,
"Center");
1050 background = giraffe_model_get_parameter(model,
"Background");
1051 dbackground = giraffe_model_get_sigma(model,
"Background");
1053 width = giraffe_model_get_parameter(model,
"Width1");
1054 dwidth = giraffe_model_get_sigma(model,
"Width1");
1062 lower = -9. * (1 - pflag) + 1.e-5 * pflag;
1063 upper = 9. * pflag - 1.e-5 * (1 - pflag);
1065 peak->amplitude.value = _giraffe_clip_value(amplitude, lower,
1067 peak->amplitude.sigma = _giraffe_clip_value(damplitude, 0.,
1070 stop = stop == FALSE ? flag == TRUE ? TRUE : FALSE : stop;
1074 lower = cpl_matrix_get(x, 1, 0);
1075 upper = cpl_matrix_get(x, cpl_matrix_get_nrow(x) - 2, 0);
1077 peak->center.value = _giraffe_clip_value(center, lower,
1079 peak->center.sigma = _giraffe_clip_value(dcenter, 0.,
1080 initial.width, NULL);
1082 stop = stop == FALSE ? flag == TRUE ? TRUE : FALSE : stop;
1089 peak->background.value = _giraffe_clip_value(background, lower,
1091 peak->background.sigma = _giraffe_clip_value(dbackground, 0.,
1094 stop = stop == FALSE ? flag == TRUE ? TRUE : FALSE : stop;
1098 lower = 0.5 * initial.width;
1099 upper = 2. * (cpl_matrix_get(x, cpl_matrix_get_nrow(x) - 2, 0) -
1100 cpl_matrix_get(x, 0, 0));
1102 peak->width.value = _giraffe_clip_value(width, lower,
1104 peak->width.sigma = _giraffe_clip_value(dwidth, 0.,
1107 stop = stop == FALSE ? flag == TRUE ? TRUE : FALSE : stop;
1109 cpl_matrix_delete(x);
1110 cpl_matrix_delete(y);
1111 cpl_matrix_delete(sigma);
1114 cpl_msg_debug(fctid,
"Cross-correlation peak fit "
1115 "parameter out of bounds!");
1134 giraffe_model_delete(model);
1142 _giraffe_compute_fiber_offsets(cpl_table* offsets,
1144 const GiSGSetup* setup)
1149 const cxdouble ccdfactor = 1.1;
1151 cxdouble gcamera = 1.;
1152 cxdouble cfactor = 1.;
1153 cxdouble lincorr = 1.;
1154 cxdouble wlen0 = 0.;
1157 cx_assert(offsets != NULL);
1159 if (!cpl_table_has_column(offsets,
"WAVELENGTH")) {
1163 if (!cpl_table_has_column(offsets,
"DWF")) {
1164 cpl_table_new_column(offsets,
"DWF", CPL_TYPE_DOUBLE);
1167 if (!cpl_table_has_column(offsets,
"DXF")) {
1168 cpl_table_new_column(offsets,
"DXF", CPL_TYPE_DOUBLE);
1177 if (setup->scale == GIREBIN_SCALE_LOG) {
1178 wlen0 = 0.5 * (exp(setup->wlmin) + exp(setup->wlmax));
1181 wlen0 = 0.5 * (setup->wlmin + setup->wlmax);
1193 gcamera = 0.3894 - 5. * (1. / wlen0 - 1. / 550.) -
1194 0.00025 * pow(1. / wlen0 - 1. / 550., 2.);
1204 cfactor = (setup->nex * setup->pixelsize / 1000. * ccdfactor) /
1212 if (setup->scale == GIREBIN_SCALE_LOG) {
1216 lincorr = 0.5 * (setup->wlmin + setup->wlmax) /
1217 exp(0.5 * (log(setup->wlmin) + log(setup->wlmax)));
1225 for (i = 0; i < cpl_table_get_nrow(offsets); i++) {
1228 cxdouble dwf = cpl_table_get_double(offsets,
"WAVELENGTH", i, NULL);
1233 dxf = dwf * cfactor;
1235 cpl_table_set_double(offsets,
"DWF", i, dwf);
1236 cpl_table_set_double(offsets,
"DXF", i, dxf);
1245 inline static cpl_table*
1246 _giraffe_compute_offsets(
const GiImage* spectra,
const GiTable* mask,
1247 const cpl_table* fibers,
const GiGrating* grating,
1251 const cxchar*
const fctid =
"_giraffe_compute_offsets";
1253 const cxint dnmin = 7;
1267 const cxdouble clight = 299702.547;
1269 cxdouble cstep = 0.;
1270 cxdouble wlen0 = 0.;
1271 cxdouble nm2km = clight;
1272 cxdouble hpixels = 0.;
1280 cpl_matrix* spectrum = NULL;
1282 cpl_image* _spectra = NULL;
1283 cpl_image* tspectra = NULL;
1285 cpl_table* peakdata = NULL;
1287 GiSGMask* _mask = NULL;
1290 cx_assert(spectra != NULL);
1291 cx_assert(mask != NULL);
1292 cx_assert(fibers != NULL);
1293 cx_assert(grating != NULL);
1294 cx_assert(setup != NULL);
1295 cx_assert(config != NULL);
1307 if (setup->scale == GIREBIN_SCALE_LOG) {
1309 cxdouble wlstep = (exp(setup->wlmax) - exp(setup->wlmin)) /
1312 sampling = (cxint)(0.5 + wlstep / config->
cc_step);
1317 sampling = (cxint)(0.5 + setup->wlstep / config->
cc_step);
1323 cstep = setup->wlstep / sampling;
1330 _mask = _giraffe_sgmask_create((setup->nx - 1) * sampling + 1,
1331 setup->wlmin, cstep, setup->scale,
1334 if (_mask == NULL) {
1343 pixel0 = setup->nx / 2;
1345 if (setup->scale == GIREBIN_SCALE_LOG) {
1351 wlen0 = 0.5 * (exp(setup->wlmin) + exp(setup->wlmax));
1361 wlen0 = 0.5 * (setup->wlmin + setup->wlmax);
1362 nm2km = clight / wlen0;
1378 cpl_msg_debug(fctid,
"Cross-correlation limits: RVlow = %.4f km/s "
1379 "(%.4f nm), RVhigh = %.4f km/s (%.4f nm)", dv1, dw1,
1382 dwd = (dw2 - dw1) / 2.;
1383 dwc = (dw2 + dw1) / 2.;
1385 dnd = CX_MIN(pixel0, CX_MAX(dnmin, (cxint)(dwd / cstep + 0.5)));
1386 dnc = CX_MIN(pixel0, CX_MAX(-pixel0, (cxint)(dwc / cstep + 0.5)));
1388 dn1 = CX_MIN(pixel0 + 1, CX_MAX(-pixel0, dnc - dnd));
1389 dn2 = CX_MIN(pixel0 + 1, CX_MAX(-pixel0, dnc + dnd + 1));
1391 cpl_msg_debug(fctid,
"Cross-correlation window: center = %.4f nm "
1392 "(%d pxl) half-width = %.4f nm (%d pxl)", dwc, dnc,
1404 if (xc1 > 0 || xc2 > 0) {
1405 _giraffe_sgmask_crop(_mask, xc1, xc2);
1408 for (i = 0; (cxsize)i < _giraffe_sgmask_size(_mask); i++) {
1410 cxdouble value = _giraffe_sgmask_get_flux(_mask, i);
1418 hpixels /= _giraffe_sgmask_holes(_mask);
1428 k = CX_MAX(0, -dn1);
1430 while (i < k || _giraffe_sgmask_get_flux(_mask, i) > 0.) {
1432 _giraffe_sgmask_set_flux(_mask, i, 0.);
1437 cpl_msg_debug(fctid,
"Mask cleared from 0 to %d", i - 1);
1439 i = _giraffe_sgmask_size(_mask);
1440 k = _giraffe_sgmask_size(_mask) - CX_MAX(0, dn2);
1442 while (i > k || _giraffe_sgmask_get_flux(_mask, i) > 0.) {
1444 _giraffe_sgmask_set_flux(_mask, i, 0.);
1449 cpl_msg_debug(fctid,
"Mask cleared from %d to %ld", k,
1450 (
long)(_giraffe_sgmask_size(_mask) - 1));
1460 if (_spectra == NULL) {
1462 _giraffe_sgmask_delete(_mask);
1469 if (config->
zmax > 0.) {
1471 cpl_image_threshold(_spectra, CX_MINDOUBLE, config->
zmax,
1477 tspectra = _giraffe_resample_image(_spectra, setup->wlstep, cstep);
1479 if (tspectra == NULL) {
1481 cpl_image_delete(_spectra);
1483 _giraffe_sgmask_delete(_mask);
1489 cpl_image_delete(_spectra);
1492 if (xc1 > 0 || xc2 > 0) {
1494 _spectra = cpl_image_extract(tspectra, 1, xc1 + 1,
1495 cpl_image_get_size_x(tspectra), xc2 + 1);
1497 if (_spectra == NULL) {
1499 cpl_image_delete(tspectra);
1501 _giraffe_sgmask_delete(_mask);
1507 cpl_image_delete(tspectra);
1513 _spectra = tspectra;
1524 peakdata = cpl_table_new(cpl_table_get_nrow(fibers));
1526 cpl_table_duplicate_column(peakdata,
"INDEX", (cpl_table*)fibers,
1528 cpl_table_duplicate_column(peakdata,
"FPS", (cpl_table*)fibers,
1531 cpl_table_new_column(peakdata,
"WAVELENGTH", CPL_TYPE_DOUBLE);
1532 cpl_table_new_column(peakdata,
"FWHM", CPL_TYPE_DOUBLE);
1533 cpl_table_new_column(peakdata,
"AMPLITUDE", CPL_TYPE_DOUBLE);
1534 cpl_table_new_column(peakdata,
"BACKGROUND", CPL_TYPE_DOUBLE);
1535 cpl_table_new_column(peakdata,
"RV", CPL_TYPE_DOUBLE);
1536 cpl_table_new_column(peakdata,
"RVERR", CPL_TYPE_DOUBLE);
1537 cpl_table_new_column(peakdata,
"RESOLUTION", CPL_TYPE_DOUBLE);
1538 cpl_table_new_column(peakdata,
"STATUS", CPL_TYPE_INT);
1546 cpl_msg_debug(fctid,
"Computing cross-correlation: central wavelength = "
1547 "%.4f, window = [%.4f, %.4f] [km/s]", wlen0, dv1, dv2);
1549 spectrum = cpl_matrix_new(1, cpl_image_get_size_y(_spectra));
1551 for (i = 0; i < cpl_table_get_nrow(fibers); i++) {
1554 cxint ns = cpl_image_get_size_x(_spectra);
1555 cxint fiber = cpl_table_get_int(fibers,
"FPS", i, NULL);
1556 cxint idx = cpl_table_get_int(fibers,
"INDEX", i, NULL) - 1;
1558 const cxdouble fwhm_ratio = 2. * sqrt(2. * log(2.));
1560 cxdouble avsigma = 0.;
1562 cxdouble fxtotal = 0.;
1564 cxdouble fxmask = 0.;
1566 cxdouble position = 0.;
1568 cxdouble width = 0.;
1569 cxdouble resolution = 0.;
1571 cxdouble rverr = 0.;
1572 cxdouble* data = cpl_image_get_data(_spectra);
1574 const cpl_matrix*
template = NULL;
1575 cpl_matrix* ccf = NULL;
1576 cpl_matrix* lambda = NULL;
1578 GiCPFitParams peak_setup;
1588 for (j = 0; j < cpl_matrix_get_ncol(spectrum); j++) {
1590 cxdouble flux = data[j * ns + idx];
1593 cpl_matrix_set(spectrum, 0, j, flux);
1596 fxmask += _giraffe_sgmask_get_flux(_mask, j);
1597 fx += flux * _giraffe_sgmask_get_flux(_mask, j);
1605 avsigma = 1. / sqrt(fx);
1608 cpl_msg_debug(fctid,
"Cross-correlation of spectrum %d in window "
1609 "from %d pxl to %d pxl (%.4f nm to %.4f nm)", fiber,
1610 dn1, dn2, dw1, dw2);
1617 lambda = cpl_matrix_new(1, dn2 - dn1);
1619 for (j = dn1; j < dn2; j++) {
1620 cpl_matrix_set(lambda, 0, j - dn1, j * cstep);
1628 template = _giraffe_sgmask_get(_mask);
1630 ccf = _giraffe_compute_cross_correlation(spectrum,
template, dn1, dn2);
1634 cpl_matrix_delete(lambda);
1635 cpl_matrix_delete(spectrum);
1637 cpl_image_delete(_spectra);
1639 cpl_table_delete(peakdata);
1641 _giraffe_sgmask_delete(_mask);
1649 for (j = 0; j < cpl_matrix_get_ncol(ccf); j++) {
1650 sum += cpl_matrix_get(ccf, 0, j);
1654 cpl_msg_debug(fctid,
"Cross-correlation failed: Skipping "
1655 "spectrum %d.", fiber);
1657 cpl_matrix_delete(lambda);
1668 peak_setup.dnmin = dnmin;
1669 peak_setup.iterations = config->
rv_niter;
1670 peak_setup.step = cstep;
1672 peak_setup.sigma = avsigma;
1673 peak_setup.scale = setup->scale;
1675 peak_setup.fit.iterations = config->
pf_niter;
1676 peak_setup.fit.tests = config->
pf_ntest;
1677 peak_setup.fit.delta = config->
pf_dchisq;
1679 status = _giraffe_peak_fit(&peak, lambda, ccf, grating, &peak_setup);
1683 cpl_matrix_delete(ccf);
1684 cpl_matrix_delete(lambda);
1686 cpl_matrix_delete(spectrum);
1687 cpl_image_delete(_spectra);
1689 cpl_table_delete(peakdata);
1691 _giraffe_sgmask_delete(_mask);
1702 if (setup->scale == GIREBIN_SCALE_LOG) {
1703 position = peak.center.value * wlen0;
1704 fwhm = (exp(peak.width.value) - 1.) * wlen0;
1707 position = peak.center.value;
1708 fwhm = peak.width.value;
1711 width = pow(fwhm_ratio * fwhm, 2.) - pow(0.6 * hpixels * cstep, 2.);
1712 resolution = width > 0. ? wlen0 / sqrt(width) : 0.;
1716 rv = CX_MAX(dv1, CX_MIN(dv2, peak.center.value * nm2km));
1717 rverr = CX_MIN(dv2 - dv1, peak.center.sigma * nm2km);
1719 cpl_table_set_double(peakdata,
"WAVELENGTH", i, position);
1720 cpl_table_set_double(peakdata,
"FWHM", i, fwhm);
1721 cpl_table_set_double(peakdata,
"AMPLITUDE", i, peak.amplitude.value);
1722 cpl_table_set_double(peakdata,
"BACKGROUND", i,
1723 peak.background.value);
1724 cpl_table_set_double(peakdata,
"RESOLUTION", i, resolution);
1725 cpl_table_set_double(peakdata,
"RV", i, rv);
1726 cpl_table_set_double(peakdata,
"RVERR", i, rverr);
1727 cpl_table_set_int(peakdata,
"STATUS", i, peak.status);
1729 cpl_matrix_delete(lambda);
1730 cpl_matrix_delete(ccf);
1734 cpl_matrix_delete(spectrum);
1735 cpl_image_delete(_spectra);
1737 _giraffe_sgmask_delete(_mask);
1744 inline static cpl_table*
1745 _giraffe_compute_slitgeometry(
const GiImage* spectra,
const GiTable* mask,
1746 const GiTable* slitgeometry,
1754 cpl_table* peakdata = NULL;
1763 status = _giraffe_create_setup(&setup, spectra);
1781 peakdata = _giraffe_compute_offsets(spectra, mask, _slitgeometry,
1782 grating, &setup, config);
1784 if (peakdata == NULL) {
1794 status = _giraffe_compute_fiber_offsets(peakdata, grating, &setup);
1797 cpl_table_delete(peakdata);
1806 cpl_table_duplicate_column(peakdata,
"XF", _slitgeometry,
"XF");
1807 cpl_table_add_columns(peakdata,
"XF",
"DXF");
1814 inline static GiTable*
1815 _giraffe_slitgeometry_table(
const cpl_table* offsets,
1816 const GiImage* spectra,
1817 const GiTable* fibers,
1818 const GiTable* slitgeometry,
1822 const cxchar* idx = NULL;
1826 cpl_propertylist* properties = NULL;
1827 cpl_propertylist* _properties = NULL;
1829 cpl_table* _slit = NULL;
1830 cpl_table* _fibers = NULL;
1831 cpl_table* _slitgeometry = NULL;
1833 GiTable* slit = NULL;
1836 cx_assert(spectra != NULL);
1837 cx_assert(fibers != NULL);
1840 cx_assert(_fibers != NULL);
1843 cx_assert(_slitgeometry != NULL);
1845 if (offsets == NULL) {
1853 cx_assert(properties != NULL);
1855 giraffe_error_push();
1857 _properties = cpl_propertylist_new();
1860 GIALIAS_INSTRUMENT);
1892 cpl_propertylist_update_double(_properties, GIALIAS_SCAL_CUTOFF,
1894 cpl_propertylist_set_comment(_properties, GIALIAS_SCAL_CUTOFF,
1895 "Cutoff pixel value.");
1897 cpl_propertylist_update_string(_properties, GIALIAS_GIRFTYPE,
"SLITGEOTAB");
1898 cpl_propertylist_set_comment(_properties, GIALIAS_GIRFTYPE,
1899 "Giraffe frame type.");
1902 _slit = cpl_table_new(cpl_table_get_nrow(_fibers));
1904 cpl_table_new_column(_slit,
"INDEX", CPL_TYPE_INT);
1906 for (i = 0; i < cpl_table_get_nrow(_slit); i++) {
1907 cpl_table_set_int(_slit,
"INDEX", i, i + 1);
1910 cpl_table_duplicate_column(_slit,
"FPS", (cpl_table*)_fibers,
"FPS");
1911 cpl_table_duplicate_column(_slit,
"SSN", (cpl_table*)_fibers,
"SSN");
1912 cpl_table_duplicate_column(_slit,
"XF", (cpl_table*)offsets,
"XF");
1913 cpl_table_duplicate_column(_slit,
"YF", (cpl_table*)_slitgeometry,
"YF");
1915 if (cpl_table_has_column(_slitgeometry,
"ZF")) {
1916 cpl_table_duplicate_column(_slit,
"ZF",
1917 (cpl_table*)_slitgeometry,
"ZF");
1920 if (cpl_table_has_column(_slitgeometry,
"ZDEFOCUS")) {
1921 cpl_table_duplicate_column(_slit,
"ZDEFOCUS",
1922 (cpl_table*)_slitgeometry,
"ZDEFOCUS");
1925 cpl_table_duplicate_column(_slit,
"RV", (cpl_table*)offsets,
"RV");
1926 cpl_table_duplicate_column(_slit,
"RVERR", (cpl_table*)offsets,
"RVERR");
1927 cpl_table_duplicate_column(_slit,
"RESOLUTION", (cpl_table*)offsets,
1931 cpl_table_duplicate_column(_slit,
"RINDEX", _fibers, idx);
1933 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1934 cpl_propertylist_delete(_properties);
1935 cpl_table_delete(_slit);
1942 giraffe_error_pop();
1945 cpl_propertylist_delete(_properties);
1948 cpl_table_delete(_slit);
1962 const GiLocalization* localization,
1963 const GiTable* fibers,
const GiTable* wlsolution,
1964 const GiTable* slitgeometry,
const GiTable* grating,
1968 const cxchar*
const fctid =
"giraffe_calibrate_slit";
1973 cpl_table* _fibers = NULL;
1974 cpl_table* _slitgeometry = NULL;
1975 cpl_table* offsets = NULL;
1977 GiTable* slit = NULL;
1981 GiExtraction* _extraction = NULL;
1984 if (result == NULL) {
1988 if (extraction == NULL) {
1992 if (extraction->spectra == NULL) {
1996 if (localization == NULL) {
2000 if (fibers == NULL) {
2004 if (wlsolution == NULL) {
2008 if (slitgeometry == NULL) {
2012 if (grating == NULL) {
2020 if (config == NULL) {
2026 cx_assert(_fibers != NULL);
2029 cx_assert(_slitgeometry != NULL);
2031 if (cpl_table_get_nrow(_fibers) != cpl_table_get_nrow(_slitgeometry)) {
2042 if (setup == NULL) {
2052 _extraction = giraffe_extraction_new();
2054 _extraction->spectra = extraction->spectra;
2055 _extraction->error = NULL;
2060 for (i = 0; i < config->
repeat; i++) {
2062 cxint fps_rvmin = 0;
2063 cxint fps_rvmax = 0;
2065 cxdouble rvmin = 0.;
2066 cxdouble rvmax = 0.;
2067 cxdouble rvmean = 0.;
2073 GiRebinConfig rebin_config = {
2074 GIREBIN_METHOD_LINEAR,
2077 GIREBIN_SCALE_LINEAR,
2084 localization, grating, slit,
2085 wlsolution, &rebin_config);
2090 giraffe_extraction_delete(_extraction);
2098 offsets = _giraffe_compute_slitgeometry(rebinning->spectra, mask,
2099 slit, setup, config);
2101 if (offsets == NULL) {
2104 giraffe_extraction_delete(_extraction);
2117 cx_assert(cpl_table_get_nrow(offsets) == cpl_table_get_nrow(_fibers));
2120 slit = _giraffe_slitgeometry_table(offsets, rebinning->spectra,
2121 fibers, slitgeometry, config);
2125 cpl_table_delete(offsets);
2127 giraffe_extraction_delete(_extraction);
2135 cpl_table_delete(offsets);
2150 cpl_msg_info(fctid,
"Iteration %d: Fiber offsets [km/s]: minimum = "
2151 "%.6e (fps %d), maximum = %.6e (fps %d), mean = %.6e",
2152 i + 1, rvmin, fps_rvmin, rvmax, fps_rvmax, rvmean);
2159 giraffe_extraction_delete(_extraction);
2162 cx_assert(slit != NULL);
2200 const GiTable* grating,
const GiTable* mask,
2214 cpl_table* _fibers = NULL;
2215 cpl_table* peakdata = NULL;
2222 if ((rebinning == NULL) || (rebinning->spectra == NULL)) {
2226 if (fibers == NULL) {
2230 if (grating == NULL) {
2238 if (config == NULL) {
2244 cx_assert(_fibers != NULL);
2252 cpl_table_unselect_all(_fibers);
2253 cpl_table_or_selected_int(_fibers,
"RP", CPL_EQUAL_TO, -1);
2255 _fibers = cpl_table_extract_selected(_fibers);
2257 if (_fibers == NULL) {
2268 if (_grating == NULL) {
2269 cpl_table_delete(_fibers);
2277 status = _giraffe_create_setup(&setup, rebinning->spectra);
2282 cpl_table_delete(_fibers);
2301 peakdata = _giraffe_compute_offsets(rebinning->spectra, mask, _fibers,
2302 _grating, &setup, config);
2304 if (peakdata == NULL) {
2307 cpl_table_delete(_fibers);
2319 status = _giraffe_compute_fiber_offsets(peakdata, _grating, &setup);
2322 cpl_table_delete(peakdata);
2323 cpl_table_delete(_fibers);
2329 cpl_table_delete(_fibers);
2345 giraffe_error_push();
2347 cpl_table_new_column(_fibers,
"WLRES", CPL_TYPE_DOUBLE);
2348 cpl_table_set_column_unit(_fibers,
"WLRES",
"nm");
2350 if (cpl_error_get_code() != CPL_ERROR_NONE) {
2351 cpl_table_delete(peakdata);
2355 giraffe_error_pop();
2358 giraffe_error_push();
2360 fps0 = cpl_table_get_int(peakdata,
"FPS", 0, NULL);
2361 dwf0 = cpl_table_get_double(peakdata,
"DWF", 0, NULL);
2363 nfibers = cpl_table_get_nrow(_fibers);
2365 fps = cpl_table_get_int(_fibers,
"FPS", 0, NULL);
2367 while (fps != fps0) {
2369 cpl_table_set_double(_fibers,
"WLRES", fiber, dwf0);
2372 fps = cpl_table_get_int(_fibers,
"FPS", fiber, NULL);
2376 for (peak = 1; peak < cpl_table_get_nrow(peakdata); ++peak) {
2378 cxdouble dwf1 = cpl_table_get_double(peakdata,
"DWF", peak, NULL);
2379 cxdouble slope = 0.;
2382 fps1 = cpl_table_get_int(peakdata,
"FPS", peak, NULL);
2384 slope = (dwf1 - dwf0) / ((cxdouble)(fps1 - fps0));
2386 while (fps != fps1) {
2388 cpl_table_set_double(_fibers,
"WLRES", fiber,
2389 slope * (fps - fps0) + dwf0);
2392 fps = cpl_table_get_int(_fibers,
"FPS", fiber, NULL);
2400 fps1 = cpl_table_get_int(_fibers,
"FPS", nfibers - 1, NULL);
2402 while (fps != fps1) {
2404 cpl_table_set_double(_fibers,
"WLRES", fiber, dwf0);
2407 fps = cpl_table_get_int(_fibers,
"FPS", fiber, NULL);
2411 cpl_table_set_double(_fibers,
"WLRES", fiber, dwf0);
2413 cx_assert(fiber == nfibers - 1);
2415 if (cpl_error_get_code() != CPL_ERROR_NONE) {
2416 cpl_table_delete(peakdata);
2420 cpl_table_delete(peakdata);
2422 giraffe_error_pop();
2445 const cxchar* s = NULL;
2447 cpl_parameter* p = NULL;
2456 config = cx_calloc(1,
sizeof *config);
2460 p = cpl_parameterlist_find(list,
"giraffe.sgcalibration.iterations");
2461 config->
repeat = cpl_parameter_get_int(p);
2463 p = cpl_parameterlist_find(list,
"giraffe.sgcalibration.zmax");
2464 config->
zmax = cpl_parameter_get_double(p);
2466 p = cpl_parameterlist_find(list,
"giraffe.sgcalibration.cc.step");
2467 config->
cc_step = cpl_parameter_get_double(p);
2469 p = cpl_parameterlist_find(list,
"giraffe.sgcalibration.cc.domain");
2470 s = cpl_parameter_get_string(p);
2474 cxchar** values = cx_strsplit(s,
",", 3);
2476 if (values == NULL) {
2486 cxdouble lower = 0.;
2487 cxdouble upper = 0.;
2490 lower = strtod(values[0], &last);
2492 if (*last !=
'\0') {
2494 cx_strfreev(values);
2501 lower = lower >= 0. ? lower : 0.;
2504 if (values[1] != NULL) {
2506 upper = strtod(values[1], &last);
2508 if (*last !=
'\0') {
2510 cx_strfreev(values);
2517 upper = upper > lower ? upper : 0.;
2526 cx_strfreev(values);
2532 p = cpl_parameterlist_find(list,
"giraffe.sgcalibration.rv.limits");
2533 s = cpl_parameter_get_string(p);
2537 cxchar** values = cx_strsplit(s,
",", 3);
2539 if (values == NULL) {
2549 cxdouble lower = 0.;
2550 cxdouble upper = 0.;
2553 lower = strtod(values[0], &last);
2555 if (*last !=
'\0') {
2557 cx_strfreev(values);
2564 if (values[1] != NULL) {
2566 upper = strtod(values[1], &last);
2568 if (*last !=
'\0') {
2570 cx_strfreev(values);
2577 if (lower > 0 || upper < lower) {
2579 cx_strfreev(values);
2603 cx_assert(lower <= 0);
2604 cx_assert(lower < upper);
2611 cx_strfreev(values);
2617 p = cpl_parameterlist_find(list,
"giraffe.sgcalibration.rv.iterations");
2618 config->
rv_niter = cpl_parameter_get_int(p);
2620 p = cpl_parameterlist_find(list,
"giraffe.sgcalibration.rv.wfactor");
2621 config->
rv_wfactor = cpl_parameter_get_double(p);
2623 p = cpl_parameterlist_find(list,
"giraffe.sgcalibration.peak.iterations");
2624 config->
pf_niter = cpl_parameter_get_int(p);
2626 p = cpl_parameterlist_find(list,
"giraffe.sgcalibration.peak.tests");
2627 config->
pf_ntest = cpl_parameter_get_int(p);
2629 p = cpl_parameterlist_find(list,
"giraffe.sgcalibration.peak.dchisquare");
2630 config->
pf_dchisq = cpl_parameter_get_double(p);
2693 p = cpl_parameter_new_value(
"giraffe.sgcalibration.iterations",
2695 "Slit geometry calibration maximum number "
2697 "giraffe.sgcalibration",
2699 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"scal-cniter");
2700 cpl_parameterlist_append(list, p);
2703 p = cpl_parameter_new_value(
"giraffe.sgcalibration.zmax",
2705 "Maximum allowed pixel value. To be "
2706 "effective it must be larger than 0.",
2707 "giraffe.sgcalibration",
2709 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"scal-zmax");
2710 cpl_parameterlist_append(list, p);
2713 p = cpl_parameter_new_value(
"giraffe.sgcalibration.cc.step",
2715 "Cross-correlation step.",
2716 "giraffe.sgcalibration",
2718 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"scal-cstep");
2719 cpl_parameterlist_append(list, p);
2722 p = cpl_parameter_new_value(
"giraffe.sgcalibration.cc.domain",
2724 "Restricts the cross-correlation to the "
2726 "giraffe.sgcalibration",
2728 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"scal-cdomain");
2729 cpl_parameterlist_append(list, p);
2732 p = cpl_parameter_new_value(
"giraffe.sgcalibration.rv.limits",
2734 "Delta RV limits of the cross-correlation "
2736 "giraffe.sgcalibration",
2738 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"scal-rvlimits");
2739 cpl_parameterlist_append(list, p);
2742 p = cpl_parameter_new_value(
"giraffe.sgcalibration.rv.iterations",
2744 "Maximum number of iterations used for the "
2745 "RV determination.",
2746 "giraffe.sgcalibration",
2748 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"scal-rvniter");
2749 cpl_parameterlist_append(list, p);
2752 p = cpl_parameter_new_value(
"giraffe.sgcalibration.rv.wfactor",
2754 "Data window width factor. The FWHM times "
2755 "this value determines the window width.",
2756 "giraffe.sgcalibration",
2758 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"scal-rvwfactor");
2759 cpl_parameterlist_append(list, p);
2762 p = cpl_parameter_new_value(
"giraffe.sgcalibration.peak.iterations",
2764 "Peak model fit maximum number of "
2766 "giraffe.sgcalibration",
2769 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"scal-pfniter");
2770 cpl_parameterlist_append(list, p);
2773 p = cpl_parameter_new_value(
"giraffe.sgcalibration.peak.tests",
2775 "Cross-correlation peak fit maximum number "
2777 "giraffe.sgcalibration",
2780 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"scal-pfntest");
2781 cpl_parameterlist_append(list, p);
2784 p = cpl_parameter_new_value(
"giraffe.sgcalibration.peak.dchisquare",
2786 "Cross-correlation peak fit minimum "
2787 "chi-square difference.",
2788 "giraffe.sgcalibration",
2791 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"scal-pfdchisq");
2792 cpl_parameterlist_append(list, p);
cxdouble giraffe_range_get_min(const GiRange *const self)
Get the minimum of a range.
GiGrating * giraffe_grating_create(const GiImage *spectra, const GiTable *grating)
Create a GiGrating from a reference image.
cxint giraffe_calibrate_slit(GiTable *result, const GiExtraction *extraction, const GiLocalization *localization, const GiTable *fibers, const GiTable *wlsolution, const GiTable *slitgeometry, const GiTable *grating, const GiTable *mask, const GiSGCalConfig *config)
Compute a slit geometry corresponding to the given rebinned spectrum.
cpl_table * giraffe_table_get(const GiTable *self)
Get the table data from a Giraffe table.
cxint giraffe_table_set(GiTable *self, cpl_table *table)
Sets the table data.
cxint giraffe_rebin_spectra(GiRebinning *rebinning, const GiExtraction *extraction, const GiTable *fibers, const GiLocalization *localization, const GiTable *grating, const GiTable *slitgeo, const GiTable *solution, const GiRebinConfig *config)
Rebin an Extracted Spectra Frame and associated Errors Frame.
void giraffe_table_delete(GiTable *self)
Destroys a Giraffe table.
GiRange * giraffe_range_create(cxdouble min, cxdouble max)
Creates a new range from the given minimum and maximum values.
const cxchar * giraffe_fiberlist_query_index(const cpl_table *fibers)
Query a fiber list for the name of the fiber reference index column.
GiTable * giraffe_table_new(void)
Creates a new, empty Giraffe table.
void giraffe_sgcalibration_config_destroy(GiSGCalConfig *config)
Destroys a sgcalibration field setup structure.
GiSGCalConfig * giraffe_sgcalibration_config_create(cpl_parameterlist *list)
Creates a setup structure for the slit geometry calibration.
cxint giraffe_table_set_properties(GiTable *self, cpl_propertylist *properties)
Attaches a property list to an table.
GiTable * giraffe_table_duplicate(const GiTable *src)
Duplicate a Giraffe table.
cxint giraffe_matrix_sort(cpl_matrix *mA)
Sort in place the matrix elements in ascending order.
cxint giraffe_propertylist_copy(cpl_propertylist *self, const cxchar *name, const cpl_propertylist *other, const cxchar *othername)
Copy a property from one list to another.
Structure to handle Grating Information.
void giraffe_rebinning_destroy(GiRebinning *rebinning)
Destroys a rebinning results container and its contents.
void giraffe_grating_delete(GiGrating *self)
Destroys an GiGrating object.
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
GiRebinning * giraffe_rebinning_new(void)
Create an empty rebinning results container.
void giraffe_sgcalibration_config_add(cpl_parameterlist *list)
Adds parameters for the sgcalibration correction computation.
Slit geometry calibration configuration data structure.
cpl_propertylist * giraffe_table_get_properties(const GiTable *self)
Gets the table properties.
void giraffe_range_delete(GiRange *self)
Destroys a range object.
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
cxdouble giraffe_range_get_max(const GiRange *const self)
Get the maximum of a range.
cxint giraffe_compute_offsets(GiTable *fibers, const GiRebinning *rebinning, const GiTable *grating, const GiTable *mask, const GiSGCalConfig *config)
Compute wavelength offsets for a set of rebinned input spectrum.