34 #include <muse_data_format_z.h> 35 #include <muse_instrument.h> 37 #include "muse_lsf_z.h" 39 #ifndef USE_LSF_PARAMS 40 #ifdef MUSE_LSF_PARAM_METHOD_HERMIT 41 #error Please remove the "method" parameter from muse_lsf_params.xml 60 cpl_ensure(aPixtable, CPL_ERROR_NULL_INPUT, NULL);
68 #pragma omp parallel for default(none) \ 69 shared(lsfCube, n_slices, slice_pixtable, aParams) 70 for (i_slice = 0; i_slice < n_slices; i_slice++) {
71 cpl_image *img = cpl_imagelist_get(lsfCube->
img, i_slice);
89 muse_lsf_subtract_arcs(
muse_lsf_cube *aLsfCube, cpl_table *aPixtable) {
90 cpl_size n_rows = cpl_table_get_nrow(aPixtable);
92 for (i_row = 0; i_row < n_rows; i_row++) {
96 double lambda = cpl_table_get(aPixtable,
"line_lambda", i_row, NULL);
97 double flux = cpl_table_get(aPixtable,
"line_flux", i_row, NULL);
100 cpl_array *val = cpl_array_wrap_double(&v, 1);
102 aLsfCube->
wcs, val, lambda);
103 cpl_array_unwrap(val);
108 return CPL_ERROR_NONE;
126 static cpl_error_code
129 cpl_ensure_code(aLsfCube, CPL_ERROR_NULL_INPUT);
131 cpl_size i_slice, n_slices = cpl_imagelist_get_size(aLsfCube->
img);
132 for (i_slice = 0; i_slice < n_slices; i_slice++) {
133 cpl_image *img = cpl_imagelist_get(aLsfCube->
img, i_slice);
134 cpl_size n_lsf = cpl_image_get_size_x(img);
135 cpl_size n_lambda = cpl_image_get_size_y(img);
136 cpl_array *fwhm = cpl_array_new(n_lambda, CPL_TYPE_DOUBLE);
138 for (i_lambda = 0; i_lambda < n_lambda; i_lambda++) {
140 double ref = cpl_image_get(img, n_lsf/2, i_lambda+1, &res);
142 for (i_min = n_lsf/2; i_min > 0; i_min--) {
143 if (cpl_image_get(img, i_min, i_lambda+1, &res) < ref/2) {
147 double f_min = (ref/2 - cpl_image_get(img, i_min, i_lambda+1, &res))
148 / (cpl_image_get(img, i_min+1, i_lambda+1, &res)
149 - cpl_image_get(img, i_min, i_lambda+1, &res));
152 for (i_max = n_lsf/2; i_max <= n_lsf; i_max++) {
153 if (cpl_image_get(img, i_max, i_lambda+1, &res) < ref/2) {
157 double f_max = (ref/2 - cpl_image_get(img, i_max, i_lambda+1, &res))
158 / (cpl_image_get(img, i_max-1, i_lambda+1, &res)
159 - cpl_image_get(img, i_max, i_lambda+1, &res));
161 double f = (i_max - f_max - i_min - f_min) * aLsfCube->
wcs->cd11;
162 cpl_array_set(fwhm, i_lambda, f);
164 char keyword[KEYWORD_LENGTH];
165 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC LSF SLICE%i FWHM MEAN",
167 cpl_propertylist_append_float(aLsfCube->
header, keyword, cpl_array_get_mean(fwhm));
168 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC LSF SLICE%i FWHM STDEV",
170 cpl_propertylist_append_float(aLsfCube->
header, keyword, cpl_array_get_stdev(fwhm));
171 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC LSF SLICE%i FWHM MIN",
173 cpl_propertylist_append_float(aLsfCube->
header, keyword, cpl_array_get_min(fwhm));
174 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC LSF SLICE%i FWHM MAX",
176 cpl_propertylist_append_float(aLsfCube->
header, keyword, cpl_array_get_max(fwhm));
177 cpl_array_delete(fwhm);
180 return CPL_ERROR_NONE;
183 #ifdef USE_LSF_PARAMS 185 muse_lsf_params_compute(cpl_table *aLines,
195 #pragma omp parallel for default(none) num_threads(2) \ 196 shared(aLines, n_slices, i_slice, lsfParams, slice_pixtable, \ 198 for (i_slice = 0; i_slice < n_slices; i_slice++) {
200 = (uint32_t)cpl_table_get_int(slice_pixtable[i_slice]->table,
205 cpl_errorstate prestate = cpl_errorstate_get();
208 if (!cpl_errorstate_is_equal(prestate)) {
209 cpl_msg_error(__func__,
"While processing slice %hu.%hu:", ifu, slice);
210 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
211 cpl_errorstate_set(prestate);
225 static cpl_error_code
226 muse_lsf_params_qc(cpl_propertylist *aHeader,
const muse_lsf_params **aSlicePars)
228 cpl_ensure_code(aHeader != NULL, CPL_ERROR_NULL_INPUT);
229 cpl_ensure_code(aSlicePars != NULL, CPL_ERROR_NULL_INPUT);
232 for (det = aSlicePars; *det != NULL; det++) {
233 cpl_size n_lambda = 30;
234 double lambda_step = (kMuseNominalLambdaMax - kMuseNominalLambdaMin)
236 cpl_array *fwhm = cpl_array_new(n_lambda, CPL_TYPE_DOUBLE);
238 for (i_lambda = 0; i_lambda < n_lambda; i_lambda++) {
239 double lambda = kMuseNominalLambdaMin + i_lambda * lambda_step;
241 cpl_array_set(fwhm, i_lambda, f);
243 char keyword[KEYWORD_LENGTH];
244 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC LSF SLICE%i FWHM MEAN",
246 cpl_propertylist_append_float(aHeader, keyword, cpl_array_get_mean(fwhm));
247 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC LSF SLICE%i FWHM STDEV",
249 cpl_propertylist_append_float(aHeader, keyword, cpl_array_get_stdev(fwhm));
250 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC LSF SLICE%i FWHM MIN",
252 cpl_propertylist_append_float(aHeader, keyword, cpl_array_get_min(fwhm));
253 snprintf(keyword, KEYWORD_LENGTH,
"ESO QC LSF SLICE%i FWHM MAX",
255 cpl_propertylist_append_float(aHeader, keyword, cpl_array_get_max(fwhm));
256 cpl_array_delete(fwhm);
259 return CPL_ERROR_NONE;
262 static cpl_error_code
263 muse_lsf_params_save_table(cpl_propertylist *aHeader,
267 cpl_error_code r = CPL_ERROR_NONE;
268 if (aSlicePars != NULL) {
271 "LSF_PROFILE", CPL_FRAME_TYPE_TABLE);
273 const char *filename = cpl_frame_get_filename(frame);
274 cpl_msg_info(__func__,
"Saving LSF table as %s", filename);
275 char *channel = cpl_sprintf(
"CHAN%02d", aIFU);
276 cpl_propertylist_update_string(aHeader,
"EXTNAME", channel);
278 r = cpl_propertylist_save(aHeader, filename, CPL_IO_CREATE);
280 if (r == CPL_ERROR_NONE) {
281 #pragma omp critical(muse_processing_output_frames) 282 cpl_frameset_insert(aProcessing->
outframes, frame);
284 cpl_frame_delete(frame);
290 #endif // defined(USE_LSF_PARAMS) 309 cpl_ensure(images, cpl_error_get_code(), -1);
316 if (!arclines || !tracetable || !wavecaltable) {
317 cpl_msg_error(__func__,
"Calibration could not be loaded:%s%s%s",
318 !arclines ?
" " :
"",
319 !tracetable ?
" "MUSE_TAG_TRACE_TABLE :
"",
320 !wavecaltable ?
" "MUSE_TAG_WAVECAL_TABLE :
"");
322 cpl_table_delete(arclines);
323 cpl_table_delete(tracetable);
324 cpl_table_delete(wavecaltable);
329 cpl_errorstate prestate = cpl_errorstate_get();
331 if (aParams->
method == MUSE_LSF_PARAM_METHOD_INTERPOLATE) {
334 images, tracetable, wavecaltable, arclines,
338 cpl_table_delete(arclines);
339 cpl_table_delete(tracetable);
340 cpl_table_delete(wavecaltable);
342 if (arcpixtable == NULL) {
343 cpl_msg_error(__func__,
"Could not create pixel table of arc lines for " 344 "IFU %d", aParams->
nifu);
348 muse_lsf_cube *lsfcube = muse_lsf_compute_slices(arcpixtable, aParams);
349 if (lsfcube == NULL) {
350 cpl_msg_error(__func__,
"Could not create LSF cube for IFU %d",
361 muse_lsf_qc(lsfcube);
365 cpl_table_duplicate_column(arcpixtable->
table,
"orig", arcpixtable->
table,
367 muse_lsf_subtract_arcs(lsfcube, arcpixtable->
table);
375 #ifdef USE_LSF_PARAMS 376 else if (aParams->
method == MUSE_LSF_PARAM_METHOD_HERMIT) {
385 cpl_table_delete(tracetable);
386 cpl_table_delete(wavecaltable);
388 cpl_msg_error(__func__,
"ARC pixel table creation failed");
389 cpl_table_delete(arclines);
395 cpl_table_unselect_all(arclines);
396 cpl_table_or_selected_int(arclines, MUSE_LINE_CATALOG_QUALITY,
398 cpl_table_or_selected_float(arclines,
"flux", CPL_NOT_GREATER_THAN, 0.);
399 cpl_table_erase_selected(arclines);
401 cpl_propertylist *flux_sort = cpl_propertylist_new();
402 cpl_propertylist_append_bool(flux_sort,
"flux", CPL_TRUE);
403 cpl_table_sort(arclines, flux_sort);
404 cpl_propertylist_delete(flux_sort);
406 if (nrows < cpl_table_get_nrow(arclines)) {
407 cpl_table_erase_window(arclines, nrows, cpl_table_get_nrow(arclines));
411 cpl_table_duplicate_column(arcpixtable->
table,
"orig", arcpixtable->
table,
414 muse_lsf_params **lsf = muse_lsf_params_compute(arclines, arcpixtable, 40);
416 cpl_propertylist *qc_header = cpl_propertylist_new();
419 aProcessing, aParams->
nifu);
421 cpl_propertylist_delete(qc_header);
429 cpl_table_delete(arclines);
432 #endif // defined(USE_LSF_PARAMS) 434 cpl_msg_error(__func__,
"Unknown LSF method %s", aParams->
method_s);
436 return (cpl_errorstate_is_equal(prestate))?0:-1;
int method
LSF generation method. Depending on this value, either an interpolated LSF cube is created...
int lambda_size
Image size in line wavelength direction.
Structure definition for a collection of muse_images.
muse_wcs * wcs
Common WCS information for each slice.
void muse_image_delete(muse_image *aImage)
Deallocate memory associated to a muse_image object.
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.
cpl_propertylist * header
Primary header used to save the LSF cube to disk.
muse_imagelist * muse_basicproc_combine_images_lampwise(muse_processing *aProcessing, unsigned char aIFU, muse_basicproc_params *aBPars, cpl_frameset ***aLabeledFrames)
Combine several images into a lampwise image list.
double muse_lsf_fwhm_lambda(const muse_lsf_params *aDP, double aLambda, double aSampling, unsigned int aLength)
Measure the FWHM of an LSF at a given wavelength.
muse_pixtable ** muse_pixtable_extracted_get_slices(muse_pixtable *aPixtable)
Extract one pixel table per IFU and slice.
int nifu
IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in ...
void muse_imagelist_delete(muse_imagelist *aList)
Free the memory of the MUSE image list.
Data cube/stacked image list containing the LSF for one IFU.
muse_basicproc_params * muse_basicproc_params_new(cpl_parameterlist *aParameters, const char *aPrefix)
Create a new structure of basic processing parameters.
muse_image * muse_combine_images(muse_combinepar *aCPars, muse_imagelist *aImages)
Combine several images into one.
Structure definition of MUSE three extension FITS file.
muse_lsf_cube * muse_lsf_cube_new(double aLsfHalfRange, cpl_size aNLsf, cpl_size aNLambda, const cpl_propertylist *aHeader)
Create a new LSF datacube.
cpl_table * table
The pixel table.
void muse_basicproc_params_delete(muse_basicproc_params *aBPars)
Free a structure of basic processing parameters.
void muse_lsf_params_delete_all(muse_lsf_params **aParams)
Delete an allocated array of muse_lsf_params structure.
int save_subtracted
Save the pixel table after the LSF subtraction.
#define MUSE_PIXTABLE_DATA
void muse_combinepar_delete(muse_combinepar *aCPars)
Clear the combination parameters.
Structure definition of MUSE pixel table.
int lsf_size
Image size in LSF direction.
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.
Structure to hold the parameters of the muse_lsf recipe.
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.
int line_quality
Minimal quality flag in line catalog for selection.
muse_combinepar * muse_combinepar_new(cpl_parameterlist *aParameters, const char *aPrefix)
Create a new set of combination parameters.
muse_lsf_params * muse_lsf_params_fit(muse_pixtable *aPixtable, cpl_table *aLines, int aMaxIter)
Fit all entries of one slice.
cpl_error_code muse_lsf_apply(const cpl_image *aLsfImage, const muse_wcs *aWCS, cpl_array *aVal, double aLambda)
Apply the LSF to a number of data points of one slice.
muse_pixtable * muse_pixtable_create(muse_image *aImage, cpl_table *aTrace, cpl_table *aWave, cpl_table *aGeoTable)
Create the pixel table for one CCD.
#define MUSE_PIXTABLE_ORIGIN
unsigned short muse_pixtable_origin_get_ifu(uint32_t aOrigin)
Get the IFU number from the encoded 32bit origin number.
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.
cpl_error_code muse_lsf_params_save(const muse_lsf_params **aLsfParams, const char *aFile)
Save slice LSF parameters to the extension "slice" on disk.
#define MUSE_PIXTABLE_LAMBDA
muse_pixtable * muse_lsf_create_arcpixtable(muse_imagelist *aImages, cpl_table *aTrace, cpl_table *aWave, cpl_table *aArcLines, int aQuality, double aWindow)
Read images and combine the arc lines into one pixtable.
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.
Structure of basic processing parameters.
const char * method_s
LSF generation method. Depending on this value, either an interpolated LSF cube is created...
void muse_lsf_cube_delete(muse_lsf_cube *aLsfCube)
Deallocate the memory for the LSF cube.
cpl_imagelist * img
Stacked image list for LSF; one per slice.
Structure definition of detector (slice) parameters.
void muse_pixtable_delete(muse_pixtable *aPixtable)
Deallocate memory associated to a pixel table object.
double lsf_range
Wavelength window (half size) around each line to estimate LSF.
cpl_parameterlist * parameters
cpl_error_code muse_lsf_fit_slice(const muse_pixtable *aPixtable, cpl_image *aLsfImage, muse_wcs *aWCS, double aLsfRegressionWindow)
Compute the LSF for all wavelengths of one slice.
cpl_propertylist * header
The FITS header.
double lsf_regression_window
Size of the regression window in LSF direction.