MUSE Pipeline Reference Manual  1.0.2
muse_sky_subtract.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 "muse_sky.h"
27 #include "muse_cplwrappers.h"
28 #include "muse_data_format_z.h"
29 
30 /*----------------------------------------------------------------------------*/
47 /*----------------------------------------------------------------------------*/
48 
51 /*----------------------------------------------------------------------------*/
61 /*----------------------------------------------------------------------------*/
62 static cpl_array *
63 muse_slice_get_skyspectrum(muse_pixtable *aPixtable, muse_sky_master *aMaster,
64  muse_lsf_params *aLsf)
65 {
66  cpl_array *lambda = NULL;
67  if (cpl_table_get_column_type(aPixtable->table, MUSE_PIXTABLE_LAMBDA)
68  == CPL_TYPE_DOUBLE) {
69  lambda = muse_cpltable_extract_column(aPixtable->table,
70  MUSE_PIXTABLE_LAMBDA);
71  } else {
72  cpl_table_cast_column(aPixtable->table, MUSE_PIXTABLE_LAMBDA,
73  "lambda_double", CPL_TYPE_DOUBLE);
74  lambda = muse_cpltable_extract_column(aPixtable->table, "lambda_double");
75  }
76 
77 
78  cpl_array *spectrum = NULL;
79  if ((aMaster->lines != NULL) && (aLsf != NULL)) {
80  spectrum = muse_sky_apply_lsf(lambda, aMaster->lines, aLsf);
81  } else {
82  spectrum = cpl_array_new(cpl_array_get_size(lambda), CPL_TYPE_DOUBLE);
83  cpl_array_fill_window(spectrum, 0, cpl_array_get_size(spectrum), 0.0);
84  }
85 
86  if (aMaster->continuum != NULL) {
87  cpl_array *continuum
89  "lambda", "flux");
90  cpl_array_add(spectrum, continuum);
91  cpl_array_delete(continuum);
92  }
93 
94  cpl_array_unwrap(lambda);
95  if (cpl_table_has_column(aPixtable->table, "lambda_double")) {
96  cpl_table_erase_column(aPixtable->table, "lambda_double");
97  }
98 
99  return spectrum;
100 }
101 
102 /*----------------------------------------------------------------------------*/
113 /*----------------------------------------------------------------------------*/
114 cpl_error_code
116  muse_lsf_params *aLsf)
117 {
118  cpl_propertylist *order = cpl_propertylist_new();
119  cpl_propertylist_append_bool(order, MUSE_PIXTABLE_LAMBDA, CPL_FALSE);
120  cpl_table_sort(aPixtable->table, order);
121  cpl_propertylist_delete(order);
122 
123  cpl_array *spectrum = muse_slice_get_skyspectrum(aPixtable, aMaster, aLsf);
124 
125  cpl_array *data = muse_cpltable_extract_column(aPixtable->table,
126  MUSE_PIXTABLE_DATA);
127  cpl_array_subtract(data, spectrum);
128 
129  cpl_size ii;
130  for (ii = 0; ii < cpl_array_get_size(data); ii++) {
131  if (!cpl_array_is_valid(spectrum, ii)) {
132  cpl_table_set_invalid(aPixtable->table, MUSE_PIXTABLE_DATA, ii);
133  }
134  }
135  cpl_array_unwrap(data);
136  cpl_array_delete(spectrum);
137 
138 
139  return CPL_ERROR_NONE;
140 }
141 
142 /*----------------------------------------------------------------------------*/
157 /*----------------------------------------------------------------------------*/
158 cpl_error_code
160  muse_lsf_params **aLsf)
161 {
162  cpl_ensure_code(aPixtable != NULL, CPL_ERROR_NULL_INPUT);
163  cpl_ensure_code(aPixtable->table != NULL, CPL_ERROR_NULL_INPUT);
164  cpl_ensure_code(muse_cpltable_check(aPixtable->table, muse_pixtable_def) == CPL_ERROR_NONE,
165  CPL_ERROR_DATA_NOT_FOUND);
166  cpl_ensure_code(aMaster != NULL, CPL_ERROR_NULL_INPUT);
167  if ((aMaster->lines == NULL) && (aMaster->continuum == NULL)) {
168  return CPL_ERROR_NONE;
169  }
170  if (aMaster->lines != NULL) {
171  cpl_ensure_code(aLsf != NULL, CPL_ERROR_NULL_INPUT);
172  }
173 
174  if (aMaster->continuum != NULL) {
175  /* cut input pixel table to the length of the continuum in the sky master */
176  double lmin = cpl_table_get_column_min(aMaster->continuum, "lambda"),
177  lmax = cpl_table_get_column_max(aMaster->continuum, "lambda");
178  cpl_msg_info(__func__, "Cutting data to %.3f...%.3f Angstrom for sky "
179  "subtraction (range of continuum)", lmin, lmax);
180  muse_pixtable_restrict_wavelength(aPixtable, lmin, lmax);
181  }
182 
183  muse_pixtable **slice_pixtable = muse_pixtable_extracted_get_slices(aPixtable);
184  cpl_size n_slices = muse_pixtable_extracted_get_size(slice_pixtable);
185  cpl_size i_slice;
186  cpl_msg_info(__func__, "Starting sky subtraction of %"CPL_SIZE_FORMAT" slices",
187  n_slices);
188  #pragma omp parallel for default(none) /* as req. by Ralf */ \
189  shared(aLsf, aMaster, n_slices, slice_pixtable)
190  for (i_slice = 0; i_slice < n_slices; i_slice++) {
191  uint32_t origin
192  = (uint32_t)cpl_table_get_int(slice_pixtable[i_slice]->table,
193  MUSE_PIXTABLE_ORIGIN, 0, NULL);
194  int ifu = muse_pixtable_origin_get_ifu(origin);
195  int slice = muse_pixtable_origin_get_slice(origin);
196  muse_lsf_params *slice_params = muse_lsf_params_get(aLsf, ifu, slice);
197  if ((slice_params == NULL) && (aMaster->lines != NULL)){
198  cpl_msg_warning(__func__, "No LSF params for slice #%i.%i."
199  " Ignoring lines in sky subtraction for this slice.",
200  ifu, slice);
201  }
202 
203  cpl_size nrows = muse_pixtable_get_nrow(slice_pixtable[i_slice]);
204  cpl_msg_debug(__func__, "Sky subtraction of %li pixels for slice #%i.%i",
205  (long)nrows, ifu, slice);
206  cpl_errorstate prestate = cpl_errorstate_get();
207  muse_sky_subtract_slice(slice_pixtable[i_slice], aMaster, slice_params);
208  if (!cpl_errorstate_is_equal(prestate)) {
209  cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
210  cpl_errorstate_set(prestate);
211  }
212  }
213  muse_pixtable_extracted_delete(slice_pixtable);
214 
215  if (aPixtable->header) {
216  /* add the status header */
217  cpl_propertylist_update_bool(aPixtable->header, MUSE_HDR_PT_SKYSUB,
218  CPL_TRUE);
219  cpl_propertylist_set_comment(aPixtable->header, MUSE_HDR_PT_SKYSUB,
220  MUSE_HDR_PT_SKYSUB_COMMENT);
221  }
222  return CPL_ERROR_NONE;
223 }
224 
cpl_array * muse_cplarray_interpolate_table_linear(const cpl_array *aTargetAbscissa, const cpl_table *aSrcTable, const char *aSrcAbscissa, const char *aSrcOrdinate)
Linear interpolation of a 1d column.
void muse_pixtable_extracted_delete(muse_pixtable **aPixtables)
Delete a pixel table array.
unsigned short muse_pixtable_origin_get_slice(uint32_t aOrigin)
Get the slice number from the encoded 32bit origin number.
cpl_size muse_pixtable_extracted_get_size(muse_pixtable **aPixtables)
Get the size of an array of extracted pixel tables.
muse_pixtable ** muse_pixtable_extracted_get_slices(muse_pixtable *aPixtable)
Extract one pixel table per IFU and slice.
cpl_size muse_pixtable_get_nrow(const muse_pixtable *aPixtable)
get the number of rows within the pixel table
Structure to hold the MASTER SKY result.
Definition: muse_sky.h:57
muse_lsf_params * muse_lsf_params_get(muse_lsf_params **aParams, int aIFU, int aSlice)
Get the slice LSF parameters for one slice.
cpl_table * table
The pixel table.
cpl_error_code muse_cpltable_check(const cpl_table *aTable, const muse_cpltable_def *aDef)
Check whether the table contains the fields of the definition.
cpl_error_code muse_pixtable_restrict_wavelength(muse_pixtable *aPixtable, double aLow, double aHigh)
Restrict a pixel table to a certain wavelength range.
Structure definition of MUSE pixel table.
cpl_array * muse_cpltable_extract_column(cpl_table *aTable, const char *aColumn)
Create an array from a section of a column.
cpl_table * lines
Table of Atmospheric emission lines and their intensities.
Definition: muse_sky.h:61
#define MUSE_HDR_PT_SKYSUB
unsigned short muse_pixtable_origin_get_ifu(uint32_t aOrigin)
Get the IFU number from the encoded 32bit origin number.
const muse_cpltable_def muse_pixtable_def[]
MUSE pixel table definition.
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:63
Structure definition of detector (slice) parameters.
Definition: muse_lsf.h:50
cpl_error_code muse_sky_subtract_pixtable(muse_pixtable *aPixtable, muse_sky_master *aMaster, muse_lsf_params **aLsf)
Subtract the sky spectrum from the "data" column of a pixel table.
cpl_error_code muse_sky_subtract_slice(muse_pixtable *aPixtable, muse_sky_master *aMaster, muse_lsf_params *aLsf)
Subtract the sky spectrum from the "data" column of a pixel table for one slice.
cpl_propertylist * header
The FITS header.