GRAVI Pipeline Reference Manual  0.9.10
gravity_piezo.c
1 /* $Id: gravity_vis.c,v 1.29 2011/12/3 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: 2011/12/3 09:16:12 $
24  * $Revision: 1.29 $
25  * $Name: $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 
36 #include <cpl.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <time.h>
40 
41 #include "gravi_data.h"
42 #include "gravi_pfits.h"
43 #include "gravi_dfs.h"
44 
45 #include "gravi_utils.h"
46 
47 #include "gravi_calib.h"
48 #include "gravi_p2vmred.h"
49 #include "gravi_eop.h"
50 #include "gravi_metrology.h"
51 
52 #include "gravi_signal.h"
53 #include "gravi_vis.h"
54 #include "gravi_tf.h"
55 
56 #include "gravi_preproc.h"
57 // #include "gravi_p2vm.h"
58 
59 /*-----------------------------------------------------------------------------
60  Private function prototypes
61  -----------------------------------------------------------------------------*/
62 
63 static int gravity_piezo_create(cpl_plugin *);
64 static int gravity_piezo_exec(cpl_plugin *);
65 static int gravity_piezo_destroy(cpl_plugin *);
66 static int gravity_piezo(cpl_frameset *, const cpl_parameterlist *);
67 
68 /*-----------------------------------------------------------------------------
69  Static variables
70  -----------------------------------------------------------------------------*/
71 
72 static char gravity_piezo_short[] = GRAVI_UNOFFERED"Calibrate the response of the piezo actuators.";
73 static char gravity_piezo_description[] = GRAVI_UNOFFERED"This recipe compute the response (open loop transfer function) of the piezo actuators used to fringe-track in GRAVITY.\n"
74  GRAVI_RECIPE_INPUT"\n"
75  GRAVI_FLAT_MAP" : flat calibration (PRO.CATG="GRAVI_FLAT_MAP")\n"
76  GRAVI_BAD_MAP" : badpixel calibration (PRO.CATG="GRAVI_BAD_MAP") \n"
77  GRAVI_WAVE_MAP" : wave calibration (PRO.CATG="GRAVI_WAVE_MAP")\n"
78  GRAVI_P2VM_MAP" : p2vm calibration (PRO.CATG="GRAVI_P2VM_MAP")\n"
79  GRAVI_DARK_MAP" : dark calibration (PRO.CATG="GRAVI_DARK_MAP")\n"
80  GRAVI_PIEZOTF_RAW" : dedicated observations \n"
81  GRAVI_RECIPE_OUTPUT"\n"
82  GRAVI_PIEZOTF_MAP" : Respose of the piezo\n"
83  "";
84 
85 /*-----------------------------------------------------------------------------
86  Function code
87  -----------------------------------------------------------------------------*/
88 
89 /*----------------------------------------------------------------------------*/
99 /*----------------------------------------------------------------------------*/
100 int cpl_plugin_get_info(cpl_pluginlist * list)
101 {
102  cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
103  cpl_plugin * plugin = &recipe->interface;
104 
105  if (cpl_plugin_init(plugin,
106  CPL_PLUGIN_API,
107  GRAVI_BINARY_VERSION,
108  CPL_PLUGIN_TYPE_RECIPE,
109  "gravity_piezo",
110  gravity_piezo_short,
111  gravity_piezo_description,
112  "Nabih Azouaoui, Vincent Lapeyrere, JB. Le Bouquin",
113  PACKAGE_BUGREPORT,
114  gravi_get_license(),
115  gravity_piezo_create,
116  gravity_piezo_exec,
117  gravity_piezo_destroy)) {
118  cpl_msg_error(cpl_func, "Plugin initialization failed");
119  (void)cpl_error_set_where(cpl_func);
120  return 1;
121  }
122 
123  if (cpl_pluginlist_append(list, plugin)) {
124  cpl_msg_error(cpl_func, "Error adding plugin to list");
125  (void)cpl_error_set_where(cpl_func);
126  return 1;
127  }
128 
129  return 0;
130 }
131 
132 /*----------------------------------------------------------------------------*/
140 /*----------------------------------------------------------------------------*/
141 static int gravity_piezo_create(cpl_plugin * plugin)
142 {
143  cpl_recipe * recipe;
144  // cpl_parameter * p;
145 
146  /* Do not create the recipe if an error code is already set */
147  if (cpl_error_get_code() != CPL_ERROR_NONE) {
148  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
149  cpl_func, __LINE__, cpl_error_get_where());
150  return (int)cpl_error_get_code();
151  }
152 
153  if (plugin == NULL) {
154  cpl_msg_error(cpl_func, "Null plugin");
155  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
156  }
157 
158  /* Verify plugin type */
159  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
160  cpl_msg_error(cpl_func, "Plugin is not a recipe");
161  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
162  }
163 
164  /* Get the recipe */
165  recipe = (cpl_recipe *)plugin;
166 
167  /* Create the parameters list in the cpl_recipe object */
168  recipe->parameters = cpl_parameterlist_new();
169  if (recipe->parameters == NULL) {
170  cpl_msg_error(cpl_func, "Parameter list allocation failed");
171  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
172  }
173 
174  /* Fill the parameters list */
175  int isCalib = 1;
176 
177  /* Use static names (output_procatg.fits) */
178  gravi_parameter_add_static_name (recipe->parameters);
179 
180  /* Intermediate files */
181  gravi_parameter_add_biassub_file (recipe->parameters);
182  gravi_parameter_add_preproc_file (recipe->parameters);
183 
184  /* Snr, signal, rejection, vis */
185  gravi_parameter_add_compute_snr (recipe->parameters, isCalib);
186  gravi_parameter_add_compute_signal (recipe->parameters, isCalib);
187  gravi_parameter_add_rejection (recipe->parameters, isCalib);
188  gravi_parameter_add_compute_vis (recipe->parameters, isCalib);
189 
190  return 0;
191 }
192 
193 /*----------------------------------------------------------------------------*/
199 /*----------------------------------------------------------------------------*/
200 static int gravity_piezo_exec(cpl_plugin * plugin)
201 {
202 
203  cpl_recipe * recipe;
204  int recipe_status;
205  cpl_errorstate initial_errorstate = cpl_errorstate_get();
206 
207 
208  /* Return immediately if an error code is already set */
209  if (cpl_error_get_code() != CPL_ERROR_NONE) {
210  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
211  cpl_func, __LINE__, cpl_error_get_where());
212  return (int)cpl_error_get_code();
213  }
214 
215  if (plugin == NULL) {
216  cpl_msg_error(cpl_func, "Null plugin");
217  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
218  }
219 
220  /* Verify plugin type */
221  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
222  cpl_msg_error(cpl_func, "Plugin is not a recipe");
223  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
224  }
225 
226  /* Get the recipe */
227  recipe = (cpl_recipe *)plugin;
228 
229  /* Verify parameter and frame lists */
230  if (recipe->parameters == NULL) {
231  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
232  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
233  }
234  if (recipe->frames == NULL) {
235  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
236  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
237  }
238 
239  /* Invoke the recipe */
240  recipe_status = gravity_piezo(recipe->frames, recipe->parameters);
241 
242  /* Ensure DFS-compliance of the products */
243  if (cpl_dfs_update_product_header(recipe->frames)) {
244  if (!recipe_status){
245  recipe_status = (int)cpl_error_get_code();
246  }
247  }
248 
249  if (!cpl_errorstate_is_equal(initial_errorstate)) {
250  /* Dump the error history since recipe execution start.
251  At this point the recipe cannot recover from the error */
252  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
253  }
254 
255  return recipe_status;
256 }
257 
258 /*----------------------------------------------------------------------------*/
264 /*----------------------------------------------------------------------------*/
265 static int gravity_piezo_destroy(cpl_plugin * plugin)
266 {
267  cpl_recipe * recipe;
268 
269  if (plugin == NULL) {
270  cpl_msg_error(cpl_func, "Null plugin");
271  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
272  }
273 
274  /* Verify plugin type */
275  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
276  cpl_msg_error(cpl_func, "Plugin is not a recipe");
277  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
278  }
279 
280  /* Get the recipe */
281  recipe = (cpl_recipe *)plugin;
282 
283  cpl_parameterlist_delete(recipe->parameters);
284 
285  return 0;
286 }
287 
288 
289 /*----------------------------------------------------------------------------*/
297 /*----------------------------------------------------------------------------*/
298 static int gravity_piezo(cpl_frameset * frameset,
299  const cpl_parameterlist * parlist)
300 {
301  cpl_frameset * recipe_frameset=NULL, * wavecalib_frameset=NULL, * dark_frameset=NULL,
302  * darkcalib_frameset=NULL, * flatcalib_frameset=NULL, * p2vmcalib_frameset=NULL,
303  * badcalib_frameset=NULL, *used_frameset=NULL, * current_frameset=NULL;
304 
305  cpl_frame * frame=NULL;
306 
307  gravi_data * p2vm_map=NULL, * data=NULL, * wave_map=NULL, * dark_map=NULL,
308  * profile_map=NULL, * badpix_map=NULL, * preproc_data=NULL, * p2vmred_data=NULL, * oi_vis=NULL;
309 
310  int nb_vis, nb_frame;
311 
312  /* Message */
313  gravity_print_banner ();
314  cpl_msg_set_time_on();
315  cpl_msg_set_component_on();
316  gravi_msg_function_start(1);
317 
318  cpl_ensure_code(gravi_dfs_set_groups(frameset) == CPL_ERROR_NONE,
319  cpl_error_get_code()) ;
320 
321  /* Dispatch the frameset */
322  p2vmcalib_frameset = gravi_frameset_extract_p2vm_map (frameset);
323  darkcalib_frameset = gravi_frameset_extract_dark_map (frameset);
324  wavecalib_frameset = gravi_frameset_extract_wave_map (frameset);
325  dark_frameset = gravi_frameset_extract_dark_data (frameset);
326  flatcalib_frameset = gravi_frameset_extract_flat_map (frameset);
327  badcalib_frameset = gravi_frameset_extract_bad_map (frameset);
328 
329  recipe_frameset = gravi_frameset_extract_piezotf_data (frameset);
330 
331  /* To use this recipe the frameset must contain the p2vm, wave and
332  * gain calibration file. */
333  if ( cpl_frameset_get_size (p2vmcalib_frameset) !=1 ||
334  cpl_frameset_get_size (wavecalib_frameset) !=1 ||
335  cpl_frameset_get_size (flatcalib_frameset) !=1 ||
336  cpl_frameset_get_size (badcalib_frameset) != 1 ||
337  cpl_frameset_get_size (recipe_frameset) < 1 ||
338  (cpl_frameset_is_empty (dark_frameset) &&
339  cpl_frameset_is_empty (darkcalib_frameset) )) {
340  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT,
341  "Illegal number of P2VM, FLAT, WAVE, BAD, DARK, PIEZOTF file on the frameset");
342  goto cleanup;
343  }
344 
345  /* Insert calibration frame into the used frameset */
346  used_frameset = cpl_frameset_new();
347 
348  /*
349  * Identify the DARK in the input frameset
350  */
351 
352  if (!cpl_frameset_is_empty (dark_frameset)) {
353 
354  frame = cpl_frameset_get_position (dark_frameset, 0);
355  data = gravi_data_load_rawframe (frame, used_frameset);
356  gravi_data_detector_cleanup (data, parlist);
357 
358  /* Compute dark */
359  dark_map = gravi_compute_dark (data);
360  FREE (gravi_data_delete, data);
361 
362  CPLCHECK_CLEAN ("Could not compute the DARK map");
363 
364  /* Save the dark map */
365  gravi_data_save_new (dark_map, frameset, NULL, parlist,
366  NULL, frame, "gravity_piezo",
367  NULL, GRAVI_DARK_MAP);
368 
369  CPLCHECK_CLEAN ("Could not save the DARK map");
370  }
371  else if (!cpl_frameset_is_empty (darkcalib_frameset)) {
372 
373  frame = cpl_frameset_get_position (darkcalib_frameset, 0);
374  dark_map = gravi_data_load_frame (frame, used_frameset);
375 
376  CPLCHECK_CLEAN ("Could not load the DARK map");
377  }
378  else
379  cpl_msg_info (cpl_func, "There is no DARK in the frame set");
380 
381  /* Identify the BAD in the input frameset */
382  frame = cpl_frameset_get_position (badcalib_frameset, 0);
383  badpix_map = gravi_data_load_frame (frame, used_frameset);
384 
385  /* Identify the FLAT in the input frameset */
386  frame = cpl_frameset_get_position (flatcalib_frameset, 0);
387  profile_map = gravi_data_load_frame (frame, used_frameset);
388 
389  /* Identify the WAVE in the input frameset */
390  frame = cpl_frameset_get_position (wavecalib_frameset, 0);
391  wave_map = gravi_data_load_frame (frame, used_frameset);
392 
393  /* Identify the P2VM in the input frameset */
394  frame = cpl_frameset_get_position (p2vmcalib_frameset, 0);
395  p2vm_map = gravi_data_load_frame (frame, used_frameset);
396 
397  /*
398  * Loop on input RAW frames to be reduced
399  */
400 
401  nb_vis = 0;
402  oi_vis = gravi_data_new(0);
403 
404  nb_frame = cpl_frameset_get_size (recipe_frameset);
405 
406  for (int thread = 0; thread < nb_frame; thread++){
407  current_frameset = cpl_frameset_duplicate (used_frameset);
408 
409  cpl_msg_info (cpl_func, " ***** OBJECT %d over %d ***** ", thread+1, nb_frame);
410 
411  /*
412  * Reduce the OBJECT
413  */
414 
415  frame = cpl_frameset_get_position (recipe_frameset, thread);
416  data = gravi_data_load_rawframe (frame, current_frameset);
417  gravi_data_detector_cleanup (data, parlist);
418 
419  /* Option save the preproc file */
420  if (gravi_param_get_bool (parlist,"gravity.dfs.bias-subtracted-file")) {
421 
422  gravi_data_save_new (data, frameset, NULL, parlist,
423  current_frameset, frame, "gravity_piezo",
424  NULL, "BIAS_SUBTRACTED");
425 
426  CPLCHECK_CLEAN ("Cannot save the BIAS_SUBTRACTED product");
427  }
428 
429 
430  /* Check the shutters */
431  if ( !gravi_data_check_shutter_open (data) ) {
432  cpl_msg_warning (cpl_func, "Shutter problem in the OBJECT");
433  }
434 
435  /* Extract spectrum */
436  preproc_data = gravi_extract_spectrum (data, profile_map, dark_map,
437  badpix_map, NULL, parlist);
438  CPLCHECK_CLEAN ("Cannot extract spectrum");
439 
440  /* Rescale to common wavelength */
441  gravi_align_spectrum (preproc_data, wave_map, p2vm_map);
442  CPLCHECK_CLEAN ("Cannot re-interpolate spectrum");
443 
444  /* Move extensions from raw_data */
445  gravi_data_move_ext (preproc_data, data, GRAVI_ARRAY_GEOMETRY_EXT);
446  gravi_data_move_ext (preproc_data, data, GRAVI_OPTICAL_TRAIN_EXT);
447  gravi_data_move_ext (preproc_data, data, GRAVI_OPDC_EXT);
448  gravi_data_move_ext (preproc_data, data, GRAVI_FDDL_EXT);
449  gravi_data_move_ext (preproc_data, data, GRAVI_METROLOGY_EXT);
450  FREE (gravi_data_delete, data);
451  CPLCHECK_CLEAN ("Cannot move ext");
452 
453  /* Option save the preproc file */
454  if (gravi_param_get_bool (parlist,"gravity.dfs.preproc-file")) {
455 
456  gravi_data_save_new (preproc_data, frameset, NULL, parlist,
457  current_frameset, frame, "gravity_piezo",
458  NULL, GRAVI_PREPROC);
459 
460  CPLCHECK_CLEAN ("Cannot save the PREPROC product");
461  }
462 
463  /* Compute the flux and visibilities for each telescope and
464  * per acquisition with the P2VM applied to preproc_data */
465  p2vmred_data = gravi_compute_p2vmred (preproc_data, p2vm_map, "single", parlist);
466  CPLCHECK_CLEAN ("Cannot apply p2vm to the preproc data");
467 
468  /* Move extensions and delete preproc */
469  gravi_data_move_ext (p2vmred_data, preproc_data, GRAVI_METROLOGY_EXT);
470  gravi_data_move_ext (p2vmred_data, preproc_data, GRAVI_FDDL_EXT);
471  gravi_data_move_ext (p2vmred_data, preproc_data, GRAVI_OPDC_EXT);
472  FREE (gravi_data_delete, preproc_data);
473  CPLCHECK_CLEAN ("Cannot delete preproc");
474 
475  /* Reduce the OPDC table */
476  gravi_compute_opdc_state (p2vmred_data);
477  CPLCHECK_CLEAN ("Cannot reduce OPDC");
478 
479  /* Reduce the metrology */
480  gravi_metrology_reduce (p2vmred_data);
481  CPLCHECK_CLEAN ("Cannot reduce metrology");
482 
483  /* Compute the SNR_SMT and GDELAY_SMT columns */
484  gravi_compute_snr (p2vmred_data, parlist);
485  CPLCHECK_MSG ("Cannot compute SNR");
486 
487  /* Compute the additional signals for averaging */
488  gravi_compute_signals (p2vmred_data, NULL, parlist);
489  CPLCHECK_MSG ("Cannot compute signals");
490 
491  /* Compute rejection flags for averaging */
492  gravi_compute_rejection (p2vmred_data, parlist);
493  CPLCHECK_MSG ("Cannot rejection flags signals");
494 
495  /* Add here your computation of QC */
496 
497  /* Save the PIEZOTF which is in fact a P2VMREDUCED */
498  gravi_data_save_new (p2vmred_data, frameset, NULL, parlist,
499  current_frameset, frame, "gravity_piezo", NULL, "PIEZOTF");
500 
501  CPLCHECK_CLEAN ("Cannot save the PIEZOTF product");
502 
503  nb_vis++;
504  cpl_msg_info (cpl_func,"Free the p2vmreduced");
505  FREE (cpl_frameset_delete, current_frameset);
506  FREE (gravi_data_delete, p2vmred_data);
507  }
508  /* End loop on the input files to reduce */
509 
510  /* Terminate the function */
511  goto cleanup;
512 
513 cleanup:
514  /* Deallocation of all variables */
515  cpl_msg_info(cpl_func,"Memory cleanup");
516 
517  FREE (gravi_data_delete,dark_map);
518  FREE (gravi_data_delete,data);
519  FREE (gravi_data_delete,preproc_data);
520  FREE (gravi_data_delete,profile_map);
521  FREE (gravi_data_delete,wave_map);
522  FREE (gravi_data_delete,badpix_map);
523  FREE (gravi_data_delete,p2vm_map);
524  FREE (gravi_data_delete,p2vmred_data);
525  FREE (gravi_data_delete,oi_vis);
526  FREE (cpl_frameset_delete,darkcalib_frameset);
527  FREE (cpl_frameset_delete,wavecalib_frameset);
528  FREE (cpl_frameset_delete,flatcalib_frameset);
529  FREE (cpl_frameset_delete,badcalib_frameset);
530  FREE (cpl_frameset_delete,p2vmcalib_frameset);
531  FREE (cpl_frameset_delete,dark_frameset);
532  FREE (cpl_frameset_delete,recipe_frameset);
533  FREE (cpl_frameset_delete,current_frameset);
534  FREE (cpl_frameset_delete,used_frameset);
535 
536  gravi_msg_function_exit(1);
537  return (int)cpl_error_get_code();
538 }