MUSE Pipeline Reference Manual  0.18.1
muse_sky_lsf.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  *
5  * This file is part of the MUSE Instrument Pipeline
6  * Copyright (C) 2005-2011 European Southern Observatory
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 /*---------------------------------------------------------------------------*
28  * Includes *
29  *---------------------------------------------------------------------------*/
30 #include <string.h>
31 #include <math.h>
32 
33 #include <muse.h>
34 #include "muse_sky_lsf_z.h"
35 
36 /*---------------------------------------------------------------------------*
37  * Functions code *
38  *---------------------------------------------------------------------------*/
39 static muse_pixtable *
40 muse_sky_lsf_load_pixtable(muse_processing *aProcessing,
41  muse_sky_lsf_params_t *aParams)
42 {
43  cpl_frameset *frames = muse_frameset_find(aProcessing->inputFrames,
44  "PIXTABLE_ARC", 0, CPL_FALSE);
45  if (frames == NULL || cpl_frameset_get_size(frames) <= 0) {
46  cpl_frameset_delete(frames);
47  return NULL;
48  }
49  cpl_frame *frame = cpl_frameset_get_position(frames, 0);
50  const char *fn = cpl_frame_get_filename(frame);
51  double lambdamin = aParams->lambdamin - kMuseSpectralSamplingA,
52  lambdamax = aParams->lambdamax + kMuseSpectralSamplingA;
54  lambdamin,
55  lambdamax);
56  cpl_msg_info(__func__, "using pixel table \"%s\"", fn);
57  muse_processing_append_used(aProcessing, frame, CPL_FRAME_GROUP_RAW, 1);
58  cpl_frameset_delete(frames);
59  if (pixtable != NULL) {
60  cpl_table_and_selected_int(pixtable->table, MUSE_PIXTABLE_DQ,
61  CPL_NOT_EQUAL_TO, EURO3D_GOODPIXEL);
62  cpl_table_erase_selected(pixtable->table);
63  /* erase pre-existing QC parameters */
64  cpl_propertylist_erase_regexp(pixtable->header, "ESO QC ", 0);
65  }
66  return pixtable;
67 }
68 
69 static cpl_table *
70 muse_sky_lsf_load_lines(muse_processing *aProcessing)
71 {
72  cpl_frameset *frames = muse_frameset_find(aProcessing->inputFrames,
73  "SKY_LINES", 0, CPL_FALSE);
74  if (frames == NULL || cpl_frameset_get_size(frames) <= 0) {
75  cpl_frameset_delete(frames);
76  return NULL;
77  }
78  cpl_frame *frame = cpl_frameset_get_position(frames, 0);
79  cpl_table *lines = cpl_table_load(cpl_frame_get_filename(frame), 1, 1);
80  cpl_msg_info(__func__, "using line table %s", cpl_frame_get_filename(frame));
81  muse_processing_append_used(aProcessing, frame, CPL_FRAME_GROUP_CALIB, 1);
82  cpl_frameset_delete(frames);
83  return lines;
84 }
85 
86 static void
87 muse_sky_lsf_save_params(cpl_propertylist *aHeader,
88  const muse_lsf_params **aSlicePars,
89  muse_processing *aProcessing)
90 {
91  if (aSlicePars != NULL) {
92  cpl_frame *frame
93  = muse_processing_new_frame(aProcessing, -1, aHeader,
94  "LSF_TABLE", CPL_FRAME_TYPE_TABLE);
95  if (frame != NULL) {
96  const char *filename = cpl_frame_get_filename(frame);
97  int r;
98  r = cpl_propertylist_save(aHeader, filename, CPL_IO_CREATE);
99  r = muse_lsf_params_save(aSlicePars, filename);
100  if (r == CPL_ERROR_NONE) {
101  cpl_frameset_insert(aProcessing->outputFrames, frame);
102  } else {
103  cpl_frame_delete(frame);
104  }
105  }
106  }
107 
108 }
109 
110 static muse_lsf_params *
111 muse_sky_lsf_compute_slice_params(cpl_table *aLines,
112  muse_pixtable *aPixtable,
113  muse_lsf_params *aFirstguess,
114  int max_iterations,
115  const muse_sky_fit_params *slice_fit_params)
116 
117 {
118  uint32_t origin = (uint32_t)cpl_table_get_int(aPixtable->table,
119  MUSE_PIXTABLE_ORIGIN, 0, NULL);
120  int i_ifu = muse_pixtable_origin_get_ifu(origin);
121  int i_slice = muse_pixtable_origin_get_slice(origin);
122  cpl_size nrows = muse_pixtable_get_nrow(aPixtable);
123 
124  cpl_msg_info(__func__, "processing slice %i.%i with %"CPL_SIZE_FORMAT" rows",
125  i_ifu, i_slice, nrows);
126 
127  cpl_propertylist *order = cpl_propertylist_new();
128  cpl_propertylist_append_bool(order, MUSE_PIXTABLE_LAMBDA, CPL_FALSE);
129  cpl_table_sort(aPixtable->table, order);
130  cpl_propertylist_delete(order);
131 
132  cpl_array *lambda = NULL;
133  if (cpl_table_get_column_type(aPixtable->table, MUSE_PIXTABLE_LAMBDA)
134  == CPL_TYPE_DOUBLE) {
135  lambda = muse_cpltable_extract_column(aPixtable->table,
136  MUSE_PIXTABLE_LAMBDA);
137  } else {
138  cpl_table_cast_column(aPixtable->table, MUSE_PIXTABLE_LAMBDA,
139  "lambda_double", CPL_TYPE_DOUBLE);
140  lambda = muse_cpltable_extract_column(aPixtable->table, "lambda_double");
141  }
142  cpl_array *data = muse_cpltable_extract_column(aPixtable->table,
143  MUSE_PIXTABLE_DATA);
144  cpl_array *stat = muse_cpltable_extract_column(aPixtable->table,
145  MUSE_PIXTABLE_STAT);
146 
147  muse_lsf_params *lsfParam
148  = muse_lsf_params_fit(lambda, data, stat, aLines, aFirstguess,
149  max_iterations, slice_fit_params);
150  lsfParam->slice = i_slice;
151  lsfParam->ifu = i_ifu;
152 
153  if (cpl_table_has_column(aPixtable->table, "lambda_double")) {
154  cpl_table_erase_column(aPixtable->table, "lambda_double");
155  }
156 
157  cpl_array_unwrap(lambda);
158  cpl_array_unwrap(data);
159  cpl_array_unwrap(stat);
160 
161  return lsfParam;
162 }
163 
164 static muse_lsf_params **
165 muse_sky_lsf_compute_slices(cpl_table *aLines,
166  muse_pixtable *aPixtable,
167  muse_lsf_params **aFirstguess,
168  int max_iterations,
169  const muse_sky_fit_params *slice_fit_params)
170 {
171  muse_pixtable **slice_pixtable = muse_pixtable_extracted_get_slices(aPixtable);
172  int n_slices = muse_pixtable_extracted_get_size(slice_pixtable);
173  int i_slice;
174 
175  muse_lsf_params **lsfParams
176  = cpl_calloc(n_slices+1, sizeof(muse_lsf_params *));
177 #if 1
178  #pragma omp parallel for default(none) /* as req. by Ralf */ \
179  shared(aLines, n_slices, i_slice, lsfParams, \
180  slice_pixtable, aFirstguess, max_iterations, slice_fit_params)
181 #endif
182  for (i_slice = 0; i_slice < n_slices; i_slice++) {
183  uint32_t origin
184  = (uint32_t)cpl_table_get_int(slice_pixtable[i_slice]->table,
185  MUSE_PIXTABLE_ORIGIN, 0, NULL);
186  int ifu = muse_pixtable_origin_get_ifu(origin);
187  int slice = muse_pixtable_origin_get_slice(origin);
188  muse_lsf_params *firstguess_slice
189  = muse_lsf_params_get(aFirstguess, ifu, slice);
190 
191  cpl_errorstate prestate = cpl_errorstate_get();
192  lsfParams[i_slice]
193  = muse_sky_lsf_compute_slice_params(aLines, slice_pixtable[i_slice],
194  firstguess_slice, max_iterations,
195  slice_fit_params);
196  if (!cpl_errorstate_is_equal(prestate)) {
197  cpl_msg_error(__func__, "While processing slice %i.%i:", ifu, slice);
198  cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
199  cpl_errorstate_set(prestate);
200  }
201  }
202 
203  muse_pixtable_extracted_delete(slice_pixtable);
204  return lsfParams;
205 }
206 
207 /*----------------------------------------------------------------------------*/
214 /*----------------------------------------------------------------------------*/
215 int
216 muse_sky_lsf_compute(muse_processing *aProcessing,
217  muse_sky_lsf_params_t *aParams)
218 {
219  cpl_msg_debug(__func__, "recipe=\"%s\", tag=\"%s\"", aProcessing->recipeName,
220  aProcessing->inputTag);
221 
222  cpl_errorstate prestate = cpl_errorstate_get();
223 
224  muse_pixtable *pixtable = muse_sky_lsf_load_pixtable(aProcessing, aParams);
225  if (pixtable == NULL) {
226  return -1;
227  }
228 
229  if (aParams->orig != NULL) {
230  cpl_table_duplicate_column(pixtable->table, aParams->orig,
231  pixtable->table, "data");
232  }
233  cpl_table *lines = muse_sky_lsf_load_lines(aProcessing);
234  if (lines == NULL) {
235  muse_pixtable_delete(pixtable);
236  return -1;
237  }
238 
239  muse_sky_fit_params *slice_fit_params = muse_sky_fit_params_new
240  (
241  aParams->slice_fit_offset,
242  aParams->slice_fit_refraction,
243  0, // sensitivity is not used here
244  aParams->slice_fit_slit_width,
245  aParams->slice_fit_bin_width,
246  aParams->slice_fit_lsf_width + 1,
247  aParams->slice_fit_h3 + 1,
248  aParams->slice_fit_h4 + 1,
249  aParams->slice_fit_h5 + 1,
250  aParams->slice_fit_h6 + 1
251  );
252 
253  muse_lsf_params **firstguess = muse_processing_lsf_params_load(aProcessing, 0);
254  muse_lsf_params **lsf = muse_sky_lsf_compute_slices(lines, pixtable, firstguess,
255  aParams->max_iterations,
256  slice_fit_params);
257  muse_lsf_params_delete(firstguess);
258  muse_sky_fit_params_delete(slice_fit_params);
259 
260  cpl_propertylist *qc_header = cpl_propertylist_new();
261  muse_sky_lsf_save_params(qc_header, (const muse_lsf_params **)lsf, aProcessing);
263 
264  if (aParams->store_subtracted) {
265  muse_processing_save_table(aProcessing, -1, pixtable, NULL,
266  MUSE_TAG_PIXTABLE_REDUCED,
268  }
269  /*
270  Clean up the local objects.
271  */
272  cpl_propertylist_delete(qc_header);
273  muse_pixtable_delete(pixtable);
274 
275  return (cpl_errorstate_is_equal(prestate))?0:-1;
276 }
int slice_fit_lsf_width
Polynomial order for the LSF width fit parameter. Use -1 to not fit the LSF width.
int store_subtracted
Output the pixel table after the LSF subtraction.
const char * inputTag
int slice_fit_slit_width
Use the slit width as fit parameter.
void muse_pixtable_extracted_delete(muse_pixtable **aPixtables)
Delete a pixel table array.
const char * orig
If specified, write an additional column containing the original data to the pixel table...
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_size muse_pixtable_get_nrow(muse_pixtable *aPixtable)
get the number of rows within the pixel table
muse_pixtable ** muse_pixtable_extracted_get_slices(muse_pixtable *aPixtable)
Extract one pixel table per IFU and slice.
int max_iterations
Maximum number of minimization steps for the slice parameter fit. If set to zero, the slice parameter...
cpl_error_code muse_lsf_params_save(const muse_lsf_params **aLsf, const char *aFile)
Save slice LSF parameters to the extension "slice" on disk.
Definition: muse_lsf.c:214
muse_lsf_params * muse_lsf_params_fit(const cpl_array *aLambda, cpl_array *aData, const cpl_array *aStat, const cpl_table *aLines, muse_lsf_params *aFirstGuess, int aMaxIter, const muse_sky_fit_params *aFitParams)
Fit all entries of one slice.
Definition: muse_lsf_fit.c:131
muse_lsf_params * muse_lsf_params_get(muse_lsf_params **aParams, int aIFU, int aSlice)
Get the slice LSF parameters for one slice.
Definition: muse_lsf.c:456
int slice_fit_h4
Polynomial order for the H4 fit parameter. Use -1 to not fit H4.
const char * recipeName
Structure to define which slice parameters are fit.
Definition: muse_sky.h:87
double lambdamin
Cut off the data below this wavelength after loading the pixel table(s).
void muse_sky_fit_params_delete(muse_sky_fit_params *)
Delete the fit parameter structure.
cpl_table * table
The pixel table.
int slice_fit_h5
Polynomial order for the H5 fit parameter. Use -1 to not fit H5.
int slice_fit_h3
Polynomial order for the H3 fit parameter. Use -1 to not fit H3.
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.
int slice_fit_refraction
Use the refraction index as slice dependent fit parameter.
cpl_frameset * outputFrames
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.
muse_sky_fit_params * muse_sky_fit_params_new(cpl_boolean, cpl_boolean, cpl_size, cpl_size, cpl_size, cpl_size, cpl_size, cpl_size, cpl_size, cpl_size)
Create a new fit parameter structure.
muse_pixtable * muse_pixtable_load_restricted_wavelength(const char *aFilename, double aLambdaMin, double aLambdaMax)
Load a pixel table from file and cut down the wavelength range.
int slice_fit_offset
Use wavelength offset as slice dependent fit parameter.
unsigned short muse_pixtable_origin_get_ifu(uint32_t aOrigin)
Get the IFU number from the encoded 32bit origin number.
Structure to hold the parameters of the muse_sky_lsf recipe.
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 slice_fit_bin_width
Use the bin width as fit parameter.
int slice_fit_h6
Polynomial order for the H6 fit parameter. Use -1 to not fit H6.
double lambdamax
Cut off the data above this wavelength after loading the pixel table(s).
muse_lsf_params ** muse_processing_lsf_params_load(muse_processing *aProcessing, int aIFU)
Load slice LSF parameters.
Definition: muse_lsf.c:392
cpl_frameset * muse_frameset_find(const cpl_frameset *aFrames, const char *aTag, unsigned char aIFU, cpl_boolean aInvert)
return frameset containing data from an IFU/channel with a certain tag
Definition: muse_utils.c:154
cpl_frameset * inputFrames
Structure definition of detector (slice) parameters.
Definition: muse_lsf.h:51
void muse_pixtable_delete(muse_pixtable *aPixtable)
Deallocate memory associated to a pixel table object.
void muse_lsf_params_delete(muse_lsf_params **aParams)
Delete an allocated array of muse_lsf_params structure.
Definition: muse_lsf.c:147
cpl_propertylist * header
The FITS header.