27 #define STORE_SLIT_WIDTH 28 #define STORE_BIN_WIDTH 39 #include "muse_lsf_params.h" 40 #include "muse_resampling.h" 41 #include "muse_pfits.h" 42 #include "muse_quality.h" 43 #include "muse_instrument.h" 44 #include "muse_optimize.h" 45 #include "muse_tracing.h" 46 #include "muse_utils.h" 66 res->refraction = 1.0;
73 for (i = 0; i < MAX_HERMIT_ORDER; i++) {
74 res->
hermit[i] = cpl_array_new(n_hermit, CPL_TYPE_DOUBLE);
75 cpl_array_fill_window_double(res->
hermit[i], 0, n_hermit, 0.0);
78 res->
lsf_width = cpl_array_new(n_lsf_width, CPL_TYPE_DOUBLE);
79 if (n_lsf_width > 0) {
80 cpl_array_fill_window_double(res->
lsf_width, 0, n_lsf_width, 0.0);
81 cpl_array_set_double(res->
lsf_width, 0, 1.0);
83 res->
sensitivity = cpl_array_new(n_sensit, CPL_TYPE_DOUBLE);
85 cpl_array_fill_window_double(res->
sensitivity, 0, n_sensit, 0.0);
100 if (aParams == NULL) {
104 for (i = 0; *aParams != NULL; i++) {
118 if (aParams != NULL) {
121 for (i = 0; i < MAX_HERMIT_ORDER; i++) {
122 cpl_array_delete(aParams->
hermit[i]);
137 if (aParams != NULL) {
139 for (det = aParams; *det != NULL; det++) {
162 {
"ifu", CPL_TYPE_INT, NULL,
"%i",
"IFU number", CPL_TRUE},
163 {
"slice", CPL_TYPE_INT, NULL,
"%i",
"slice number within the IFU", CPL_TRUE},
164 {
"sensitivity", CPL_TYPE_DOUBLE | CPL_TYPE_POINTER, NULL,
"%e",
165 "detector sensitivity, relative to the reference", CPL_TRUE},
166 {
"offset", CPL_TYPE_DOUBLE, NULL,
"%e",
"wavelength calibration offset", CPL_TRUE},
167 {
"refraction", CPL_TYPE_DOUBLE, NULL,
"%e",
"relative refraction index", CPL_TRUE},
168 #ifdef STORE_SLIT_WIDTH 169 {
"slit_width", CPL_TYPE_DOUBLE,
"Angstrom",
"%e",
"slit width", CPL_TRUE},
171 #ifdef STORE_BIN_WIDTH 172 {
"bin_width", CPL_TYPE_DOUBLE,
"Angstrom",
"%e",
"bin width", CPL_TRUE},
174 {
"lsf_width", CPL_TYPE_DOUBLE | CPL_TYPE_POINTER,
"Angstrom",
"%e",
175 " LSF gauss-hermitean width", CPL_TRUE},
176 {
"hermit3", CPL_TYPE_DOUBLE | CPL_TYPE_POINTER, NULL,
"%e",
177 "3rd order hermitean coefficient", CPL_TRUE},
178 {
"hermit4", CPL_TYPE_DOUBLE | CPL_TYPE_POINTER, NULL,
"%e",
179 "4th order hermitean coefficient", CPL_TRUE},
180 {
"hermit5", CPL_TYPE_DOUBLE | CPL_TYPE_POINTER, NULL,
"%e",
181 "5th order hermitean coefficient", CPL_TRUE},
182 {
"hermit6", CPL_TYPE_DOUBLE | CPL_TYPE_POINTER, NULL,
"%e",
183 "6th order hermitean coefficient", CPL_TRUE},
184 { NULL, 0, NULL, NULL, NULL, CPL_FALSE }
204 cpl_ensure_code(aLsfParams != NULL, CPL_ERROR_NULL_INPUT);
205 cpl_ensure_code(*aLsfParams != NULL, CPL_ERROR_DATA_NOT_FOUND);
206 cpl_ensure_code(aFile != NULL, CPL_ERROR_NULL_INPUT);
210 cpl_size sensitivity_order = 1;
211 cpl_size lsf_order = 1;
212 cpl_size hermit_order[MAX_HERMIT_ORDER];
214 for (i = 0; i < MAX_HERMIT_ORDER; i++) {
217 for (det = aLsfParams; *det != NULL; det++, nrows++) {
218 sensitivity_order = fmax(sensitivity_order,
219 cpl_array_get_size((*det)->sensitivity));
220 lsf_order = fmax(lsf_order, cpl_array_get_size((*det)->lsf_width));
221 for (i = 0; i < MAX_HERMIT_ORDER; i++) {
222 hermit_order[i] = fmax(hermit_order[i],
223 cpl_array_get_size((*det)->hermit[i]));
227 cpl_table *slice_param = cpl_table_new(nrows);
228 cpl_table_new_column(slice_param,
"ifu", CPL_TYPE_INT);
229 cpl_table_new_column(slice_param,
"slice", CPL_TYPE_INT);
230 cpl_table_new_column_array(slice_param,
"sensitivity",
231 cpl_array_get_type(aLsfParams[0]->sensitivity),
233 cpl_table_new_column(slice_param,
"offset", CPL_TYPE_DOUBLE);
234 cpl_table_new_column(slice_param,
"refraction", CPL_TYPE_DOUBLE);
235 #ifdef STORE_SLIT_WIDTH 236 cpl_table_new_column(slice_param,
"slit_width", CPL_TYPE_DOUBLE);
238 #ifdef STORE_BIN_WIDTH 239 cpl_table_new_column(slice_param,
"bin_width", CPL_TYPE_DOUBLE);
241 cpl_table_new_column_array(slice_param,
"lsf_width",
242 cpl_array_get_type(aLsfParams[0]->lsf_width),
244 cpl_table_new_column_array(slice_param,
"hermit3",
245 cpl_array_get_type(aLsfParams[0]->hermit[0]),
247 cpl_table_new_column_array(slice_param,
"hermit4",
248 cpl_array_get_type(aLsfParams[0]->hermit[1]),
250 cpl_table_new_column_array(slice_param,
"hermit5",
251 cpl_array_get_type(aLsfParams[0]->hermit[2]),
253 cpl_table_new_column_array(slice_param,
"hermit6",
254 cpl_array_get_type(aLsfParams[0]->hermit[3]),
258 for (det = aLsfParams; *det != NULL; det++, iRow++) {
259 cpl_table_set(slice_param,
"ifu", iRow, (*det)->ifu);
260 cpl_table_set(slice_param,
"slice", iRow, (*det)->slice);
261 cpl_table_set_array(slice_param,
"sensitivity", iRow, (*det)->sensitivity);
262 cpl_table_set(slice_param,
"offset", iRow, (*det)->offset);
263 cpl_table_set(slice_param,
"refraction", iRow, (*det)->refraction);
264 #ifdef STORE_SLIT_WIDTH 265 cpl_table_set(slice_param,
"slit_width", iRow, (*det)->slit_width);
267 #ifdef STORE_BIN_WIDTH 268 cpl_table_set(slice_param,
"bin_width", iRow, (*det)->bin_width);
270 cpl_table_set_array(slice_param,
"lsf_width", iRow, (*det)->lsf_width);
271 cpl_table_set_array(slice_param,
"hermit3", iRow, (*det)->hermit[0]);
272 cpl_table_set_array(slice_param,
"hermit4", iRow, (*det)->hermit[1]);
273 cpl_table_set_array(slice_param,
"hermit5", iRow, (*det)->hermit[2]);
274 cpl_table_set_array(slice_param,
"hermit6", iRow, (*det)->hermit[3]);
279 cpl_table_delete(slice_param);
299 cpl_errorstate prestate = cpl_errorstate_get();
304 char *extname = cpl_sprintf(
"CHAN%02d.SLICE_PARAM", aIFU);
308 if (aParams == NULL) {
310 cpl_errorstate_set(prestate);
314 cpl_error_set_message(__func__, cpl_error_get_code(),
"Loading LSF data from " 315 "\"%s[SLICE_PARAMS]\" and \"%s[CHAH%02d.SLICE_PARAMS]\" " 316 "failed", aFile, aFile, aIFU);
321 cpl_size n_rows = cpl_table_get_nrow(lsfTable);
324 = cpl_realloc(aParams, (n_rows + n_rows_old + 1) *
sizeof(
muse_lsf_params *));
325 lsfParams[n_rows + n_rows_old] = NULL;
326 cpl_size i_row_new = n_rows_old;
328 for (i_row = 0; i_row < n_rows; i_row++) {
329 int ifu = cpl_table_get(lsfTable,
"ifu", i_row, NULL);
330 lsfParams[i_row + n_rows_old] = NULL;
331 if ((aIFU <= 0) || (ifu == aIFU)) {
333 lsfParams[i_row_new] = det;
336 det->slice = cpl_table_get(lsfTable,
"slice", i_row, NULL);
340 det->offset = cpl_table_get(lsfTable,
"offset", i_row, NULL);
341 det->refraction = cpl_table_get(lsfTable,
"refraction", i_row, NULL);
342 #ifdef STORE_SLIT_WIDTH 343 det->
slit_width = cpl_table_get(lsfTable,
"slit_width", i_row, NULL);
345 #ifdef STORE_BIN_WIDTH 346 det->
bin_width = cpl_table_get(lsfTable,
"bin_width", i_row, NULL);
351 cpl_array_delete(det->
hermit[0]);
354 cpl_array_delete(det->
hermit[1]);
357 cpl_array_delete(det->
hermit[2]);
360 cpl_array_delete(det->
hermit[3]);
365 cpl_table_delete(lsfTable);
389 cpl_ensure(aProcessing, CPL_ERROR_NULL_INPUT, NULL);
391 MUSE_TAG_LSF_PROFILE, aIFU,
393 if (frames == NULL) {
397 cpl_errorstate state = cpl_errorstate_get();
398 cpl_size iframe, nframes = cpl_frameset_get_size(frames);
400 for (iframe = 0; iframe < nframes; iframe++) {
401 cpl_frame *frame = cpl_frameset_get_position(frames, iframe);
405 cpl_msg_info(__func__,
"Loaded slice LSF params from \"%s\"",
406 cpl_frame_get_filename(frame));
411 if (!cpl_errorstate_is_equal(state)) {
412 errmsg = cpl_strdup(cpl_error_get_message());
414 cpl_errorstate_set(state);
417 if (!lsfParams && aIFU == 0 && nframes == 1) {
418 cpl_msg_debug(__func__,
"No LSF parameters loaded yet, trying merged table " 421 cpl_frame *frame = cpl_frameset_get_position(frames, 0);
422 const char *fname = cpl_frame_get_filename(frame);
423 state = cpl_errorstate_get();
425 for (ifu = 1; ifu <= kMuseNumIFUs; ifu++) {
428 cpl_errorstate_set(state);
430 cpl_msg_info(__func__,
"Loaded (merged) slice LSF params from \"%s\"", fname);
434 cpl_frameset_delete(frames);
438 cpl_msg_debug(__func__,
"Loading %ss from input frameset did not succeed: " 439 "%s", MUSE_TAG_LSF_PROFILE, errmsg);
453 if (aParams == NULL) {
457 for (i_det = 0; aParams[i_det] != NULL; i_det++) {
458 if (aParams[i_det]->ifu == aIFU && aParams[i_det]->slice == aSlice) {
459 return aParams[i_det];
485 cpl_ensure(aX != NULL, CPL_ERROR_NULL_INPUT, NULL);
486 cpl_ensure(aCoeffs != NULL, CPL_ERROR_NULL_INPUT, NULL);
488 cpl_array *y = cpl_array_duplicate(aX);
489 cpl_array_multiply(y, y);
490 cpl_array_multiply_scalar(y, -1);
492 cpl_array *y2 = cpl_array_duplicate(y);
494 cpl_array_multiply_scalar(y2, 1.0/60);
496 cpl_array_multiply_scalar(y, 0.5);
499 cpl_array *R = cpl_array_duplicate(aX);
501 cpl_array_multiply(y2, R);
503 cpl_array_add(y, y2);
505 cpl_array_copy_data_double(y2, cpl_array_get_data_double(aX));
506 cpl_array_multiply_scalar(y2, sqrt(0.5));
508 cpl_array_multiply_scalar(y2, sqrt(CPL_MATH_PI / 2));
509 cpl_array_multiply(y2, aX);
510 cpl_array_add(y, y2);
511 cpl_array_delete(y2);
540 cpl_array *aVal,
double aLambda)
543 cpl_ensure_code(aVal != NULL, CPL_ERROR_NULL_INPUT);
544 cpl_ensure_code(aLsfParams != NULL, CPL_ERROR_NULL_INPUT);
547 double bin_width = aLsfParams->
bin_width;
559 cpl_array *coeff = cpl_array_new(5, CPL_TYPE_DOUBLE);
560 cpl_array_set(coeff, 4, 2 * sqrt(5) * h6);
561 cpl_array_set(coeff, 3, 2 * sqrt(15) * h5);
562 cpl_array_set(coeff, 2, 5 * sqrt(6) * h4 - 6 * sqrt(5) * h6);
563 cpl_array_set(coeff, 1, 10 * sqrt(3) * h3 - 3 * sqrt(15) * h5);
564 cpl_array_set(coeff, 0, -2.5 * sqrt(6) * h4 + 1.5 * sqrt(5) * h6);
566 cpl_array_divide_scalar(aVal, width);
567 bin_width /= 2 * width;
568 slit_width /= 2 * width;
570 cpl_array *x = cpl_array_duplicate(aVal);
573 cpl_array_add_scalar(x, slit_width + bin_width);
576 cpl_array_copy_data_double(x, cpl_array_get_data_double(aVal));
577 cpl_array_add_scalar(x, slit_width - bin_width);
579 cpl_array_subtract(y, y1);
580 cpl_array_delete(y1);
582 cpl_array_copy_data_double(x, cpl_array_get_data_double(aVal));
583 cpl_array_add_scalar(x, -slit_width + bin_width);
585 cpl_array_subtract(y, y1);
586 cpl_array_delete(y1);
588 cpl_array_copy_data_double(x, cpl_array_get_data_double(aVal));
589 cpl_array_add_scalar(x, -slit_width - bin_width);
592 cpl_array_add(y, y1);
593 cpl_array_delete(y1);
595 cpl_array_divide_scalar(y, sqrt(CPL_MATH_PI * 32)
596 * bin_width * slit_width * width * width);
597 cpl_array_multiply_scalar(y, width);
598 cpl_array_copy_data_double(aVal, cpl_array_get_data_double(y));
600 cpl_array_delete(coeff);
602 return CPL_ERROR_NONE;
626 cpl_size n_lines = cpl_table_get_nrow(aLines);
628 cpl_array *spectrum = cpl_array_new(cpl_array_get_size(aLambda),
630 cpl_array_fill_window(spectrum, 0, cpl_array_get_size(aLambda), 0.0);
632 feclearexcept(FE_UNDERFLOW);
633 for (i_line = 0; i_line < n_lines; i_line++) {
634 double l_lambda = cpl_table_get(aLines,
"lambda", i_line, NULL);
635 double l_flux = cpl_table_get(aLines,
"flux", i_line, NULL);
643 cpl_array *l0 = cpl_array_extract(aLambda, imin, imax-imin+1);
644 cpl_array_subtract_scalar(l0, l_lambda);
646 cpl_array_multiply_scalar(l0, l_flux);
648 cpl_array_delete(l0);
650 if (fetestexcept(FE_UNDERFLOW)) {
652 feclearexcept(FE_UNDERFLOW);
678 cpl_size aSensitivity, cpl_size aSlitWidth,
679 cpl_size aBinWidth, cpl_size aLSFWidth,
680 cpl_size aHermit3, cpl_size aHermit4,
681 cpl_size aHermit5, cpl_size aHermit6)
684 params->offset = aOffset;
685 params->refraction = aRefraction;
686 params->sensitivity = aSensitivity;
687 params->slit_width = aSlitWidth;
688 params->bin_width = aBinWidth;
689 params->lsf_width = aLSFWidth;
690 params->hermit[0] = aHermit3;
691 params->hermit[1] = aHermit4;
692 params->hermit[2] = aHermit5;
693 params->hermit[3] = aHermit6;
695 params->n_param = params->offset + params->refraction + params->sensitivity +
696 params->slit_width + params->bin_width + params->lsf_width;
698 for (i = 0; i < MAX_HERMIT_ORDER; i++) {
699 params->n_param += params->hermit[i];
730 cpl_array *pars = cpl_array_new(aFitParams->n_param, CPL_TYPE_DOUBLE);
734 if (aFitParams->offset > 0) {
735 cpl_array_set(pars, offset++, 0.0);
739 if (aFitParams->refraction > 0) {
740 cpl_array_set(pars, offset++, 0.0);
745 for (j = 0; j < aFitParams->sensitivity; j++) {
746 cpl_array_set(pars, offset++, (j == 0)?1.0:0.0);
750 if (aFitParams->slit_width > 0) {
751 cpl_array_set(pars, offset++, kMuseSliceSlitWidthA);
755 if (aFitParams->bin_width > 0) {
756 cpl_array_set(pars, offset++, kMuseSpectralSamplingA);
760 for (j = 0; j < aFitParams->lsf_width; j++) {
761 cpl_array_set(pars, offset++, (j == 0)?0.5:0.0);
766 for (i = 0; i < MAX_HERMIT_ORDER; i++) {
767 for (j = 0; j < aFitParams->hermit[i]; j++) {
768 cpl_array_set(pars, offset++, 0.0);
772 if (offset > cpl_array_get_size(pars)) {
773 cpl_msg_error(__func__,
774 "inconsistent array: size %ld, filled with %ld values",
775 (
long)cpl_array_get_size(pars), (
long)offset);
792 cpl_array *pars = cpl_array_new(aFitParams->n_param, CPL_TYPE_DOUBLE);
796 if (aFitParams->offset > 0) {
797 cpl_array_set(pars, offset++, aLsfParams->offset);
799 if (aFitParams->refraction > 0) {
800 cpl_array_set(pars, offset++, aLsfParams->refraction -1);
804 cpl_size n = cpl_array_get_size(aLsfParams->
sensitivity);
805 for (j = 0; j < aFitParams->sensitivity; j++) {
807 cpl_msg_debug(__func__,
"S[%li]=%f", (
long)j,
809 cpl_array_set(pars, offset++,
812 cpl_array_set(pars, offset++, (j == 0)?1.0:0.0);
816 if (aFitParams->slit_width > 0) {
817 cpl_array_set(pars, offset++, aLsfParams->
slit_width);
820 if (aFitParams->bin_width > 0) {
821 cpl_array_set(pars, offset++, aLsfParams->
bin_width);
825 n = cpl_array_get_size(aLsfParams->
lsf_width);
826 for (j = 0; j < aFitParams->lsf_width; j++) {
828 cpl_array_set(pars, offset++,
829 cpl_array_get(aLsfParams->
lsf_width, j, NULL));
831 cpl_array_set(pars, offset++, (j == 0)?1.0:0.0);
837 for (i = 0; i < MAX_HERMIT_ORDER; i++) {
838 n = cpl_array_get_size(aLsfParams->
hermit[i]);
839 for (j = 0; j < aFitParams->hermit[i]; j++) {
841 cpl_array_set(pars, offset++,
842 cpl_array_get(aLsfParams->
hermit[i], j, NULL));
844 cpl_array_set(pars, offset++, 0.0);
849 if (offset > cpl_array_get_size(pars)) {
850 cpl_msg_error(__func__,
851 "inconsistent array: size %ld, filled with %ld values",
852 (
long)cpl_array_get_size(pars), (
long)offset);
871 const cpl_array *aPar,
877 cpl_size max_hermit = 0;
878 for (j = 0; j < MAX_HERMIT_ORDER; j++) {
879 if (max_hermit < aFitParams->hermit[j]) {
880 max_hermit = aFitParams->hermit[j];
885 aFitParams->sensitivity:
887 (aFitParams->lsf_width > 0)?
888 aFitParams->lsf_width:
889 cpl_array_get_size(aTemplate->
lsf_width),
892 cpl_array_get_size(aTemplate->
hermit[0]));
895 if (aFitParams->offset > 0) {
896 lsf->offset = cpl_array_get(aPar, offset++, NULL);
898 lsf->offset = aTemplate->offset;
901 if (aFitParams->refraction > 0) {
902 lsf->refraction = 1.0 + cpl_array_get(aPar, offset++, NULL);
904 lsf->refraction = aTemplate->refraction;
908 if (aFitParams->sensitivity > 0) {
909 for (j = 0; j < n; j++) {
910 if (j < aFitParams->sensitivity) {
912 cpl_array_get(aPar, offset++, NULL));
918 for (j = 0; j < n; j++) {
924 if (aFitParams->slit_width > 0) {
925 lsf->
slit_width = cpl_array_get(aPar, offset++, NULL);
930 if (aFitParams->bin_width > 0) {
931 lsf->
bin_width = cpl_array_get(aPar, offset++, NULL);
937 if (aFitParams->lsf_width > 0) {
938 for (j = 0; j < n; j++) {
939 if (j < aFitParams->lsf_width) {
941 cpl_array_get(aPar, offset++, NULL));
947 for (j = 0; j < n; j++) {
949 cpl_array_get(aTemplate->
lsf_width, j, NULL));
954 for (i = 0; i < MAX_HERMIT_ORDER; i++) {
955 n = cpl_array_get_size(lsf->
hermit[i]);
956 if (aFitParams->hermit[i] > 0) {
957 for (j = 0; j < n; j++) {
958 if (j < aFitParams->hermit[i]) {
959 cpl_array_set(lsf->
hermit[i], j,
960 cpl_array_get(aPar, offset++, NULL));
962 cpl_array_set(lsf->
hermit[i], j, 0.0);
966 for (j = 0; j < n; j++) {
967 cpl_array_set(lsf->
hermit[i], j,
974 if (offset > cpl_array_get_size(aPar)) {
975 cpl_msg_error(__func__,
976 "inconsistent array: size %ld, read with %ld values",
977 (
long)cpl_array_get_size(aPar), (
long)offset);
992 const cpl_table *lines;
995 } muse_lsf_fit_struct;
1007 static cpl_error_code
1008 muse_lsf_eval(
void *aData, cpl_array *aPar, cpl_array *aRetval) {
1010 muse_lsf_fit_struct *data = aData;
1011 cpl_size size = cpl_array_get_size(aRetval);
1014 = muse_lsf_apply_parametrization(data->firstGuess, aPar, data->fit_params);
1016 cpl_table *lines = cpl_table_duplicate(data->lines);
1018 if (!cpl_table_has_column(lines,
"flux")) {
1019 cpl_array *linesFlux = cpl_array_extract(aPar, cpl_array_get_size(aPar)
1020 - cpl_table_get_nrow(data->lines),
1021 cpl_table_get_nrow(data->lines));
1022 cpl_table_wrap_double(lines, cpl_array_unwrap(linesFlux),
"flux");
1025 cpl_array *simulated
1028 cpl_table_delete(lines);
1031 cpl_array_subtract(simulated, data->values);
1032 cpl_array_divide(simulated, data->stat);
1034 cpl_array_fill_window_double(aRetval, 0, size, 0.0);
1035 memcpy(cpl_array_get_data_double(aRetval),
1036 cpl_array_get_data_double_const(simulated),
1037 size *
sizeof(
double));
1041 double *d = cpl_array_get_data_double(aRetval);
1042 for (i = 0; i < size; i++) {
1048 cpl_array_delete(simulated);
1049 return CPL_ERROR_NONE;
1069 cpl_ensure(aPixtable, CPL_ERROR_NULL_INPUT, NULL);
1070 uint32_t origin = (uint32_t)cpl_table_get_int(aPixtable->
table,
1076 cpl_propertylist *order = cpl_propertylist_new();
1078 cpl_table_sort(aPixtable->
table, order);
1079 cpl_propertylist_delete(order);
1083 cpl_table *lines = cpl_table_duplicate(aLines);
1089 cpl_size reduction = 1;
1090 cpl_size size = cpl_table_get_nrow(aPixtable->
table)/reduction;
1091 cpl_array *lambda = cpl_array_new(size, CPL_TYPE_DOUBLE);
1092 cpl_array *data = cpl_array_new(size, CPL_TYPE_DOUBLE);
1093 cpl_array *stat = cpl_array_new(size, CPL_TYPE_DOUBLE);
1095 cpl_msg_info(__func__,
"processing slice %2i.%02i" 1096 " with %"CPL_SIZE_FORMAT
" entries",
1097 i_ifu, i_slice, size);
1100 for (i = 0; i < size; i++) {
1102 cpl_array_set(lambda, i, cpl_table_get(aPixtable->
table,
1104 reduction * i, &iflg));
1105 cpl_array_set(data, i, cpl_table_get(aPixtable->
table,
1107 reduction * i, &iflg));
1108 cpl_array_set(stat, i, sqrt(cpl_table_get(aPixtable->
table,
1110 reduction * i, &iflg)));
1115 int debug = getenv(
"MUSE_DEBUG_LSF_FIT")
1116 && atoi(getenv(
"MUSE_DEBUG_LSF_FIT")) > 0;
1139 muse_lsf_fit_struct fit_data = {
1148 cpl_array *pars = muse_lsf_firstguess(slice_fit_params0);
1152 cpl_array *linesFlux = cpl_array_cast(lf, CPL_TYPE_DOUBLE);
1153 cpl_array_unwrap(lf);
1154 cpl_array_insert(pars, linesFlux, cpl_array_get_size(pars));
1155 cpl_table_erase_column(lines,
"flux");
1160 if (r != CPL_ERROR_NONE) {
1161 cpl_array_delete(pars);
1162 pars = muse_lsf_firstguess(slice_fit_params0);
1163 cpl_array_insert(pars, linesFlux, cpl_array_get_size(pars));
1184 fit_data.fit_params = slice_fit_params;
1186 cpl_array_delete(linesFlux);
1187 linesFlux = cpl_array_extract(pars, cpl_array_get_size(pars)
1188 - cpl_table_get_nrow(lines),
1189 cpl_table_get_nrow(lines));
1190 cpl_table_wrap_double(lines, cpl_array_unwrap(linesFlux),
"flux");
1192 fit_data.firstGuess = muse_lsf_apply_parametrization(firstGuess, pars,
1195 cpl_array_delete(pars);
1196 pars = muse_lsf_set_param(fit_data.firstGuess, slice_fit_params);
1199 if (r != CPL_ERROR_NONE) {
1200 cpl_array_delete(pars);
1201 pars = muse_lsf_firstguess(slice_fit_params);
1205 = muse_lsf_apply_parametrization(firstGuess, pars, slice_fit_params);
1206 lsfParam->ifu = i_ifu;
1207 lsfParam->slice = i_slice;
1209 cpl_msg_debug(__func__,
"Slice %2i.%02i: Slit width: %f (%s), bin width: %f (%s)",
1211 lsfParam->
slit_width, slice_fit_params->slit_width?
"fit":
"fixed",
1212 lsfParam->
bin_width, slice_fit_params->bin_width?
"fit":
"fixed");
1215 cpl_table_wrap_double(aPixtable->
table, cpl_array_unwrap(simulated),
1219 cpl_table_erase_column(aPixtable->
table,
"simulated");
1222 cpl_array_delete(pars);
1223 if (cpl_table_has_column(aPixtable->
table,
"lambda_double")) {
1224 cpl_table_erase_column(aPixtable->
table,
"lambda_double");
1226 cpl_array_delete(fit_data.lambda);
1227 cpl_array_delete(fit_data.values);
1228 cpl_array_delete(fit_data.stat);
1232 cpl_table_delete(lines);
1261 double aSampling,
unsigned int aLength)
1263 cpl_ensure(aDP, CPL_ERROR_NULL_INPUT, 0.);
1265 cpl_ensure(cpl_array_get(aDP->
lsf_width, 0, NULL) != 1 &&
1266 cpl_array_get(aDP->
lsf_width, 0, NULL) != 0,
1267 CPL_ERROR_ILLEGAL_INPUT, 0.);
1269 cpl_table *line = cpl_table_new(1);
1270 cpl_table_new_column(line,
"lambda", CPL_TYPE_DOUBLE);
1271 cpl_table_new_column(line,
"flux", CPL_TYPE_FLOAT);
1272 cpl_table_set_double(line,
"lambda", 0, aLambda);
1273 cpl_table_set_float(line,
"flux", 0, 1.0);
1275 cpl_array *lambda = cpl_array_new(aLength, CPL_TYPE_DOUBLE);
1277 for (i = 0; i < aLength; i++) {
1278 cpl_array_set_double(lambda, i, (i + 1. - aLength/2) * aSampling + aLambda);
1283 cpl_array_get_maxpos(spec, &imax);
1284 double max = cpl_array_get_max(spec),
1288 (vl = cpl_array_get_double(spec, i, NULL)) > max/2.) ;
1291 while (++i < aLength &&
1292 (vr = cpl_array_get_double(spec, i, NULL)) > max/2.) ;
1296 double fwhm = (ir - il) * aSampling;
1297 cpl_array_delete(spec);
1298 cpl_array_delete(lambda);
1299 cpl_table_delete(line);
1300 cpl_ensure(il > 0 && ir < aLength, CPL_ERROR_ILLEGAL_OUTPUT, 0.);
cpl_array * muse_lsf_params_spectrum(const cpl_array *aLambda, cpl_table *aLines, const muse_lsf_params *aLsfParams)
Create spectrum for a single slice.
unsigned short muse_pixtable_origin_get_slice(uint32_t aOrigin)
Get the slice number from the encoded 32bit origin number.
double muse_lsf_fwhm_lambda(const muse_lsf_params *aDP, double aLambda, double aSampling, unsigned int aLength)
Measure the FWHM of an LSF at a given wavelength.
void muse_lsf_params_delete(muse_lsf_params *aParams)
Delete an allocated muse_lsf_params structure.
cpl_error_code muse_cpl_optimize_lvmq(void *aData, cpl_array *aPar, int aSize, muse_cpl_evaluate_func *aFunction, muse_cpl_optimize_control_t *aCtrl)
Minimize a function with the Levenberg-Marquardt algorithm.
muse_lsf_params * muse_lsf_params_get(muse_lsf_params **aParams, int aIFU, int aSlice)
Get the slice LSF parameters for one slice.
cpl_error_code muse_cplarray_poly1d(cpl_array *aArray, const cpl_array *aCoeff)
Apply a polynomial to an array.
cpl_table * table
The pixel table.
void muse_lsf_params_delete_all(muse_lsf_params **aParams)
Delete an allocated array of muse_lsf_params structure.
cpl_table * muse_cpltable_load(const char *aFile, const char *aExtension, const muse_cpltable_def aDefinition[])
Load a table from disk (and check against definition).
#define MUSE_PIXTABLE_DATA
double bin_width
Bin width.
muse_lsf_fit_params * muse_lsf_fit_params_new(cpl_boolean aOffset, cpl_boolean aRefraction, cpl_size aSensitivity, cpl_size aSlitWidth, cpl_size aBinWidth, cpl_size aLSFWidth, cpl_size aHermit3, cpl_size aHermit4, cpl_size aHermit5, cpl_size aHermit6)
Create a new fit parameter structure.
cpl_array * hermit[MAX_HERMIT_ORDER]
coefficients for the damped gauss-hermitean parametrization
muse_lsf_params * muse_lsf_params_new(cpl_size n_sensit, cpl_size n_lsf_width, cpl_size n_hermit)
Create a new lsf_params structure.
cpl_array * sensitivity
Relative detector sensitivity parametrization.
cpl_error_code muse_cplarray_exp(cpl_array *aArray)
Compute the exponential function of array elements.
Structure definition of MUSE pixel table.
double slit_width
Slit width.
cpl_array * muse_cpltable_get_array_copy(cpl_table *aTable, const char *aColumn, cpl_size aRow)
Return the copy of an array of a table cell.
cpl_array * lsf_width
LSF width.
cpl_array * muse_cpltable_extract_column(cpl_table *aTable, const char *aColumn)
Create an array from a section of a column.
Optimization control parameters.
muse_lsf_params * muse_lsf_params_fit(muse_pixtable *aPixtable, cpl_table *aLines, int aMaxIter)
Fit all entries of one slice.
void muse_processing_append_used(muse_processing *aProcessing, cpl_frame *aFrame, cpl_frame_group aGroup, int aDuplicate)
Add a frame to the set of used frames.
cpl_error_code muse_cplarray_erf(cpl_array *aArray)
Compute the error function of array elements.
cpl_error_code muse_lsf_params_apply(const muse_lsf_params *aLsfParams, cpl_array *aVal, double aLambda)
Apply the MUSE LSF function to a single line.
cpl_size muse_lsf_params_get_size(muse_lsf_params **aParams)
Count the number of entries in the array.
cpl_error_code muse_cplarray_add_window(cpl_array *aDest, cpl_size aStart, const cpl_array *aArray)
Add the value of an array to a window of a table column.
#define MUSE_PIXTABLE_ORIGIN
const muse_cpltable_def muse_lsfparams_def[]
Definition of a lsf parameters table.
muse_lsf_params ** muse_lsf_params_load(const char *aFile, muse_lsf_params **aParams, int aIFU)
Load slice LSF parameters from the extension "SLICE_PARAM".
Structure to define which slice parameters are fit.
unsigned short muse_pixtable_origin_get_ifu(uint32_t aOrigin)
Get the IFU number from the encoded 32bit origin number.
cpl_error_code muse_lsf_params_save(const muse_lsf_params **aLsfParams, const char *aFile)
Save slice LSF parameters to the extension "slice" on disk.
double lambda_ref
Reference wavelength for polynomial parametrizations.
#define MUSE_PIXTABLE_STAT
#define MUSE_PIXTABLE_LAMBDA
static cpl_array * muse_lsf_G(cpl_array *aX, cpl_array *aCoeffs)
Helper function "G" for integrated damped gauss-hermitean function.
Definition of a cpl table structure.
muse_lsf_params ** muse_processing_lsf_params_load(muse_processing *aProcessing, int aIFU)
Load slice LSF parameters.
cpl_frameset * muse_frameset_find(const cpl_frameset *aFrames, const char *aTag, unsigned char aIFU, cpl_boolean aInvert)
return frameset containing data from an IFU/channel with a certain tag
void muse_lsf_fit_params_delete(muse_lsf_fit_params *params)
Delete the fit parameter structure.
Structure definition of detector (slice) parameters.
double muse_cplarray_poly1d_double(double aDouble, const cpl_array *aCoeff)
Apply a polynomial to a double value.
cpl_size muse_cplarray_find_sorted(const cpl_array *aArray, double aValue)
Find a row in an array.
cpl_error_code muse_cpltable_append_file(const cpl_table *aTable, const char *aFile, const char *aExtension, const muse_cpltable_def aDefinition[])
Save a table to disk (into a FITS extension)