30 #include "muse_instrument.h"
32 #include "muse_optimize.h"
59 cpl_size aSensitivity, cpl_size aSlitWidth,
60 cpl_size aBinWidth, cpl_size aLSFWidth,
61 cpl_size aHermit3, cpl_size aHermit4,
62 cpl_size aHermit5, cpl_size aHermit6)
65 params->offset = aOffset;
66 params->refraction = aRefraction;
67 params->sensitivity = aSensitivity;
68 params->slit_width = aSlitWidth;
69 params->bin_width = aBinWidth;
70 params->lsf_width = aLSFWidth;
71 params->hermit[0] = aHermit3;
72 params->hermit[1] = aHermit4;
73 params->hermit[2] = aHermit5;
74 params->hermit[3] = aHermit6;
76 params->n_param = params->offset + params->refraction + params->sensitivity +
77 params->slit_width + params->bin_width + params->lsf_width;
79 for (i = 0; i < MAX_HERMIT_ORDER; i++) {
80 params->n_param += params->hermit[i];
111 const cpl_array *aPar,
117 cpl_size max_hermit = 0;
118 for (j = 0; j < MAX_HERMIT_ORDER; j++) {
119 if (max_hermit < aFitParams->hermit[j]) {
120 max_hermit = aFitParams->hermit[j];
125 aFitParams->sensitivity:
127 (aFitParams->lsf_width > 0)?
128 aFitParams->lsf_width:
129 cpl_array_get_size(aTemplate->
lsf_width),
132 cpl_array_get_size(aTemplate->
hermit[0]));
135 if (aFitParams->offset > 0) {
136 lsf->offset = cpl_array_get(aPar, offset++, NULL);
138 lsf->offset = aTemplate->offset;
141 if (aFitParams->refraction > 0) {
142 lsf->refraction = 1.0 + cpl_array_get(aPar, offset++, NULL);
144 lsf->refraction = aTemplate->refraction;
148 if (aFitParams->sensitivity > 0) {
149 for (j = 0; j < n; j++) {
150 if (j < aFitParams->sensitivity) {
152 cpl_array_get(aPar, offset++, NULL));
158 for (j = 0; j < n; j++) {
164 if (aFitParams->slit_width > 0) {
165 lsf->
slit_width = cpl_array_get(aPar, offset++, NULL);
170 if (aFitParams->bin_width > 0) {
171 lsf->
bin_width = cpl_array_get(aPar, offset++, NULL);
177 if (aFitParams->lsf_width > 0) {
178 for (j = 0; j < n; j++) {
179 if (j < aFitParams->lsf_width) {
181 cpl_array_get(aPar, offset++, NULL));
187 for (j = 0; j < n; j++) {
189 cpl_array_get(aTemplate->
lsf_width, j, NULL));
194 for (i = 0; i < MAX_HERMIT_ORDER; i++) {
195 n = cpl_array_get_size(lsf->
hermit[i]);
196 if (aFitParams->hermit[i] > 0) {
197 for (j = 0; j < n; j++) {
198 if (j < aFitParams->hermit[i]) {
199 cpl_array_set(lsf->
hermit[i], j,
200 cpl_array_get(aPar, offset++, NULL));
202 cpl_array_set(lsf->
hermit[i], j, 0.0);
206 for (j = 0; j < n; j++) {
207 cpl_array_set(lsf->
hermit[i], j,
214 if (offset > cpl_array_get_size(aPar)) {
215 cpl_msg_error(__func__,
216 "inconsistent array: size %ld, read with %ld values",
217 (
long)cpl_array_get_size(aPar), (
long)offset);
237 cpl_array *pars = cpl_array_new(aFitParams->n_param, CPL_TYPE_DOUBLE);
241 if (aFitParams->offset > 0) {
242 cpl_array_set(pars, offset++, aLsf->offset);
244 if (aFitParams->refraction > 0) {
245 cpl_array_set(pars, offset++, aLsf->refraction -1);
249 cpl_size n = cpl_array_get_size(aLsf->
sensitivity);
250 for (j = 0; j < aFitParams->sensitivity; j++) {
252 cpl_msg_debug(__func__,
"S[%li]=%f", (
long)j,
254 cpl_array_set(pars, offset++,
257 cpl_array_set(pars, offset++, (j == 0)?1.0:0.0);
261 if (aFitParams->slit_width > 0) {
262 cpl_array_set(pars, offset++, aLsf->
slit_width);
265 if (aFitParams->bin_width > 0) {
266 cpl_array_set(pars, offset++, aLsf->
bin_width);
271 for (j = 0; j < aFitParams->lsf_width; j++) {
273 cpl_array_set(pars, offset++,
274 cpl_array_get(aLsf->
lsf_width, j, NULL));
276 cpl_array_set(pars, offset++, (j == 0)?1.0:0.0);
282 for (i = 0; i < MAX_HERMIT_ORDER; i++) {
283 n = cpl_array_get_size(aLsf->
hermit[i]);
284 for (j = 0; j < aFitParams->hermit[i]; j++) {
286 cpl_array_set(pars, offset++,
287 cpl_array_get(aLsf->
hermit[i], j, NULL));
289 cpl_array_set(pars, offset++, 0.0);
294 if (offset > cpl_array_get_size(pars)) {
295 cpl_msg_error(__func__,
296 "inconsistent array: size %ld, filled with %ld values",
297 (
long)cpl_array_get_size(pars), (
long)offset);
315 cpl_array *pars = cpl_array_new(aFitParams->n_param, CPL_TYPE_DOUBLE);
319 if (aFitParams->offset > 0) {
320 cpl_array_set(pars, offset++, 0.0);
324 if (aFitParams->refraction > 0) {
325 cpl_array_set(pars, offset++, 0.0);
330 for (j = 0; j < aFitParams->sensitivity; j++) {
331 cpl_array_set(pars, offset++, (j == 0)?1.0:0.0);
335 if (aFitParams->slit_width > 0) {
336 cpl_array_set(pars, offset++, kMuseSliceSlitWidthA);
340 if (aFitParams->bin_width > 0) {
341 cpl_array_set(pars, offset++, kMuseSpectralSamplingA);
345 for (j = 0; j < aFitParams->lsf_width; j++) {
346 cpl_array_set(pars, offset++, (j == 0)?0.5:0.0);
351 for (i = 0; i < MAX_HERMIT_ORDER; i++) {
352 for (j = 0; j < aFitParams->hermit[i]; j++) {
353 cpl_array_set(pars, offset++, 0.0);
357 if (offset > cpl_array_get_size(pars)) {
358 cpl_msg_error(__func__,
359 "inconsistent array: size %ld, filled with %ld values",
360 (
long)cpl_array_get_size(pars), (
long)offset);
369 cpl_array *sensitivity;
370 cpl_array *continuum;
374 } muse_slice_fit_struct;
386 static cpl_error_code
387 muse_sky_slice_eval(
void *aData, cpl_array *aPar, cpl_array *aRetval) {
389 muse_slice_fit_struct *data = aData;
390 cpl_size size = cpl_array_get_size(aRetval);
394 aPar, data->fit_params);
400 cpl_array_subtract(simulated, data->values);
401 cpl_array_fill_window_double(aRetval, 0, size, 0.0);
402 memcpy(cpl_array_get_data_double(aRetval),
403 cpl_array_get_data_double_const(simulated),
404 size *
sizeof(
double));
406 cpl_array_delete(simulated);
408 return CPL_ERROR_NONE;
428 const cpl_array *aStat,
const cpl_table *aLines,
429 const cpl_array *aContinuum,
430 const cpl_array *aSensitivity,
436 cpl_size reduction = 5;
437 cpl_size size = cpl_array_get_size(aLambda)/reduction;
438 cpl_array *lambda = cpl_array_new(size, CPL_TYPE_DOUBLE);
439 cpl_array *data = cpl_array_new(size, CPL_TYPE_DOUBLE);
440 cpl_array *continuum = NULL;
441 if (aContinuum != NULL) {
442 continuum = cpl_array_new(size, CPL_TYPE_DOUBLE);
444 cpl_array *sensitivity = NULL;
445 if (aSensitivity != NULL) {
446 sensitivity = cpl_array_new(size, CPL_TYPE_DOUBLE);
449 for (i = 0; i < size; i++) {
450 cpl_array_set(lambda, i, cpl_array_get(aLambda, reduction * i, NULL));
451 cpl_array_set(data, i, cpl_array_get(aData, reduction * i, NULL));
452 if (aContinuum != NULL) {
453 cpl_array_set(continuum, i, cpl_array_get(aContinuum, reduction * i, NULL));
455 if (aSensitivity != NULL) {
456 cpl_array_set(sensitivity, i,
457 cpl_array_get(aSensitivity, reduction * i, NULL));
461 cpl_array *stat = cpl_array_new(size, CPL_TYPE_DOUBLE);
462 for (i = 0; i < size; i++) {
463 cpl_array_set(stat, i, sqrt(cpl_array_get(aStat, reduction * i, NULL)));
466 cpl_table *lines = cpl_table_duplicate(aLines);
467 double maxflux = cpl_table_get_column_max(lines,
"flux");
470 muse_slice_fit_struct fit_data = {
481 cpl_array *pars = (aFirstGuess == NULL)?
485 cpl_error_code r = CPL_ERROR_NONE;
486 int debug = getenv(
"MUSE_DEBUG_LSF_FIT")
487 && atoi(getenv(
"MUSE_DEBUG_LSF_FIT")) > 0;
495 muse_sky_slice_eval, &ctrl);
498 if (r != CPL_ERROR_NONE) {
499 cpl_array_delete(pars);
500 pars = (aFirstGuess == NULL)?
508 cpl_array_delete(pars);
509 cpl_table_delete(fit_data.lines);
510 cpl_array_delete(fit_data.lambda);
511 cpl_array_delete(fit_data.sensitivity);
512 cpl_array_delete(fit_data.continuum);
513 cpl_array_delete(fit_data.values);
514 cpl_array_delete(fit_data.stat);
515 if (aFirstGuess == NULL) {
void muse_lsf_params_delete_one(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.
cpl_array * muse_sky_slice_lsf_firstguess(const muse_sky_fit_params *aFitParams)
Return the parametrization values of the first guess.
Structure to define which slice parameters are fit.
void muse_sky_fit_params_delete(muse_sky_fit_params *params)
Delete the fit parameter structure.
double bin_width
Bin width.
muse_lsf_params * muse_sky_lsf_params_fit(const cpl_array *aLambda, const cpl_array *aData, const cpl_array *aStat, const cpl_table *aLines, const cpl_array *aContinuum, const cpl_array *aSensitivity, muse_lsf_params *aFirstGuess, int aMaxIter, const muse_sky_fit_params *aFitParams)
Fit all entries of one slice.
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.
double slit_width
Slit width.
cpl_array * lsf_width
LSF width.
Optimization control parameters.
muse_lsf_params * muse_sky_slice_apply_lsf_parametrization(const muse_lsf_params *template, const cpl_array *aPar, const muse_sky_fit_params *aFitParams)
Convert a parametrization to LSF parameters.
muse_sky_fit_params * muse_sky_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_error_code muse_sky_lines_cut(cpl_table *, double)
Remove all lines below a certain flux limit.
cpl_array * muse_sky_apply_lsf(const cpl_array *, const cpl_table *, const muse_lsf_params *)
Apply the LSF parameters to a spectrum.
Structure definition of detector (slice) parameters.
cpl_array * muse_sky_slice_lsf_set_param(muse_lsf_params *aLsf, const muse_sky_fit_params *aFitParams)
Return the parametrization values for the specific LSF params.