GRAVI Pipeline Reference Manual  1.2.3
gravity_wavelamp.c
1 /* $Id: gravity_wavelamp.c,v 1.29 2015/01/10 09:16:12 nazouaoui Exp $
2  *
3  * This file is part of the GRAVI Pipeline
4  * Copyright (C) 2002,2003 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: nazouaoui $
23  * $Date: 2015/01/10 09:16:12 $
24  * $Revision: 1.29 $
25  * $Name: $
26  *
27  * History :
28  * ekw 07/12/2018 Add wave_param frameset
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34 
35 /*-----------------------------------------------------------------------------
36  Includes
37  -----------------------------------------------------------------------------*/
38 
39 #include <cpl.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <time.h>
43 
44 #include "gravi_data.h"
45 #include "gravi_pfits.h"
46 #include "gravi_dfs.h"
47 
48 #include "gravi_utils.h"
49 
50 #include "gravi_calib.h"
51 #include "gravi_wave.h"
52 #include "gravi_preproc.h"
53 #include "gravi_disp.h"
54 
55 /*-----------------------------------------------------------------------------
56  Private function prototypes
57  -----------------------------------------------------------------------------*/
58 
59 static int gravity_wavelamp_create(cpl_plugin *);
60 static int gravity_wavelamp_exec(cpl_plugin *);
61 static int gravity_wavelamp_destroy(cpl_plugin *);
62 static int gravity_wavelamp(cpl_frameset *, const cpl_parameterlist *);
63 
64 /*-----------------------------------------------------------------------------
65  Static variables
66  -----------------------------------------------------------------------------*/
67 
68 static char gravity_wavelamp_short[] = "Measure the position of the Argon lines in the spectra.";
69 static char gravity_wavelamp_description[] =
70 "This recipe is associated to the template gravity_wavelamp.\n"
71 "It reduces the raw file obtained with the Argon lamp (WAVELAMP) and process it so that it can be used to calibrate the fiber dispersion (recipe gravity_disp).\n"
72  GRAVI_RECIPE_FLOW"\n"
73  "* Extract the spectra of the Argon exposure\n"
74  "* Interpolate the spectra into a common wavelength table\n"
75  "* Measure the wavelength position of known Argon lines\n"
76  "* Write the product\n"
77  GRAVI_RECIPE_INPUT"\n"
78  GRAVI_FLAT_MAP" : flat calibration (PRO.CATG="GRAVI_FLAT_MAP")\n"
79  GRAVI_BAD_MAP" : badpixel calibration (PRO.CATG="GRAVI_BAD_MAP") \n"
80  GRAVI_WAVE_MAP" : wave calibration (PRO.CATG="GRAVI_WAVE_MAP")\n"
81  GRAVI_P2VM_MAP" : p2vm calibration (PRO.CATG="GRAVI_P2VM_MAP")\n"
82  GRAVI_WAVELAMP_RAW" : long exposure of Argon lamp\n"
83  GRAVI_DARK_RAW" : dark of Argon exposure\n"
84  GRAVI_RECIPE_OUTPUT"\n"
85  GRAVI_WAVELAMP_MAP" : spectrum of Argon, with position of lines\n"
86  "";
87 
88 /*-----------------------------------------------------------------------------
89  Function code
90  -----------------------------------------------------------------------------*/
91 
92 /*----------------------------------------------------------------------------*/
102 /*----------------------------------------------------------------------------*/
103 int cpl_plugin_get_info(cpl_pluginlist * list)
104 {
105  cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
106  cpl_plugin * plugin = &recipe->interface;
107 
108  if (cpl_plugin_init(plugin,
109  CPL_PLUGIN_API,
110  GRAVI_BINARY_VERSION,
111  CPL_PLUGIN_TYPE_RECIPE,
112  "gravity_wavelamp",
113  gravity_wavelamp_short,
114  gravity_wavelamp_description,
115  "Nabih Azouaoui, Vincent Lapeyrere, JB. Le Bouquin",
116  PACKAGE_BUGREPORT,
118  gravity_wavelamp_create,
119  gravity_wavelamp_exec,
120  gravity_wavelamp_destroy)) {
121  cpl_msg_error(cpl_func, "Plugin initialization failed");
122  (void)cpl_error_set_where(cpl_func);
123  return 1;
124  }
125 
126  if (cpl_pluginlist_append(list, plugin)) {
127  cpl_msg_error(cpl_func, "Error adding plugin to list");
128  (void)cpl_error_set_where(cpl_func);
129  return 1;
130  }
131 
132  return 0;
133 }
134 
135 /*----------------------------------------------------------------------------*/
143 /*----------------------------------------------------------------------------*/
144 static int gravity_wavelamp_create(cpl_plugin * plugin)
145 {
146  cpl_recipe * recipe;
147 
148  /* Do not create the recipe if an error code is already set */
149  if (cpl_error_get_code() != CPL_ERROR_NONE) {
150  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
151  cpl_func, __LINE__, cpl_error_get_where());
152  return (int)cpl_error_get_code();
153  }
154 
155  if (plugin == NULL) {
156  cpl_msg_error(cpl_func, "Null plugin");
157  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
158  }
159 
160  /* Verify plugin type */
161  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
162  cpl_msg_error(cpl_func, "Plugin is not a recipe");
163  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
164  }
165 
166  /* Get the recipe */
167  recipe = (cpl_recipe *)plugin;
168 
169  /* Create the parameters list in the cpl_recipe object */
170  recipe->parameters = cpl_parameterlist_new();
171  if (recipe->parameters == NULL) {
172  cpl_msg_error(cpl_func, "Parameter list allocation failed");
173  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
174  }
175 
176  /* Fill the parameters list */
177  gravi_parameter_add_static_name (recipe->parameters);
178 
179  return 0;
180 }
181 
182 /*----------------------------------------------------------------------------*/
188 /*----------------------------------------------------------------------------*/
189 static int gravity_wavelamp_exec(cpl_plugin * plugin)
190 {
191 
192  cpl_recipe * recipe;
193  int recipe_status;
194  cpl_errorstate initial_errorstate = cpl_errorstate_get();
195 
196  /* Return immediately if an error code is already set */
197  if (cpl_error_get_code() != CPL_ERROR_NONE) {
198  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
199  cpl_func, __LINE__, cpl_error_get_where());
200  return (int)cpl_error_get_code();
201  }
202 
203  if (plugin == NULL) {
204  cpl_msg_error(cpl_func, "Null plugin");
205  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
206  }
207 
208  /* Verify plugin type */
209  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
210  cpl_msg_error(cpl_func, "Plugin is not a recipe");
211  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
212  }
213 
214  /* Get the recipe */
215  recipe = (cpl_recipe *)plugin;
216 
217  /* Verify parameter and frame lists */
218  if (recipe->parameters == NULL) {
219  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
220  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
221  }
222  if (recipe->frames == NULL) {
223  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
224  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
225  }
226 
227  /* Invoke the recipe */
228  recipe_status = gravity_wavelamp(recipe->frames, recipe->parameters);
229 
230  /* Ensure DFS-compliance of the products */
231 
232  if (cpl_dfs_update_product_header(recipe->frames)) {
233  if (!recipe_status){
234  recipe_status = (int)cpl_error_get_code();
235  }
236  }
237 
238  if (!cpl_errorstate_is_equal(initial_errorstate)) {
239  /* Dump the error history since recipe execution start.
240  At this point the recipe cannot recover from the error */
241  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
242  }
243 
244  return recipe_status;
245 }
246 
247 /*----------------------------------------------------------------------------*/
253 /*----------------------------------------------------------------------------*/
254 static int gravity_wavelamp_destroy(cpl_plugin * plugin)
255 {
256  cpl_recipe * recipe;
257 
258  if (plugin == NULL) {
259  cpl_msg_error(cpl_func, "Null plugin");
260  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
261  }
262 
263  /* Verify plugin type */
264  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
265  cpl_msg_error(cpl_func, "Plugin is not a recipe");
266  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
267  }
268 
269  /* Get the recipe */
270  recipe = (cpl_recipe *)plugin;
271 
272  cpl_parameterlist_delete(recipe->parameters);
273 
274  return 0;
275 }
276 
277 
278 /*----------------------------------------------------------------------------*/
286 /*----------------------------------------------------------------------------*/
287 static int gravity_wavelamp(cpl_frameset * frameset,
288  const cpl_parameterlist * parlist)
289 {
290  cpl_frameset * wavecalib_frameset = NULL,
291  * badcalib_frameset = NULL, * flatcalib_frameset = NULL,
292  * p2vmcalib_frameset = NULL, * dark_frameset = NULL,
293  * wavelamp_frameset = NULL, * used_frameset = NULL,
294  * darkcalib_frameset = NULL, *wave_param_frameset= NULL;
295 
296  cpl_frame * frame;
297 
298  gravi_data * data = NULL, * dark_map = NULL, * wave_map = NULL,
299  * profile_map = NULL, * badpix_map = NULL, * preproc_data = NULL, * p2vm_map = NULL,
300  * wave_param = NULL;
301 
302  /* Message */
303  gravity_print_banner ();
304  cpl_msg_set_time_on();
305  cpl_msg_set_component_on();
306  gravi_msg_function_start(1);
307 
308  cpl_ensure_code(gravi_dfs_set_groups(frameset) == CPL_ERROR_NONE,
309  cpl_error_get_code()) ;
310 
311  /* Identify the input framesets */
312  wavelamp_frameset = gravi_frameset_extract_wavelamp_data (frameset);
313  dark_frameset = gravi_frameset_extract_dark_data (frameset);
314  darkcalib_frameset = gravi_frameset_extract_dark_map (frameset);
315  p2vmcalib_frameset = gravi_frameset_extract_p2vm_map (frameset);
316  wavecalib_frameset = gravi_frameset_extract_wave_map (frameset);
317  flatcalib_frameset = gravi_frameset_extract_flat_map (frameset);
318  badcalib_frameset = gravi_frameset_extract_bad_map (frameset);
319  /* EKW 07/12/2018 Extract new calibration file wave_param frameset */
320  wave_param_frameset = gravi_frameset_extract_wave_param (frameset);
321 
322  /* Check input framesets */
323  if ( (cpl_frameset_is_empty (dark_frameset) &&
324  cpl_frameset_is_empty (darkcalib_frameset)) ||
325  cpl_frameset_is_empty (wavelamp_frameset) ||
326  cpl_frameset_is_empty (p2vmcalib_frameset) ||
327  cpl_frameset_is_empty (wavecalib_frameset) ||
328  cpl_frameset_is_empty (flatcalib_frameset) ||
329  cpl_frameset_is_empty (badcalib_frameset) ) {
330 
331  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT,
332  "Mising DARK, WAVELAMP, P2VM, WAVE, FLAT or BAD") ;
333  goto cleanup;
334  }
335 
336  /* Insert calibration frame into the used frameset */
337  used_frameset = cpl_frameset_new();
338 
339  /*
340  * Identify the DARK in the input frameset
341  */
342 
343  if (!cpl_frameset_is_empty (dark_frameset)) {
344 
345  frame = cpl_frameset_get_position (dark_frameset, 0);
346  data = gravi_data_load_rawframe (frame, used_frameset);
347  gravi_data_detector_cleanup (data, parlist);
348 
349  /* Compute dark */
350  dark_map = gravi_compute_dark (data);
351  FREE (gravi_data_delete, data);
352 
353  CPLCHECK_CLEAN ("Could not compute the DARK map");
354 
355  /* Save the dark map */
356  gravi_data_save_new (dark_map, frameset, NULL, NULL, parlist,
357  NULL, frame, "gravity_wavelamp",
358  NULL, GRAVI_DARK_MAP);
359 
360  CPLCHECK_CLEAN ("Could not save the DARK map");
361  }
362  else if (!cpl_frameset_is_empty (darkcalib_frameset)) {
363 
364  frame = cpl_frameset_get_position (darkcalib_frameset, 0);
365  dark_map = gravi_data_load_frame (frame, used_frameset);
366 
367  CPLCHECK_CLEAN ("Could not load the DARK map");
368  }
369  else
370  cpl_msg_info (cpl_func, "There is no DARK in the frame set");
371 
372 
373  /* Identify the BAD in the input frameset */
374  frame = cpl_frameset_get_position (badcalib_frameset, 0);
375  badpix_map = gravi_data_load_frame (frame, used_frameset);
376 
377  /* Identify the FLAT in the input frameset */
378  frame = cpl_frameset_get_position (flatcalib_frameset, 0);
379  profile_map = gravi_data_load_frame (frame, used_frameset);
380 
381  /* Identify the WAVE in the input frameset */
382  frame = cpl_frameset_get_position (wavecalib_frameset, 0);
383  wave_map = gravi_data_load_frame (frame, used_frameset);
384 
385  /* Identify the P2VM in the input frameset */
386  frame = cpl_frameset_get_position (p2vmcalib_frameset, 0);
387  p2vm_map = gravi_data_load_frame (frame, used_frameset);
388 
389  CPLCHECK_CLEAN ("Error while loading the calibration map");
390 
391 
392  /*
393  * Load input WAVELAMP_RAW
394  */
395  frame = cpl_frameset_get_position (wavelamp_frameset, 0);
396  data = gravi_data_load_rawframe (frame, used_frameset);
397  gravi_data_detector_cleanup (data, parlist);
398 
399  /* Create output data (FIXME: probably not necessary) */
400  gravi_data * argon_data = gravi_data_new (0);
401  cpl_propertylist * argon_header = gravi_data_get_header (argon_data);
402  cpl_propertylist_append (argon_header, gravi_data_get_header (data));
403 
404  /* Copy the IMAGING_DATA and IMAGING_DETECTOR extensions */
405  gravi_data_copy_ext (argon_data, data, GRAVI_IMAGING_DETECTOR_SC_EXT);
406  gravi_data_copy_ext (argon_data, data, GRAVI_IMAGING_DATA_SC_EXT);
407 
408  FREE (gravi_data_delete, data);
409 
410  /* Collapse ARGON */
411  cpl_imagelist * imglist = gravi_data_get_cube (argon_data, GRAVI_IMAGING_DATA_SC_EXT);
412  cpl_image * img_median = cpl_imagelist_collapse_median_create (imglist);
413 
414  /* Replace data in-place */
415  cpl_imagelist_empty (imglist);
416  cpl_imagelist_set (imglist, img_median, 0);
417 
418  /* Extract spectrum */
419  preproc_data = gravi_extract_spectrum (argon_data, profile_map, dark_map,
420  badpix_map, NULL, parlist,
421  GRAVI_DET_ALL);
422  FREE (gravi_data_delete, argon_data);
423  CPLCHECK_CLEAN ("Cannot extract spectrum");
424 
425  /* Compute the ARGON WAVE */
426  //cpl_table * spectrum_table, * argonwave_table;
427  //spectrum_table = gravi_data_get_spectrum_data (preproc_data, GRAVI_SC);
428  //argonwave_table = gravi_compute_argon_wave (spectrum_table);
429  //gravi_data_add_table (preproc_data, NULL, "WAVE_ARGON_RAW", argonwave_table);
430 
431  /* Rescale to common wavelength */
432  gravi_align_spectrum (preproc_data, wave_map, p2vm_map, GRAVI_DET_ALL, parlist);
433  CPLCHECK_CLEAN ("Cannot re-interpolate spectrum");
434 
435  /* Compute the ARGON WAVE */
436  //spectrum_table = gravi_data_get_spectrum_data (preproc_data, GRAVI_SC);
437  //argonwave_table = gravi_compute_argon_wave (spectrum_table);
438  //gravi_data_add_table (preproc_data, NULL, "WAVE_ARGON_RESAMP", argonwave_table);
439 
440  /* START EKW 07/12/2018 read wave parameter from calibration file - Load the WAVE_PARAM Parameter */
441  cpl_frame *frame2;
442  if (!cpl_frameset_is_empty (wave_param_frameset)) {
443  frame2 = cpl_frameset_get_position (wave_param_frameset, 0);
444  wave_param = gravi_data_load_frame (frame2, used_frameset);
445  }
446  else
447  cpl_msg_error (cpl_func, "There is no WAVE_PARAM in the frameset");
448 
449  /* END EKW 07/12/2018 read wave parameter from calibration file - Load the WAVE_PARAM Parameter */
450 
451  /* Compute position */
452  gravi_compute_argon_pos (preproc_data, wave_param);
453 
454  CPLCHECK_CLEAN ("Cannot compute the positions");
455 
456  /* Save the output data file */
457  gravi_data_save_new (preproc_data, frameset, NULL, NULL, parlist,
458  used_frameset, frame, "gravity_wavelamp",
459  NULL, GRAVI_WAVELAMP_MAP);
460 
461  CPLCHECK_CLEAN("Could not save the WAVELAMP");
462 
463  /* Deallocation of all variables */
464  goto cleanup;
465 
466 cleanup :
467  cpl_msg_info(cpl_func,"Memory cleanup");
468  FREE (cpl_frameset_delete, wavelamp_frameset);
469  FREE (cpl_frameset_delete, wavecalib_frameset);
470  FREE (cpl_frameset_delete, badcalib_frameset);
471  FREE (cpl_frameset_delete, flatcalib_frameset);
472  FREE (cpl_frameset_delete, p2vmcalib_frameset);
473  FREE (cpl_frameset_delete, used_frameset);
474  FREE (cpl_frameset_delete, dark_frameset);
475  FREE (cpl_frameset_delete, darkcalib_frameset);
476  FREE (cpl_frameset_delete, wave_param_frameset);
477 
478  FREE (gravi_data_delete, dark_map);
479  FREE (gravi_data_delete, wave_map);
480  FREE (gravi_data_delete, profile_map);
481  FREE (gravi_data_delete, badpix_map);
482  FREE (gravi_data_delete, p2vm_map);
483  FREE (gravi_data_delete, preproc_data);
484  FREE (gravi_data_delete, wave_param);
485 
486  gravi_msg_function_exit(1);
487  return (int)cpl_error_get_code();
488 }
489 
490 
gravi_data * gravi_data_new(int nb_ext)
Create an empty gravi_data.
Definition: gravi_data.c:102
gravi_data * gravi_data_load_frame(cpl_frame *frame, cpl_frameset *used_frameset)
Load a FITS file and create a gravi_data.
Definition: gravi_data.c:573
cpl_error_code gravi_data_copy_ext(gravi_data *output, gravi_data *input, const char *name)
Copy extensions from one data to another.
Definition: gravi_data.c:1325
cpl_frameset * gravi_frameset_extract_dark_data(cpl_frameset *frameset)
Extract DARK_RAW frame from the input frameset.
Definition: gravi_dfs.c:913
cpl_error_code gravi_compute_argon_pos(gravi_data *preproc_data, gravi_data *wave_param)
Compute position of argon lines in SC spectrum.
Definition: gravi_disp.c:898
gravi_data * gravi_data_load_rawframe(cpl_frame *frame, cpl_frameset *used_frameset)
Load a RAW FITS file and create a gravi_data.
Definition: gravi_data.c:690
cpl_error_code gravi_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: gravi_dfs.c:78
const char * gravi_get_license(void)
Get the pipeline copyright and license.
Definition: gravi_utils.c:104
cpl_error_code gravi_data_detector_cleanup(gravi_data *data, const cpl_parameterlist *parlist)
Perform self-bias correction to the SC raw data.
Definition: gravi_data.c:1086
cpl_error_code gravi_data_save_new(gravi_data *self, cpl_frameset *allframes, const char *filename, const char *suffix, const cpl_parameterlist *parlist, cpl_frameset *usedframes, cpl_frame *frame, const char *recipe, cpl_propertylist *applist, const char *proCatg)
Save a gravi data in a CPL-complian FITS file.
Definition: gravi_data.c:896
cpl_imagelist * gravi_data_get_cube(gravi_data *self, const char *extname)
Return a pointer on an IMAGE extension by its EXTNAME.
Definition: gravi_data.c:1751
cpl_error_code gravi_align_spectrum(gravi_data *spectrum_data, gravi_data *wave_map, gravi_data *p2vm_map, enum gravi_detector_type det_type, const cpl_parameterlist *parlist)
Regrid the regions into a common wavelength (in-place)
void gravi_data_delete(gravi_data *self)
Delete a gravi data.
Definition: gravi_data.c:137
gravi_data * gravi_extract_spectrum(gravi_data *raw_data, gravi_data *profile_map, gravi_data *dark_map, gravi_data *bad_map, gravi_data *sky_map, const cpl_parameterlist *parlist, enum gravi_detector_type det_type)
Create the SPECTRUM gravi_data with extracted spectrum per region.
gravi_data * gravi_compute_dark(gravi_data *raw_data)
Compute the DARK calibration map.
Definition: gravi_calib.c:122