33 #include "muse_create_sky_z.h"
47 cpl_msg_error(__func__,
"no science exposures found in input");
50 int nexposures = cpl_table_get_nrow(exposures);
51 if (nexposures != 1) {
52 cpl_msg_error(__func__,
"More than one exposure (%i) in sky creation",
58 for (i = 0; i < nexposures; i++) {
59 cpl_table *thisexp = cpl_table_extract(exposures, i, 1);
63 cpl_table_delete(thisexp);
65 cpl_propertylist_erase_regexp(p->
header,
"ESO QC ", 0);
66 if (pixtable == NULL) {
70 cpl_table_get_nrow(pixtable->
table));
74 cpl_table_delete(exposures);
77 cpl_msg_error(__func__,
"Pixel table already sky subtracted");
82 cpl_table *response =
muse_table_load(aProcessing, MUSE_TAG_STD_RESPONSE, 0);
83 cpl_table *extinction =
muse_table_load(aProcessing, MUSE_TAG_EXTINCT_TABLE, 0);
84 cpl_table *telluric =
muse_table_load(aProcessing, MUSE_TAG_STD_TELLURIC, 0);
86 if ((pixtable != NULL) && (response != NULL)) {
88 cpl_msg_error(__func__,
89 "Pixel table already flux calibrated. Dont specify %s, %s, %s",
90 MUSE_TAG_STD_RESPONSE, MUSE_TAG_EXTINCT_TABLE,
91 MUSE_TAG_STD_TELLURIC);
96 if (rc != CPL_ERROR_NONE) {
97 cpl_msg_error(__func__,
"while muse_flux_calibrate");
104 cpl_table_delete(response);
105 cpl_table_delete(extinction);
106 cpl_table_delete(telluric);
109 cpl_msg_error(__func__,
"Pixel table not flux calibrated");
114 if (pixtable != NULL) {
115 cpl_table_and_selected_int(pixtable->
table, MUSE_PIXTABLE_DQ,
116 CPL_NOT_EQUAL_TO, EURO3D_GOODPIXEL);
117 cpl_table_erase_selected(pixtable->
table);
123 muse_create_sky_compute_master(cpl_table *spectrum,
muse_processing *aProcessing)
126 double lambda_low = cpl_array_get_min(lambda);
127 double lambda_high = cpl_array_get_max(lambda);
129 if (sky_lines != NULL) {
136 cpl_errorstate prestate = cpl_errorstate_get();
138 if (!cpl_errorstate_is_equal(prestate)) {
139 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
140 cpl_errorstate_set(prestate);
143 cpl_table_delete(sky_lines);
144 cpl_array_unwrap(lambda);
145 cpl_array_unwrap(data);
146 cpl_array_unwrap(stat);
147 cpl_table_delete(spectrum);
153 muse_create_sky_save_master(cpl_propertylist *aHeader,
159 "SKY_LINES", CPL_FRAME_TYPE_TABLE);
161 const char *filename = cpl_frame_get_filename(frame);
163 r = cpl_propertylist_save(aHeader, filename, CPL_IO_CREATE);
166 if (r == CPL_ERROR_NONE) {
169 cpl_frame_delete(frame);
173 "SKY_CONTINUUM", CPL_FRAME_TYPE_TABLE);
175 const char *filename = cpl_frame_get_filename(frame);
177 r = cpl_propertylist_save(aHeader, filename, CPL_IO_CREATE);
180 if (r == CPL_ERROR_NONE) {
183 cpl_frame_delete(frame);
195 static cpl_error_code
196 muse_create_sky_qc_sky(cpl_propertylist *aHeader,
199 cpl_ensure_code(aHeader && aMaster, CPL_ERROR_NULL_INPUT);
201 cpl_ensure_code(aMaster->
lines && cpl_table_get_nrow(aMaster->
lines) > 0,
202 CPL_ERROR_DATA_NOT_FOUND);
203 char keyword[KEYWORD_LENGTH];
204 int i, ngroups = cpl_table_get_column_max(aMaster->
lines,
"group") + 1;
205 for (i = 0; i < ngroups; i++) {
206 cpl_table_unselect_all(aMaster->
lines);
207 cpl_table_or_selected_int(aMaster->
lines,
"group", CPL_EQUAL_TO, i);
208 cpl_table *gtable = cpl_table_extract_selected(aMaster->
lines);
210 cpl_table_get_column_maxpos(gtable,
"flux", &row);
211 const char *name = cpl_table_get_string(gtable,
"name", row);
212 double wavelength = cpl_table_get_double(gtable,
"lambda", row, NULL),
213 flux = cpl_table_get_double(gtable,
"flux", row, NULL);
214 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC SKY LINE%i NAME", i+1);
215 cpl_propertylist_append_string(aHeader, keyword, name);
216 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC SKY LINE%i AWAV", i+1);
217 cpl_propertylist_append_double(aHeader, keyword, wavelength);
218 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC SKY LINE%i FLUX", i+1);
219 if (!isfinite(flux)) {
222 cpl_propertylist_append_double(aHeader, keyword, -9999.999);
223 cpl_msg_error(__func__,
"Sky-line fit failed for group %d, computed "
224 "flux is infinite!", i+1);
226 cpl_propertylist_append_double(aHeader, keyword, flux);
228 cpl_table_delete(gtable);
229 double offset = aMaster->
lsf[0]->offset
230 + (aMaster->
lsf[0]->refraction - 1) * wavelength;
231 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC SKY LINE%i OFFSET", i+1);
232 cpl_propertylist_append_double(aHeader, keyword, offset);
234 cpl_table_unselect_all(aMaster->
lines);
237 CPL_ERROR_DATA_NOT_FOUND);
238 cpl_size row, nrows = cpl_table_get_nrow(aMaster->
continuum);
240 for (row = 0; row < nrows; row++) {
241 flux += cpl_table_get_double(aMaster->
continuum,
"flux", row, NULL);
243 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC SKY CONT FLUX");
244 if (!isfinite(flux)) {
246 cpl_propertylist_append_double(aHeader, keyword, -9999.999);
247 cpl_msg_error(__func__,
"Sky-continuum contains infinite values, fit may "
250 cpl_propertylist_append_double(aHeader, keyword, flux);
253 prev = cpl_table_get_double(aMaster->
continuum,
"flux", 0, NULL),
254 l_prev = cpl_table_get_double(aMaster->
continuum,
"lambda", 0, NULL);
255 for (row = 1; row < nrows; row++) {
256 double cur = cpl_table_get_double(aMaster->
continuum,
"flux", row, NULL),
257 l_cur = cpl_table_get_double(aMaster->
continuum,
"lambda", row, NULL),
258 dev = fabs((cur - prev)/ (l_cur - l_prev));
265 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC SKY CONT MAXDEV");
266 cpl_propertylist_append_double(aHeader, keyword, maxdev);
268 return CPL_ERROR_NONE;
281 muse_create_sky_whitelight_image(
muse_pixtable *aPixtable,
int aCr)
283 cpl_boolean usegrid = getenv(
"MUSE_COLLAPSE_PIXTABLE")
284 && atoi(getenv(
"MUSE_COLLAPSE_PIXTABLE")) > 0;
294 usegrid ? &grid : NULL);
300 cube, fwhite, params);
307 cpl_table_delete(fwhite);
334 cpl_table_erase_column(aMaster->
continuum,
"stat");
335 cpl_table_erase_column(aMaster->
continuum,
"dq");
336 cpl_table_name_column(aMaster->
continuum,
"data",
"flux");
351 muse_pixtable *pixtable = muse_create_sky_load_pixtable(aProcessing, aParams);
352 if (pixtable == NULL) {
353 cpl_msg_error(__func__,
"Could not load pixel table");
366 cpl_table_select_all(pixtable->
table);
371 int cube_cr = (!strncmp(aParams->
cr_s,
"cube", 5));
372 muse_image *whitelight = muse_create_sky_whitelight_image(pixtable, cube_cr);
378 cpl_table_select_all(pixtable->
table);
385 if (!strncmp(aParams->
cr_s,
"spectrum", 9)) {
387 cpl_table_delete(spectrum);
391 if (spectrum == NULL) {
403 cpl_msg_info(__func__,
"Creating master sky spectrum using fits to lines "
404 "(fluxes) and residual continuum");
406 = muse_create_sky_compute_master(spectrum, aProcessing);
407 if (master == NULL) {
412 cpl_errorstate prestate = cpl_errorstate_get();
417 if (continuum != NULL) {
420 }
else if (lsfParam != NULL) {
421 muse_create_sky_create_continuum(pixtable, master,
426 cpl_propertylist *qc_header = cpl_propertylist_new();
427 muse_create_sky_qc_sky(qc_header, master);
429 muse_create_sky_save_master(qc_header, master, aProcessing);
433 cpl_propertylist_delete(qc_header);
435 return cpl_errorstate_is_equal(prestate) ? 0 : -1;
Structure definition of a MUSE datacube.
void muse_image_delete(muse_image *aImage)
Deallocate memory associated to a muse_image object.
int muse_processing_save_mask(muse_processing *aProcessing, int aIFU, muse_mask *aMask, const char *aTag)
Save a computed MUSE mask to disk.
cpl_error_code muse_pixtable_and_selected_mask(muse_pixtable *aPixtable, muse_mask *aMask)
Select all pixels where the (x,y) positions are enabled in the given mask.
cpl_table * muse_sky_lines_load(muse_processing *)
Load the sky data files.
Structure to hold the MASTER SKY result.
double csampling
Spectral sampling of the continuum spectrum [Angstrom].
void muse_datacube_delete(muse_datacube *aCube)
Deallocate memory associated to a muse_datacube object.
muse_image * muse_datacube_collapse(muse_datacube *aCube, cpl_table *aFilter)
Integrate a FITS NAXIS=3 datacube along the wavelength direction.
muse_mask * muse_sky_create_skymask(muse_image *, double)
Select spaxels to be considered as sky.
Structure definition of MUSE three extension FITS file.
muse_mask * muse_processing_mask_load(muse_processing *aProcessing, const char *aTag)
Load a mask file and its FITS header.
cpl_table * table
The pixel table.
cpl_table * muse_table_load_filter(muse_processing *aProcessing, const char *aFilterName)
Load a table for a given filter name.
void muse_sky_mark_cosmic(cpl_table *aSpectrum, muse_pixtable *aPixtable)
Mark all pixel above a certain limit as COSMIC.
muse_resampling_crstats_type crtype
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 spectrum.
Structure definition of MUSE pixel table.
cpl_frame * muse_processing_new_frame(muse_processing *aProcessing, int aIFU, cpl_propertylist *aHeader, const char *aTag, cpl_frame_type aType)
Create a new frame for a result file.
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.
muse_resampling_params * muse_resampling_params_new(muse_resampling_type aMethod)
Create the resampling parameters structure.
cpl_boolean muse_pixtable_is_fluxcal(muse_pixtable *aPixtable)
Determine whether the pixel table is flux calibrated.
cpl_frameset * outputFrames
cpl_error_code muse_flux_calibrate(muse_pixtable *aPixtable, const cpl_table *aResponse, const cpl_table *aExtinction, const cpl_table *aTelluric)
Convert the input pixel table from counts to fluxes.
const muse_cpltable_def muse_fluxspectrum_def[]
Definition of the flux spectrum table structure.
cpl_error_code muse_sky_lines_set_range(cpl_table *, double, double)
Limit the lines in the table to a wavelength range.
void muse_sky_master_delete(muse_sky_master *)
Delete a MASTER SKY structure.
muse_datacube * muse_resampling_cube(muse_pixtable *aPixtable, muse_resampling_params *aParams, muse_pixgrid **aPixgrid)
Resample a pixel table onto a regular grid structure representing a FITS NAXIS=3 datacube.
muse_sky_master * muse_sky_master_fit(const cpl_array *, const cpl_array *, const cpl_array *, const cpl_table *)
Fit all entries of the pixel table to the master sky.
muse_image * muse_resampling_collapse_pixgrid(muse_pixtable *aPixtable, muse_pixgrid *aPixgrid, muse_datacube *aCube, cpl_table *aFilter, muse_resampling_params *aParams)
Integrate a pixel table / pixel grid along the wavelength direction.
void muse_pixgrid_delete(muse_pixgrid *aPixels)
Delete a pixgrid and remove its memory.
int muse_processing_save_image(muse_processing *aProcessing, int aIFU, muse_image *aImage, const char *aTag)
Save a computed MUSE image to disk.
muse_pixtable * muse_pixtable_load_merge_channels(cpl_table *aExposureList, double aLambdaMin, double aLambdaMax)
Load and merge the pixel tables of the 24 MUSE sub-fields.
Handling of "mask" files.
double lambdamin
Cut off the data below this wavelength after loading the pixel table(s).
double sampling
Spectral sampling of the sky spectrum [Angstrom].
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
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.
double fraction
Fraction of the image to be considered as sky. If an input sky mask is provided, the fraction is appl...
muse_resampling_type
Resampling types.
double lambdamax
Cut off the data above this wavelength after loading the pixel table(s).
void muse_resampling_params_delete(muse_resampling_params *aParams)
Delete a resampling parameters structure.
muse_resampling_type method
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.
const char * cr_s
Type of cosmic ray cleaning to use. "Cube" is the standard CR cleaning which works on a datacube...
cpl_table * continuum
Continuum flux table
cpl_table * muse_resampling_spectrum(muse_pixtable *aPixtable, double aBinwidth)
Resample the selected pixels of a pixel table into a spectrum.
cpl_table * muse_processing_sort_exposures(muse_processing *aProcessing)
Sort input frames (containing lists of pixel table filenames) into different exposures.
Structure definition of detector (slice) parameters.
void muse_pixtable_delete(muse_pixtable *aPixtable)
Deallocate memory associated to a pixel table object.
Structure to hold the parameters of the muse_create_sky recipe.
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.
void muse_lsf_params_delete(muse_lsf_params **aParams)
Delete an allocated array of muse_lsf_params structure.
cpl_error_code muse_cpltable_append_file(const cpl_table *aTable, const char *aFile, const char *aExtension, const muse_cpltable_def aDefinition[])
Save a table to disk (into a FITS extension)
cpl_propertylist * header
The FITS header.