MUSE Pipeline Reference Manual  2.1.1
muse_standard.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_standard_z.h"
33 
34 /*---------------------------------------------------------------------------*
35  * Functions code *
36  *---------------------------------------------------------------------------*/
37 
38 /*----------------------------------------------------------------------------*/
51 /*----------------------------------------------------------------------------*/
52 int
53 muse_standard_compute(muse_processing *aProcessing,
54  muse_standard_params_t *aParams)
55 {
56  cpl_errorstate state = cpl_errorstate_get();
57 
58  muse_postproc_properties *prop = muse_postproc_properties_new(MUSE_POSTPROC_STANDARD);
59  /* per-exposure parameters */
60  prop->lambdamin = aParams->lambdamin;
61  prop->lambdamax = aParams->lambdamax;
62  prop->lambdaref = aParams->lambdaref;
63  prop->darcheck = MUSE_POSTPROC_DARCHECK_NONE;
64  if (aParams->darcheck == MUSE_STANDARD_PARAM_DARCHECK_CHECK) {
65  prop->darcheck = MUSE_POSTPROC_DARCHECK_CHECK;
66  } else if (aParams->darcheck == MUSE_STANDARD_PARAM_DARCHECK_CORRECT) {
67  prop->darcheck = MUSE_POSTPROC_DARCHECK_CORRECT;
68  }
69  /* setup and check flux integration profiles */
71  if (aParams->profile == MUSE_STANDARD_PARAM_PROFILE_MOFFAT) {
73  } else if (aParams->profile == MUSE_STANDARD_PARAM_PROFILE_CIRCLE) {
75  } else if (aParams->profile == MUSE_STANDARD_PARAM_PROFILE_SQUARE) {
77  } else if (aParams->profile != MUSE_STANDARD_PARAM_PROFILE_GAUSSIAN) {
78  cpl_msg_error(__func__, "unknown profile \"%s\"", aParams->profile_s);
80  return -1;
81  }
82  /* flux reference */
83  prop->refframe = muse_frameset_find_master(aProcessing->inframes,
84  MUSE_TAG_STD_FLUX_TABLE, 0);
85  if (!prop->refframe) {
86  cpl_msg_error(__func__, "Required input %s not found in input files",
87  MUSE_TAG_STD_FLUX_TABLE);
88  cpl_error_set_message(__func__, CPL_ERROR_NULL_INPUT,
89  MUSE_TAG_STD_FLUX_TABLE" missing");
91  return -1;
92  }
93  muse_processing_append_used(aProcessing, prop->refframe,
94  CPL_FRAME_GROUP_CALIB, 1);
96  if (aParams->select == MUSE_STANDARD_PARAM_SELECT_DISTANCE) {
98  } else if (aParams->select != MUSE_STANDARD_PARAM_SELECT_FLUX) {
99  cpl_msg_error(__func__, "unknown selection \"%s\"", aParams->select_s);
101  return -1;
102  }
104  if (aParams->smooth == MUSE_STANDARD_PARAM_SMOOTH_MEDIAN) {
106  } else if (aParams->smooth == MUSE_STANDARD_PARAM_SMOOTH_NONE) {
108  } else if (aParams->smooth != MUSE_STANDARD_PARAM_SMOOTH_PPOLY) {
109  cpl_msg_error(__func__, "unknown smoothing \"%s\"", aParams->smooth_s);
111  return -1;
112  }
113  prop->extinction = muse_processing_load_ctable(aProcessing,
114  MUSE_TAG_EXTINCT_TABLE, 0);
115  /* telluric regions */
116  prop->tellregions = muse_processing_load_ctable(aProcessing, MUSE_TAG_TELLREG, 0);
117  if (!prop->tellregions) {
118  cpl_msg_debug(__func__, "%s could not be found or loaded, using defaults",
119  MUSE_TAG_TELLREG);
120  }
121 
122  /* sort input pixel tables into different exposures */
123  prop->exposures = muse_processing_sort_exposures(aProcessing);
124  if (!prop->exposures) {
125  cpl_msg_error(__func__, "No standard star exposures found in input!");
127  return -1;
128  }
129  int nexposures = cpl_table_get_nrow(prop->exposures);
130 
131  /* now process all the pixel tables, do it separately for each exposure */
132  muse_flux_object **fluxobjs = cpl_calloc(nexposures, sizeof(muse_flux_object *));
133  int i;
134  for (i = 0; i < nexposures; i++) {
135  fluxobjs[i] = muse_postproc_process_exposure(prop, i, NULL);
136  if (!fluxobjs[i]) {
137  int i2;
138  for (i2 = 0; i2 <= i; i2++) {
139  muse_flux_object_delete(fluxobjs[i2]);
140  } /* for i2 */
141  cpl_free(fluxobjs);
143  return -1; /* enough error messages, just return */
144  }
145  } /* for i (exposures) */
147 
148  /* XXX now combine the possibly more than one response tables */
149 
150  cpl_array *filters = muse_cplarray_new_from_delimited_string(aParams->filter,
151  ",");
152  for (i = 0; i < nexposures; i++) {
153  int ifilt, ipos = 0, nfilt = cpl_array_get_size(filters);
154  for (ifilt = 0; ifilt < nfilt; ifilt++) {
155  /* try to find and load the filter from a table */
156  const char *filtername = cpl_array_get_string(filters, ifilt);
157  muse_table *filter = muse_table_load_filter(aProcessing, filtername);
158  if (!filter) {
159  continue;
160  }
161  /* add an image integrated over this filter to the output cube */
162  muse_image *fov = muse_datacube_collapse(fluxobjs[i]->cube, filter);
163  if (!fluxobjs[i]->cube->recimages) {
164  fluxobjs[i]->cube->recimages = muse_imagelist_new();
165  fluxobjs[i]->cube->recnames = cpl_array_new(0, CPL_TYPE_STRING);
166  }
167  muse_imagelist_set(fluxobjs[i]->cube->recimages, fov, ipos);
168  cpl_array_set_size(fluxobjs[i]->cube->recnames, ipos+1);
169  cpl_array_set_string(fluxobjs[i]->cube->recnames, ipos,
170  cpl_array_get_string(filters, ifilt));
171  /* check that the filter we are processing is one for which *
172  * we actually want a zeropoint measurement before calling */
173  if (!strncmp(filtername, "Johnson_V", 10) ||
174  !strncmp(filtername, "Cousins_R", 10) ||
175  !strncmp(filtername, "Cousins_I", 10)) {
176  /* add zeropoint to the QC parameters, using this filter */
177  muse_flux_compute_qc_zp(fluxobjs[i], filter, filtername);
178  } /* if matching filter */
179  muse_table_delete(filter);
180  ipos++;
181  } /* for ifilt (all filters) */
182  muse_postproc_qc_fwhm(aProcessing, fluxobjs[i]->cube); /* before NANs! */
183  muse_datacube_convert_dq(fluxobjs[i]->cube);
184  muse_processing_save_cube(aProcessing, -1, fluxobjs[i]->cube,
185  MUSE_TAG_CUBE_STD, MUSE_CUBE_TYPE_FITS);
186  /* save the integrated flux image as well */
187  muse_processing_save_image(aProcessing, -1, fluxobjs[i]->intimage,
188  MUSE_TAG_STD_INTIMAGE);
189 
190  /* save the response-curve and the telluric correction */
191  cpl_propertylist *header = cpl_propertylist_duplicate(fluxobjs[i]->cube->header);
192  cpl_propertylist_erase_regexp(header, "^NAXIS|^EXPTIME$|"MUSE_WCS_KEYS, 0);
193  char *objorig = cpl_strdup(cpl_propertylist_get_string(header, "OBJECT"));
194  char *object = cpl_sprintf("Response curve (%s)", objorig);
195  cpl_propertylist_update_string(header, "OBJECT", object);
196  cpl_error_code rc = rc = muse_processing_save_table(aProcessing, -1,
197  fluxobjs[i]->response,
198  header,
199  MUSE_TAG_STD_RESPONSE,
201  cpl_free(object);
202  if (rc != CPL_ERROR_NONE) {
203  cpl_free(objorig);
204  cpl_propertylist_delete(header);
205  for ( ; i < nexposures; i++) {
206  muse_flux_object_delete(fluxobjs[i]);
207  } /* for rest of i */
208  break;
209  } /* if */
210  object = cpl_sprintf("Telluric correction (%s)", objorig);
211  cpl_propertylist_update_string(header, "OBJECT", object);
212  rc = muse_processing_save_table(aProcessing, -1, fluxobjs[i]->telluric, header,
213  MUSE_TAG_STD_TELLURIC, MUSE_TABLE_TYPE_MUSE);
214  cpl_free(object);
215  cpl_free(objorig);
216  cpl_propertylist_delete(header);
217  muse_flux_object_delete(fluxobjs[i]);
218  if (rc != CPL_ERROR_NONE) {
219  for ( ; i < nexposures; i++) {
220  muse_flux_object_delete(fluxobjs[i]);
221  } /* for rest of i */
222  break;
223  } /* if */
224  } /* for i (exposures) */
225  cpl_array_delete(filters);
226  cpl_free(fluxobjs);
227 
228  return cpl_errorstate_is_equal(state) ? 0 : -1;
229 } /* muse_standard_compute() */
muse_postproc_properties * muse_postproc_properties_new(muse_postproc_type aType)
Create a post-processing properties object.
Definition: muse_postproc.c:77
muse_flux_selection_type select
int profile
Type of flux integration to use. "gaussian" and "moffat" use 2D profile fitting, circle and square ar...
cpl_error_code muse_postproc_qc_fwhm(muse_processing *aProcessing, muse_datacube *aCube)
Compute QC1 parameters for datacubes and save them in the FITS header.
int select
How to select the star for flux integration, "flux" uses the brightest star in the field...
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.
int smooth
How to smooth the response curve before writing it to disk. "none" does not do any kind of smoothing ...
const char * profile_s
Type of flux integration to use. "gaussian" and "moffat" use 2D profile fitting, circle and square ar...
Structure definition of MUSE three extension FITS file.
Definition: muse_image.h:40
const char * select_s
How to select the star for flux integration, "flux" uses the brightest star in the field...
cpl_array * recnames
the reconstructed image filter names
Definition: muse_datacube.h:71
muse_flux_profile_type profile
cpl_error_code muse_flux_compute_qc_zp(muse_flux_object *aFluxObj, const muse_table *aFilter, const char *aName)
Compute QC zeropoint for given filter.
Definition: muse_flux.c:2972
cpl_array * muse_cplarray_new_from_delimited_string(const char *aString, const char *aDelim)
Convert a delimited string into an array of strings.
Flux object to store data needed while computing the flux calibration.
Definition: muse_flux.h:78
cpl_error_code muse_datacube_convert_dq(muse_datacube *aCube)
Convert the DQ extension of a datacube to NANs in DATA and STAT.
#define MUSE_WCS_KEYS
regular expression for WCS properties
Definition: muse_wcs.h:48
double lambdamin
Cut off the data below this wavelength after loading the pixel table(s).
cpl_error_code muse_processing_save_cube(muse_processing *aProcessing, int aIFU, void *aCube, const char *aTag, muse_cube_type aType)
Save a MUSE datacube to disk.
muse_flux_smooth_type smooth
Structure definition of the post-processing properties.
Definition: muse_postproc.h:91
muse_datacube * cube
Definition: muse_flux.h:80
muse_table * muse_table_load_filter(muse_processing *aProcessing, const char *aFilterName)
Load a table for a given filter name.
Definition: muse_utils.c:799
void muse_postproc_properties_delete(muse_postproc_properties *aProp)
Free memory taken by a post-processing properties object and all its components.
double lambdaref
Reference wavelength used for correction of differential atmospheric refraction. The R-band (peak wav...
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 store a table together with a property list.
Definition: muse_table.h:43
void muse_table_delete(muse_table *aTable)
Deallocate memory associated to a muse_table object.
Definition: muse_table.c:80
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.
Structure to hold the parameters of the muse_standard recipe.
cpl_table * muse_processing_load_ctable(muse_processing *aProcessing, const char *aTag, unsigned char aIFU)
Load a CPL table according to its tag and IFU/channel number.
muse_imagelist * muse_imagelist_new(void)
Create a new (empty) MUSE image list.
cpl_frameset * inframes
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_image * muse_datacube_collapse(muse_datacube *aCube, const muse_table *aFilter)
Integrate a FITS NAXIS=3 datacube along the wavelength direction.
int darcheck
Carry out a check of the theoretical DAR correction using source centroiding. If "correct" it will al...
cpl_table * muse_processing_sort_exposures(muse_processing *aProcessing)
Sort input frames (containing lists of pixel table filenames) into different exposures.
muse_postproc_darcheck darcheck
Definition: muse_postproc.h:97
cpl_error_code muse_imagelist_set(muse_imagelist *aList, muse_image *aImage, unsigned int aIdx)
Set the muse_image of given list index.
cpl_frame * muse_frameset_find_master(const cpl_frameset *aFrames, const char *aTag, unsigned char aIFU)
find the master frame according to its CCD number and tag
Definition: muse_utils.c:505
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...
void muse_flux_object_delete(muse_flux_object *aFluxObj)
Deallocate memory associated to a muse_flux_object.
Definition: muse_flux.c:89
muse_imagelist * recimages
the reconstructed image data
Definition: muse_datacube.h:64
const char * smooth_s
How to smooth the response curve before writing it to disk. "none" does not do any kind of smoothing ...