37 #include <cxstrutils.h>
39 #include <cpl_error.h>
45 #include "gigrating.h"
47 #include "gilinedata.h"
48 #include "giwlsolution.h"
50 #include "gimessages.h"
51 #include "gifiberutils.h"
53 #include "giwlcalibration.h"
71 GI_LINETYPE_UNDEFINED,
76 typedef enum GiLineType GiLineType;
117 OPTM_FLENGTH = 1 << 0,
118 OPTM_GCAMERA = 1 << 1,
130 enum GiOpticalModelInfo {
131 GI_OPTM_PARAMETER_VALUES,
132 GI_OPTM_PARAMETER_ERRORS,
133 GI_OPTM_PARAMETER_STATUS
136 typedef enum GiOpticalModelInfo GiOpticalModelInfo;
143 struct GiLineParams {
160 typedef struct GiLineParams GiLineParams;
167 struct GiOpticalModelParams {
174 typedef struct GiOpticalModelParams GiOpticalModelParams;
181 struct GiSCFitParams {
194 typedef struct GiSCFitParams GiSCFitParams;
213 typedef struct GiWCalInfo GiWCalInfo;
217 _giraffe_window_compare(cxcptr first, cxcptr second)
220 cxint *_first = (cxint *)first;
221 cxint *_second = (cxint *)second;
223 return *_second - *_first;
228 inline static GiLineParams *
229 _giraffe_lineparams_create(GiLineType type,
const GiGrating *grating,
233 GiLineParams *
self = NULL;
236 cx_assert(grating != NULL);
237 cx_assert(config != NULL);
239 self = cx_calloc(1,
sizeof(GiLineParams));
250 self->grwid = 1. / grating->
band * (grating->
wlen0 / grating->
resol);
268 _giraffe_lineparams_delete(GiLineParams *
self)
274 cx_free((cxptr)self->model);
286 inline static cxdouble
287 _giraffe_get_fiber_position(
const cpl_image *locy, cxint cs, cxdouble xccd)
290 cxint xlower = (cxint)floor(xccd);
291 cxint xupper = (cxint)ceil(xccd);
293 const cxdouble *ldata = cpl_image_get_data_const(locy);
295 cxdouble ylower = 0.;
296 cxdouble yupper = 0.;
299 cx_assert(ldata != NULL);
301 ylower = ldata[xlower * cpl_image_get_size_x(locy) + cs];
302 yupper = ldata[xupper * cpl_image_get_size_x(locy) + cs];
304 return giraffe_interpolate_linear(xccd, xlower, ylower, xupper, yupper);
310 _giraffe_subslit_get_max(
const cpl_table *fibers)
313 return cpl_table_get_column_max((cpl_table *)fibers,
"SSN");
318 inline static cpl_table *
319 _giraffe_subslit_get(
const cpl_table *fibers, cxint ssn)
327 cx_assert(fibers != NULL);
328 cx_assert(cpl_table_has_column((cpl_table *)fibers,
"SSN"));
330 ssn_max = _giraffe_subslit_get_max(fibers);
332 if (ssn < 0 || ssn > ssn_max) {
336 cpl_table_unselect_all((cpl_table *)fibers);
337 cpl_table_or_selected_int((cpl_table *)fibers,
"SSN", CPL_EQUAL_TO, ssn);
339 _fibers = cpl_table_extract_selected((cpl_table *)fibers);
347 _giraffe_subslit_range(
const cpl_table *subslit,
const cpl_image *locy,
348 const cpl_image *locw, cxdouble *ymin, cxdouble *ymax)
351 const cxchar *idx = NULL;
357 const cxdouble *_locy = NULL;
358 const cxdouble *_locw = NULL;
360 cxdouble _ymin = CX_MAXDOUBLE;
363 cx_assert(subslit != NULL);
364 cx_assert(locy != NULL);
365 cx_assert(locw != NULL);
369 ns = cpl_image_get_size_x(locy);
370 nx = cpl_image_get_size_y(locy);
372 _locy = cpl_image_get_data_const(locy);
373 _locw = cpl_image_get_data_const(locw);
375 for (i = 0; i < cpl_table_get_nrow((cpl_table *)subslit); i++) {
378 cxint cs = cpl_table_get_int((cpl_table *)subslit, idx, i, NULL) - 1;
380 for (j = 0; j < nx; j++) {
382 register cxint k = j * ns + cs;
384 cxdouble ylower = _locy[k] - _locw[k];
385 cxdouble yupper = _locy[k] + _locw[k];
387 _ymin = CX_MIN(_ymin, ylower);
388 _ymax = CX_MAX(_ymax, yupper);
412 _giraffe_get_residuals(cpl_image *residuals,
const cpl_image *positions,
413 const cpl_image *fit)
421 const cxdouble *_positions = NULL;
422 const cxdouble *_fit = NULL;
424 cxdouble *_residuals = NULL;
427 cx_assert(residuals != NULL);
428 cx_assert(positions != NULL);
429 cx_assert(fit != NULL);
431 nfibers = cpl_image_get_size_x(positions);
432 nlines = cpl_image_get_size_y(positions);
433 nx = cpl_image_get_size_y(fit);
435 cx_assert(nfibers == cpl_image_get_size_x(residuals));
436 cx_assert(nlines == cpl_image_get_size_y(residuals));
438 _residuals = cpl_image_get_data(residuals);
439 _positions = cpl_image_get_data_const(positions);
440 _fit = cpl_image_get_data_const(fit);
442 for (i = 0; i < nlines; i++) {
446 for (j = 0; j < nfibers; j++) {
448 register cxdouble line_pos = _positions[i * nfibers + j];
450 line_pos = CX_MIN(CX_MAX(line_pos, 0.), nx - 1);
451 _residuals[i * nfibers + j] = _fit[(cxint)line_pos * nfibers + j];
463 _giraffe_apply_residuals(cpl_image *xccd,
const cpl_image *residuals,
464 const cpl_image *lflags, cxdouble value)
467 cx_assert(xccd != NULL);
468 cx_assert(residuals != NULL);
470 cpl_image_subtract(xccd, residuals);
472 if (lflags != NULL) {
474 const cxint *_lflags = cpl_image_get_data_const(lflags);
477 cxint nfibers = cpl_image_get_size_x(xccd);
478 cxint nlines = cpl_image_get_size_y(xccd);
480 cxdouble *_xccd = cpl_image_get_data(xccd);
483 cx_assert(nfibers == cpl_image_get_size_x(lflags));
484 cx_assert(nlines == cpl_image_get_size_y(lflags));
486 for (i = 0; i < nlines; i++) {
490 for (j = 0; j < nfibers; j++) {
492 if (_lflags[i * nfibers + j] > 0) {
493 _xccd[i * nfibers + j] = value;
508 _giraffe_linelist_setup(GiTable *lines,
GiGrating *grating,
512 const cxchar *
const fctid =
"_giraffe_linelist_setup";
515 const cxdouble fraction = 500.;
523 cxdouble margin = 0.;
525 cpl_table *_lines = NULL;
529 cx_assert(lines != NULL);
530 cx_assert(grating != NULL);
531 cx_assert(config != NULL);
536 if (_lines == NULL) {
540 if (!cpl_table_has_column(_lines,
"WLEN") ||
541 !cpl_table_has_column(_lines,
"FLUX")) {
551 nlines = cpl_table_get_nrow(_lines);
552 cpl_table_unselect_all(_lines);
567 margin = (wlmax - wlmin) / fraction;
569 cpl_msg_debug(fctid,
"Selecting wavelength range [%.4f, %.4f[ [nm] with "
570 "margin %.4f nm.", wlmin, wlmax, margin);
572 cpl_table_or_selected_double(_lines,
"WLEN", CPL_LESS_THAN,
574 cpl_table_or_selected_double(_lines,
"WLEN", CPL_NOT_LESS_THAN,
577 cpl_table_erase_selected(_lines);
579 if (cpl_table_get_nrow(_lines) <= 0) {
580 cpl_msg_debug(fctid,
"Invalid line list! All lines have been "
585 nreject = nlines - cpl_table_get_nrow(_lines);
586 cpl_msg_debug(fctid,
"%d of %d lines rejected because of wavelength "
587 "range.", nreject, nlines);
594 nlines = cpl_table_get_nrow(_lines);
601 cpl_propertylist *sorting_order = NULL;
604 if (line_count > nlines) {
605 cpl_msg_debug(fctid,
"Too few lines in line list for brightness "
612 cpl_msg_debug(fctid,
"Skipping brightness selection!");
617 sorting_order = cpl_propertylist_new();
618 cpl_propertylist_append_bool(sorting_order,
"FLUX", 1);
620 cpl_table_sort(_lines, sorting_order);
622 cpl_propertylist_delete(sorting_order);
623 sorting_order = NULL;
625 cpl_table_select_all(_lines);
627 for (i = 0; i < line_count; i++) {
628 cpl_table_unselect_row(_lines, i);
631 status = cpl_table_erase_selected(_lines);
633 if (cpl_table_get_nrow(_lines) <= 0) {
637 sorting_order = cpl_propertylist_new();
638 cpl_propertylist_append_bool(sorting_order,
"WLEN", 0);
640 cpl_table_sort(_lines, sorting_order);
642 cpl_propertylist_delete(sorting_order);
643 sorting_order = NULL;
649 cpl_table_select_all(_lines);
650 cpl_table_and_selected_double(_lines,
"FLUX", CPL_NOT_GREATER_THAN,
653 cpl_table_erase_selected(_lines);
655 if (cpl_table_get_nrow(_lines) <= 0) {
656 cpl_msg_debug(fctid,
"Invalid line brightness! All lines have "
663 nreject = nlines - cpl_table_get_nrow(_lines);
664 cpl_msg_debug(fctid,
"%d of %d lines rejected because brightness "
665 "criteria.", nreject, nlines);
673 inline static cpl_table *
674 _giraffe_linelist_select(
const GiTable *lines,
const GiImage *spectra,
675 const GiGrating *grating, cxdouble width,
679 const cxchar *
const fctid =
"_giraffe_linelist_select";
687 cxdouble separation = 0.;
689 cpl_image *_spectra = NULL;
691 cpl_table *_lines = NULL;
694 cx_assert(lines != NULL);
695 cx_assert(spectra != NULL);
696 cx_assert(grating != NULL);
697 cx_assert(config != NULL);
700 cx_assert(_spectra != NULL);
704 if (_lines == NULL) {
708 nlines = cpl_table_get_nrow(_lines);
716 scale = fabs(cpl_image_get_size_y(_spectra)) / grating->
band;
719 cpl_msg_debug(fctid,
"Estimated wavelength scale: %.4e nm/pxl",
721 cpl_msg_debug(fctid,
"Minimum required line separation: %.4f nm (%.4f "
722 "pxl)", separation, separation * scale);
738 cpl_table_unselect_all(_lines);
740 for (i = 0; i < cpl_table_get_nrow(_lines); i++) {
744 register cxdouble w = cpl_table_get(_lines,
"WLEN", i, NULL);
745 register cxdouble f = cpl_table_get(_lines,
"FLUX", i, NULL);
748 for (j = 0; j < cpl_table_get_nrow(_lines); j++) {
752 register cxdouble _w = cpl_table_get(_lines,
"WLEN", j, NULL);
753 register cxdouble _f = cpl_table_get(_lines,
"FLUX", j, NULL);
756 if (fabs(w - _w) < separation &&
757 f / _f < config->line_fluxratio) {
759 cpl_table_select_row(_lines, i);
770 cpl_table_erase_selected(_lines);
772 if (cpl_table_get_nrow(_lines) <= 0) {
773 cpl_table_delete(_lines);
777 nreject = nlines - cpl_table_get_nrow(_lines);
778 cpl_msg_debug(fctid,
"%d of %d lines rejected due to crowding.",
791 cpl_msg_debug(fctid,
"Removing lines with non-zero line quality.");
793 nlines = cpl_table_get_nrow(_lines);
794 cpl_table_unselect_all(_lines);
796 if (cpl_table_has_column(_lines,
"FLAGS")) {
798 cpl_table_or_selected_int(_lines,
"FLAGS", CPL_NOT_EQUAL_TO, 0);
803 if (cpl_table_has_column(_lines,
"COMMENT")) {
805 for (i = 0; i < nlines; i++) {
807 cxchar *s = cx_strdup(cpl_table_get_string(_lines,
810 if (strlen(cx_strstrip(s)) > 3) {
811 cpl_table_select_row(_lines, i);
821 cpl_msg_debug(fctid,
"No comments found in line list! No line "
822 "quality checks will be done!");
828 cpl_table_erase_selected(_lines);
830 if (cpl_table_get_nrow(_lines) <= 0) {
831 cpl_msg_debug(fctid,
"Invalid line list! All lines have been "
833 cpl_table_delete(_lines);
837 nreject = nlines - cpl_table_get_nrow(_lines);
838 cpl_msg_debug(fctid,
"%d of %d lines rejected because of line quality.",
847 inline static cpl_image *
848 _giraffe_line_abscissa(
const cpl_table *lines,
const GiTable *slitgeometry,
849 const GiTable *fibers,
const GiWlSolution *solution,
850 const GiLocalization *localization, cxbool residuals)
853 const cxchar *
const fctid =
"_giraffe_line_abscissa";
856 const cxchar *idx = NULL;
862 cpl_table *_lines = NULL;
863 cpl_table *_fibers = NULL;
864 cpl_table *_slitgeometry = NULL;
866 cpl_image *abscissa = NULL;
869 cx_assert(lines != NULL);
870 cx_assert(slitgeometry != NULL);
871 cx_assert(fibers != NULL);
872 cx_assert(solution != NULL);
874 _lines = (cpl_table *)lines;
877 cx_assert(_fibers != NULL);
880 cx_assert(_slitgeometry != NULL);
883 nlines = cpl_table_get_nrow(_lines);
884 nfibers = cpl_table_get_nrow(_fibers);
886 if (nfibers != cpl_table_get_nrow(_slitgeometry)) {
887 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
895 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
900 if (residuals == TRUE) {
902 if (localization == NULL) {
903 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
907 if (localization->locy == NULL || localization->locw == NULL) {
908 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
913 if (giraffe_wlsolution_get_residuals(solution) == NULL) {
914 cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
921 abscissa = cpl_image_new(nfibers, nlines, CPL_TYPE_DOUBLE);
923 for (i = 0; i < nfibers; i++) {
927 cxdouble xf = cpl_table_get(_slitgeometry,
"XF", i, NULL);
928 cxdouble yf = cpl_table_get(_slitgeometry,
"YF", i, NULL);
929 cxdouble *data = cpl_image_get_data(abscissa);
932 for (j = 0; j < nlines; j++) {
936 cxdouble lambda = cpl_table_get(_lines,
"WLEN", j, NULL);
941 xccd = giraffe_wlsolution_compute_pixel(solution, lambda, xf, yf,
945 cpl_image_delete(abscissa);
949 if (residuals == TRUE) {
951 cxint cs = cpl_table_get_int(_fibers, idx, i, NULL) - 1;
958 cx_assert(_locy != NULL);
960 if (xccd > 0. && xccd < cpl_image_get_size_y(_locy)) {
964 yccd = _giraffe_get_fiber_position(_locy, cs, xccd);
965 xres = giraffe_wlsolution_compute_residual(solution,
973 data[j * nfibers + i] = xccd;
984 inline static cpl_image *
985 _giraffe_line_ordinate(GiTable *lines,
const GiTable *slitgeometry,
986 const GiWlSolution *solution)
1000 _giraffe_line_fit_setup(GiModel *model, cxdouble width, cxint xmin,
1001 const cpl_matrix *y,
const cpl_matrix *sigma,
1002 const GiLineParams *setup, cxint *lflags)
1009 cxdouble amplitude = 0.;
1010 cxdouble background = 0.;
1011 cxdouble _sigma = 0.;
1013 cpl_matrix *_y = NULL;
1016 cx_assert(model != NULL);
1017 cx_assert(y != NULL);
1018 cx_assert(setup != NULL);
1019 cx_assert(lflags != NULL);
1022 if (*lflags != LF_R_NONE) {
1037 for (k = 0; k < cpl_matrix_get_nrow((cpl_matrix*)y); k++) {
1038 if (cpl_matrix_get((cpl_matrix *)y, k, 0) >= amplitude) {
1041 amplitude = cpl_matrix_get((cpl_matrix *)y, k, 0);
1048 _y = cpl_matrix_duplicate((cpl_matrix *)y);
1052 background = 0.5 * (cpl_matrix_get(_y, 0, 0) + cpl_matrix_get(_y, 1, 0));
1053 cpl_matrix_delete(_y);
1063 _sigma = cpl_matrix_get((cpl_matrix *)sigma, xline, 0) * setup->thres;
1065 if (amplitude <= _sigma || amplitude > setup->satlv) {
1066 *lflags |= LF_R_AMPLI;
1070 giraffe_model_set_parameter(model,
"Amplitude", amplitude - background);
1071 giraffe_model_set_parameter(model,
"Center", center);
1072 giraffe_model_set_parameter(model,
"Background", background);
1073 giraffe_model_set_parameter(model,
"Width1", width);
1075 if (strncmp(giraffe_model_get_name(model),
"psfexp", 6) == 0) {
1077 cxdouble width2 = setup->psfexp < 0. ? -setup->psfexp : setup->psfexp;
1079 giraffe_model_set_parameter(model,
"Width2", width2);
1087 if (setup->psfexp >= 0.) {
1088 giraffe_model_freeze_parameter(model,
"Width2");
1091 giraffe_model_thaw_parameter(model,
"Width2");
1102 _giraffe_line_fit(GiLineData *lines,
const cpl_image *positions, cxint width,
1103 const GiExtraction *extraction,
const GiTable *fibers,
1104 const GiImage *locy,
const GiLineParams *setup)
1107 const cxchar *
const fctid =
"_giraffe_line_fit";
1110 const cxchar *idx = NULL;
1116 const cxdouble LOG2 = log(2.);
1117 const cxdouble fwhm_ratio = 2. * sqrt(2. * LOG2);
1119 cpl_image *_spectra = NULL;
1120 cpl_image *_errors = NULL;
1121 cpl_image *_locy = NULL;
1123 cpl_matrix *x = NULL;
1124 cpl_matrix *y = NULL;
1125 cpl_matrix *sigma = NULL;
1127 cpl_table *_fibers = NULL;
1129 GiModel *model = NULL;
1132 cx_assert(positions != NULL);
1133 cx_assert(width > 0);
1135 cx_assert(extraction != NULL);
1136 cx_assert(extraction->spectra != NULL && extraction->error != NULL);
1138 cx_assert(fibers != NULL);
1139 cx_assert(locy != NULL);
1140 cx_assert(setup != NULL);
1144 cx_assert(_fibers != NULL);
1147 cx_assert(_spectra != NULL);
1150 cx_assert(_errors != NULL);
1153 cx_assert(_locy != NULL);
1155 nfibers = cpl_table_get_nrow(_fibers);
1157 cx_assert(nfibers == cpl_image_get_size_x(_spectra));
1158 cx_assert(nfibers == cpl_image_get_size_x(_errors));
1165 cx_assert(idx != NULL);
1167 nlines = cpl_image_get_size_y(positions);
1174 if (strcmp(setup->model,
"gaussian") != 0 &&
1175 strcmp(setup->model,
"psfexp") != 0 &&
1176 strcmp(setup->model,
"psfexp2") != 0) {
1177 cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
1181 model = giraffe_model_new(setup->model);
1183 if (giraffe_model_get_type(model) != GI_MODEL_LINE) {
1184 giraffe_model_delete(model);
1188 giraffe_model_thaw(model);
1190 giraffe_model_set_iterations(model, setup->fit.iterations);
1191 giraffe_model_set_tests(model, setup->fit.tests);
1192 giraffe_model_set_delta(model, setup->fit.delta);
1199 x = cpl_matrix_new(width, 1);
1200 y = cpl_matrix_new(width, 1);
1201 sigma = cpl_matrix_new(width, 1);
1203 for (i = 0; i < nfibers; i++) {
1207 for (j = 0; j < nlines; j++) {
1210 cxint lflags = LF_R_NONE;
1211 cxint iterations = 0;
1215 cxint nx = cpl_image_get_size_y(_spectra);
1219 cxdouble lwidth = 0.;
1220 cxdouble amplitude = 0.;
1221 cxdouble background = 0.;
1222 cxdouble center = 0.;
1223 cxdouble width1 = 0.;
1224 cxdouble exponent = 0.;
1225 cxdouble error = 0.;
1226 cxdouble gwidth = 0.;
1228 const cxdouble *_positions = cpl_image_get_data_const(positions);
1235 xccd = _positions[j * nfibers + i];
1240 if (0 < xccd && xccd < nx) {
1242 cxint cs = cpl_table_get_int(_fibers, idx, i, NULL) - 1;
1250 xmin = (cxint)(xccd - 0.5 * width + 0.5);
1251 xmax = (cxint)(xccd + 0.5 * width + 0.5);
1253 xmin = CX_MAX(CX_MIN(xmin, nx - 1), 0);
1254 xmax = CX_MAX(CX_MIN(xmax, nx - 1), 0);
1256 ndata = xmax - xmin;
1263 yccd = _giraffe_get_fiber_position(_locy, cs, xccd);
1274 lflags |= LF_R_XCCD;
1282 if (ndata != cpl_matrix_get_nrow(x)) {
1283 cpl_matrix_set_size(x, ndata, 1);
1284 cpl_matrix_set_size(y, ndata, 1);
1285 cpl_matrix_set_size(sigma, ndata, 1);
1288 for (k = 0; k < ndata; k++) {
1292 cxdouble *sdata = cpl_image_get_data(_spectra);
1293 cxdouble *edata = cpl_image_get_data(_errors);
1295 cpl_matrix_set(x, k, 0, xmin + k);
1296 cpl_matrix_set(y, k, 0, sdata[l * nfibers + i]);
1297 cpl_matrix_set(sigma, k, 0, edata[l * nfibers + i]);
1314 if (strcmp(setup->model,
"psfexp") == 0) {
1316 exponent = fabs(setup->psfexp);
1318 lwidth = pow(0.5 * setup->grwid * nx, exponent) / LOG2;
1321 else if (strcmp(setup->model,
"psfexp2") == 0) {
1323 exponent = fabs(setup->psfexp);
1325 lwidth = setup->grwid * nx / (2. * pow(LOG2, 1. / exponent));
1328 else if (strcmp(setup->model,
"gaussian") == 0) {
1330 lwidth = setup->grwid * nx / fwhm_ratio;
1339 gi_error(
"Unsupported line model encountered!");
1350 _giraffe_line_fit_setup(model, lwidth, xmin, y, sigma, setup,
1354 if (lflags == LF_R_NONE) {
1356 cxint xline = giraffe_model_get_parameter(model,
"Center");
1358 cxdouble hwidth = 0.;
1367 status = giraffe_model_fit(model, x, y, sigma);
1370 amplitude = giraffe_model_get_parameter(model,
"Amplitude");
1371 background = giraffe_model_get_parameter(model,
"Background");
1372 center = giraffe_model_get_parameter(model,
"Center");
1380 if (strcmp(setup->model,
"psfexp") == 0) {
1382 width1 = giraffe_model_get_parameter(model,
"Width1");
1383 exponent = giraffe_model_get_parameter(model,
"Width2");
1386 gwidth = 2. * pow(width1 * LOG2, 1. / exponent);
1389 else if (strcmp(setup->model,
"psfexp2") == 0) {
1391 width1 = giraffe_model_get_parameter(model,
"Width1");
1392 exponent = giraffe_model_get_parameter(model,
"Width2");
1395 gwidth = 2. * pow(LOG2, 1. / exponent) * width1;
1398 else if (strcmp(setup->model,
"gaussian") == 0) {
1400 width1 = giraffe_model_get_parameter(model,
"Width1");
1403 gwidth = width1 * fwhm_ratio;
1412 gi_error(
"Unsupported line model encountered!");
1416 hwidth = gwidth / 2.;
1417 iterations = giraffe_model_get_position(model);
1428 lflags |= LF_R_ERROR;
1432 if (iterations >= giraffe_model_get_iterations(model)) {
1435 lflags |= LF_R_NITER;
1439 if (xmin > center || center > xmax) {
1442 lflags |= LF_R_CENTR;
1446 if ((center - hwidth) < xmin) {
1449 lflags |= LF_R_LEFT;
1453 if ((center + hwidth) > xmax) {
1456 lflags |= LF_R_RIGHT;
1460 if ((center - xline) >= setup->offst) {
1463 lflags |= LF_R_OFFST;
1467 if (width1 < 0. || exponent < 0.) {
1470 lflags |= LF_R_BADLN;
1474 if (gwidth > (xmax - xmin)) {
1477 lflags |= LF_R_WIDTH;
1481 if (gwidth < (setup->grwid * nx * setup->wfact)) {
1484 lflags |= LF_R_RESOL;
1488 if (gwidth > (setup->grwid * nx / setup->wfact)) {
1491 lflags |= LF_R_RESOL;
1504 giraffe_linedata_set_status(lines, i, j, lflags);
1506 giraffe_linedata_set(lines,
"Iterations", i, j,iterations);
1507 giraffe_linedata_set(lines,
"Chi-square", i, j,
1508 giraffe_model_get_chisq(model));
1509 giraffe_linedata_set(lines,
"DoF", i, j,
1510 giraffe_model_get_df(model));
1511 giraffe_linedata_set(lines,
"R-square", i, j,
1512 giraffe_model_get_rsquare(model));
1513 giraffe_linedata_set(lines,
"Xccd", i, j, xccd);
1514 giraffe_linedata_set(lines,
"Yccd", i, j, yccd);
1524 giraffe_linedata_set(lines,
"Amplitude", i, j, amplitude);
1525 giraffe_linedata_set(lines,
"Background", i, j, background);
1526 giraffe_linedata_set(lines,
"Center", i, j, center);
1527 giraffe_linedata_set(lines,
"Width1", i, j, width1);
1529 if (strncmp(setup->model,
"psfexp", 6) == 0) {
1530 giraffe_linedata_set(lines,
"Width2", i, j, exponent);
1533 giraffe_linedata_set(lines,
"FWHM", i, j, gwidth);
1537 error = giraffe_model_get_sigma(model,
"Amplitude");
1538 giraffe_linedata_set(lines,
"dAmplitude", i, j, error);
1540 error = giraffe_model_get_sigma(model,
"Center");
1541 giraffe_linedata_set(lines,
"dCenter", i, j, error);
1543 error = giraffe_model_get_sigma(model,
"Background");
1544 giraffe_linedata_set(lines,
"dBackground", i, j, error);
1546 error = giraffe_model_get_sigma(model,
"Width1");
1547 giraffe_linedata_set(lines,
"dWidth1", i, j, error);
1549 if (strncmp(setup->model,
"psfexp", 6) == 0) {
1550 error = giraffe_model_get_sigma(model,
"Width2");
1551 giraffe_linedata_set(lines,
"dWidth2", i, j, error);
1558 cpl_matrix_delete(x);
1559 cpl_matrix_delete(y);
1560 cpl_matrix_delete(sigma);
1562 giraffe_model_delete(model);
1569 inline static cpl_image *
1570 _giraffe_psf_fit(GiLineData *lines,
const GiLocalization *localization,
1571 GiTable *fibers, GiTable *slitgeometry, GiSCFitParams *setup)
1574 const cxchar *
const fctid =
"_giraffe_psf_fit";
1581 cxint nsubslits = 1;
1584 cpl_table *_fibers = NULL;
1586 cpl_image *locy = NULL;
1587 cpl_image *locw = NULL;
1588 cpl_image *psfwidth = NULL;
1591 cx_assert(lines != NULL);
1592 cx_assert(localization != NULL);
1593 cx_assert(fibers != NULL);
1594 cx_assert(slitgeometry != NULL);
1595 cx_assert(setup != NULL);
1598 cx_assert(_fibers != NULL);
1601 cx_assert(locy != NULL);
1604 cx_assert(locw != NULL);
1606 nx = cpl_image_get_size_y(locy);
1607 nlines = giraffe_linedata_lines(lines);
1609 psfwidth = cpl_image_new(cpl_table_get_nrow(_fibers), nx,
1612 if (setup->subslits == TRUE) {
1613 nsubslits = _giraffe_subslit_get_max(_fibers);
1616 for (i = 0; i < nsubslits; i++) {
1623 cxint iterations = 0;
1629 cxdouble ratio = 1.;
1631 cpl_matrix *xss = NULL;
1632 cpl_matrix *yss = NULL;
1633 cpl_matrix *wss = NULL;
1634 cpl_matrix *sss = NULL;
1635 cpl_matrix *nss = NULL;
1636 cpl_matrix *lss = NULL;
1637 cpl_matrix *base = NULL;
1638 cpl_matrix *fit = NULL;
1639 cpl_matrix *coeff = NULL;
1640 cpl_matrix *chebyshev = NULL;
1642 cpl_table *subslit = NULL;
1644 GiChebyshev2D *psffit = NULL;
1647 if (setup->subslits == TRUE) {
1648 subslit = _giraffe_subslit_get(_fibers, i + 1);
1649 ssn = cpl_table_get_int(subslit,
"SSN", 0, NULL);
1651 cx_assert(ssn == i + 1);
1654 subslit = cpl_table_duplicate(_fibers);
1658 if (subslit == NULL) {
1662 _giraffe_subslit_range(subslit, locy, locw, &ymin, &ymax);
1664 nfibers = cpl_table_get_nrow(subslit);
1665 ndata = nfibers * nlines;
1668 xss = cpl_matrix_new(ndata, 1);
1669 yss = cpl_matrix_new(ndata, 1);
1670 wss = cpl_matrix_new(1, ndata);
1671 sss = cpl_matrix_new(ndata, 1);
1672 nss = cpl_matrix_new(ndata, 1);
1673 lss = cpl_matrix_new(ndata, 1);
1683 for (j = 0; j < nfibers; j++) {
1686 cxint n = cpl_table_get_int(subslit,
"INDEX", j, NULL) - 1;
1688 for (l = 0; l < nlines; l++) {
1690 cxdouble value = 0.;
1691 cxdouble yccd = giraffe_linedata_get(lines,
"Yccd", n, l);
1693 if (giraffe_linedata_get_status(lines, n, l) != 0) {
1697 if (yccd < ymin || yccd > ymax) {
1701 value = giraffe_linedata_get(lines,
"Xccd", n, l);
1702 cpl_matrix_set(xss, k, 0, value);
1704 cpl_matrix_set(yss, k, 0, yccd);
1713 value = giraffe_linedata_get(lines,
"FWHM", n, l);
1714 cpl_matrix_set(wss, 0, k, value);
1716 value = giraffe_linedata_get(lines,
"dWidth1", n, l);
1717 cpl_matrix_set(sss, k, 0, value);
1719 cpl_matrix_set(nss, k, 0, n);
1720 cpl_matrix_set(lss, k, 0, l);
1729 cpl_msg_debug(fctid,
"Skipping subslit %d: No input lines left! "
1730 "All lines have non-zero status or are beyond the "
1731 "subslit boundaries (%.4f, %.4f).", ssn, ymin, ymax);
1739 cpl_matrix_set_size(xss, k, 1);
1740 cpl_matrix_set_size(yss, k, 1);
1741 cpl_matrix_set_size(wss, 1, k);
1742 cpl_matrix_set_size(sss, k, 1);
1743 cpl_matrix_set_size(nss, k, 1);
1744 cpl_matrix_set_size(lss, k, 1);
1753 accepted = cpl_matrix_get_ncol(wss);
1756 while (accepted > 0 && iterations < setup->clip.iterations &&
1757 ratio > setup->clip.fraction) {
1759 base = giraffe_chebyshev_base2d(0., ymin, nx, ymax - ymin + 1.,
1760 setup->fit.xorder + 1,
1761 setup->fit.yorder + 1, xss, yss);
1763 if (coeff != NULL) {
1764 cpl_matrix_delete(coeff);
1770 if (coeff == NULL) {
1771 cpl_msg_debug(fctid,
"Error solving linear system for "
1772 "subslit %d, skipping subslit.", ssn);
1776 fit = cpl_matrix_product_create(coeff, base);
1780 for (j = 0; j < cpl_matrix_get_ncol(fit); j++) {
1782 cxdouble _fit = cpl_matrix_get(fit, 0, j);
1783 cxdouble _wss = cpl_matrix_get(wss, 0, j);
1784 cxdouble _sss = cpl_matrix_get(sss, j, 0);
1786 if (fabs(_fit - _wss) >= setup->clip.level * _sss) {
1788 cxint n = (cxint)cpl_matrix_get(nss, j, 0);
1789 cxint l = (cxint)cpl_matrix_get(lss, j, 0);
1795 giraffe_linedata_set_status(lines, n, l, LF_R_PSFIT);
1800 cpl_matrix_set(xss, k, 0, cpl_matrix_get(xss, j, 0));
1801 cpl_matrix_set(yss, k, 0, cpl_matrix_get(yss, j, 0));
1802 cpl_matrix_set(wss, 0, k, cpl_matrix_get(wss, 0, j));
1803 cpl_matrix_set(sss, k, 0, cpl_matrix_get(sss, j, 0));
1804 cpl_matrix_set(nss, k, 0, cpl_matrix_get(nss, j, 0));
1805 cpl_matrix_set(lss, k, 0, cpl_matrix_get(lss, j, 0));
1810 cpl_matrix_delete(base);
1811 cpl_matrix_delete(fit);
1813 if (k == accepted) {
1823 ratio = (cxdouble)accepted / (cxdouble)total;
1825 cpl_matrix_set_size(xss, k, 1);
1826 cpl_matrix_set_size(yss, k, 1);
1827 cpl_matrix_set_size(wss, 1, k);
1828 cpl_matrix_set_size(sss, k, 1);
1829 cpl_matrix_set_size(nss, k, 1);
1830 cpl_matrix_set_size(lss, k, 1);
1838 if (accepted == 0) {
1839 cpl_msg_debug(fctid,
"Subslit %d: All lines rejected.", ssn);
1843 if (coeff == NULL) {
1849 cpl_matrix_delete(xss);
1850 cpl_matrix_delete(yss);
1851 cpl_matrix_delete(wss);
1852 cpl_matrix_delete(sss);
1853 cpl_matrix_delete(nss);
1854 cpl_matrix_delete(lss);
1861 xss = cpl_matrix_new(nx * nfibers, 1);
1862 yss = cpl_matrix_new(nx * nfibers, 1);
1864 giraffe_compute_image_coordinates(nx, nfibers, xss, NULL);
1866 for (j = 0; j < cpl_table_get_nrow(subslit); j++) {
1871 cxint ns = cpl_image_get_size_x(locy);
1872 cxint cs = cpl_table_get_int(subslit, idx, j, NULL) - 1;
1874 cxdouble *data = cpl_image_get_data(locy);
1877 for (l = 0; l < nx; l++) {
1878 cpl_matrix_set(yss, l * nfibers + j, 0, data[l * ns + cs]);
1888 base = giraffe_chebyshev_base2d(0., ymin, nx, ymax - ymin + 1.,
1889 setup->fit.xorder + 1,
1890 setup->fit.yorder + 1, xss, yss);
1892 fit = cpl_matrix_product_create(coeff, base);
1894 cpl_matrix_delete(xss);
1897 cpl_matrix_delete(yss);
1910 chebyshev = cpl_matrix_wrap(setup->fit.xorder + 1,
1911 setup->fit.yorder + 1,
1912 cpl_matrix_get_data(coeff));
1914 psffit = giraffe_chebyshev2d_new(setup->fit.xorder, setup->fit.yorder);
1915 status = giraffe_chebyshev2d_set(psffit, 0., nx, ymin, ymax,
1920 giraffe_chebyshev2d_delete(psffit);
1922 cpl_matrix_unwrap(chebyshev);
1924 cpl_matrix_delete(base);
1925 cpl_matrix_delete(coeff);
1926 cpl_matrix_delete(fit);
1928 cpl_table_delete(subslit);
1930 cpl_image_delete(psfwidth);
1936 cpl_matrix_unwrap(chebyshev);
1939 giraffe_chebyshev2d_delete(psffit);
1947 for (j = 0; j < cpl_table_get_nrow(subslit); j++) {
1950 cxint n = cpl_table_get_int(subslit,
"INDEX", j, NULL) - 1;
1951 cxint ns = cpl_table_get_nrow(_fibers);
1953 cxdouble *data = cpl_image_get_data(psfwidth);
1955 for (l = 0; l < nx; l++) {
1956 data[l * ns + n] = cpl_matrix_get(fit, 0, l * nfibers + j);
1961 cpl_matrix_delete(base);
1962 cpl_matrix_delete(coeff);
1963 cpl_matrix_delete(fit);
1965 cpl_table_delete(subslit);
1975 _giraffe_opticalmodel_fit(GiWlSolution *solution, GiLineData *lines,
1976 GiTable *fibers, GiTable *slitgeometry,
1977 GiOpticalModelParams *setup)
1980 const cxchar *
const fctid =
"_giraffe_opticalmodel_fit";
1989 cpl_matrix *x = NULL;
1990 cpl_matrix *y = NULL;
1991 cpl_matrix *sigma = NULL;
1993 cpl_table *_fibers = NULL;
1994 cpl_table *_slitgeometry = NULL;
1996 GiModel *model = NULL;
1999 cx_assert(solution != NULL);
2000 cx_assert(lines != NULL);
2001 cx_assert(fibers != NULL);
2002 cx_assert(slitgeometry != NULL);
2003 cx_assert(setup != NULL);
2006 cx_assert(_fibers != NULL);
2009 cx_assert(_slitgeometry != NULL);
2011 model = giraffe_wlsolution_model(solution);
2018 ndata = giraffe_linedata_lines(lines) * giraffe_linedata_fibers(lines);
2020 x = cpl_matrix_new(ndata, giraffe_model_count_arguments(model));
2021 y = cpl_matrix_new(ndata, 1);
2022 sigma = cpl_matrix_new(ndata, 1);
2024 for (i = 0; i < giraffe_linedata_fibers(lines); i++) {
2028 cxdouble xf = cpl_table_get(_slitgeometry,
"XF", i, NULL);
2029 cxdouble yf = cpl_table_get(_slitgeometry,
"YF", i, NULL);
2032 for (j = 0; j < giraffe_linedata_lines(lines); j++) {
2034 if (giraffe_linedata_get_status(lines, i, j) != 0) {
2041 if (giraffe_linedata_get(lines,
"dCenter", i, j) <= 0.) {
2045 cpl_matrix_set(x, ngood, 0,
2046 giraffe_linedata_get_wavelength(lines, j));
2047 cpl_matrix_set(x, ngood, 1, xf);
2048 cpl_matrix_set(x, ngood, 2, yf);
2050 cpl_matrix_set(y, ngood, 0,
2051 giraffe_linedata_get(lines,
"Center", i, j));
2052 cpl_matrix_set(sigma, ngood, 0,
2053 giraffe_linedata_get(lines,
"dCenter", i, j));
2061 cpl_msg_debug(fctid,
"Using %d of %d line positions for optical "
2062 "model fit.", ngood, ndata);
2066 cpl_matrix_delete(x);
2067 cpl_matrix_delete(y);
2068 cpl_matrix_delete(sigma);
2078 cpl_matrix_set_size(x, ngood, giraffe_model_count_arguments(model));
2079 cpl_matrix_set_size(y, ngood, 1);
2080 cpl_matrix_set_size(sigma, ngood, 1);
2087 giraffe_model_freeze(model);
2089 if (setup->flags & OPTM_FLENGTH) {
2090 giraffe_model_thaw_parameter(model,
"FocalLength");
2093 if (setup->flags & OPTM_GCAMERA) {
2094 giraffe_model_thaw_parameter(model,
"Magnification");
2097 if (setup->flags & OPTM_THETA) {
2098 giraffe_model_thaw_parameter(model,
"Angle");
2101 if (strcmp(giraffe_model_get_name(model),
"xoptmod2") == 0) {
2102 if (setup->flags & OPTM_SX) {
2103 giraffe_model_thaw_parameter(model,
"Sdx");
2106 if (setup->flags & OPTM_SY) {
2107 giraffe_model_thaw_parameter(model,
"Sdy");
2110 if (setup->flags & OPTM_SPHI) {
2111 giraffe_model_thaw_parameter(model,
"Sphi");
2115 giraffe_model_set_iterations(model, setup->fit.iterations);
2116 giraffe_model_set_tests(model, setup->fit.tests);
2117 giraffe_model_set_delta(model, setup->fit.delta);
2124 status = giraffe_model_fit(model, x, y, sigma);
2128 cpl_matrix_delete(x);
2129 cpl_matrix_delete(y);
2130 cpl_matrix_delete(sigma);
2136 cpl_matrix_delete(x);
2137 cpl_matrix_delete(y);
2138 cpl_matrix_delete(sigma);
2146 _giraffe_opticalmodel_format(cx_string *s,
const GiModel *model,
2147 GiOpticalModelInfo info)
2150 const cxchar *name = NULL;
2152 cxbool offsets = FALSE;
2157 cx_assert(s != NULL);
2159 if (model == NULL) {
2163 name = giraffe_model_get_name(model);
2165 if (name == NULL || strncmp(name,
"xoptmod", 7) != 0) {
2169 if (strncmp(name,
"xoptmod2", 8) == 0) {
2176 case GI_OPTM_PARAMETER_VALUES:
2179 cxdouble fcoll = 0.;
2181 cxdouble theta = 0.;
2183 fcoll = giraffe_model_get_parameter(model,
"FocalLength");
2184 gcam = giraffe_model_get_parameter(model,
"Magnification");
2185 theta = giraffe_model_get_parameter(model,
"Angle");
2187 cx_string_sprintf(s,
"focal length = %.6f, camera "
2188 "magnification = %.6f, grating angle = %.9f",
2189 fcoll, gcam, theta);
2191 if (offsets == TRUE) {
2197 cx_string *_s = cx_string_new();
2199 sdx = giraffe_model_get_parameter(model,
"Sdx");
2200 sdy = giraffe_model_get_parameter(model,
"Sdy");
2201 sphi = giraffe_model_get_parameter(model,
"Sphi");
2203 cx_string_sprintf(_s,
", slit x-shift = %.9f, slit "
2204 "y-shift = %.9f, slit rotation = %.9f",
2206 cx_string_append(s, cx_string_get(_s));
2208 cx_string_delete(_s);
2216 case GI_OPTM_PARAMETER_ERRORS:
2219 cxdouble fcoll = 0.;
2221 cxdouble theta = 0.;
2223 fcoll = giraffe_model_get_sigma(model,
"FocalLength");
2224 gcam = giraffe_model_get_sigma(model,
"Magnification");
2225 theta = giraffe_model_get_sigma(model,
"Angle");
2227 cx_string_sprintf(s,
"focal length = %.6f, camera "
2228 "magnification = %.6f, grating angle = %.9f",
2229 fcoll, gcam, theta);
2231 if (offsets == TRUE) {
2237 cx_string *_s = cx_string_new();
2239 sdx = giraffe_model_get_sigma(model,
"Sdx");
2240 sdy = giraffe_model_get_sigma(model,
"Sdy");
2241 sphi = giraffe_model_get_sigma(model,
"Sphi");
2243 cx_string_sprintf(_s,
", slit x-shift = %.9f, slit "
2244 "y-shift = %.9f, slit rotation = %.9f",
2246 cx_string_append(s, cx_string_get(_s));
2248 cx_string_delete(_s);
2256 case GI_OPTM_PARAMETER_STATUS:
2259 const cxchar *
const s_free =
"free";
2260 const cxchar *
const s_frozen =
"frozen";
2261 const cxchar *t = NULL;
2263 cx_string *buffer = cx_string_new();
2266 t = giraffe_model_frozen_parameter(model,
"FocalLength") ?
2268 cx_string_sprintf(buffer,
"focal length = %s", t);
2269 cx_string_set(s, cx_string_get(buffer));
2271 t = giraffe_model_frozen_parameter(model,
"Magnification") ?
2273 cx_string_sprintf(buffer,
", camera magnification = %s", t);
2274 cx_string_append(s, cx_string_get(buffer));
2276 t = giraffe_model_frozen_parameter(model,
"Angle") ?
2278 cx_string_sprintf(buffer,
", grating angle = %s", t);
2279 cx_string_append(s, cx_string_get(buffer));
2282 if (offsets == TRUE) {
2284 t = giraffe_model_frozen_parameter(model,
"Sdx") ?
2286 cx_string_sprintf(buffer,
", slit x-shift = %s", t);
2287 cx_string_append(s, cx_string_get(buffer));
2289 t = giraffe_model_frozen_parameter(model,
"Sdy") ?
2291 cx_string_sprintf(buffer,
", slit y-shift = %s", t);
2292 cx_string_append(s, cx_string_get(buffer));
2294 t = giraffe_model_frozen_parameter(model,
"Sphi") ?
2296 cx_string_sprintf(buffer,
", slit rotation = %s", t);
2297 cx_string_append(s, cx_string_get(buffer));
2301 cx_string_delete(buffer);
2318 inline static cpl_image *
2319 _giraffe_residuals_fit(GiWlResiduals *residuals, GiLineData *lines,
2320 const GiLocalization *localization, GiTable *fibers,
2321 GiTable *slitgeometry, GiSCFitParams *setup)
2324 const cxchar *
const fctid =
"_giraffe_residuals_fit";
2331 cxint nsubslits = 1;
2334 cpl_table *_fibers = NULL;
2336 cpl_image *locy = NULL;
2337 cpl_image *locw = NULL;
2338 cpl_image *xresiduals = NULL;
2341 cx_assert(lines != NULL);
2342 cx_assert(localization != NULL);
2343 cx_assert(fibers != NULL);
2344 cx_assert(slitgeometry != NULL);
2345 cx_assert(setup != NULL);
2348 cx_assert(_fibers != NULL);
2351 cx_assert(locy != NULL);
2354 cx_assert(locw != NULL);
2356 nx = cpl_image_get_size_y(locy);
2357 nlines = giraffe_linedata_lines(lines);
2359 xresiduals = cpl_image_new(cpl_table_get_nrow(_fibers), nx,
2362 if (setup->subslits == TRUE) {
2363 nsubslits = _giraffe_subslit_get_max(_fibers);
2366 for (i = 0; i < nsubslits; i++) {
2373 cxint iterations = 0;
2379 cxdouble ratio = 1.;
2380 cxdouble sigma = 0.;
2382 cpl_matrix *xss = NULL;
2383 cpl_matrix *yss = NULL;
2384 cpl_matrix *rss = NULL;
2385 cpl_matrix *sss = NULL;
2386 cpl_matrix *nss = NULL;
2387 cpl_matrix *lss = NULL;
2388 cpl_matrix *base = NULL;
2389 cpl_matrix *fit = NULL;
2390 cpl_matrix *coeff = NULL;
2391 cpl_matrix *chebyshev = NULL;
2393 cpl_table *subslit = NULL;
2395 GiChebyshev2D *xwsfit = NULL;
2398 if (setup->subslits == TRUE) {
2399 subslit = _giraffe_subslit_get(_fibers, i + 1);
2400 ssn = cpl_table_get_int(subslit,
"SSN", 0, NULL);
2402 cx_assert(ssn == i + 1);
2405 subslit = cpl_table_duplicate(_fibers);
2409 if (subslit == NULL) {
2413 _giraffe_subslit_range(subslit, locy, locw, &ymin, &ymax);
2415 nfibers = cpl_table_get_nrow(subslit);
2416 ndata = nfibers * nlines;
2419 xss = cpl_matrix_new(ndata, 1);
2420 yss = cpl_matrix_new(ndata, 1);
2421 rss = cpl_matrix_new(1, ndata);
2422 sss = cpl_matrix_new(ndata, 1);
2423 nss = cpl_matrix_new(ndata, 1);
2424 lss = cpl_matrix_new(ndata, 1);
2434 for (j = 0; j < nfibers; j++) {
2437 cxint n = cpl_table_get_int(subslit,
"INDEX", j, NULL) - 1;
2439 for (l = 0; l < nlines; l++) {
2441 cxdouble value = 0.;
2442 cxdouble xccd = giraffe_linedata_get(lines,
"Xccd", n, l);
2443 cxdouble yccd = giraffe_linedata_get(lines,
"Yccd", n, l);
2445 if (giraffe_linedata_get_status(lines, n, l) != 0) {
2449 if (yccd < ymin || yccd > ymax) {
2453 cpl_matrix_set(xss, k, 0, xccd);
2454 cpl_matrix_set(yss, k, 0, yccd);
2456 value = xccd - giraffe_linedata_get(lines,
"Center", n, l);
2458 cpl_matrix_set(rss, 0, k, value);
2459 giraffe_linedata_set(lines,
"Xoff", n, l, value);
2461 value = giraffe_linedata_get(lines,
"dCenter", n, l);
2462 cpl_matrix_set(sss, k, 0, value);
2464 cpl_matrix_set(nss, k, 0, n);
2465 cpl_matrix_set(lss, k, 0, l);
2474 cpl_msg_debug(fctid,
"Skipping subslit %d: No input lines left! "
2475 "All lines have non-zero status or are beyond the "
2476 "subslit boundaries (%.4f, %.4f).", ssn, ymin, ymax);
2484 cpl_matrix_set_size(xss, k, 1);
2485 cpl_matrix_set_size(yss, k, 1);
2486 cpl_matrix_set_size(rss, 1, k);
2487 cpl_matrix_set_size(sss, k, 1);
2488 cpl_matrix_set_size(nss, k, 1);
2489 cpl_matrix_set_size(lss, k, 1);
2497 sigma = cpl_matrix_get_median(sss);
2506 accepted = cpl_matrix_get_ncol(rss);
2509 while (accepted > 0 && iterations < setup->clip.iterations &&
2510 ratio > setup->clip.fraction) {
2512 base = giraffe_chebyshev_base2d(0., ymin, nx, ymax - ymin + 1.,
2513 setup->fit.xorder + 1,
2514 setup->fit.yorder + 1, xss, yss);
2516 if (coeff != NULL) {
2517 cpl_matrix_delete(coeff);
2523 if (coeff == NULL) {
2524 cpl_msg_debug(fctid,
"Error solving linear system for "
2525 "subslit %d, skipping subslit.", ssn);
2529 fit = cpl_matrix_product_create(coeff, base);
2533 for (j = 0; j < cpl_matrix_get_ncol(fit); j++) {
2535 cxdouble _fit = cpl_matrix_get(fit, 0, j);
2536 cxdouble _rss = cpl_matrix_get(rss, 0, j);
2538 if (fabs(_fit - _rss) >= setup->clip.level * sigma) {
2540 cxint n = (cxint)cpl_matrix_get(nss, j, 0);
2541 cxint l = (cxint)cpl_matrix_get(lss, j, 0);
2547 giraffe_linedata_set_status(lines, n, l, LF_R_XRFIT);
2552 cpl_matrix_set(xss, k, 0, cpl_matrix_get(xss, j, 0));
2553 cpl_matrix_set(yss, k, 0, cpl_matrix_get(yss, j, 0));
2554 cpl_matrix_set(rss, 0, k, cpl_matrix_get(rss, 0, j));
2555 cpl_matrix_set(sss, k, 0, cpl_matrix_get(sss, j, 0));
2556 cpl_matrix_set(nss, k, 0, cpl_matrix_get(nss, j, 0));
2557 cpl_matrix_set(lss, k, 0, cpl_matrix_get(lss, j, 0));
2562 cpl_matrix_delete(base);
2563 cpl_matrix_delete(fit);
2565 if (k == accepted) {
2575 ratio = (cxdouble)accepted / (cxdouble)total;
2577 cpl_matrix_set_size(xss, k, 1);
2578 cpl_matrix_set_size(yss, k, 1);
2579 cpl_matrix_set_size(rss, 1, k);
2580 cpl_matrix_set_size(sss, k, 1);
2581 cpl_matrix_set_size(nss, k, 1);
2582 cpl_matrix_set_size(lss, k, 1);
2590 if (accepted == 0) {
2591 cpl_msg_debug(fctid,
"Subslit %d: All lines rejected.", ssn);
2595 if (coeff == NULL) {
2601 cpl_matrix_delete(xss);
2602 cpl_matrix_delete(yss);
2603 cpl_matrix_delete(rss);
2604 cpl_matrix_delete(sss);
2605 cpl_matrix_delete(nss);
2606 cpl_matrix_delete(lss);
2613 xss = cpl_matrix_new(nx * nfibers, 1);
2614 yss = cpl_matrix_new(nx * nfibers, 1);
2616 giraffe_compute_image_coordinates(nx, nfibers, xss, NULL);
2618 for (j = 0; j < cpl_table_get_nrow(subslit); j++) {
2623 cxint ns = cpl_image_get_size_x(locy);
2624 cxint cs = cpl_table_get_int(subslit, idx, j, NULL) - 1;
2626 cxdouble *data = cpl_image_get_data(locy);
2629 for (l = 0; l < nx; l++) {
2630 cpl_matrix_set(yss, l * nfibers + j, 0, data[l * ns + cs]);
2640 base = giraffe_chebyshev_base2d(0., ymin, nx, ymax - ymin + 1.,
2641 setup->fit.xorder + 1,
2642 setup->fit.yorder + 1, xss, yss);
2644 fit = cpl_matrix_product_create(coeff, base);
2646 cpl_matrix_delete(xss);
2649 cpl_matrix_delete(yss);
2664 chebyshev = cpl_matrix_wrap(setup->fit.xorder + 1,
2665 setup->fit.yorder + 1,
2666 cpl_matrix_get_data(coeff));
2668 xwsfit = giraffe_chebyshev2d_new(setup->fit.xorder, setup->fit.yorder);
2669 status = giraffe_chebyshev2d_set(xwsfit, 0., nx, ymin, ymax,
2674 giraffe_chebyshev2d_delete(xwsfit);
2676 cpl_matrix_unwrap(chebyshev);
2678 cpl_matrix_delete(base);
2679 cpl_matrix_delete(coeff);
2680 cpl_matrix_delete(fit);
2682 cpl_table_delete(subslit);
2684 cpl_image_delete(xresiduals);
2690 cpl_matrix_unwrap(chebyshev);
2693 giraffe_wlresiduals_set(residuals, ssn, xwsfit);
2701 for (j = 0; j < cpl_table_get_nrow(subslit); j++) {
2704 cxint n = cpl_table_get_int(subslit,
"INDEX", j, NULL) - 1;
2705 cxint ns = cpl_table_get_nrow(_fibers);
2707 cxdouble *data = cpl_image_get_data(xresiduals);
2709 for (l = 0; l < nx; l++) {
2710 data[l * ns + n] = cpl_matrix_get(fit, 0, l * nfibers + j);
2715 cpl_matrix_delete(base);
2716 cpl_matrix_delete(coeff);
2717 cpl_matrix_delete(fit);
2719 cpl_table_delete(subslit);
2728 inline static cxdouble
2729 _giraffe_compute_statistics(
const GiLineData *lines,
const cpl_image *xwsfit,
2730 const cpl_image *lflags)
2741 cpl_image *xccd = NULL;
2744 cx_assert(lines != NULL);
2747 nlines = giraffe_linedata_lines(lines);
2748 nfibers = giraffe_linedata_fibers(lines);
2750 xccd = cpl_image_duplicate(giraffe_linedata_get_data(lines,
"Xccd"));
2752 if (xwsfit != NULL) {
2754 cpl_image *residuals = NULL;
2757 cx_assert(lflags != NULL);
2759 residuals = cpl_image_new(giraffe_linedata_fibers(lines),
2760 giraffe_linedata_lines(lines),
2763 _giraffe_get_residuals(residuals, xccd, xwsfit);
2764 _giraffe_apply_residuals(xccd, residuals, lflags, 0.);
2766 cpl_image_delete(residuals);
2771 _xccd = cpl_image_get_data(xccd);
2773 for (i = 0; i < nfibers; i++) {
2777 for (j = 0; j < nlines; j++) {
2779 if (giraffe_linedata_get_status(lines, i, j) == LF_R_NONE) {
2781 cxdouble center = giraffe_linedata_get(lines,
"Center", i, j);
2783 sum += pow(center - _xccd[j * nfibers + i], 2.);
2791 cpl_image_delete(xccd);
2793 rms = sqrt(sum / CX_MAX(giraffe_linedata_accepted(lines), 1.));
2801 _giraffe_convert_wlsolution(GiTable *result,
const GiWlSolution *solution,
2802 const GiImage *spectra,
const GiGrating *setup,
2810 cxdouble value = 0.;
2811 cxdouble scale = 0.;
2812 cxdouble xccd[2] = {0., 0.};
2814 cx_string *s = NULL;
2816 cpl_propertylist *properties = NULL;
2818 cpl_table *coeffs = NULL;
2820 const GiModel *model = NULL;
2822 const GiWlResiduals *residuals = NULL;
2825 cx_assert(result != NULL);
2826 cx_assert(solution != NULL);
2828 s = cx_string_new();
2837 cpl_propertylist_erase(properties,
"NAXIS1");
2838 cpl_propertylist_erase(properties,
"NAXIS2");
2839 cpl_propertylist_erase(properties, GIALIAS_DATAMIN);
2840 cpl_propertylist_erase(properties, GIALIAS_DATAMAX);
2841 cpl_propertylist_erase(properties, GIALIAS_EXTNAME);
2843 cpl_propertylist_erase(properties, GIALIAS_PROCATG);
2844 cpl_propertylist_erase(properties, GIALIAS_PROTYPE);
2845 cpl_propertylist_erase(properties, GIALIAS_DATAMEAN);
2846 cpl_propertylist_erase(properties, GIALIAS_DATAMEDI);
2847 cpl_propertylist_erase(properties, GIALIAS_DATASIG);
2849 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
2851 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
2852 "Giraffe frame type.");
2876 cpl_propertylist_update_string(properties, GIALIAS_WSOL_LMNAME,
2878 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMNAME,
2879 "Line profile model");
2881 cpl_propertylist_update_bool(properties, GIALIAS_WSOL_LMRES, info->residuals);
2882 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMRES,
2883 "Line detection optical model residuals flag");
2885 cpl_propertylist_update_int(properties, GIALIAS_WSOL_LMWIDTH, info->width);
2886 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMWIDTH,
2887 "Line detection window size [pxl]");
2889 cpl_propertylist_update_double(properties, GIALIAS_WSOL_LMTHRESH,
2891 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMTHRESH,
2892 "Calibration line threshold");
2894 cpl_propertylist_update_int(properties, GIALIAS_WSOL_LMITER,
2896 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMITER,
2897 "Line profile fit maximum number "
2900 cpl_propertylist_update_int(properties, GIALIAS_WSOL_LMTEST,
2902 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMTEST,
2903 "Line profile fit maximum number "
2904 "of chi-square tests");
2906 cpl_propertylist_update_double(properties, GIALIAS_WSOL_LMDCHISQ,
2908 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_LMDCHISQ,
2909 "Line profile fit minimum delta "
2919 cpl_propertylist_update_string(properties, GIALIAS_WSOL_PWORDER,
2921 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_PWORDER,
2922 "PSF width fit polynomial order");
2924 cpl_propertylist_update_double(properties, GIALIAS_WSOL_PWSIGMA,
2926 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_PWSIGMA,
2927 "PSF width fit sigma clipping level");
2929 cpl_propertylist_update_int(properties, GIALIAS_WSOL_PWITER,
2931 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_PWITER,
2932 "PSF width fit maximum number of "
2935 cpl_propertylist_update_double(properties, GIALIAS_WSOL_PWFRAC,
2937 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_PWFRAC,
2938 "PSF width fit minimum fraction of "
2946 cpl_propertylist_update_bool(properties, GIALIAS_WSOL_OMFIT,
2948 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMFIT,
2949 "Optical model fit flag");
2951 cpl_propertylist_update_string(properties, GIALIAS_WSOL_OMNAME,
2952 giraffe_wlsolution_name(solution));
2953 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMNAME,
2954 "Optical model name");
2956 model = giraffe_wlsolution_model(solution);
2958 sign = giraffe_model_get_parameter(model,
"Orientation") < 0 ? -1 : 1;
2959 cpl_propertylist_update_int(properties, GIALIAS_WSOL_OMDIR, sign);
2960 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMDIR,
2961 "Optical model orientation");
2963 value = giraffe_model_get_parameter(model,
"FocalLength");
2964 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMFCOLL, value);
2965 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMFCOLL,
2966 "Optical model focal length");
2968 value = giraffe_model_get_parameter(model,
"Magnification");
2969 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMGCAM, value);
2970 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMGCAM,
2971 "Optical model camera factor");
2973 value = giraffe_model_get_parameter(model,
"Angle");
2974 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMGTHETA, value);
2975 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMGTHETA,
2976 "Optical model grating angle");
2978 if (strcmp(giraffe_wlsolution_name(solution),
"xoptmod2") == 0) {
2980 value = giraffe_model_get_parameter(model,
"Sdx");
2981 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSDX, value);
2982 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSDX,
2983 "Optical model slit x-offset");
2985 value = giraffe_model_get_parameter(model,
"Sdy");
2986 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSDY, value);
2987 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSDY,
2988 "Optical model slit y-offset");
2990 value = giraffe_model_get_parameter(model,
"Sphi");
2991 cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSPHI, value);
2992 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSPHI,
2993 "Optical model slit rotation");
3003 residuals = giraffe_wlsolution_get_residuals(solution);
3005 cpl_propertylist_update_bool(properties, GIALIAS_WSOL_SUBSLITS,
3006 giraffe_wlsolution_get_subslits(solution));
3007 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_SUBSLITS,
3008 "Subslit fit flag");
3011 cpl_propertylist_update_int(properties, GIALIAS_WSOL_XRSSN,
3012 giraffe_wlresiduals_get_size(residuals));
3013 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_XRSSN,
3014 "Number of subslits");
3019 cpl_propertylist_update_string(properties, GIALIAS_WSOL_XRORDER,
3021 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_XRORDER,
3022 "Residual fit polynomial order");
3025 cpl_propertylist_update_double(properties, GIALIAS_WSOL_XRSIGMA,
3027 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_XRSIGMA,
3028 "Residual fit sigma clipping level");
3030 cpl_propertylist_update_int(properties, GIALIAS_WSOL_XRITER,
3032 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_XRITER,
3033 "Residual fit maximum number of "
3036 cpl_propertylist_update_double(properties, GIALIAS_WSOL_XRFRAC,
3038 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_XRFRAC,
3039 "Residual fit minimum fraction of "
3042 cpl_propertylist_update_int(properties, GIALIAS_WSOL_NLINES,
3044 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_NLINES,
3045 "Number of calibration lines used.");
3047 cpl_propertylist_update_int(properties, GIALIAS_WSOL_NACCEPT,
3049 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_NACCEPT,
3050 "Number of accepted lines");
3052 cpl_propertylist_update_int(properties, GIALIAS_WSOL_NREJECT,
3054 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_NREJECT,
3055 "Number of rejected lines");
3057 cpl_propertylist_update_double(properties, GIALIAS_WSOL_RMS,
3059 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_RMS,
3060 "Average RMS [pxl] of fitted line "
3069 xccd[0] = giraffe_wlsolution_compute_pixel(solution, setup->
wlenmin,
3071 xccd[1] = giraffe_wlsolution_compute_pixel(solution, setup->
wlenmax,
3077 cpl_propertylist_update_double(properties, GIALIAS_WSOL_WLMIN,
3079 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_WLMIN,
3080 "Wavelength solution minimum wavelength");
3082 cpl_propertylist_update_double(properties, GIALIAS_WSOL_WLMAX,
3084 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_WLMAX,
3085 "Wavelength solution maximum wavelength");
3087 cpl_propertylist_update_double(properties, GIALIAS_WSOL_SCALE, scale);
3088 cpl_propertylist_set_comment(properties, GIALIAS_WSOL_SCALE,
3089 "Approximate wavelength scale [nm/pxl]");
3092 cx_string_delete(s);
3100 for (i = 0; (cxsize)i < giraffe_wlresiduals_get_size(residuals); i++) {
3102 const GiChebyshev2D *fit = giraffe_wlresiduals_get(residuals, i);
3111 giraffe_chebyshev2d_get_order(fit, &xorder, &yorder);
3115 gi_error(
"Invalid wavelength solution. Inconsistent residual "
3116 "fit polynomial order!");
3129 coeffs = giraffe_wlresiduals_table(residuals);
3131 if (coeffs == NULL) {
3132 cpl_propertylist_delete(properties);
3137 cpl_propertylist_delete(properties);
3142 cpl_table_delete(coeffs);
3151 giraffe_wcaldata_new(
void)
3154 GiWCalData *
self = cx_calloc(1,
sizeof *
self);
3156 self->coeffs = NULL;
3158 self->linedata = NULL;
3166 giraffe_wcaldata_delete(GiWCalData *
self)
3173 self->coeffs = NULL;
3181 if (self->linedata) {
3182 giraffe_linedata_delete(self->linedata);
3183 self->linedata = NULL;
3218 GiLocalization *localization, GiTable *fibers,
3219 GiTable *slitgeometry, GiTable *grating,
3220 GiTable *lines, GiTable *initial,
3224 const cxchar *fctid =
"giraffe_calibrate_wavelength";
3227 cxbool residuals = FALSE;
3236 cpl_image *psf_fit = NULL;
3237 cpl_image *xws_fit = NULL;
3239 GiTable *tsolution = NULL;
3243 GiSCFitParams psf_setup;
3244 GiSCFitParams xws_setup;
3246 GiLineParams *line_setup = NULL;
3248 GiLineData *line_data = NULL;
3250 GiWlSolution *solution = NULL;
3255 if (extraction == NULL) {
3259 if (extraction->spectra == NULL || extraction->error == NULL) {
3264 if (fibers == NULL) {
3268 if (slitgeometry == NULL) {
3272 if (grating == NULL) {
3276 if (lines == NULL) {
3287 if (setup == NULL) {
3288 cpl_msg_error(fctid,
"Cannot initialize grating setup parameters!");
3306 cpl_msg_info(fctid,
"Setting initial slit offsets: x-shift = %.9f, "
3307 "y-shift = %.9f, rotation = %.9f", setup->
sdx,
3322 line_setup = _giraffe_lineparams_create(GI_LINETYPE_THARNE, setup,
3325 if (line_setup == NULL) {
3326 cpl_msg_error(fctid,
"Cannot initialize line fit setup parameters!");
3338 if (initial == NULL) {
3341 cxdouble pixelsize = 0.;
3343 cpl_propertylist *properties = NULL;
3345 cpl_image *spectra = NULL;
3349 cx_assert(properties != NULL);
3352 cx_assert(spectra != NULL);
3354 pixelsize = cpl_propertylist_get_double(properties, GIALIAS_PIXSIZY);
3355 npixel = cpl_image_get_size_y(spectra);
3357 solution = giraffe_wlsolution_new(config->
opt_model,
3361 if (solution == NULL) {
3362 cpl_msg_error(fctid,
"Cannot initialize initial wavelength "
3367 _giraffe_lineparams_delete(line_setup);
3375 const cpl_propertylist* _properties =
3394 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_WLMIN) == TRUE) {
3396 setup->
wlenmin = cpl_propertylist_get_double(_properties,
3397 GIALIAS_WSOL_WLMIN);
3399 cpl_msg_debug(fctid,
"Using minimum wavelength %.2f from "
3400 "initial solution", setup->
wlenmin);
3404 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_WLMAX) == TRUE) {
3406 setup->
wlenmax = cpl_propertylist_get_double(_properties,
3407 GIALIAS_WSOL_WLMAX);
3409 cpl_msg_debug(fctid,
"Using maximum wavelength %.2f from "
3410 "initial solution", setup->
wlenmax);
3416 giraffe_wlsolution_set_subslits(solution, config->
opt_subslits);
3419 cpl_msg_info(fctid,
"Computing line positions on the CCD using "
3420 "model `%s'", giraffe_wlsolution_name(solution));
3429 if (giraffe_wlsolution_get_residuals(solution) == NULL) {
3431 cpl_msg_error(fctid,
"Initial wavelength solution does not "
3432 "provide optical model residuals!");
3436 _giraffe_lineparams_delete(line_setup);
3438 giraffe_wlsolution_delete(solution);
3450 residuals = giraffe_wlsolution_get_residuals(solution) != NULL;
3452 if (residuals == TRUE) {
3453 cpl_msg_info(fctid,
"Using wavelength solution residuals when "
3454 "computing line positions.");
3469 status = _giraffe_linelist_setup(lines, setup, config);
3472 cpl_msg_error(fctid,
"Line list creation failed!");
3476 _giraffe_lineparams_delete(line_setup);
3478 giraffe_wlsolution_delete(solution);
3484 cpl_msg_info(fctid,
"%d lines have been selected from the line list.",
3492 line_data = giraffe_linedata_new();
3501 cpl_table *_lines = NULL;
3504 cpl_image *xccd = NULL;
3505 cpl_image *xres = NULL;
3506 cpl_image *line_status = NULL;
3508 GiWlResiduals *xws_coeffs = NULL;
3514 cpl_msg_info(fctid,
"Current search window width: %d pxl", width);
3515 cpl_msg_info(fctid,
"Applying crowding criterium to line list.");
3517 _lines = _giraffe_linelist_select(lines, extraction->spectra, setup,
3519 if (_lines == NULL) {
3520 cpl_msg_error(fctid,
"Removing crowded lines from line list "
3521 "for search window width %d pxl failed!", width);
3525 _giraffe_lineparams_delete(line_setup);
3527 giraffe_wlsolution_delete(solution);
3532 _nlines = cpl_table_get_nrow(_lines);
3535 cpl_msg_info(fctid,
"%d lines used for fit. %d of %d lines rejected "
3536 "due to crowding.", _nlines, nlines - _nlines, nlines);
3538 cpl_msg_info(fctid,
"%d lines used for fit. %d of %d lines "
3539 "rejected due to crowding and line quality.",
3540 _nlines, nlines - _nlines, nlines);
3548 xccd = _giraffe_line_abscissa(_lines, slitgeometry, fibers,
3549 solution, localization, residuals);
3551 _nfibers = cpl_image_get_size_x(xccd);
3552 _nlines = cpl_image_get_size_y(xccd);
3559 cpl_msg_info(fctid,
"Fitting %d line profiles for %d spectra using "
3560 "line model `%s'", _nlines, _nfibers , line_setup->model);
3562 cpl_msg_info(fctid,
"Total number of lines to fit: %d (%d x %d)",
3563 _nlines * _nfibers, _nfibers, _nlines);
3566 status = giraffe_linedata_reset(line_data, _lines, _fibers,
3571 cpl_msg_error(fctid,
"Line profile fit failed!");
3573 cpl_image_delete(xccd);
3575 cpl_table_delete(_lines);
3576 giraffe_linedata_delete(line_data);
3580 _giraffe_lineparams_delete(line_setup);
3582 giraffe_wlsolution_delete(solution);
3588 status = _giraffe_line_fit(line_data, xccd, width, extraction, fibers,
3589 localization->locy, line_setup);
3593 cpl_msg_error(fctid,
"Line profile fit failed!");
3595 cpl_image_delete(xccd);
3597 cpl_table_delete(_lines);
3598 giraffe_linedata_delete(line_data);
3602 _giraffe_lineparams_delete(line_setup);
3604 giraffe_wlsolution_delete(solution);
3610 cpl_image_delete(xccd);
3613 if (giraffe_linedata_accepted(line_data) == 0) {
3614 cpl_msg_error(fctid,
"No lines left after line profile fit!");
3616 cpl_table_delete(_lines);
3617 giraffe_linedata_delete(line_data);
3621 _giraffe_lineparams_delete(line_setup);
3623 giraffe_wlsolution_delete(solution);
3629 _nreject = giraffe_linedata_rejected(line_data);
3630 _ngood = giraffe_linedata_accepted(line_data);
3632 cpl_msg_info(fctid,
"Number of good lines: %d. %d of %d lines "
3633 "rejected due to line profile fit.", _ngood, _nreject,
3640 line_status = giraffe_linedata_status(line_data);
3647 cpl_msg_info(fctid,
"Fit of the line profile PSF width variation.");
3649 psf_setup.subslits = giraffe_wlsolution_get_subslits(solution);
3653 cpl_msg_info(fctid,
"Chebyshev polynomial order is (%d, %d).",
3654 psf_setup.fit.xorder, psf_setup.fit.yorder);
3660 cpl_msg_info(fctid,
"Sigma clipping: iterations = %d, level = %.4f, "
3661 "fraction = %.4f", psf_setup.clip.iterations,
3662 psf_setup.clip.level, psf_setup.clip.fraction);
3665 psf_fit = _giraffe_psf_fit(line_data, localization, fibers,
3666 slitgeometry, &psf_setup);
3669 if (psf_fit == NULL) {
3671 cpl_msg_error(fctid,
"Fit of the line profile PSF width "
3672 "variation failed!");
3674 cpl_table_delete(_lines);
3675 cpl_image_delete(line_status);
3676 giraffe_linedata_delete(line_data);
3680 _giraffe_lineparams_delete(line_setup);
3682 giraffe_wlsolution_delete(solution);
3693 cpl_image_delete(psf_fit);
3697 if (giraffe_linedata_accepted(line_data) == 0) {
3698 cpl_msg_error(fctid,
"No lines left after line profile PSF "
3701 cpl_table_delete(_lines);
3702 cpl_image_delete(line_status);
3703 giraffe_linedata_delete(line_data);
3707 _giraffe_lineparams_delete(line_setup);
3709 giraffe_wlsolution_delete(solution);
3715 cpl_msg_info(fctid,
"Number of good lines: %"
3716 CX_PRINTF_FORMAT_SIZE_TYPE
". %"
3717 CX_PRINTF_FORMAT_SIZE_TYPE
" of %d lines "
3718 "rejected due to line profile PSF width fit.",
3719 giraffe_linedata_accepted(line_data),
3720 giraffe_linedata_rejected(line_data) - _nreject, _ngood);
3722 _ngood = giraffe_linedata_accepted(line_data);
3723 _nreject = giraffe_linedata_rejected(line_data);
3733 cxint iterations = 0;
3736 cxdouble chisq = 0.;
3737 cxdouble rsquare = 0.;
3739 cx_string *s = NULL;
3741 GiOpticalModelParams om_setup;
3743 GiModel *guess = NULL;
3744 GiModel *model = giraffe_wlsolution_model(solution);
3751 guess = giraffe_model_clone(model);
3753 om_setup.fit.iterations = config->
opt_niter;
3758 cpl_msg_info(fctid,
"Optical model fit setup: iterations = %d, "
3759 "tests = %d, delta = %.4f", om_setup.fit.iterations,
3760 om_setup.fit.tests, om_setup.fit.delta);
3762 status = _giraffe_opticalmodel_fit(solution, line_data, fibers,
3763 slitgeometry, &om_setup);
3766 cpl_msg_error(fctid,
"Optical model fit failed!");
3768 giraffe_model_delete(guess);
3770 cpl_table_delete(_lines);
3771 cpl_image_delete(line_status);
3772 giraffe_linedata_delete(line_data);
3776 _giraffe_lineparams_delete(line_setup);
3778 giraffe_wlsolution_delete(solution);
3789 cpl_msg_info(fctid,
"Optical model parameters:");
3791 s = cx_string_new();
3793 _giraffe_opticalmodel_format(s, guess, GI_OPTM_PARAMETER_VALUES);
3794 cpl_msg_info(fctid,
"Initial: %s", cx_string_get(s));
3796 _giraffe_opticalmodel_format(s, model, GI_OPTM_PARAMETER_VALUES);
3797 cpl_msg_info(fctid,
" Fitted: %s", cx_string_get(s));
3799 _giraffe_opticalmodel_format(s, model, GI_OPTM_PARAMETER_ERRORS);
3800 cpl_msg_info(fctid,
" Sigma: %s", cx_string_get(s));
3802 _giraffe_opticalmodel_format(s, model, GI_OPTM_PARAMETER_STATUS);
3803 cpl_msg_info(fctid,
" Status: %s", cx_string_get(s));
3805 cx_string_delete(s);
3809 if (strcmp(giraffe_model_get_name(model),
"xoptmod2") == 0) {
3811 cxdouble flength = 0.;
3816 cx_string *s = cx_string_new();
3819 flength = giraffe_model_get_parameter(guess,
"FocalLength");
3820 sdx = giraffe_model_get_parameter(guess,
"Sdx");
3821 sdy = giraffe_model_get_parameter(guess,
"Sdy");
3822 sphi = giraffe_model_get_parameter(guess,
"Sphi");
3824 cx_string_sprintf(s,
"Initial: focal length = %.6f, slit "
3825 "x-shift = %.9f, slit y-shift = %.9f, "
3826 "slit rotation = %.9f", flength, sdx, sdy,
3828 cpl_msg_info(fctid,
"%s", cx_string_get(s));
3831 flength = giraffe_model_get_parameter(model,
"FocalLength");
3832 sdx = giraffe_model_get_parameter(model,
"Sdx");
3833 sdy = giraffe_model_get_parameter(model,
"Sdy");
3834 sphi = giraffe_model_get_parameter(model,
"Sphi");
3836 cx_string_sprintf(s,
" Fitted: focal length = %.6f, slit "
3837 "x-shift = %.9f, slit y-shift = %.9f, "
3838 "slit rotation = %.9f", flength, sdx, sdy,
3840 cpl_msg_info(fctid,
"%s", cx_string_get(s));
3843 flength = giraffe_model_get_sigma(model,
"FocalLength");
3844 sdx = giraffe_model_get_sigma(model,
"Sdx");
3845 sdy = giraffe_model_get_sigma(model,
"Sdy");
3846 sphi = giraffe_model_get_sigma(model,
"Sphi");
3848 cx_string_sprintf(s,
" Sigma: focal length = %.6f, slit "
3849 "x-shift = %.9f, slit y-shift = %.9f, "
3850 "slit rotation = %.9f", flength, sdx, sdy,
3852 cpl_msg_info(fctid,
"%s", cx_string_get(s));
3854 cx_string_delete(s);
3859 cxdouble flength = 0.;
3861 cx_string *s = cx_string_new();
3864 flength = giraffe_model_get_parameter(guess,
"FocalLength");
3866 cx_string_sprintf(s,
"Initial: focal length = %.6f", flength);
3867 cpl_msg_info(fctid,
"%s", cx_string_get(s));
3870 flength = giraffe_model_get_parameter(model,
"FocalLength");
3872 cx_string_sprintf(s,
" Fitted: focal length = %.6f", flength);
3873 cpl_msg_info(fctid,
"%s", cx_string_get(s));
3876 flength = giraffe_model_get_sigma(model,
"FocalLength");
3878 cx_string_sprintf(s,
" Sigma: focal length = %.6f", flength);
3879 cpl_msg_info(fctid,
"%s", cx_string_get(s));
3881 cx_string_delete(s);
3886 giraffe_model_delete(guess);
3889 iterations = giraffe_model_get_position(model);
3890 df = giraffe_model_get_df(model);
3892 chisq = giraffe_model_get_chisq(model);
3893 rsquare = giraffe_model_get_rsquare(model);
3895 cpl_msg_info(fctid,
"Optical model fit statistics: iterations = "
3896 "%d, DoF = %d, Chi-square = %.6g, Chi-square/DoF = "
3897 "%.6g, R-square = %.6g", iterations, df, chisq,
3898 chisq / df, rsquare);
3906 setup->
fcoll = giraffe_model_get_parameter(model,
"FocalLength");
3907 setup->
gcam = giraffe_model_get_parameter(model,
"Magnification");
3908 setup->
theta = giraffe_model_get_parameter(model,
"Angle");
3909 setup->
order = giraffe_model_get_parameter(model,
"Order");
3910 setup->
space = giraffe_model_get_parameter(model,
"Spacing");
3912 if (strcmp(giraffe_model_get_name(model),
"xoptmod2") == 0) {
3913 setup->
sdx = giraffe_model_get_parameter(model,
"Sdx");
3914 setup->
sdy = giraffe_model_get_parameter(model,
"Sdy");
3915 setup->
sphi = giraffe_model_get_parameter(model,
"Sphi");
3930 cpl_msg_info(fctid,
"Re-computing line positions with updated "
3933 xccd = _giraffe_line_abscissa(_lines, slitgeometry, fibers,
3934 solution, localization, FALSE);
3936 giraffe_linedata_set_data(line_data,
"Xccd", xccd);
3942 cx_string *s = cx_string_new();
3944 GiModel *model = giraffe_wlsolution_model(solution);
3947 _giraffe_opticalmodel_format(s, model, GI_OPTM_PARAMETER_VALUES);
3948 cpl_msg_info(fctid,
"Optical model: %s", cx_string_get(s));
3950 cx_string_delete(s);
3955 rms = _giraffe_compute_statistics(line_data, NULL, NULL);
3957 cpl_msg_info(fctid,
"Average RMS [pxl] of line positions using "
3958 "%d of %d lines: %.4f", _ngood, _nlines * _nfibers,
3967 cpl_msg_info(fctid,
"Fit of the wavelength solution coefficients "
3968 "using %" CX_PRINTF_FORMAT_SIZE_TYPE
" lines",
3969 giraffe_linedata_accepted(line_data));
3971 xws_setup.subslits = giraffe_wlsolution_get_subslits(solution);
3975 cpl_msg_info(fctid,
"Chebyshev polynomial order is (%d, %d).",
3976 xws_setup.fit.xorder, xws_setup.fit.yorder);
3982 cpl_msg_info(fctid,
"Sigma clipping: iterations = %d, level = %.4f, "
3983 "fraction = %.4f", xws_setup.clip.iterations,
3984 xws_setup.clip.level, xws_setup.clip.fraction);
3986 xws_coeffs = giraffe_wlresiduals_new();
3988 xws_fit = _giraffe_residuals_fit(xws_coeffs, line_data, localization,
3989 fibers, slitgeometry, &xws_setup);
3992 if (xws_fit == NULL) {
3994 cpl_msg_error(fctid,
"Fit of the wavelength solution "
3995 "coefficients failed!");
3997 giraffe_wlresiduals_delete(xws_coeffs);
3999 cpl_table_delete(_lines);
4000 cpl_image_delete(line_status);
4001 giraffe_linedata_delete(line_data);
4005 _giraffe_lineparams_delete(line_setup);
4007 giraffe_wlsolution_delete(solution);
4019 xres = cpl_image_new(giraffe_linedata_fibers(line_data),
4020 giraffe_linedata_lines(line_data),
4023 _giraffe_get_residuals(xres,
4024 giraffe_linedata_get_data(line_data,
"Xccd"),
4026 giraffe_linedata_set_data(line_data,
"Xres", xres);
4029 if (giraffe_linedata_accepted(line_data) == 0) {
4030 cpl_msg_error(fctid,
"No lines left after wavelength solution "
4031 "coefficients fit!");
4033 giraffe_wlresiduals_delete(xws_coeffs);
4035 cpl_table_delete(_lines);
4036 cpl_image_delete(line_status);
4037 cpl_image_delete(xws_fit);
4038 giraffe_linedata_delete(line_data);
4042 _giraffe_lineparams_delete(line_setup);
4044 giraffe_wlsolution_delete(solution);
4050 cpl_msg_info(fctid,
"Number of good lines: %"
4051 CX_PRINTF_FORMAT_SIZE_TYPE
". %"
4052 CX_PRINTF_FORMAT_SIZE_TYPE
" of %d lines "
4053 "rejected due to wavelength solution coefficients fit.",
4054 giraffe_linedata_accepted(line_data),
4055 giraffe_linedata_rejected(line_data) - _nreject, _ngood);
4057 _ngood = giraffe_linedata_accepted(line_data);
4058 _nreject = giraffe_linedata_rejected(line_data);
4065 giraffe_wlsolution_set_residuals(solution, xws_coeffs);
4075 rms = _giraffe_compute_statistics(line_data, xws_fit, line_status);
4077 cpl_msg_info(fctid,
"Average RMS [pxl] of line positions using "
4078 "%d of %d lines: %.4f", _ngood, _nlines * _nfibers,
4088 info.residuals = residuals;
4090 info.nlines = _nlines;
4091 info.nfibers = _nfibers;
4093 info.ngood = _ngood;
4094 info.nreject = _nreject;
4103 cpl_image_delete(xws_fit);
4105 cpl_table_delete(_lines);
4106 cpl_image_delete(line_status);
4118 status = _giraffe_convert_wlsolution(tsolution, solution,
4119 extraction->spectra, setup,
4128 _giraffe_lineparams_delete(line_setup);
4130 giraffe_wlsolution_delete(solution);
4141 result->coeffs = tsolution;
4144 result->linedata = line_data;
4152 giraffe_wlsolution_delete(solution);
4154 _giraffe_lineparams_delete(line_setup);
4175 const cxchar *s = NULL;
4176 const cpl_parameter *p = NULL;
4185 config = cx_calloc(1,
sizeof *config);
4200 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.widths");
4201 s = cpl_parameter_get_string(p);
4205 cxchar **values = cx_strsplit(s,
",", -1);
4208 if (values == NULL) {
4221 while (values[n] != NULL) {
4226 config->
line_widths = cx_malloc(n *
sizeof(cxint));
4230 while (values[n] != NULL) {
4232 cxint w = strtol(values[n], &last, 10);
4234 if (*last !=
'\0') {
4235 cx_strfreev(values);
4248 sizeof(cxint), _giraffe_window_compare);
4251 cx_strfreev(values);
4259 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.separation");
4262 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.fluxratio");
4265 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.brightness");
4268 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.count");
4269 config->
line_count = cpl_parameter_get_int(p);
4271 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.wrange");
4272 s = cpl_parameter_get_string(p);
4276 cxchar **values = cx_strsplit(s,
",", 3);
4278 if (values == NULL) {
4288 cxdouble lower = 0.;
4289 cxdouble upper = 0.;
4292 lower = strtod(values[0], &last);
4294 if (*last !=
'\0') {
4296 cx_strfreev(values);
4303 lower = lower >= 0. ? lower : 0.;
4306 if (values[1] != NULL) {
4308 upper = strtod(values[1], &last);
4310 if (*last !=
'\0') {
4312 cx_strfreev(values);
4319 upper = upper > lower ? upper : 0.;
4328 cx_strfreev(values);
4334 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.model");
4335 s = cpl_parameter_get_string(p);
4337 if (strcmp(s,
"psfexp") != 0 &&
4338 strcmp(s,
"psfexp2") != 0 &&
4339 strcmp(s,
"gaussian") != 0) {
4350 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.residuals");
4351 s = cpl_parameter_get_string(p);
4353 if (strcmp(s,
"auto") != 0 &&
4354 strcmp(s,
"enable") != 0 &&
4355 strcmp(s,
"disable") != 0) {
4366 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.threshold");
4369 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.offset");
4370 config->
line_offset = cpl_parameter_get_double(p);
4372 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.iterations");
4373 config->
line_niter = cpl_parameter_get_int(p);
4375 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.tests");
4376 config->
line_ntest = cpl_parameter_get_int(p);
4378 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.dchisquare");
4379 config->
line_dchisq = cpl_parameter_get_double(p);
4381 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.rwidthratio");
4384 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.line.exponent");
4388 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.slit.offset");
4389 s = cpl_parameter_get_string(p);
4391 cx_assert(s != NULL);
4393 if (cx_strncasecmp(s,
"setup", 5) != 0) {
4395 cxchar **values = cx_strsplit(s,
",", 4);
4403 if (values == NULL || values[0] == NULL) {
4413 if (*values[0] !=
'\0') {
4416 cxdouble sdx = strtod(values[0], &last);
4418 if (*last !=
'\0') {
4419 cx_strfreev(values);
4432 if (values[1] == NULL) {
4437 if (*values[1] !=
'\0') {
4440 cxdouble sdy = strtod(values[1], &last);
4442 if (*last !=
'\0') {
4443 cx_strfreev(values);
4458 if (!eol && values[2] != NULL) {
4460 if (*values[2] !=
'\0') {
4463 cxdouble sphi = strtod(values[2], &last);
4465 if (*last !=
'\0') {
4466 cx_strfreev(values);
4481 cx_strfreev(values);
4489 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.opt.model");
4490 s = cpl_parameter_get_string(p);
4492 if (strcmp(s,
"xoptmod") != 0 && strcmp(s,
"xoptmod2") != 0) {
4503 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.opt.direction");
4506 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.opt.solution");
4509 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.opt.subslits");
4512 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.opt.flags");
4513 s = cpl_parameter_get_string(p);
4517 cxchar **values = cx_strsplit(s,
",", -1);
4519 if (values == NULL) {
4532 while (values[i] != NULL) {
4534 if (strncmp(values[i],
"fcoll", 5) == 0) {
4538 else if (strncmp(values[i],
"gcam", 4) == 0) {
4542 else if (strncmp(values[i],
"theta", 5) == 0) {
4546 else if (strncmp(values[i],
"sdx", 3) == 0) {
4550 else if (strncmp(values[i],
"sdy", 3) == 0) {
4554 else if (strncmp(values[i],
"sphi", 4) == 0) {
4563 cx_strfreev(values);
4581 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.opt.iterations");
4582 config->
opt_niter = cpl_parameter_get_int(p);
4584 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.opt.tests");
4585 config->
opt_ntest = cpl_parameter_get_int(p);
4587 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.opt.dchisquare");
4588 config->
opt_dchisq = cpl_parameter_get_double(p);
4591 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.psf.sigma");
4594 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.psf.iterations");
4597 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.psf.fraction");
4600 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.psf.order");
4601 s = cpl_parameter_get_string(p);
4605 cxchar **values = cx_strsplit(s,
",", 3);
4607 if (values == NULL || values[1] == NULL) {
4618 config->
pxw_xorder = strtol(values[0], &last, 10);
4620 if (*last !=
'\0') {
4622 cx_strfreev(values);
4629 config->
pxw_yorder = strtol(values[1], &last, 10);
4631 if (*last !=
'\0') {
4633 cx_strfreev(values);
4642 cx_strfreev(values);
4648 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.wsol.sigma");
4651 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.wsol.iterations");
4654 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.wsol.fraction");
4657 p = cpl_parameterlist_find(list,
"giraffe.wlcalibration.wsol.order");
4658 s = cpl_parameter_get_string(p);
4662 cxchar **values = cx_strsplit(s,
",", 3);
4664 if (values == NULL || values[1] == NULL) {
4675 config->
xws_xorder = strtol(values[0], &last, 10);
4677 if (*last !=
'\0') {
4679 cx_strfreev(values);
4686 config->
xws_yorder = strtol(values[1], &last, 10);
4688 if (*last !=
'\0') {
4690 cx_strfreev(values);
4699 cx_strfreev(values);
4781 p = cpl_parameter_new_value(
"giraffe.wlcalibration.line.widths",
4783 "List of window widths [pxl] used for line "
4784 "detection and fit (e.g. '60,40,15').",
4785 "giraffe.wlcalibration",
4787 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lswidth");
4788 cpl_parameterlist_append(list, p);
4791 p = cpl_parameter_new_value(
"giraffe.wlcalibration.line.separation",
4793 "Factor used to compute the minimum line "
4794 "separation from the window width.",
4795 "giraffe.wlcalibration",
4797 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lssep");
4798 cpl_parameterlist_append(list, p);
4801 p = cpl_parameter_new_value(
"giraffe.wlcalibration.line.fluxratio",
4803 "Selects only lines whose neighbours have "
4804 "a relative intensity less than "
4806 "giraffe.wlcalibration",
4809 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lsfxratio");
4810 cpl_parameterlist_append(list, p);
4813 p = cpl_parameter_new_value(
"giraffe.wlcalibration.line.brightness",
4815 "Selects lines having an intensity greater "
4816 "or equal to the given intensity.",
4817 "giraffe.wlcalibration",
4820 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lsbright");
4821 cpl_parameterlist_append(list, p);
4824 p = cpl_parameter_new_value(
"giraffe.wlcalibration.line.count",
4826 "Sets the minimum number of lines to select; "
4827 "selected are lines with the highest nominal "
4828 "intensity. A value of 0 turns this selection "
4829 "off. If the value is less than 0 the "
4830 "selection is skipped if the line list does "
4831 "not contain enough lines.",
4832 "giraffe.wlcalibration",
4835 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lscount");
4836 cpl_parameterlist_append(list, p);
4839 p = cpl_parameter_new_value(
"giraffe.wlcalibration.line.wrange",
4841 "Selects only lines within the given "
4842 "wavelength range [nm].",
4843 "giraffe.wlcalibration",
4846 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lswrange");
4847 cpl_parameterlist_append(list, p);
4854 p = cpl_parameter_new_enum(
"giraffe.wlcalibration.line.model",
4856 "Line profile model.",
4857 "giraffe.wlcalibration",
4858 "psfexp", 3,
"psfexp",
"psfexp2",
"gaussian");
4860 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lfmodel");
4861 cpl_parameterlist_append(list, p);
4864 p = cpl_parameter_new_enum(
"giraffe.wlcalibration.line.residuals",
4866 "Use optical model residuals for line "
4868 "giraffe.wlcalibration",
4869 "auto", 3,
"auto",
"enable",
"disable");
4871 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lfres");
4872 cpl_parameterlist_append(list, p);
4875 p = cpl_parameter_new_value(
"giraffe.wlcalibration.line.threshold",
4877 "Line detection threshold during the "
4878 "line fitting (multiple of bias sigma)",
4879 "giraffe.wlcalibration",
4882 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lfthreshold");
4883 cpl_parameterlist_append(list, p);
4886 p = cpl_parameter_new_value(
"giraffe.wlcalibration.line.offset",
4888 "Maximum allowed difference between the "
4889 "fitted and raw line peak position.",
4890 "giraffe.wlcalibration",
4893 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lfoffset");
4894 cpl_parameterlist_append(list, p);
4897 p = cpl_parameter_new_value(
"giraffe.wlcalibration.line.iterations",
4899 "Line detection fit maximum number of "
4901 "giraffe.wlcalibration",
4904 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lfniter");
4905 cpl_parameterlist_append(list, p);
4908 p = cpl_parameter_new_value(
"giraffe.wlcalibration.line.tests",
4910 "Line detection fit maximum number of "
4912 "giraffe.wlcalibration",
4915 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lfntest");
4916 cpl_parameterlist_append(list, p);
4919 p = cpl_parameter_new_value(
"giraffe.wlcalibration.line.dchisquare",
4921 "Line detection fit minimum chi-square "
4923 "giraffe.wlcalibration",
4926 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lfdchisq");
4927 cpl_parameterlist_append(list, p);
4930 p = cpl_parameter_new_value(
"giraffe.wlcalibration.line.rwidthratio",
4932 "Line width/resolution width factor.",
4933 "giraffe.wlcalibration",
4936 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lfreswid");
4937 cpl_parameterlist_append(list, p);
4940 p = cpl_parameter_new_value(
"giraffe.wlcalibration.line.exponent",
4942 "Exponential line profile exponent; it will "
4943 "not be fitted if it is larger than 0.",
4944 "giraffe.wlcalibration",
4947 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-lfexpwid");
4948 cpl_parameterlist_append(list, p);
4956 p = cpl_parameter_new_value(
"giraffe.wlcalibration.slit.offset",
4958 "Initial slit position offsets along the "
4959 "x and y direction and rotation angle.",
4960 "giraffe.wlcalibration",
4963 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-soffset");
4964 cpl_parameterlist_append(list, p);
4971 p = cpl_parameter_new_enum(
"giraffe.wlcalibration.opt.model",
4974 "giraffe.wlcalibration",
4975 "xoptmod2", 2,
"xoptmod",
"xoptmod2");
4977 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-ommodel");
4978 cpl_parameterlist_append(list, p);
4981 p = cpl_parameter_new_value(
"giraffe.wlcalibration.opt.direction",
4983 "Dispersion direction flag.",
4984 "giraffe.wlcalibration",
4987 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-omdir");
4988 cpl_parameterlist_append(list, p);
4991 p = cpl_parameter_new_value(
"giraffe.wlcalibration.opt.solution",
4993 "Controls optical model parameter fitting.",
4994 "giraffe.wlcalibration",
4997 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-omsol");
4998 cpl_parameterlist_append(list, p);
5001 p = cpl_parameter_new_value(
"giraffe.wlcalibration.opt.flags",
5003 "List of flags defining the set of free "
5004 "parameters used for fitting the optical "
5005 "model. Possible values are: fcoll, gcam, "
5006 "theta, sdx, sdy, sphi",
5007 "giraffe.wlcalibration",
5010 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-omflags");
5011 cpl_parameterlist_append(list, p);
5014 p = cpl_parameter_new_value(
"giraffe.wlcalibration.opt.subslits",
5016 "Controls subslit geometry usage in the "
5017 "optical model fit; subslits are used if "
5019 "giraffe.wlcalibration",
5022 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-omsslits");
5023 cpl_parameterlist_append(list, p);
5026 p = cpl_parameter_new_value(
"giraffe.wlcalibration.opt.iterations",
5028 "Optical model fit maximum number of "
5030 "giraffe.wlcalibration",
5033 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-omniter");
5034 cpl_parameterlist_append(list, p);
5037 p = cpl_parameter_new_value(
"giraffe.wlcalibration.opt.tests",
5039 "Optical model fit maximum number of "
5041 "giraffe.wlcalibration",
5044 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-omntest");
5045 cpl_parameterlist_append(list, p);
5048 p = cpl_parameter_new_value(
"giraffe.wlcalibration.opt.dchisquare",
5050 "Optical model fit minimum chi-square "
5052 "giraffe.wlcalibration",
5055 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-omdchisq");
5056 cpl_parameterlist_append(list, p);
5063 p = cpl_parameter_new_value(
"giraffe.wlcalibration.psf.sigma",
5065 "PSF width fit sigma clipping factor.",
5066 "giraffe.wlcalibration",
5069 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-xwsigma");
5070 cpl_parameterlist_append(list, p);
5073 p = cpl_parameter_new_value(
"giraffe.wlcalibration.psf.iterations",
5075 "PSF width fit sigma clipping maximum "
5076 "number of iterations.",
5077 "giraffe.wlcalibration",
5080 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-xwniter");
5081 cpl_parameterlist_append(list, p);
5084 p = cpl_parameter_new_range(
"giraffe.wlcalibration.psf.fraction",
5086 "PSF width fit sigma clipping minimum "
5087 "fraction of points accepted/total.",
5088 "giraffe.wlcalibration",
5091 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-xwmfrac");
5092 cpl_parameterlist_append(list, p);
5095 p = cpl_parameter_new_value(
"giraffe.wlcalibration.psf.order",
5097 "X and Y polynomial orders for PSF x-width "
5099 "giraffe.wlcalibration",
5102 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-xworder");
5103 cpl_parameterlist_append(list, p);
5110 p = cpl_parameter_new_value(
"giraffe.wlcalibration.wsol.sigma",
5112 "Chebyshev correction sigma clipping factor.",
5113 "giraffe.wlcalibration",
5116 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-wssigma");
5117 cpl_parameterlist_append(list, p);
5120 p = cpl_parameter_new_value(
"giraffe.wlcalibration.wsol.iterations",
5122 "Chebyshev correction sigma clipping "
5123 "maximum number of iterations",
5124 "giraffe.wlcalibration",
5127 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-wsniter");
5128 cpl_parameterlist_append(list, p);
5131 p = cpl_parameter_new_range(
"giraffe.wlcalibration.wsol.fraction",
5133 "Chebyshev correction sigma clipping "
5134 "minimum fraction of points accepted/total.",
5135 "giraffe.wlcalibration",
5138 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-wsmfrac");
5139 cpl_parameterlist_append(list, p);
5142 p = cpl_parameter_new_value(
"giraffe.wlcalibration.wsol.order",
5144 "X and Y polynomial orders for the wavelength "
5145 "solution Chebyshev correction.",
5146 "giraffe.wlcalibration",
5149 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcal-wsorder");
5150 cpl_parameterlist_append(list, p);