MUSE Pipeline Reference Manual  2.1.1
muse_scipost_subtract_sky.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) 2005-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 /*---------------------------------------------------------------------------*
27  * Includes *
28  *---------------------------------------------------------------------------*/
29 #include <muse.h>
30 #include "muse_scipost_subtract_sky_z.h"
31 
32 /*----------------------------------------------------------------------------*/
40 /*----------------------------------------------------------------------------*/
41 int
42 muse_scipost_subtract_sky_compute(muse_processing *aProcessing,
44 {
45  cpl_table *continuum = muse_sky_continuum_load(aProcessing);
46  cpl_table *lines = muse_sky_lines_load(aProcessing);
47  cpl_errorstate prestate = cpl_errorstate_get();
48  muse_lsf_cube **lsfCubes = NULL;
49 #ifdef USE_LSF_PARAMS
50  muse_lsf_params **lsfParams = NULL;
51 #endif
52  if (lines != NULL) {
53  lsfCubes = muse_lsf_cube_load_all(aProcessing);
54  if (lsfCubes == NULL) {
55 #ifdef USE_LSF_PARAMS
56  lsfParams = muse_processing_lsf_params_load(aProcessing, 0);
57  if (lsfParams == NULL) {
58 #endif
59  cpl_msg_error(__func__, "Could not load LSF");
60  cpl_table_delete(continuum);
61  cpl_table_delete(lines);
62  return CPL_ERROR_NULL_INPUT;
63 #ifdef USE_LSF_PARAMS
64  }
65  cpl_errorstate_set(prestate);
66 #endif
67  }
68  } else {
69  cpl_msg_warning(__func__, "Could not load sky lines");
70  }
71  cpl_frameset *inframes = muse_frameset_find_tags(aProcessing->inframes,
72  aProcessing->intags, 0,
73  CPL_FALSE);
74  cpl_error_code rc = CPL_ERROR_NONE;
75  cpl_size iframe, nframes = cpl_frameset_get_size(inframes);
76  for (iframe = 0; iframe < nframes; iframe++) {
77  cpl_frame *frame = cpl_frameset_get_position(inframes, iframe);
78  const char *fn = cpl_frame_get_filename(frame);
79  muse_pixtable *pixtable =
81  aParams->lambdamin,
82  aParams->lambdamax);
83  if (pixtable == NULL) {
84  cpl_msg_error(__func__, "NULL pixel table for %s", fn);
85  rc = CPL_ERROR_NULL_INPUT;
86  break;
87  }
88  muse_processing_append_used(aProcessing, frame, CPL_FRAME_GROUP_RAW, 1);
89 
90  /* erase pre-existing QC parameters */
91  cpl_propertylist_erase_regexp(pixtable->header, "ESO QC ", 0);
92  if (muse_pixtable_is_fluxcal(pixtable) != CPL_TRUE) {
93  cpl_msg_error(__func__, "Pixel table %s not flux calibrated",
94  cpl_frame_get_filename(frame));
95  muse_pixtable_delete(pixtable);
96  rc = CPL_ERROR_ILLEGAL_INPUT;
97  break;
98  }
99 
100  if (muse_pixtable_is_skysub(pixtable) == CPL_TRUE) {
101  cpl_msg_error(__func__, "Pixel table %s already sky subtracted",
102  cpl_frame_get_filename(frame));
103  muse_pixtable_delete(pixtable);
104  rc = CPL_ERROR_ILLEGAL_INPUT;
105  break;
106  }
107 
108  /* to fix the flux offset (using propagated flat-field fluxes) */
109  double fluxs = cpl_propertylist_get_double(pixtable->header,
110  MUSE_HDR_FLAT_FLUX_SKY);
111  double fluxl = cpl_propertylist_get_double(pixtable->header,
112  MUSE_HDR_FLAT_FLUX_LAMP);
113  cpl_errorstate_set(prestate); /* ignore errors here */
114 
115  if (aParams->orig != NULL) {
116  cpl_table_duplicate_column(pixtable->table, aParams->orig,
117  pixtable->table, MUSE_PIXTABLE_DATA);
118  }
119 
120  double scale = 1.;
121 
122  if (aParams->flux_sky > 0. && fluxs > 0.) { /* prefer sky flat flux scaling */
123  scale = fluxs / aParams->flux_sky;
124  cpl_msg_debug(__func__, "Scaling by SKY %e/%e = %f",
125  fluxs, aParams->flux_sky, scale);
126  } else if (aParams->flux_lamp > 0. && fluxl > 0.) {
127  scale = fluxl / aParams->flux_lamp;
128  cpl_msg_debug(__func__, "Scaling by LAMP %e/%e = %f",
129  fluxl, aParams->flux_lamp, scale);
130  }
131 
132  cpl_table_divide_scalar(pixtable->table, MUSE_PIXTABLE_DATA, scale);
133 
134  if (continuum != NULL) {
135  rc = muse_sky_subtract_continuum(pixtable, continuum);
136  }
137  if (rc != CPL_ERROR_NONE) {
138  cpl_msg_error(__func__, "while muse_sky_subtract_continuum(%s)",
139  cpl_frame_get_filename(frame));
140  muse_pixtable_delete(pixtable);
141  break;
142  }
143  if (lines != NULL) {
144  if (lsfCubes != NULL) {
145  rc = muse_sky_subtract_lines(pixtable, lines, lsfCubes);
146 #ifdef USE_LSF_PARAMS
147  } else if (lsfParams != NULL) {
148  rc = muse_sky_subtract_lines_old(pixtable, lines, lsfParams);
149 #endif
150  }
151  if (rc != CPL_ERROR_NONE) {
152  cpl_msg_error(__func__, "while muse_sky_subtract_lines(%s)",
153  cpl_frame_get_filename(frame));
154  muse_pixtable_delete(pixtable);
155  break;
156  }
157  }
158  cpl_table_multiply_scalar(pixtable->table, MUSE_PIXTABLE_DATA, scale);
159  if (pixtable->header) {
160  /* add the status header */
161  cpl_propertylist_update_bool(pixtable->header, MUSE_HDR_PT_SKYSUB,
162  CPL_TRUE);
163  cpl_propertylist_set_comment(pixtable->header, MUSE_HDR_PT_SKYSUB,
164  MUSE_HDR_PT_SKYSUB_COMMENT);
165  }
166  muse_processing_save_table(aProcessing, -1, pixtable, NULL,
167  MUSE_TAG_PIXTABLE_REDUCED,
169  muse_pixtable_delete(pixtable);
170  } /* for iframe (all input frames) */
171  cpl_frameset_delete(inframes);
172  cpl_table_delete(continuum);
173  cpl_table_delete(lines);
174  muse_lsf_cube_delete_all(lsfCubes);
175 
176  return cpl_error_get_code();
177 } /* muse_scipost_subtract_sky_compute() */
double lambdamin
Cut off the data below this wavelength after loading the pixel table(s).
const char * orig
If specified, write an additional column containing the original data to the pixel table...
cpl_table * muse_sky_lines_load(muse_processing *)
Load the sky data files.
Data cube/stacked image list containing the LSF for one IFU.
Definition: muse_lsf.h:49
cpl_table * table
The pixel table.
#define MUSE_PIXTABLE_DATA
Definition: muse_pixtable.h:48
cpl_boolean muse_pixtable_is_skysub(muse_pixtable *aPixtable)
Determine whether the pixel table is sky subtracted.
cpl_table * muse_sky_continuum_load(muse_processing *)
Load the sky continuum.
Structure definition of MUSE pixel table.
cpl_error_code muse_sky_subtract_lines_old(muse_pixtable *aPixtable, cpl_table *aLines, muse_lsf_params **aLsfParams)
Subtract sky lines from a pixtable.
Definition: muse_sky_old.c:532
double lambdamax
Cut off the data above this wavelength after loading the pixel table(s).
double flux_lamp
Reference flat field flux, obtained by lamp exposure. This parameter is needed to scale the data of e...
#define MUSE_HDR_PT_SKYSUB
cpl_boolean muse_pixtable_is_fluxcal(muse_pixtable *aPixtable)
Determine whether the pixel table is flux calibrated.
muse_lsf_cube ** muse_lsf_cube_load_all(muse_processing *aProcessing)
Load all LSF cubes for all IFUs into an array.
cpl_error_code muse_sky_subtract_continuum(muse_pixtable *, cpl_table *)
Subtract sky continuum from pixel table.
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.
Structure to hold the parameters of the muse_scipost_subtract_sky recipe.
muse_pixtable * muse_pixtable_load_restricted_wavelength(const char *aFilename, double aLambdaMin, double aLambdaMax)
Load a pixel table from file and cut down the wavelength range.
double flux_sky
Reference flat field flux, obtained by sky exposure. This parameter is needed to scale the data of ea...
cpl_array * intags
void muse_lsf_cube_delete_all(muse_lsf_cube **aLsfCube)
Delete all LSF cubes.
cpl_frameset * inframes
cpl_error_code muse_sky_subtract_lines(muse_pixtable *, cpl_table *, muse_lsf_cube **)
Subtract sky lines from a pixtable.
cpl_error_code muse_processing_save_table(muse_processing *aProcessing, int aIFU, void *aTable, cpl_propertylist *aHeader, const char *aTag, muse_table_type aType)
Save a computed table to disk.
muse_lsf_params ** muse_processing_lsf_params_load(muse_processing *aProcessing, int aIFU)
Load slice LSF parameters.
Structure definition of detector (slice) parameters.
void muse_pixtable_delete(muse_pixtable *aPixtable)
Deallocate memory associated to a pixel table object.
cpl_propertylist * header
The FITS header.
cpl_frameset * muse_frameset_find_tags(const cpl_frameset *aFrames, const cpl_array *aTags, unsigned char aIFU, cpl_boolean aInvert)
return frameset containing data from an IFU/channel with the given tag(s)
Definition: muse_utils.c:253