MUSE Pipeline Reference Manual  1.0.2
muse_scipost.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 <string.h>
30 
31 #include <muse.h>
32 #include "muse_scipost_z.h"
33 
34 /*---------------------------------------------------------------------------*
35  * Functions code *
36  *---------------------------------------------------------------------------*/
37 
38 /*----------------------------------------------------------------------------*/
54 /*----------------------------------------------------------------------------*/
55 int
56 muse_scipost_compute(muse_processing *aProcessing,
57  muse_scipost_params_t *aParams)
58 {
59  const char *savevalid = "cube,skymodel,individual,positioned,combined,stacked";
60  if (!muse_postproc_check_save_param(aParams->save, savevalid)) {
61  return -1;
62  }
63  muse_postproc_properties *prop = muse_postproc_properties_new(MUSE_POSTPROC_SCIPOST);
64  /* per-exposure parameters */
65  prop->lambdamin = aParams->lambdamin;
66  prop->lambdamax = aParams->lambdamax;
67  prop->lambdaref = aParams->lambdaref;
68  prop->darcheck = MUSE_POSTPROC_DARCHECK_NONE;
69  if (aParams->darcheck == MUSE_SCIPOST_PARAM_DARCHECK_CHECK) {
70  prop->darcheck = MUSE_POSTPROC_DARCHECK_CHECK;
71  } else if (aParams->darcheck == MUSE_SCIPOST_PARAM_DARCHECK_CORRECT) {
72  prop->darcheck = MUSE_POSTPROC_DARCHECK_CORRECT;
73  }
74  prop->rvtype = muse_rvcorrect_select_type(aParams->rvcorr_s);
75  /* flux calibration */
76  prop->response = muse_table_load(aProcessing, MUSE_TAG_STD_RESPONSE, 0);
77  prop->extinction = muse_table_load(aProcessing, MUSE_TAG_EXTINCT_TABLE, 0);
78  prop->telluric = muse_table_load(aProcessing, MUSE_TAG_STD_TELLURIC, 0);
79  /* astrometric correction */
80  if (aParams->astrometry) {
81  prop->wcs = muse_propertylist_load(aProcessing, MUSE_TAG_ASTROMETRY_WCS);
82  if (!prop->wcs) {
83  /* if it was not in the input, create a default WFM astrometry */
84  cpl_msg_warning(__func__, "Using default MUSE WFM astrometry, output "
85  "world coordinates will be inaccurate!");
86  prop->wcs = muse_wcs_create_default();
87  }
88  }
89 
90  const struct {
91  int par;
92  muse_postproc_skymethod postproc;
93  } skymethod[] = {
94  { MUSE_SCIPOST_PARAM_SKYMETHOD_NONE, MUSE_POSTPROC_SKYMETHOD_NONE },
95  { MUSE_SCIPOST_PARAM_SKYMETHOD_SUBTRACT_MODEL, MUSE_POSTPROC_SKYMETHOD_NONE }, /* sic! */
96  { MUSE_SCIPOST_PARAM_SKYMETHOD_MODEL, MUSE_POSTPROC_SKYMETHOD_MODEL },
97  /* { MUSE_SCIPOST_PARAM_SKYMETHOD_ROW_BY_ROW, MUSE_POSTPROC_SKYMETHOD_ROWBYROW }, */
98  { MUSE_SCIPOST_PARAM_SKYMETHOD_INVALID_VALUE, MUSE_POSTPROC_SKYMETHOD_MODEL },
99  };
100  prop->skymethod = MUSE_POSTPROC_SKYMETHOD_MODEL;
101  int i_method;
102  for (i_method = 0;
103  skymethod[i_method].par != MUSE_SCIPOST_PARAM_SKYMETHOD_INVALID_VALUE;
104  i_method++) {
105  if (skymethod[i_method].par == aParams->skymethod) {
106  prop->skymethod = skymethod[i_method].postproc;
107  break;
108  }
109  }
110  prop->skymodel_params.fraction = aParams->skymodel_fraction;
111  prop->skymodel_params.sampling = aParams->skymodel_sampling;
112  prop->skymodel_params.csampling = aParams->skymodel_csampling;
113 
114  prop->sky = muse_sky_master_new();
115  if (aParams->skymethod == MUSE_SCIPOST_PARAM_SKYMETHOD_SUBTRACT_MODEL) {
116  prop->sky->lsf = muse_processing_lsf_params_load(aProcessing, 0);
117  if (prop->sky->lsf != NULL) {
118  prop->sky->lines = muse_sky_lines_load(aProcessing);
119  if (prop->sky->lines == NULL) {
120  cpl_msg_warning(__func__, "Sky lines missing for subtraction");
121  }
122  }
123  prop->sky->continuum = muse_sky_continuum_load(aProcessing);
124  } else if (aParams->skymethod == MUSE_SCIPOST_PARAM_SKYMETHOD_MODEL) {
125  prop->sky->lsf = muse_processing_lsf_params_load(aProcessing, 0);
126  if (prop->sky->lsf == NULL) {
127  cpl_msg_error(__func__, "Missing required LSF parameter frames for sky model");
128  }
129  prop->sky->lines = muse_sky_lines_load(aProcessing);
130  if (prop->sky->lines == NULL) {
131  cpl_msg_error(__func__, "Missing required sky lines frame for sky model");
132  }
133  if ((prop->sky->lsf == NULL) || (prop->sky->lines == NULL)) {
135  return -1;
136  }
137  prop->sky->continuum = muse_sky_continuum_load(aProcessing);
138  prop->sky_mask = muse_processing_mask_load(aProcessing, MUSE_TAG_SKY_MASK);
139  }
140 
141  /* sort input pixel tables into different exposures */
142  prop->exposures = muse_processing_sort_exposures(aProcessing);
143  if (!prop->exposures) {
144  cpl_msg_error(__func__, "no science exposures found in input");
146  return -1;
147  }
148  int nexposures = cpl_table_get_nrow(prop->exposures);
149 
150  /* now process all the pixel tables, do it separately for each exposure */
151  /* allocate one additional element for NULL termination */
152  muse_pixtable **pixtables = cpl_calloc(nexposures + 1, sizeof(muse_pixtable *));
153  int i;
154  for (i = 0; i < nexposures; i++) {
155  muse_postproc_sky_outputs *skyout = cpl_calloc(1, sizeof(muse_postproc_sky_outputs));
156  pixtables[i] = muse_postproc_process_exposure(prop, i, skyout);
157  if (!pixtables[i]) {
158  int i2;
159  for (i2 = 0; i2 <= i; i2++) {
160  muse_pixtable_delete(pixtables[i2]);
161  } /* for i2 */
162  cpl_free(pixtables);
164  return -1; /* enough error messages, just return */
165  }
166  /* save the effectively used sky products, if requested */
167  if (strstr(aParams->save, "skymodel")) {
168  if (skyout->mask) {
169  muse_processing_save_mask(aProcessing, -1, skyout->mask, MUSE_TAG_SKY_MASK);
170  }
171  if (skyout->spectrum) {
172  cpl_propertylist *header = cpl_propertylist_duplicate(pixtables[i]->header);
173  cpl_propertylist_erase_regexp(header, MUSE_HDR_PT_REGEXP, 0);
174  muse_processing_save_table(aProcessing, -1, skyout->spectrum, header,
175  MUSE_TAG_SKY_SPECTRUM, MUSE_TABLE_TYPE_CPL);
176  cpl_propertylist_delete(header);
177  }
178  if (skyout->lines) {
179  cpl_propertylist *header = cpl_propertylist_duplicate(pixtables[i]->header);
180  cpl_propertylist_erase_regexp(header, MUSE_HDR_PT_REGEXP, 0);
181  muse_sky_qc_lines(header, skyout->lines, "ESO QC SCIPOST");
182  muse_sky_lines_save(aProcessing, skyout->lines, header);
183  cpl_propertylist_delete(header);
184  }
185  if (skyout->continuum) {
186  cpl_propertylist *header = cpl_propertylist_duplicate(pixtables[i]->header);
187  cpl_propertylist_erase_regexp(header, MUSE_HDR_PT_REGEXP, 0);
188  muse_sky_qc_continuum(header, skyout->continuum, "ESO QC SCIPOST");
189  muse_sky_save_continuum(aProcessing, skyout->continuum, header);
190  cpl_propertylist_delete(header);
191  }
192  }
193  muse_mask_delete(skyout->mask);
194  cpl_table_delete(skyout->spectrum);
195  cpl_table_delete(skyout->lines);
196  cpl_table_delete(skyout->continuum);
197  cpl_free(skyout);
198 
199  if (strstr(aParams->save, "individual")) {
200  muse_processing_save_table(aProcessing, -1, pixtables[i], NULL,
201  MUSE_TAG_PIXTABLE_REDUCED,
203  }
204  if (strstr(aParams->save, "positioned")) {
205  /* duplicate table to not mess with the coordinates in the individual *
206  * pixel tables, which are still needed when combining the exposures */
207  muse_pixtable *pt = muse_pixtable_duplicate(pixtables[i]);
208  double ra = muse_pfits_get_ra(pt->header),
209  dec = muse_pfits_get_dec(pt->header);
210  muse_wcs_position_celestial(pt, ra, dec);
211  muse_processing_save_table(aProcessing, -1, pt, NULL,
212  MUSE_TAG_PIXTABLE_POSITIONED,
215  }
216  } /* for i (exposures) */
218 
219  /* now combine the possibly more than one exposures */
220  muse_pixtable *bigpixtable = NULL;
221  if (nexposures > 1) {
223  cpl_error_code rc = muse_xcombine_weights(pixtables, weight);
224  if (rc != CPL_ERROR_NONE) {
225  cpl_msg_error(__func__, "weighting the pixel tables didn't work: %s",
226  cpl_error_get_message());
227  for (i = 0; i < nexposures; i++) {
228  muse_pixtable_delete(pixtables[i]);
229  } /* for i (exposures) */
230  cpl_free(pixtables);
231  return -1;
232  }
233  /* combine individual pixel tables and delete them */
234  bigpixtable = muse_xcombine_tables(pixtables);
235  if (!bigpixtable) {
236  cpl_msg_error(__func__, "combining the pixel tables didn't work: %s",
237  cpl_error_get_message());
238  for (i = 0; i < nexposures; i++) {
239  muse_pixtable_delete(pixtables[i]);
240  } /* for i (exposures) */
241  cpl_free(pixtables);
242  return -1;
243  }
244  } else {
245  bigpixtable = pixtables[0];
246  muse_wcs_position_celestial(bigpixtable,
247  muse_pfits_get_ra(bigpixtable->header),
248  muse_pfits_get_dec(bigpixtable->header));
249  }
250  cpl_free(pixtables);
251 
252  cpl_error_code rc = CPL_ERROR_NONE;
253  if (strstr(aParams->save, "cube")) {
254  muse_resampling_type resample
257  rp->dx = aParams->dx;
258  rp->dy = aParams->dy;
259  rp->dlambda = aParams->dlambda;
260  rp->crtype = muse_postproc_get_cr_type(aParams->crtype_s);
261  rp->crsigma = aParams->crsigma;
262  rp->ld = aParams->ld;
263  rp->rc = aParams->rc;
264  rp->pfx = aParams->pixfrac;
265  rp->pfy = aParams->pixfrac;
266  rp->pfl = aParams->pixfrac;
267  cpl_propertylist *outwcs = muse_postproc_cube_load_output_wcs(aProcessing);
268  muse_resampling_params_set_wcs(rp, outwcs);
269  cpl_propertylist_delete(outwcs);
271  rc = muse_postproc_cube_resample_and_collapse(aProcessing, bigpixtable,
272  format, rp, aParams->filter);
274  } /* if save contains cube */
275  if (strstr(aParams->save, "combined")) {
276  muse_processing_save_table(aProcessing, -1, bigpixtable, NULL,
277  MUSE_TAG_PIXTABLE_COMBINED,
279  }
280  if (strstr(aParams->save, "stacked")) {
281  cpl_msg_debug(__func__, "additional output as column-stacked image");
282  muse_image *img = muse_resampling_image(bigpixtable,
284  aParams->dx, aParams->dlambda);
285  muse_processing_save_image(aProcessing, -1, img, MUSE_TAG_OBJECT_RESAMPLED);
286  muse_image_delete(img);
287  }
288 
289  muse_pixtable_delete(bigpixtable);
290 
291  /* the cube is normally the main output, check only its return code */
292  return rc == CPL_ERROR_NONE ? 0 : -1;
293 } /* muse_scipost_compute() */
muse_rvcorrect_type rvtype
Definition: muse_postproc.h:96
muse_image * muse_resampling_image(muse_pixtable *aPixtable, muse_resampling_type aMethod, double aDX, double aDLambda)
Resample a pixel table onto a two-dimensional regular grid.
cpl_propertylist * muse_postproc_cube_load_output_wcs(muse_processing *aProcessing)
Find a file with a usable output WCS in the input frameset.
muse_postproc_properties * muse_postproc_properties_new(muse_postproc_type aType)
Create a post-processing properties object.
Definition: muse_postproc.c:67
muse_postproc_skymethod
Method of sky subtraction to apply.
Definition: muse_postproc.h:67
void muse_image_delete(muse_image *aImage)
Deallocate memory associated to a muse_image object.
Definition: muse_image.c:85
double lambdamin
Cut off the data below this wavelength after loading the pixel table(s).
muse_pixtable * muse_pixtable_duplicate(muse_pixtable *aPixtable)
Make a copy of the pixtanle.
int muse_processing_save_mask(muse_processing *aProcessing, int aIFU, muse_mask *aMask, const char *aTag)
Save a computed MUSE mask to disk.
double muse_pfits_get_ra(const cpl_propertylist *aHeaders)
find out the right ascension
Definition: muse_pfits.c:232
cpl_error_code muse_resampling_params_set_wcs(muse_resampling_params *aParams, const cpl_propertylist *aWCS)
Set an output WCS (and wavelength scale) in the resampling parameters.
cpl_error_code muse_sky_lines_save(muse_processing *, const cpl_table *, cpl_propertylist *)
Save sky lines table to file.
muse_xcombine_types muse_postproc_get_weight_type(const char *aWeightString)
Select correct weighting type for weight string.
cpl_table * muse_sky_lines_load(muse_processing *)
Load the sky data files.
muse_resampling_crstats_type muse_postproc_get_cr_type(const char *aCRTypeString)
Select correct cosmic ray rejection type for crtype string.
int ld
Number of adjacent pixels to take into account during resampling in all three directions (loop distan...
const char * rvcorr_s
Correct the radial velocity of the telescope with reference to either the barycenter of the Solar Sys...
muse_rvcorrect_type muse_rvcorrect_select_type(const char *aTypeString)
Select type of radial velocity correction to be done from type string.
void muse_sky_qc_lines(cpl_propertylist *, cpl_table *, const char *)
Fill a header with the QC parameters for the sky lines.
Definition: muse_sky_qc.c:46
void * muse_postproc_process_exposure(muse_postproc_properties *aProp, unsigned int aIndex, muse_postproc_sky_outputs *aSkyOut)
Merge and process pixel tables from one exposure.
Structure definition of MUSE three extension FITS file.
Definition: muse_image.h:40
cpl_error_code muse_postproc_cube_resample_and_collapse(muse_processing *aProcessing, muse_pixtable *aPixtable, muse_cube_type aFormat, muse_resampling_params *aParams, const char *aFilter)
High level function to resample to a datacube and collapse that to an image of the field of view and ...
muse_mask * muse_processing_mask_load(muse_processing *aProcessing, const char *aTag)
Load a mask file and its FITS header.
cpl_error_code muse_xcombine_weights(muse_pixtable **aPixtables, muse_xcombine_types aWeighting)
compute the weights for combination of two or more exposures
Definition: muse_xcombine.c:81
muse_postproc_skymethod skymethod
const char * filter
The filter name(s) to be used for the output field-of-view image. Each name has to correspond to an E...
muse_resampling_crstats_type crtype
void muse_sky_qc_continuum(cpl_propertylist *, cpl_table *, const char *)
Fill a header with the QC parameters for the sky continuum.
Definition: muse_sky_qc.c:102
const char * weight_s
Type of weighting scheme to use when combining multiple exposures. "exptime" just uses the exposure t...
cpl_table * muse_sky_continuum_load(muse_processing *)
Load the SKY_CONTINUUM spectrum.
Structure definition of MUSE pixel table.
muse_cube_type muse_postproc_get_cube_format(const char *aFormatString)
Select correct cube format for format string.
double dy
Vertical step size for resampling (in arcsec or pixel). The following defaults are taken when this va...
cpl_boolean muse_postproc_check_save_param(const char *aSave, const char *aValid)
Check the –save parameter contents against allowed options.
cpl_table * lines
Table of Atmospheric emission lines and their intensities.
Definition: muse_sky.h:61
muse_resampling_params * muse_resampling_params_new(muse_resampling_type aMethod)
Create the resampling parameters structure.
double pixfrac
Pixel down-scaling factor for the "drizzle" resampling method.
double lambdaref
Reference wavelength used for correction of differential atmospheric refraction. The R-band (peak wav...
double rc
Critical radius for the "renka" resampling method.
muse_cube_type
cpl_propertylist * wcs
Structure definition of the post-processing properties.
Definition: muse_postproc.h:89
double skymodel_fraction
Fraction of the image to be considered as sky. If an input sky mask is provided, the fraction is appl...
void muse_postproc_properties_delete(muse_postproc_properties *aProp)
Free memory taken by a post-processing properties object and all its components.
Definition: muse_postproc.c:94
const char * crtype_s
Type of statistics used for detection of cosmic rays during final resampling. "iraf" uses the varianc...
int darcheck
Carry out a check of the theoretical DAR correction using source centroiding. If "correct" it will al...
double skymodel_sampling
Spectral sampling of the sky spectrum [Angstrom].
double muse_pfits_get_dec(const cpl_propertylist *aHeaders)
find out the declination
Definition: muse_pfits.c:250
int astrometry
If false, skip any astrometric calibration, even if one was passed in the input set of files...
double skymodel_csampling
Spectral sampling of the continuum spectrum [Angstrom].
const char * format_s
Type of output file format, "Cube" is a standard FITS cube with NAXIS=3 and multiple extensions (for ...
double lambdamax
Cut off the data above this wavelength after loading the pixel table(s).
int muse_processing_save_image(muse_processing *aProcessing, int aIFU, muse_image *aImage, const char *aTag)
Save a computed MUSE image to disk.
muse_resampling_type muse_postproc_get_resampling_type(const char *aResampleString)
Select correct resampling type for resample string.
double dx
Horizontal step size for resampling (in arcsec or pixel). The following defaults are taken when this ...
muse_pixtable * muse_xcombine_tables(muse_pixtable **aPixtables)
combine the pixel tables of several exposures into one
muse_sky_master * sky
int skymethod
The method used to subtract the sky background. "model" should work in all cases, it uses a global sk...
Structure to hold the parameters of the muse_scipost recipe.
cpl_table * muse_table_load(muse_processing *aProcessing, const char *aTag, unsigned char aIFU)
load a table according to its tag and IFU/channel number
Definition: muse_utils.c:721
double crsigma
Sigma rejection factor to use for cosmic ray rejection during final resampling. A zero or negative va...
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_resampling_type
Resampling types.
Resampling parameters.
Structure definition of the post-processing output sky data.
void muse_resampling_params_delete(muse_resampling_params *aParams)
Delete a resampling parameters structure.
muse_lsf_params ** muse_processing_lsf_params_load(muse_processing *aProcessing, int aIFU)
Load slice LSF parameters.
void muse_mask_delete(muse_mask *aMask)
Deallocate memory associated to a muse_mask object.
Definition: muse_mask.c:68
cpl_propertylist * muse_propertylist_load(muse_processing *aProcessing, const char *aTag)
load a propertylist according to its tag
Definition: muse_utils.c:789
cpl_table * continuum
Continuum flux table
Definition: muse_sky.h:63
cpl_error_code muse_wcs_position_celestial(muse_pixtable *aPixtable, double aRA, double aDEC)
Convert native to celestial spherical coordinates in a pixel table.
Definition: muse_wcs.c:1133
muse_sky_params skymodel_params
cpl_table * muse_processing_sort_exposures(muse_processing *aProcessing)
Sort input frames (containing lists of pixel table filenames) into different exposures.
void muse_pixtable_delete(muse_pixtable *aPixtable)
Deallocate memory associated to a pixel table object.
muse_postproc_darcheck darcheck
Definition: muse_postproc.h:95
muse_xcombine_types
Xposure combination types.
Definition: muse_xcombine.h:44
double dlambda
Wavelength step size (in Angstrom). Natural instrument sampling is used, if this is 0...
muse_lsf_params ** lsf
LSF parameter for the resampled spectrum.
Definition: muse_sky.h:65
const char * resample_s
The resampling technique to use for the final output cube. (as string)
cpl_propertylist * header
The FITS header.
muse_sky_master * muse_sky_master_new(void)
Create a muse_sky_master structure.
const char * save
Select output product(s) to save. Can contain one or more of "cube", "skymodel", "individual", "positioned", "combined", and "stacked". If several options are given, they have to be comma-separated. ("cube": output cube and associated images, if this is not given, no final resampling is done at all – "skymodel": up to four additional output products about the effectively used sky that was subtracted with the "model" method – "individual": fully reduced pixel table for each individual exposure – "positioned": fully reduced and positioned pixel table for each individual exposure, the difference to "individual" is that here, the output pixel tables have coordinates in RA and DEC; this is only useful, if both the relative exposure weighting and the final resampling are to be done externally – "combined": fully reduced and combined pixel table for the full set of exposures, the difference to "positioned" is that all pixel tables are combined into one, with an added weight column; this is useful, if only the final resampling step is to be done separately – "stacked": an additional output file in form of a 2D column-stacked image, i.e. x direction is pseudo-spatial, y direction is wavelength.)
cpl_propertylist * muse_wcs_create_default(void)
Create FITS headers containing a default (relative) WCS.
Definition: muse_wcs.c:839
cpl_error_code muse_sky_save_continuum(muse_processing *, const cpl_table *, cpl_propertylist *)
Save sky continuum table to file.