MUSE Pipeline Reference Manual  0.18.1
muse_sky_master.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set sw=2 sts=2 et cin: */
3 /*
4  * This file is part of the MUSE Instrument Pipeline
5  * Copyright (C) 2008-2014 European Southern Observatory
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 
26 #include <math.h>
27 #include <string.h>
28 
29 #include "muse_sky.h"
30 #include "muse_instrument.h"
31 #include "muse_lsf.h"
32 #include "muse_optimize.h"
33 #include "muse_utils.h"
34 #include "muse_data_format_z.h"
35 
40 /*----------------------------------------------------------------------------*/
45 /*----------------------------------------------------------------------------*/
48  return cpl_calloc(1, sizeof(muse_sky_master));
49 }
50 
51 /*----------------------------------------------------------------------------*/
57 /*----------------------------------------------------------------------------*/
58 void
60  if (aMaster != NULL) {
61  cpl_table_delete(aMaster->lines);
62  cpl_table_delete(aMaster->continuum);
63  muse_lsf_params_delete(aMaster->lsf);
64  cpl_free(aMaster);
65  }
66 }
67 
68 /*----------------------------------------------------------------------------*/
75 /*----------------------------------------------------------------------------*/
76 typedef struct {
78  cpl_array *line_strength;
80  cpl_array *continuum;
82  muse_lsf_params *lsf;
83 } muse_sky_master_params;
84 
85 /*----------------------------------------------------------------------------*/
93 /*----------------------------------------------------------------------------*/
94 static muse_sky_master_params *
95 muse_sky_master_params_new(cpl_size n_groups, cpl_size n_continuum) {
96  muse_sky_master_params *res = cpl_calloc(1, sizeof(muse_sky_master_params));
97  res->line_strength = cpl_array_new(n_groups, CPL_TYPE_DOUBLE);
98  cpl_array_fill_window_double(res->line_strength, 0, n_groups, 1.0);
99  res->continuum = cpl_array_new(n_continuum, CPL_TYPE_DOUBLE);
100  cpl_array_fill_window_double(res->continuum, 0, n_continuum, 0.0);
101  return res;
102 }
103 
104 /*----------------------------------------------------------------------------*/
110 /*----------------------------------------------------------------------------*/
111 static void
112 muse_sky_master_params_delete(muse_sky_master_params *aParams) {
113  if (aParams != NULL) {
114  cpl_array_delete(aParams->line_strength);
115  cpl_array_delete(aParams->continuum);
116  muse_lsf_params_delete_one(aParams->lsf);
117  cpl_free(aParams);
118  }
119 }
120 
121 /*----------------------------------------------------------------------------*/
133 /*----------------------------------------------------------------------------*/
134 static muse_sky_master_params *
135 muse_sky_master_apply_sky_parametrization(const cpl_array *aPar,
136  cpl_size *offset,
137  int ngroups) {
138  muse_sky_master_params *p = muse_sky_master_params_new(ngroups, 0);
139 
140  int i;
141  for (i = 0; i < ngroups; i++) {
142  double s = (cpl_array_get(aPar, (*offset)++, NULL));
143  cpl_array_set(p->line_strength, i, s*s);
144  }
145  return p;
146 }
147 
148 /*----------------------------------------------------------------------------*/
158 /*----------------------------------------------------------------------------*/
159 static cpl_array *
160 muse_sky_master_sky_firstguess(int ngroups) {
161  cpl_array *pars = cpl_array_new(0 + ngroups, CPL_TYPE_DOUBLE);
162  cpl_size offset = 0;
163 
164  // Line strengths
165  int i;
166  for (i = 0; i < ngroups; i++) {
167  cpl_array_set(pars, offset++, 1e-1);
168  }
169 
170  if (offset != cpl_array_get_size(pars)) {
171  cpl_msg_error(__func__,
172  "inconsistent array: size %li; filled with %li values",
173  (long)cpl_array_get_size(pars), (long)offset);
174  }
175  return pars;
176 }
177 
178 /*----------------------------------------------------------------------------*/
189 /*----------------------------------------------------------------------------*/
190 static muse_lsf_params *
191 muse_sky_master_apply_lsf_parametrization(const cpl_array *aPar,
192  cpl_size *offset)
193 {
194  muse_lsf_params *lsf = muse_lsf_params_new(1, 3, 1);
195  cpl_array_set(lsf->sensitivity, 0, 1.0);
196  lsf->offset = cpl_array_get(aPar, (*offset)++, NULL);
197  lsf->refraction = 1.0 + cpl_array_get(aPar, (*offset)++, NULL);
198  cpl_array_set(lsf->lsf_width, 0,
199  cpl_array_get(aPar, (*offset)++, NULL));
200 #if 1
201  cpl_array_set(lsf->lsf_width, 1,
202  cpl_array_get(aPar, (*offset)++, NULL));
203  cpl_array_set(lsf->lsf_width, 2,
204  cpl_array_get(aPar, (*offset)++, NULL));
205 #endif
206  cpl_size i;
207  for (i = 0; i < MAX_HERMIT_ORDER; i++) {
208  cpl_array_set(lsf->hermit[i], 0,
209  cpl_array_get(aPar, (*offset)++, NULL));
210  }
211  return lsf;
212 }
213 
214 /*----------------------------------------------------------------------------*/
223 /*----------------------------------------------------------------------------*/
224 static cpl_array *
225 muse_sky_master_lsf_firstguess(void) {
226  cpl_array *pars = cpl_array_new(5 + MAX_HERMIT_ORDER, CPL_TYPE_DOUBLE);
227  cpl_size offset = 0;
228 
229  // wavelength calibration offset
230  cpl_array_set(pars, offset++, 0.0);
231  // Relative refraction - 1
232  cpl_array_set(pars, offset++, 0.0);
233 
234  // LSF width
235  cpl_array_set(pars, offset++, 1.0);
236 #if 1
237  cpl_array_set(pars, offset++, 0);
238  cpl_array_set(pars, offset++, 0);
239 #endif
240  // Hermitean coefficients
241  cpl_size i;
242  for (i = 0; i < MAX_HERMIT_ORDER; i++) {
243  cpl_array_set(pars, offset++, 0.0);
244  }
245  if (offset != cpl_array_get_size(pars)) {
246  cpl_msg_error(__func__,
247  "inconsistent array: size %ld, filled with %ld values",
248  (long)cpl_array_get_size(pars), (long)offset);
249  }
250  return pars;
251 }
252 
253 /*----------------------------------------------------------------------------*/
264 /*----------------------------------------------------------------------------*/
265 static muse_sky_master_params *
266 muse_sky_master_apply_parametrization(const cpl_array *aPar, int ngroups) {
267  cpl_size offset = 0;
268  muse_sky_master_params *p = muse_sky_master_apply_sky_parametrization(aPar, &offset,
269  ngroups);
270  p->lsf = muse_sky_master_apply_lsf_parametrization(aPar, &offset);
271 
272  if (offset != cpl_array_get_size(aPar)) {
273  cpl_msg_error(__func__,
274  "inconsistent array: size %ld, read with %ld values",
275  (long)cpl_array_get_size(aPar), (long)offset);
276  cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
277  muse_sky_master_params_delete(p);
278  return NULL;
279  }
280  return p;
281 }
282 
283 /*----------------------------------------------------------------------------*/
294 /*----------------------------------------------------------------------------*/
295 
296 static cpl_array *
297 simulate_master_sky_parameters(const cpl_table *aLines,
298  cpl_size aNgroups,
299  const cpl_array *aLambda,
300  const cpl_array *aPar) {
301  muse_sky_master_params *p
302  = muse_sky_master_apply_parametrization(aPar, aNgroups);
303 
304  cpl_array *continuum = cpl_array_duplicate(aLambda);
305  muse_cplarray_poly1d(continuum, p->continuum);
306 
307  cpl_table *lines = cpl_table_duplicate(aLines);
308  muse_sky_lines_apply_strength(lines, p->line_strength);
309  double maxflux = cpl_table_get_column_max(lines, "flux");
310  muse_sky_lines_cut(lines, 1e-4 * maxflux);
311 
312  cpl_array *simulated = muse_sky_apply_lsf(aLambda, lines, p->lsf);
313  cpl_array_add(simulated, continuum);
314 
315  cpl_array_delete(continuum);
316  cpl_table_delete(lines);
317  muse_sky_master_params_delete(p);
318  return simulated;
319 
320 }
321 
322 typedef struct {
323  const cpl_array *lambda; // wavelength
324  const cpl_array *values; // data values
325  const cpl_array *stat; // data statistics
326  const cpl_table *sky; // constant sky physics data
327  const cpl_size ngroups; // number of groups in the data
328 } muse_master_fit_struct;
329 
330 
331 /*----------------------------------------------------------------------------*/
340 /*----------------------------------------------------------------------------*/
341 static cpl_error_code
342 muse_sky_master_eval(void *aData, cpl_array *aPar, cpl_array *aRetval) {
343  cpl_size size = cpl_array_get_size(aRetval);
344  muse_master_fit_struct *data = aData;
345  cpl_array *simulated
346  = simulate_master_sky_parameters(data->sky, data->ngroups,
347  data->lambda, aPar);
348 
349  cpl_array_subtract(simulated, data->values);
350  cpl_array *dsimulated = muse_cplarray_diff(simulated, 1);
351  cpl_array_divide(dsimulated, data->stat);
352 
353  cpl_array_fill_window_double(aRetval, 0, size, 0.0);
354  memcpy(cpl_array_get_data_double(aRetval),
355  cpl_array_get_data_double_const(dsimulated),
356  size * sizeof(double));
357 
358  cpl_array_delete(simulated);
359  cpl_array_delete(dsimulated);
360 
361  return CPL_ERROR_NONE;
362 }
363 
364 /*----------------------------------------------------------------------------*/
381 /*----------------------------------------------------------------------------*/
382 
383 static cpl_error_code
384 muse_sky_master_correct_firstguess(const cpl_table *aLines,
385  cpl_size aNgroups,
386  const cpl_array *aLambda,
387  const cpl_array *aData,
388  cpl_array *aPars) {
389 
390  // evaluate the first guess
391  cpl_array *simulated
392  = simulate_master_sky_parameters(aLines, aNgroups, aLambda, aPars);
393 
394  cpl_size offset = 0;
395  muse_sky_master_params *msp
396  = muse_sky_master_apply_sky_parametrization(aPars, &offset, aNgroups);
397  cpl_table *lines = cpl_table_duplicate(aLines);
398  muse_sky_lines_apply_strength(lines, msp->line_strength);
399  muse_sky_master_params_delete(msp);
400  cpl_size i_group;
401  double delta = 0.0;
402  for (i_group = 0; i_group < aNgroups; i_group++) {
403  // take the strongest line of each group
404  cpl_table_unselect_all(lines);
405  cpl_table_or_selected_int(lines, "group", CPL_EQUAL_TO, i_group);
406  cpl_table *gtable = cpl_table_extract_selected(lines);
407  cpl_size row;
408  cpl_table_get_column_maxpos(gtable, "flux", &row);
409  double wavelength = cpl_table_get_double(gtable, "lambda", row, NULL);
410  cpl_table_delete(gtable);
411 
412  // divide measured data and first guess result
413  cpl_size i_lbda1 = muse_cplarray_find_sorted(aLambda, wavelength - 2.0);
414  cpl_size i_lbda2 = muse_cplarray_find_sorted(aLambda, wavelength + 2.0);
415  double y_data = 0;
416  double y_sim = 0;
417  double avg_data = 0;
418  double avg_sim = 0;
419  cpl_size i_lbda;
420  for (i_lbda = i_lbda1; i_lbda <= i_lbda2; i_lbda++) {
421  double lbda = cpl_array_get(aLambda, i_lbda, NULL);
422  double wy_data = cpl_array_get(aData, i_lbda, NULL);
423  double wy_sim = cpl_array_get(simulated, i_lbda, NULL);
424  y_data += wy_data;
425  avg_data += wy_data * lbda;
426  y_sim += wy_sim;
427  avg_sim += wy_sim * lbda;
428  }
429 
430  // take this as correction factor
431  if (y_sim > 0) {
432  cpl_array_set(aPars, i_group,
433  cpl_array_get(aPars, i_group, NULL)*sqrt(y_data/y_sim));
434  avg_data /= y_data;
435  avg_sim /= y_sim;
436  delta += avg_data - avg_sim;
437  }
438  }
439  cpl_array_set(aPars, aNgroups,
440  cpl_array_get(aPars, aNgroups, NULL) + delta/aNgroups);
441  cpl_table_delete(lines);
442  cpl_array_delete(simulated);
443 
444  return CPL_ERROR_NONE;
445 }
446 
447 /*----------------------------------------------------------------------------*/
462 /*----------------------------------------------------------------------------*/
464 muse_sky_master_fit(const cpl_array *aLambda, const cpl_array *aData,
465  const cpl_array *aStat, const cpl_table *aLines)
466 {
467  cpl_ensure(aLambda, CPL_ERROR_NULL_INPUT, NULL);
468  cpl_ensure(aData, CPL_ERROR_NULL_INPUT, NULL);
469  cpl_ensure(aStat, CPL_ERROR_NULL_INPUT, NULL);
470  cpl_ensure(aLines, CPL_ERROR_NULL_INPUT, NULL);
471 
472  cpl_size nstat = cpl_array_get_size(aStat);
473  cpl_ensure(nstat > 0, CPL_ERROR_DATA_NOT_FOUND, NULL);
474  cpl_array *stat = cpl_array_extract(aStat, 0, nstat - 1);
475  cpl_array *s2 = cpl_array_extract(aStat, 1, nstat);
476  cpl_array_add(stat, s2);
477  cpl_array_delete(s2);
478  cpl_array_power(stat, 0.5);
479 
480  muse_master_fit_struct data = {
481  aLambda,
482  aData,
483  stat,
484  aLines,
485  cpl_table_get_column_max(aLines, "group") + 1
486  };
487 
488  cpl_array *pars = muse_sky_master_sky_firstguess(data.ngroups);
489  cpl_array *dpars = muse_sky_master_lsf_firstguess();
490  cpl_array_insert(pars, dpars, cpl_array_get_size(pars));
491  cpl_array_delete(dpars);
492 
493  // run the correction twice: in the first run, mainly the offset for
494  // the wavelength is calculated. In the second step, the lines strengts
495  // are corrected with a better guess of the window (with the offset from
496  // the first step). Also the wavelength offset is corrected.
497  muse_sky_master_correct_firstguess(aLines, data.ngroups, aLambda, aData, pars);
498  muse_sky_master_correct_firstguess(aLines, data.ngroups, aLambda, aData, pars);
499  muse_sky_master_correct_firstguess(aLines, data.ngroups, aLambda, aData, pars);
500 
501  cpl_size size = cpl_array_get_size(aLambda);
502  // do the fit, ignoring possible errors
503  int debug = getenv("MUSE_DEBUG_LSF_FIT")
504  && atoi(getenv("MUSE_DEBUG_LSF_FIT")) > 0;
506  -1, -1, -1, -1, // default ftol, xtol, gtol, maxiter
507  debug
508  };
509  /* this potentially takes a long time, better output something */
510  cpl_msg_info(__func__, "Starting master sky fit");
511  cpl_error_code r = muse_cpl_optimize_lvmq(&data, pars, size-1,
512  muse_sky_master_eval, &ctrl);
513  if (r != CPL_ERROR_NONE) {
514  cpl_msg_error(__func__, "Master sky fit failed with error code %i: %s",
515  r, cpl_error_get_message());
516  } else {
517  cpl_msg_info(__func__, "Master sky fit finished successfully.");
518  }
519 
520  muse_sky_master_params *p = muse_sky_master_apply_parametrization(pars, data.ngroups);
521 
522  cpl_array_delete(pars);
523 
525  res->lines = cpl_table_duplicate(aLines);
526  muse_sky_lines_apply_strength(res->lines, p->line_strength);
527  cpl_propertylist *order = cpl_propertylist_new();
528 // cpl_propertylist_append_bool(order, "lambda", FALSE);
529  cpl_propertylist_append_bool(order, "flux", TRUE);
530  cpl_table_sort(res->lines, order);
531  cpl_propertylist_delete(order);
532 
533  cpl_array *continuum = muse_sky_apply_lsf(aLambda, res->lines, p->lsf);
534  cpl_msg_info(__func__, "refraction index=1%s%g, offset=%f Angstrom",
535  p->lsf->refraction < 1?"-":"+",
536  fabs(p->lsf->refraction-1), p->lsf->offset);
537 
538  cpl_array_subtract(continuum, aData);
539  cpl_array_multiply_scalar(continuum, -1);
540 
541  /*
542  * ::TODO::
543  * In the moment, the continuum is just calculated by subtracting
544  * the fitted line spectrum from the original spectrum. This is a
545  * source of errors since the original spectrum is created by many
546  * slices with different LSF parameters and also rebinned; so the
547  * subtraction contains a residual from rebinning artefacts.
548  *
549  * It would be much better if we would use the pixel table of the sky
550  * regions (created in muse_create_sky) and the slice-dependent LSF
551  * parameters to create a subtracted sky pixel table first, and then
552  * rebin this into the continuum spectrum.
553 
554  * This also makes the resolution of the continuum independent of
555  * the resolution for the fit; the later one could be largely
556  * reduced and optimized in a way that we have clear bins with lines
557  * and other bins that don't contain (many) lines, without edge
558  * problems. This would also eliminate the LSF parameter fit here
559  * Also we don't suffer from (small) wavelength calibration errors
560  * here. This all would make this fit faster and more stable.
561  */
563  cpl_array_get_size(aLambda));
564  muse_cpltable_copy_array(res->continuum, "lambda", aLambda);
565  muse_cpltable_copy_array(res->continuum, "flux", continuum);
566  cpl_array_delete(continuum);
567 
568  res->lsf = cpl_calloc(2, sizeof(muse_lsf_params));
569  res->lsf[0] = p->lsf;
570  p->lsf = NULL;
571 
572  cpl_array_delete(stat);
573  muse_sky_master_params_delete(p);
574 
575  return res;
576 }
577 
578 /*----------------------------------------------------------------------------*/
584 /*----------------------------------------------------------------------------*/
585 cpl_table *
587 {
588  cpl_ensure(aProcessing, CPL_ERROR_NULL_INPUT, NULL);
589 
590  /* search for frames with the SKY_CONTINUUM tag set */
591  cpl_frameset *frames_c = muse_frameset_find(aProcessing->inputFrames,
592  "SKY_CONTINUUM", 0, CPL_FALSE);
593  if (frames_c == NULL || cpl_frameset_get_size(frames_c) < 1) {
594  cpl_frameset_delete(frames_c);
595  return NULL;
596  }
597  cpl_frame *frame_c = cpl_frameset_get_position(frames_c, 0);
598  const char *fn = cpl_frame_get_filename(frame_c);
599  cpl_table *continuum = muse_cpltable_load(fn, "CONTINUUM",
601 
602  if (continuum == NULL) {
603  cpl_frameset_delete(frames_c);
604  return NULL;
605  }
606 
607  muse_processing_append_used(aProcessing, frame_c, CPL_FRAME_GROUP_CALIB, 1);
608  cpl_frameset_delete(frames_c);
609  return continuum;
610 } /* muse_processing_sky_continuum_load() */
611 
612 /*----------------------------------------------------------------------------*/
623 /*----------------------------------------------------------------------------*/
626 {
627  cpl_ensure(aProcessing, CPL_ERROR_NULL_INPUT, NULL);
628 
629  /* load the three different sky properties from the corresponding file */
631 
632  /* search for frames with the SKY_LINES tag set */
633  cpl_frameset *frames_l = muse_frameset_find(aProcessing->inputFrames,
634  "SKY_LINES", 0, CPL_FALSE);
635  if (cpl_frameset_get_size(frames_l) < 1) {
636  cpl_frameset_delete(frames_l);
638  return NULL;
639  }
640  cpl_frame *frame_l = cpl_frameset_get_position(frames_l, 0);
641  const char *fn = cpl_frame_get_filename(frame_l);
643 
644  /* search for frames with the SKY_CONTINUUM tag set */
645  cpl_frameset *frames_c = muse_frameset_find(aProcessing->inputFrames,
646  "SKY_CONTINUUM", 0, CPL_FALSE);
647  if (cpl_frameset_get_size(frames_c) < 1) {
648  cpl_frameset_delete(frames_c);
649  cpl_frameset_delete(frames_l);
651  return NULL;
652  }
653  cpl_frame *frame_c = cpl_frameset_get_position(frames_c, 0);
654  fn = cpl_frame_get_filename(frame_c);
655  sky->continuum = muse_cpltable_load(fn, "CONTINUUM", muse_fluxspectrum_def);
656 
657  /* search for frames with the LSF tag set */
658  cpl_frameset *frames_d = muse_frameset_find(aProcessing->inputFrames,
659  "LSF_TABLE", 0, CPL_FALSE);
660  cpl_size iframe, nframes = cpl_frameset_get_size(frames_d);
661  for (iframe = 0; iframe < nframes; iframe++) {
662  cpl_frame *frame_d = cpl_frameset_get_position(frames_d, iframe);
663  fn = cpl_frame_get_filename(frame_d);
664  sky->lsf = muse_lsf_params_load(fn, sky->lsf, 0);
665  } /* for iframe (all frames) */
666 
667  /* if not all could be loaded, clean up and return now */
668  if (!sky->lines || !sky->continuum || !sky->lsf) {
670  cpl_frameset_delete(frames_d);
671  cpl_frameset_delete(frames_c);
672  cpl_frameset_delete(frames_l);
673  return NULL;
674  }
675 
676  muse_processing_append_used(aProcessing, frame_l, CPL_FRAME_GROUP_CALIB, 1);
677  muse_processing_append_used(aProcessing, frame_c, CPL_FRAME_GROUP_CALIB, 1);
678  for (iframe = 0; iframe < nframes; iframe++) {
679  cpl_frame *frame_d = cpl_frameset_get_position(frames_d, iframe);
680  muse_processing_append_used(aProcessing, frame_d,
681  CPL_FRAME_GROUP_CALIB, 1);
682  } /* for iframe (all frames) */
683  cpl_frameset_delete(frames_l);
684  cpl_frameset_delete(frames_c);
685  cpl_frameset_delete(frames_d);
686 
687  return sky;
688 } /* muse_sky_master_load() */
689 
void muse_lsf_params_delete_one(muse_lsf_params *aParams)
Delete an allocated muse_lsf_params structure.
Definition: muse_lsf.c:128
cpl_error_code muse_sky_lines_apply_strength(cpl_table *, const cpl_array *)
Apply the line strengths to the lines.
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.
Structure to hold the MASTER SKY result.
Definition: muse_sky.h:59
const muse_cpltable_def muse_sky_lines_lines_def[]
cpl_error_code muse_cplarray_poly1d(cpl_array *aArray, const cpl_array *aCoeff)
Apply a polynomial to an array.
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).
cpl_table * muse_cpltable_new(const muse_cpltable_def *aDef, cpl_size aLength)
Create an empty table according to the specified definition.
cpl_array * hermit[MAX_HERMIT_ORDER]
coefficients for the damped gauss-hermitean parametrization
Definition: muse_lsf.h:67
cpl_table * muse_sky_continuum_load(muse_processing *aProcessing)
Load the SKY_CONTINUUM spectrum.
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.
Definition: muse_lsf.c:74
cpl_array * sensitivity
Relative detector sensitivity parametrization.
Definition: muse_lsf.h:59
cpl_array * lsf_width
LSF width.
Definition: muse_lsf.h:65
cpl_table * lines
Table of Atmospheric emission lines and their intensities.
Definition: muse_sky.h:63
Optimization control parameters.
Definition: muse_optimize.h:33
const muse_cpltable_def muse_fluxspectrum_def[]
Definition of the flux spectrum table structure.
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.
void muse_sky_master_delete(muse_sky_master *)
Delete a MASTER SKY structure.
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".
Definition: muse_lsf.c:308
muse_sky_master * muse_sky_master_fit(const cpl_array *aLambda, const cpl_array *aData, const cpl_array *aStat, const cpl_table *aLines)
Fit all entries of the pixel table to the master sky.
cpl_error_code muse_cpltable_copy_array(cpl_table *aTable, const char *aColumn, const cpl_array *aArray)
Copy an array into a table.
cpl_array * muse_cplarray_diff(const cpl_array *aArray, int aOffset)
Build the difference of any element and one of the next elements.
cpl_error_code muse_sky_lines_cut(cpl_table *, double)
Remove all lines below a certain flux limit.
muse_sky_master * muse_sky_master_load(muse_processing *aProcessing)
Load SKY_LINES, SKY_CONTINUUM, and LSF_TABLE into a structure.
cpl_array * muse_sky_apply_lsf(const cpl_array *, const cpl_table *, const muse_lsf_params *)
Apply the LSF parameters to a spectrum.
cpl_table * continuum
Continuum flux table
Definition: muse_sky.h:65
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
Definition: muse_utils.c:154
cpl_frameset * inputFrames
Structure definition of detector (slice) parameters.
Definition: muse_lsf.h:51
cpl_size muse_cplarray_find_sorted(const cpl_array *aArray, double aValue)
Find a row in an array.
muse_lsf_params ** lsf
LSF parameter for the resampled spectrum.
Definition: muse_sky.h:67
void muse_lsf_params_delete(muse_lsf_params **aParams)
Delete an allocated array of muse_lsf_params structure.
Definition: muse_lsf.c:147
muse_sky_master * muse_sky_master_new(void)
Create a muse_sky_master structure.