MUSE Pipeline Reference Manual  1.0.2
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 /*---------------------------------------------------------------------------*
33  * Functions code *
34  *---------------------------------------------------------------------------*/
35 
36 /*----------------------------------------------------------------------------*/
44 /*----------------------------------------------------------------------------*/
45 int
46 muse_scipost_subtract_sky_compute(muse_processing *aProcessing,
48 {
49  muse_sky_master *sky = muse_sky_master_load(aProcessing);
50  if (!sky) {
51  cpl_msg_error(__func__, "Could not load sky files");
52  return CPL_ERROR_NULL_INPUT;
53  }
54 
55  cpl_frameset *inframes = muse_frameset_find_tags(aProcessing->inframes,
56  aProcessing->intags, 0,
57  CPL_FALSE);
58  cpl_error_code rc = CPL_ERROR_NONE;
59  cpl_size iframe, nframes = cpl_frameset_get_size(inframes);
60  for (iframe = 0; iframe < nframes; iframe++) {
61  cpl_frame *frame = cpl_frameset_get_position(inframes, iframe);
62  const char *fn = cpl_frame_get_filename(frame);
63  muse_pixtable *pixtable =
65  aParams->lambdamin,
66  aParams->lambdamax);
67  if (pixtable == NULL) {
68  cpl_msg_error(__func__, "NULL pixel table for %s", fn);
69  rc = CPL_ERROR_NULL_INPUT;
70  break;
71  }
72  muse_processing_append_used(aProcessing, frame, CPL_FRAME_GROUP_RAW, 1);
73 
74  /* erase pre-existing QC parameters */
75  cpl_propertylist_erase_regexp(pixtable->header, "ESO QC ", 0);
76  if (muse_pixtable_is_fluxcal(pixtable) != CPL_TRUE) {
77  cpl_msg_error(__func__, "Pixel table %s not flux calibrated, cannot "
78  "subtract sky!", cpl_frame_get_filename(frame));
79  muse_pixtable_delete(pixtable);
80  rc = CPL_ERROR_ILLEGAL_INPUT;
81  break;
82  }
83 
84  if (muse_pixtable_is_skysub(pixtable) == CPL_TRUE) {
85  cpl_msg_error(__func__, "Pixel table %s already sky subtracted",
86  cpl_frame_get_filename(frame));
87  muse_pixtable_delete(pixtable);
88  rc = CPL_ERROR_ILLEGAL_INPUT;
89  break;
90  }
91 
92  /* to fix the flux offset (using propagated flat-field fluxes) */
93  cpl_errorstate prestate = cpl_errorstate_get();
94  double fluxs = cpl_propertylist_get_double(pixtable->header,
95  MUSE_HDR_FLAT_FLUX_SKY);
96  double fluxl = cpl_propertylist_get_double(pixtable->header,
97  MUSE_HDR_FLAT_FLUX_LAMP);
98  cpl_errorstate_set(prestate); /* ignore errors here */
99 
100  if (aParams->orig != NULL) {
101  cpl_table_duplicate_column(pixtable->table, aParams->orig,
102  pixtable->table, MUSE_PIXTABLE_DATA);
103  }
104 
105  double scale = 1.;
106 
107  if (aParams->flux_sky > 0. && fluxs > 0.) { /* prefer sky flat flux scaling */
108  scale = fluxs / aParams->flux_sky;
109  cpl_msg_debug(__func__, "Scaling by SKY %e/%e = %f",
110  fluxs, aParams->flux_sky, scale);
111  } else if (aParams->flux_lamp > 0. && fluxl > 0.) {
112  scale = fluxl / aParams->flux_lamp;
113  cpl_msg_debug(__func__, "Scaling by LAMP %e/%e = %f",
114  fluxl, aParams->flux_lamp, scale);
115  }
116 
117  cpl_table_divide_scalar(pixtable->table, MUSE_PIXTABLE_DATA, scale);
118 
119 
120  rc = muse_sky_subtract_pixtable(pixtable, sky, sky->lsf);
121  if (rc != CPL_ERROR_NONE) {
122  cpl_msg_error(__func__, "while muse_sky_subtract_pixtable(%s)",
123  cpl_frame_get_filename(frame));
124  muse_pixtable_delete(pixtable);
125  break;
126  }
127  cpl_table_multiply_scalar(pixtable->table, MUSE_PIXTABLE_DATA, scale);
128  if (pixtable->header) {
129  /* add the status header */
130  cpl_propertylist_update_bool(pixtable->header, MUSE_HDR_PT_SKYSUB,
131  CPL_TRUE);
132  cpl_propertylist_set_comment(pixtable->header, MUSE_HDR_PT_SKYSUB,
133  MUSE_HDR_PT_SKYSUB_COMMENT);
134  }
135  muse_processing_save_table(aProcessing, -1, pixtable, NULL,
136  MUSE_TAG_PIXTABLE_REDUCED,
138  muse_pixtable_delete(pixtable);
139  } /* for iframe (all input frames) */
140  cpl_frameset_delete(inframes);
142 
143  return cpl_error_get_code();
144 } /* 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...
Structure to hold the MASTER SKY result.
Definition: muse_sky.h:57
cpl_table * table
The pixel table.
cpl_boolean muse_pixtable_is_skysub(muse_pixtable *aPixtable)
Determine whether the pixel table is sky subtracted.
Structure definition of MUSE pixel table.
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.
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.
void muse_sky_master_delete(muse_sky_master *)
Delete a MASTER SKY structure.
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
cpl_frameset * inframes
muse_sky_master * muse_sky_master_load(muse_processing *)
Load SKY_LINES, SKY_CONTINUUM, and LSF_PROFILE into a structure.
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.
void muse_pixtable_delete(muse_pixtable *aPixtable)
Deallocate memory associated to a pixel table object.
cpl_error_code muse_sky_subtract_pixtable(muse_pixtable *a, muse_sky_master *, muse_lsf_params **)
Subtract the sky spectrum from the "data" column of a pixel table.
muse_lsf_params ** lsf
LSF parameter for the resampled spectrum.
Definition: muse_sky.h:65
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:243