36 #include "muse_flat_z.h"
52 cpl_msg_debug(__func__,
"Adding QC keywords");
54 unsigned stats = CPL_STATS_MEDIAN | CPL_STATS_MEAN | CPL_STATS_STDEV
55 | CPL_STATS_MIN | CPL_STATS_MAX;
60 char *keyword = cpl_sprintf(QC_FLAT_PREFIXi, i+1);
62 aImage->
header, keyword, stats);
64 keyword = cpl_sprintf(QC_FLAT_PREFIXi
" "QC_BASIC_NSATURATED, i+1);
67 cpl_propertylist_update_int(aImage->
header, keyword, nsaturated);
72 stats |= CPL_STATS_FLUX;
74 QC_FLAT_MASTER_PREFIX, stats);
85 muse_flat_qc_trace_header(cpl_propertylist *aHeader,
const cpl_table *aTrace)
87 if (!aHeader || !aTrace) {
91 cpl_msg_debug(__func__,
"Adding tracing QC keywords for IFU %hhu", ifu);
94 cpl_array *gaps = cpl_array_new(kMuseSlicesPerCCD - 1, CPL_TYPE_DOUBLE);
97 for (nslice = 1; nslice <= kMuseSlicesPerCCD; nslice++) {
101 cpl_msg_warning(__func__,
"slice %2d of IFU %hhu: tracing polynomials "
102 "missing!", nslice, ifu);
107 float xpos = cpl_polynomial_eval_1d(ptrace[MUSE_TRACE_CENTER],
108 kMuseOutputYTop/2, NULL);
109 if (xpos < 1 || xpos > kMuseOutputXRight || !isnormal(xpos)) {
110 cpl_msg_warning(__func__,
"slice %2d of IFU %hhu: faulty polynomial "
111 "detected at y=%d (center: %f)", nslice, ifu,
112 kMuseOutputYTop/2, xpos);
118 double x1 = cpl_polynomial_eval_1d(ptrace[MUSE_TRACE_CENTER], 1, NULL),
119 x2 = cpl_polynomial_eval_1d(ptrace[MUSE_TRACE_CENTER],
120 kMuseOutputYTop, NULL);
121 float tilt = atan((x2 - x1) / (kMuseOutputYTop - 1)) * CPL_MATH_DEG_RAD;
123 cpl_propertylist_append_float(aHeader, QC_TRACE_L_XPOS, xpos);
124 cpl_propertylist_append_float(aHeader, QC_TRACE_L_TILT, tilt);
125 }
else if (nslice == kMuseSlicesPerCCD) {
126 cpl_propertylist_append_float(aHeader, QC_TRACE_R_XPOS, xpos);
127 cpl_propertylist_append_float(aHeader, QC_TRACE_R_TILT, tilt);
132 double gap = cpl_polynomial_eval_1d(ptrace[MUSE_TRACE_LEFT],
133 kMuseOutputYTop/2, NULL)
135 cpl_array_set_double(gaps, nslice - 2, gap);
138 redge = cpl_polynomial_eval_1d(ptrace[MUSE_TRACE_RIGHT], kMuseOutputYTop/2,
143 double maxslope = 0.;
144 int ipoly, j, jmax = -1, ipolymax = -1;
145 for (ipoly = MUSE_TRACE_CENTER; ipoly <= MUSE_TRACE_RIGHT; ipoly++) {
146 cpl_polynomial_derivative(ptrace[ipoly], 0);
149 for (j = 1; j <= kMuseOutputYTop; j++) {
150 double slope = cpl_polynomial_eval_1d(ptrace[ipoly], j, NULL);
151 if (fabs(slope) > fabs(maxslope)) {
158 #define MAX_NORMAL_SLOPE 0.015
159 if (fabs(maxslope) > MAX_NORMAL_SLOPE) {
160 cpl_msg_warning(__func__,
"Slope in slice %2d of IFU %hhu is unusually "
161 "high (maximum in polynomial %d at y=%d is |%f| > %f)",
162 nslice, ifu, ipolymax, jmax, maxslope, MAX_NORMAL_SLOPE);
164 char *kw = cpl_sprintf(QC_TRACE_SLICE_MAXSLOPE, nslice);
165 cpl_propertylist_append_float(aHeader, kw, maxslope);
170 float median, mean, stdev, min, max;
172 median = cpl_array_get_median(gaps);
173 mean = cpl_array_get_mean(gaps);
174 stdev = cpl_array_get_stdev(gaps);
175 min = cpl_array_get_min(gaps);
176 max = cpl_array_get_max(gaps);
177 cpl_propertylist_append_float(aHeader, QC_TRACE_GAPS_MEDIAN, median);
178 cpl_propertylist_append_float(aHeader, QC_TRACE_GAPS_MEAN, mean);
179 cpl_propertylist_append_float(aHeader, QC_TRACE_GAPS_STDEV, stdev);
180 cpl_propertylist_append_float(aHeader, QC_TRACE_GAPS_MIN, min);
181 cpl_propertylist_append_float(aHeader, QC_TRACE_GAPS_MAX, max);
182 cpl_array_delete(gaps);
185 median = cpl_table_get_column_median(aTrace, MUSE_TRACE_TABLE_COL_WIDTH);
186 mean = cpl_table_get_column_mean(aTrace, MUSE_TRACE_TABLE_COL_WIDTH);
187 stdev = cpl_table_get_column_stdev(aTrace, MUSE_TRACE_TABLE_COL_WIDTH);
188 min = cpl_table_get_column_min(aTrace, MUSE_TRACE_TABLE_COL_WIDTH);
189 max = cpl_table_get_column_max(aTrace, MUSE_TRACE_TABLE_COL_WIDTH);
190 cpl_propertylist_append_float(aHeader, QC_TRACE_WIDTHS_MEDIAN, median);
191 cpl_propertylist_append_float(aHeader, QC_TRACE_WIDTHS_MEAN, mean);
192 cpl_propertylist_append_float(aHeader, QC_TRACE_WIDTHS_STDEV, stdev);
193 cpl_propertylist_append_float(aHeader, QC_TRACE_WIDTHS_MIN, min);
194 cpl_propertylist_append_float(aHeader, QC_TRACE_WIDTHS_MAX, max);
205 muse_flat_qc_per_slice(
muse_image *aImage,
const cpl_table *aTrace)
207 if (!aImage->
header || !aTrace) {
211 cpl_msg_debug(__func__,
"Adding per-slice QC statistics for IFU %hhu", ifu);
214 const int y1 = kMuseOutputYTop/2 - 100,
215 y2 = kMuseOutputYTop/2 + 100;
217 for (nslice = 1; nslice <= kMuseSlicesPerCCD; nslice++) {
221 cpl_msg_warning(__func__,
"slice %2d of IFU %hhu: tracing polynomials "
222 "missing!", nslice, ifu);
225 char *kwmean = cpl_sprintf(QC_FLAT_MASTER_SLICEj_MEAN, nslice),
226 *kwstdev = cpl_sprintf(QC_FLAT_MASTER_SLICEj_STDEV, nslice);
228 int x1 = lround(cpl_polynomial_eval_1d(ptrace[MUSE_TRACE_LEFT],
229 kMuseOutputYTop/2, NULL)) + 1,
230 x2 = lround(cpl_polynomial_eval_1d(ptrace[MUSE_TRACE_RIGHT],
231 kMuseOutputYTop/2, NULL)) - 1;
232 if (x1 < 1 || x2 > kMuseOutputXRight || x1 > x2) {
233 cpl_msg_warning(__func__,
"slice %2d of IFU %hhu: faulty polynomial "
234 "detected at y=%d (borders: %d ... %d)", nslice, ifu,
235 kMuseOutputYTop/2, x1, x2);
239 double mean = cpl_image_get_mean_window(aImage->
data, x1, y1, x2, y2),
240 stdev = cpl_image_get_stdev_window(aImage->
data, x1, y1, x2, y2);
241 cpl_propertylist_update_float(aImage->
header, kwmean, mean);
242 cpl_propertylist_update_float(aImage->
header, kwstdev, stdev);
263 cpl_table *samples = NULL;
266 aParams->
samples ? &samples : NULL);
268 cpl_table_delete(samples);
269 return cpl_error_get_code();
273 cpl_propertylist *header = cpl_propertylist_duplicate(aImage->
header);
274 cpl_propertylist_erase_regexp(header,
275 "^SIMPLE$|^BITPIX$|^NAXIS|^EXTEND$|^XTENSION$|"
276 "^DATASUM$|^DATAMIN$|^DATAMAX$|^DATAMD5$|"
277 "^PCOUNT$|^GCOUNT$|^HDUVERS$|^BLANK$|"
278 "^BZERO$|^BSCALE$|^BUNIT$|^CHECKSUM$|^INHERIT$|"
279 "^PIPEFILE$|^ESO QC |^ESO PRO ", 0);
281 muse_flat_qc_trace_header(header, tracetable);
283 header, MUSE_TAG_TRACE_TABLE,
287 cpl_propertylist_erase_regexp(header, QC_TRACE_PREFIX, 0);
290 cpl_table_delete(samples);
292 cpl_propertylist_delete(header);
294 if (rc != CPL_ERROR_NONE) {
295 cpl_table_delete(tracetable);
303 cpl_msg_info(__func__,
"found %d bad pixels in the flat-field image", nbad);
306 muse_flat_qc_per_slice(aImage, tracetable);
308 cpl_table_delete(tracetable);
327 cpl_ensure(images, cpl_error_get_code(), -1);
334 cpl_msg_error(__func__,
"Combining input frames failed!");
338 cpl_propertylist_erase_regexp(masterimage->
header, MUSE_WCS_KEYS, 0);
340 muse_flat_qc_header(masterimage, images);
343 int rc = CPL_ERROR_NONE;
344 if (aParams->
trace) {
347 rc = muse_flat_trace_badpix(aProcessing, aParams, masterimage);
348 if (rc != CPL_ERROR_NONE) {
351 cpl_msg_warning(__func__,
"Tracing/bad pixel search failed");
357 double mean = cpl_propertylist_get_float(masterimage->
header,
358 QC_FLAT_MASTER_PREFIX
" MEAN");
364 MUSE_TAG_MASTER_FLAT);
366 return rc == CPL_ERROR_NONE ? 0 : -1;
muse_imagelist * muse_basicproc_load(muse_processing *aProcessing, unsigned char aIFU, muse_basicproc_params *aBPars)
Load the raw input files from disk and do basic processing.
cpl_polynomial ** muse_trace_table_get_polys_for_slice(const cpl_table *aTable, const unsigned short aSlice)
construct polynomial from the trace table entry for the given slice
int nifu
IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in ...
int order
Order of polynomial fit to the trace.
Structure definition for a collection of muse_images.
void muse_image_delete(muse_image *aImage)
Deallocate memory associated to a muse_image object.
int muse_quality_flat_badpix(muse_image *aFlat, cpl_table *aTrace, double aSigmaLo, double aSigmaHi)
Find bad (especially dark) pixels (in a master flat).
int muse_image_scale(muse_image *aImage, double aScale)
Scale a muse_image with correct treatment of variance.
cpl_table * muse_trace(const muse_image *aImage, int aNSum, double aEdgeFrac, int aFitorder, cpl_table **aSamples)
carry out the tracing of the slices on CCD, save parameters in table
unsigned char muse_utils_get_ifu(const cpl_propertylist *aHeaders)
Find out the IFU/channel from which this header originated.
cpl_image * data
the data extension
int normalize
Normalize the master flat to the average flux.
Structure to hold the parameters of the muse_flat recipe.
void muse_imagelist_delete(muse_imagelist *aList)
Free the memory of the MUSE image list.
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.
void muse_basicproc_params_delete(muse_basicproc_params *aBPars)
Free a structure of basic processing parameters.
cpl_propertylist * header
the FITS header
unsigned int muse_imagelist_get_size(muse_imagelist *aList)
Return the number of stored images.
void muse_trace_polys_delete(cpl_polynomial *aPolys[])
Delete the multi-polynomial array created in relation to tracing.
void muse_combinepar_delete(muse_combinepar *aCPars)
Clear the combination parameters.
muse_image * muse_imagelist_get(muse_imagelist *aList, unsigned int aIdx)
Get the muse_image of given list index.
int nsum
Number of lines over which to average when tracing.
int samples
Create a table containing all tracing sample points.
muse_combinepar * muse_combinepar_new(cpl_parameterlist *aParameters, const char *aPrefix)
Create a new set of combination parameters.
cpl_error_code muse_basicproc_stats_append_header(cpl_image *aImage, cpl_propertylist *aHeader, const char *aPrefix, unsigned aStats)
Compute image statistics of an image and add them to a header.
int muse_processing_save_image(muse_processing *aProcessing, int aIFU, muse_image *aImage, const char *aTag)
Save a computed MUSE image to disk.
double edgefrac
Fractional change required to identify edge when tracing.
double losigmabadpix
Low sigma to find dark pixels in the master flat.
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.
int trace
Trace the position of the slices on the master flat.
Structure of basic processing parameters.
cpl_parameterlist * parameters
double hisigmabadpix
High sigma to find bright pixels in the master flat.
cpl_error_code muse_basicproc_qc_saturated(muse_image *aImage, const char *aPrefix)
Add QC parameter about saturated pixels to a muse_image.