MIDI Pipeline Reference Manual  2.8.3
midi_intopd.c
1 /* $Id: midi_intopd.c,v 1.55 2011-11-21 09:40:20 agabasch Exp $
2  *
3  * This file is part of the MIDI 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: agabasch $
23  * $Date: 2011-11-21 09:40:20 $
24  * $Revision: 1.55 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 #include <math.h>
36 #include <cpl.h>
37 #include "midi_utils.h"
38 #include "midi_cplutils.h"
39 #include "cpl_image_filter.h"
40 #include <fitsio.h>
41 #include "midiConst.h"
42 #include "midi_dfs.h"
43 #include "string.h"
44 #include "lomb_scargel.h"
45 #include "midi_cplupgrade.h"
46 
47 #define DIMENDATA 2
48 /*-----------------------------------------------------------------------------
49  Private function prototypes
50  -----------------------------------------------------------------------------*/
51 
52 static int midi_intopd_create(cpl_plugin *);
53 static int midi_intopd_exec(cpl_plugin *);
54 static int midi_intopd_destroy(cpl_plugin *);
55 static int midi_intopd(cpl_frameset *, const cpl_parameterlist *);
56 
57 
58 static void midi_intopd_check_parameter(int * llx, int * lly,
59  int * urx, int * ury,
60  double * fmin, double * fmax,
61  int * sampling,
62  cpl_imagelist * imglst_ABOPEN0);
63 
64 static int append_image_to_table(cpl_table * table, const char * columname,
65  cpl_image * image, int row);
66 
67 static void save_mask_for_ews(cpl_frameset * frameset, const cpl_parameterlist * parlist,
68  cpl_image ** opdmask,const char * name,
69  char * first_valid_frame);
70 
71 static int midi_copy_extension(const char * infile , const char * outfile,
72  const char * extension_name);
73 
74 static void midi_intopd_qc_stats(cpl_propertylist * pro_list,
75  cpl_table * table, const char * column_name);
76 
77 
78 /*-----------------------------------------------------------------------------
79  Static variables
80  -----------------------------------------------------------------------------*/
81 
82 /* These wavelength calibration is taken from the static calibration file */
83 static double wavecalib_prism_hs_frequency[]={0.0706326774, 0.0707558873, 0.0708812144, 0.0710086692, 0.0711382772, 0.0712700642, 0.0714040373, 0.0715402332, 0.0716786644, 0.0718193590, 0.0719623404, 0.0721076328, 0.0722552605, 0.0724052439, 0.0725576234, 0.0727124054, 0.0728696265, 0.0730293143, 0.0731914915, 0.0733561970, 0.0735234497, 0.0736932899, 0.0738657377, 0.0740408347, 0.0742186024, 0.0743990732, 0.0745822912, 0.0747682797, 0.0749570788, 0.0751487242, 0.0753432522, 0.0755407000, 0.0757411057, 0.0759445081, 0.0761509415, 0.0763604520, 0.0765730812, 0.0767888660, 0.0770078611, 0.0772301053, 0.0774556385, 0.0776845187, 0.0779167818, 0.0781524825, 0.0783916647, 0.0786343910, 0.0788807019, 0.0791306567, 0.0793843101, 0.0796417240, 0.0799029438, 0.0801680280, 0.0804370487, 0.0807100554, 0.0809871170, 0.0812682981, 0.0815536648, 0.0818432783, 0.0821372209, 0.0824355571, 0.0827383534, 0.0830456908, 0.0833576459, 0.0836742903, 0.0839957179, 0.0843219977, 0.0846532210, 0.0849894814, 0.0853308542, 0.0856774376, 0.0860293181, 0.0863866060, 0.0867493857, 0.0871177658, 0.0874918501, 0.0878717455, 0.0882575543, 0.0886494115, 0.0890474028, 0.0894516622, 0.0898623119, 0.0902794776, 0.0907032805, 0.0911338691, 0.0915713642, 0.0920159223, 0.0924676717, 0.0929267693, 0.0933933680, 0.0938676170, 0.0943496952, 0.0948397528, 0.0953379702, 0.0958445247, 0.0963595988, 0.0968833719, 0.0974160647, 0.0979578415, 0.0985089263, 0.0990695319, 0.0996398781, 0.1002201913, 0.1008106958, 0.1014116523, 0.1020233009, 0.1026458890, 0.1032796929, 0.1039249773, 0.1045820472, 0.1052511762, 0.1059326790, 0.1066268812, 0.1073340762, 0.1080546341, 0.1087889046, 0.1095372161, 0.1102999658, 0.1110775425, 0.1118703495, 0.1126788049, 0.1135033426, 0.1143444129, 0.1152024835, 0.1160780271, 0.1169715608, 0.1178835959, 0.1188147173, 0.1197654389, 0.1207363775, 0.1217281474, 0.1227413885, 0.1237767821, 0.1248349940, 0.1259167631, 0.1270228297, 0.1281540054, 0.1293111060, 0.1304949757, 0.1317065291, 0.1329467317, 0.1342165168, 0.1355169386, 0.1368490662, 0.1382140376, 0.1396130370, 0.1410472968, 0.1425181298, 0.1440268952, 0.1455750610, 0.1471641000, 0.1487956338, 0.1504713171, 0.1521929141, 0.1539622963, 0.1557814268, 0.1576523663, 0.1595773159, 0.1615586032, 0.1635986409, 0.1657000609, 0.1678655738, 0.1700981363, 0.1724008044, 0.1747769110, 0.1772299438, 0.1797636156, 0.1823819143, 0.1850890631, 0.1878896053, 0.1907884167, 0.1937905936, 0.1968915361};
84 
85 
86 static char midi_intopd_description[] =
87 
88 "This recipe calculates the internal OPD stability of MIDI based on\n"
89 "the group delay. It follows the paper of Lawson, P.R. 1995\n"
90 "(J. Opt. Soc. Am. A, Vol. 12, No. 2, p. 366 - 374) and analizes\n"
91 "the fringes in the frequency domain by the usage of the Scargle-Lomb\n"
92 "algorithm (ApJ, vol. 263, Dec. 15, 1982, p. 835-853).\n"
93 "\n"
94 "Input files:\n\n"
95 " DO category: Type: Explanation: Required:\n"
96 " INTERNAL_OPD Raw Raw data frame Y\n\n"
97 "Output files:\n\n"
98 " DO category: Data type: Explanation:\n"
99 " MIDI_INTOPD FITS table Internal OPD offset of MIDI\n"
100 " MIDI_MASK_INTOPD FITS table Mask for signal extraction\n"
101 " MIDI_MASK_DATA1 FITS image Mask for DATA1 signal extraction\n"
102 " MIDI_MASK_DATA2 FITS image Mask for DATA2 signal extraction\n\n";
103 
104 /*-----------------------------------------------------------------------------
105  Function code
106  -----------------------------------------------------------------------------*/
107 
108 /*----------------------------------------------------------------------------*/
113 /*----------------------------------------------------------------------------*/
114 
117 /*----------------------------------------------------------------------------*/
127 /*----------------------------------------------------------------------------*/
128 int cpl_plugin_get_info(cpl_pluginlist * list)
129 {
130  cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
131  cpl_plugin * plugin = &recipe->interface;
132 
133  if (cpl_plugin_init(plugin,
134  CPL_PLUGIN_API,
135  MIDI_BINARY_VERSION,
136  CPL_PLUGIN_TYPE_RECIPE,
137  "midi_intopd",
138  "Derives the internal OPD stability",
139  midi_intopd_description,
140  "Armin Gabasch",
141  PACKAGE_BUGREPORT,
143  midi_intopd_create,
144  midi_intopd_exec,
145  midi_intopd_destroy)) {
146  cpl_msg_error(cpl_func, "Plugin initialization failed");
147  (void)cpl_error_set_where(cpl_func);
148  return 1;
149  }
150 
151  if (cpl_pluginlist_append(list, plugin)) {
152  cpl_msg_error(cpl_func, "Error adding plugin to list");
153  (void)cpl_error_set_where(cpl_func);
154  return 1;
155  }
156 
157  return 0;
158 }
159 
160 /*----------------------------------------------------------------------------*/
168 /*----------------------------------------------------------------------------*/
169 static int midi_intopd_create(cpl_plugin * plugin)
170 {
171  cpl_recipe * recipe;
172  cpl_parameter * p;
173 
174  /* Do not create the recipe if an error code is already set */
175  if (cpl_error_get_code() != CPL_ERROR_NONE) {
176  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
177  cpl_func, __LINE__, cpl_error_get_where());
178  return (int)cpl_error_get_code();
179  }
180 
181  if (plugin == NULL) {
182  cpl_msg_error(cpl_func, "Null plugin");
183  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
184  }
185 
186  /* Verify plugin type */
187  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
188  cpl_msg_error(cpl_func, "Plugin is not a recipe");
189  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
190  }
191 
192  /* Get the recipe */
193  recipe = (cpl_recipe *)plugin;
194 
195  /* Create the parameters list in the cpl_recipe object */
196  recipe->parameters = cpl_parameterlist_new();
197  if (recipe->parameters == NULL) {
198  cpl_msg_error(cpl_func, "Parameter list allocation failed");
199  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
200  }
201 
202  /* Fill the parameters list */
203 
204  p = cpl_parameter_new_value("midi.midi_intopd.llx",
205  CPL_TYPE_INT, "Lower left x-value of the window where the signal resides", "midi.midi_intopd",60);
206  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "llx");
207  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
208  cpl_parameterlist_append(recipe->parameters, p);
209 
210  p = cpl_parameter_new_value("midi.midi_intopd.lly",
211  CPL_TYPE_INT, "Lower left y-value of the window where the signal resides", "midi.midi_intopd",11);
212  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lly");
213  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
214  cpl_parameterlist_append(recipe->parameters, p);
215 
216 
217  p = cpl_parameter_new_value("midi.midi_intopd.urx",
218  CPL_TYPE_INT, "Upper right x-value of the window where the signal resides", "midi.midi_intopd",130);
219  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "urx");
220  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
221  cpl_parameterlist_append(recipe->parameters, p);
222 
223 
224  p = cpl_parameter_new_value("midi.midi_intopd.ury",
225  CPL_TYPE_INT, "Upper right y-value of the window where the signal resides", "midi.midi_intopd",18);
226  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ury");
227  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
228  cpl_parameterlist_append(recipe->parameters, p);
229 
230 
231 
232  p = cpl_parameter_new_value("midi.midi_intopd.lomb_fmin",
233  CPL_TYPE_DOUBLE, "Minimum frequency of the Lomb evaluation window", "midi.midi_intopd",70.);
234  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmin");
235  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
236  cpl_parameterlist_append(recipe->parameters, p);
237 
238  p = cpl_parameter_new_value("midi.midi_intopd.lomb_fmax",
239  CPL_TYPE_DOUBLE, "Maximum frequency of the Lomb evaluation window", "midi.midi_intopd",130.);
240  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmax");
241  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
242  cpl_parameterlist_append(recipe->parameters, p);
243 
244 
245  p = cpl_parameter_new_value("midi.midi_intopd.lomb_sampling",
246  CPL_TYPE_INT, "Sampling rate inside the Lomb evaluation window", "midi.midi_intopd",12000);
247  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sampling");
248  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
249  cpl_parameterlist_append(recipe->parameters, p);
250 
251  return 0;
252 }
253 
254 /*----------------------------------------------------------------------------*/
260 /*----------------------------------------------------------------------------*/
261 static int midi_intopd_exec(cpl_plugin * plugin)
262 {
263 
264  cpl_recipe * recipe;
265  int recipe_status;
266  cpl_errorstate initial_errorstate = cpl_errorstate_get();
267 
268  /* Return immediately if an error code is already set */
269  if (cpl_error_get_code() != CPL_ERROR_NONE) {
270  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
271  cpl_func, __LINE__, cpl_error_get_where());
272  return (int)cpl_error_get_code();
273  }
274 
275  if (plugin == NULL) {
276  cpl_msg_error(cpl_func, "Null plugin");
277  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
278  }
279 
280  /* Verify plugin type */
281  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
282  cpl_msg_error(cpl_func, "Plugin is not a recipe");
283  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
284  }
285 
286  /* Get the recipe */
287  recipe = (cpl_recipe *)plugin;
288 
289  /* Verify parameter and frame lists */
290  if (recipe->parameters == NULL) {
291  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
292  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
293  }
294  if (recipe->frames == NULL) {
295  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
296  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
297  }
298 
299  /* Invoke the recipe */
300  recipe_status = midi_intopd(recipe->frames, recipe->parameters);
301 
302  /* Ensure DFS-compliance of the products */
303  if (cpl_dfs_update_product_header(recipe->frames)) {
304  if (!recipe_status) recipe_status = (int)cpl_error_get_code();
305  }
306 
307  if (!cpl_errorstate_is_equal(initial_errorstate)) {
308  /* Dump the error history since recipe execution start.
309  At this point the recipe cannot recover from the error */
310  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
311  }
312 
313  return recipe_status;
314 }
315 
316 /*----------------------------------------------------------------------------*/
322 /*----------------------------------------------------------------------------*/
323 static int midi_intopd_destroy(cpl_plugin * plugin)
324 {
325  cpl_recipe * recipe;
326 
327  if (plugin == NULL) {
328  cpl_msg_error(cpl_func, "Null plugin");
329  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
330  }
331 
332  /* Verify plugin type */
333  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
334  cpl_msg_error(cpl_func, "Plugin is not a recipe");
335  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
336  }
337 
338  /* Get the recipe */
339  recipe = (cpl_recipe *)plugin;
340 
341  cpl_parameterlist_delete(recipe->parameters);
342 
343  return 0;
344 }
345 
346 /*----------------------------------------------------------------------------*/
353 /*----------------------------------------------------------------------------*/
354 static int midi_intopd(cpl_frameset * frameset,
355  const cpl_parameterlist * parlist)
356 {
357 
358  int llx=0;
359  int lly=0;
360  int urx=0;
361  int ury=0;
362  cpl_image * opdmask[DIMENDATA]={NULL,NULL};
363  cpl_image * dummy_image=NULL;
364  cpl_image * dummy_image_data1=NULL;
365  cpl_image * dummy_image_data2=NULL;
366  int Cgood=0;
367  int Csaturated=0;
368 
369  cpl_image * dummy_image_ycollapsed=NULL;
370  cpl_image * mask_goodvalues=NULL;
371  char * first_valid_frame=NULL;
372  int isFirst=0;
373  char * filename=NULL;
374  double image_max_data1=0;
375  double image_max_data2=0;
376  int ext_imaging_data=0;
377  cpl_table * timetable=NULL;
378 
379 
380  cpl_frame * cur_frame=NULL;
381  int dimenDATA=DIMENDATA; /* Assumption: HS Data */
382  cpl_imagelist * imglst_ABOPEN[DIMENDATA]={NULL,NULL}; /* Assumption: HS Data */
383  cpl_imagelist * imglst_ABOPEN_ycollapsed[DIMENDATA]={NULL,NULL}; /* Assumption: HS Data */
384 
385  cpl_errorstate prestate = cpl_errorstate_get();
386  int i=0;
387  /* int j=0; */
388  char * tag=NULL;
389 
390  cpl_table * table=NULL;
391  char * dataname=NULL;
392  cpl_propertylist * qclist=NULL;
393  /* cpl_propertylist * pro_list=NULL; */
394  /* cpl_mask * mask=NULL; */
395  cpl_table * intopd_table=NULL;
396 
397  cpl_array * frequency=NULL;
398 
399  cpl_array * dummy_frequency=NULL;
400  cpl_array * dummy_fringe=NULL;
401 
402  cpl_array ** fringe=NULL;
403  cpl_array ** lomb_out=NULL;
404  cpl_size lomb_maxpos=0;
405  int size_fringe=0;
406  int size_imglist_ABOPEN_ycollapsed=0;
407  double fmin=0.;
408  double fmax=0.;
409  int sampling=0;
410  int workcounter=0;
411 
412 
413 
414 
415 /* Check if siutable files are present in the SOF */
416  if(midi_check_sof(frameset,MIDI_INTERNAL_OPD)<1)
417  {
418  return (int)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
419  "SOF has no appropriate AOPEN fitsfiles! Aborting!");
420  }
421 
422  /* RETRIEVE THE INPUT PARAMETERS */
423 
424  llx = cpl_parameter_get_int(cpl_parameterlist_find_const(parlist, "midi.midi_intopd.llx"));
425  lly = cpl_parameter_get_int(cpl_parameterlist_find_const(parlist, "midi.midi_intopd.lly"));
426  urx = cpl_parameter_get_int(cpl_parameterlist_find_const(parlist, "midi.midi_intopd.urx"));
427  ury = cpl_parameter_get_int(cpl_parameterlist_find_const(parlist, "midi.midi_intopd.ury"));
428 
429  fmin = cpl_parameter_get_double(cpl_parameterlist_find_const(parlist, "midi.midi_intopd.lomb_fmin"));
430  fmax = cpl_parameter_get_double(cpl_parameterlist_find_const(parlist, "midi.midi_intopd.lomb_fmax"));
431  sampling = cpl_parameter_get_int(cpl_parameterlist_find_const(parlist, "midi.midi_intopd.lomb_sampling"));
432 
433 
434  if (!cpl_errorstate_is_equal(prestate)) {
435  return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(), "Could not retrieve the input parameters");
436  }
437 
438  /* Identify the RAW and CALIB frames in the input frameset */
439  cpl_ensure_code(midi_dfs_set_groups(frameset) == CPL_ERROR_NONE,
440  cpl_error_get_code());
441 
442 
443  for (i=0; i<dimenDATA;i++){
444  imglst_ABOPEN[i]=cpl_imagelist_new();
445  imglst_ABOPEN_ycollapsed[i]=cpl_imagelist_new();
446 
447  }
448 
449  timetable=cpl_table_new(0);
450  cpl_table_new_column(timetable,"TIME",CPL_TYPE_DOUBLE);
451  cpl_table_set_column_unit(timetable,"TIME","DAY");
452 
453  cur_frame = cpl_frameset_get_first(frameset);
454  if (cur_frame == NULL) {
455  return (int)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
456  "SOF does not have any file");
457  }
458 
459 /* Walk through the whole Set of Frames SOF and */
460 /* append the images from the tables to the various imagelists */
461 /* as well as the the timetable*/
462 
463  while(cur_frame)
464  {
465 
466  tag = (char*)cpl_frame_get_tag(cur_frame);
467  if (strcmp(tag, MIDI_INTERNAL_OPD)) {
468  cur_frame = cpl_frameset_get_next( frameset );
469  continue;
470  }
471 
472  /* Save the name of the first valid frame to be EWS compatible in the product*/
473  /* Check the recipe input parameters */
474 
475  if(isFirst<1){
476  isFirst=1;
477  first_valid_frame=cpl_sprintf(cpl_frame_get_filename(cur_frame));
478  }
479  cpl_msg_info(cpl_func, "Processing file %s",cpl_frame_get_filename(cur_frame));
480 
481  /* Load extension Imaging Data */
482  ext_imaging_data=cpl_fits_find_extension(cpl_frame_get_filename(cur_frame),"IMAGING_DATA");
483  table = cpl_table_load(cpl_frame_get_filename(cur_frame), ext_imaging_data, 1);
484  if (table == NULL) {
485  return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
486  "Could not load the table");
487  }
488  cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
489 
490 /* Load columns DATA... */
491  for (i=0; i<dimenDATA;i++){
492  dataname=cpl_sprintf("DATA%d",i+1);
493 
494  /* cpl_msg_info(cpl_func, "Scanning for dataname ..."); */
495  if (cpl_table_has_column(table,dataname)){
496  table_to_imglst(dataname,imglst_ABOPEN[i],table);
497  }
498  cpl_msg_info(cpl_func, "Number of so far processed %s Frames: % " CPL_SIZE_FORMAT " ",dataname,cpl_imagelist_get_size(imglst_ABOPEN[i]));
499  cpl_free(dataname);
500  }
501  cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
502 
503  /* Load column TIME... */
504 
505  if (cpl_table_has_column(table,"TIME")){
506  timetable_to_cpltable("TIME",table,timetable);
507  }
508  cpl_msg_info(cpl_func, "Number of so far processed Timestamps: % " CPL_SIZE_FORMAT " ",cpl_table_get_nrow(timetable));
509  cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
510 
511  cpl_table_delete(table);
512 
513 
514  cur_frame = cpl_frameset_get_next( frameset );
515  }
516 
517 
518  midi_intopd_check_parameter(&llx, &lly, &urx, &ury, &fmin, &fmax, &sampling, imglst_ABOPEN[0]);
519 
520 /* Create the mask */
521  cpl_msg_info(cpl_func, "Creating the mask for signal extraction:");
522  cpl_msg_info(cpl_func, "Signal in x: pixel %3d to pixel %3d (all inclusive)",llx,urx);
523  cpl_msg_info(cpl_func, "Signal in y: pixel %3d to pixel %3d (all inclusive)",lly,ury);
524 
525  mask_goodvalues=cpl_image_new((urx-llx)+1,(ury-lly)+1, CPL_TYPE_DOUBLE);
526  cpl_image_add_scalar(mask_goodvalues,1);
527  dummy_image=cpl_imagelist_get(imglst_ABOPEN[1],1);
528  for (i=0; i<dimenDATA;i++){
529  opdmask[i]=cpl_image_new(cpl_image_get_size_x(dummy_image),cpl_image_get_size_y(dummy_image),CPL_TYPE_DOUBLE );
530  cpl_image_copy(opdmask[i],mask_goodvalues,llx,lly);
531  }
532  cpl_image_delete(mask_goodvalues);
533 
534  cpl_msg_info(cpl_func,"Saving the mask file ...");
535  save_mask_for_ews(frameset,parlist,opdmask,"opdmask", first_valid_frame);
536  cpl_free(first_valid_frame);
537 
538 
539 /* Multiply the mask files to the single images in the imagelists */
540  cpl_msg_info(cpl_func,"Multiplying the mask with the images ...");
541 
542  for (i=0; i<dimenDATA;i++){
543  cpl_imagelist_multiply_image(imglst_ABOPEN[i],opdmask[i]);
544  }
545 
546 /* Collapse the single images in the imagelist in y-direction */
547 /* and remove saturated images */
548 
549  cpl_msg_info(cpl_func,"Collapsing images in y-direction and removing saturated images...");
550  Cgood=0;
551  Csaturated=0;
552  for (i=0; i<cpl_imagelist_get_size(imglst_ABOPEN[0]);i++){
553  dummy_image_data1=cpl_imagelist_get(imglst_ABOPEN[0],i);
554  dummy_image_data2=cpl_imagelist_get(imglst_ABOPEN[1],i);
555  image_max_data1=cpl_image_get_max(dummy_image_data1);
556  image_max_data2=cpl_image_get_max(dummy_image_data2);
557  if(image_max_data1>=PIXEL_SATURATION || image_max_data2>=PIXEL_SATURATION ){
558  cpl_table_set_invalid(timetable,"TIME",i);
559  Csaturated++;
560  continue;
561  }
562 
563  dummy_image_ycollapsed=cpl_image_collapse_create(dummy_image_data1,0);
564  cpl_imagelist_set(imglst_ABOPEN_ycollapsed[0],dummy_image_ycollapsed,Cgood);
565 
566  dummy_image_ycollapsed=cpl_image_collapse_create(dummy_image_data2,0);
567  cpl_imagelist_set(imglst_ABOPEN_ycollapsed[1],dummy_image_ycollapsed,Cgood);
568  Cgood++;
569  }
570 
571  if(Csaturated>0){
572  cpl_msg_warning(cpl_func,"%d saturated images skipped",Csaturated);
573  }
574  else {
575  cpl_msg_info(cpl_func,"No saturated images found");
576  }
577 
578  /* If all frames are saturated, exit! */
579  if(cpl_imagelist_get_size(imglst_ABOPEN_ycollapsed[0])<1){
580 
581  cpl_msg_error(cpl_func,"All frames are saturated! Exiting...");
582  /* ---------- Free the memory ---------- */
583  for (i=0; i<dimenDATA;i++){
584  while(cpl_imagelist_get_size(imglst_ABOPEN[i])>0){
585  cpl_image_delete(cpl_imagelist_unset(imglst_ABOPEN[i],0));
586  }
587  while(cpl_imagelist_get_size(imglst_ABOPEN_ycollapsed[i])>0){
588  cpl_image_delete(cpl_imagelist_unset(imglst_ABOPEN_ycollapsed[i],0));
589  }
590 
591 
592  cpl_imagelist_delete(imglst_ABOPEN[i]);
593  cpl_imagelist_delete(imglst_ABOPEN_ycollapsed[i]);
594  cpl_image_delete(opdmask[i]);
595  }
596  cpl_table_delete(timetable);
597  /* ---------- Free the memory ---------- */
598  return -1;
599  }
600 
601  /* Clean the timetable where the corresponding images are saturated */
602  cpl_table_erase_invalid(timetable);
603 
604  cpl_msg_info(cpl_func,"Subtracting DATA2 from DATA1 to remove the background and extract the fringes ...");
605  cpl_imagelist_subtract(imglst_ABOPEN_ycollapsed[0], imglst_ABOPEN_ycollapsed[1]);
606 
607 /* For Diagnostic during development */
608  if(0){
609 /* cpl_imagelist_save(imglst_ABOPEN_ycollapsed[0], "armin.fits", CPL_BPP_IEEE_FLOAT, NULL, CPL_IO_CREATE); */
610 /* for (i=0; i<cpl_imagelist_get_size(imglst_ABOPEN_ycollapsed[0]);i=i+50){ */
611  for (i=0; i<30;i=i+1){
612  filename = cpl_sprintf("slice_%d.fits",i);
613  cpl_image_save(cpl_imagelist_get(imglst_ABOPEN_ycollapsed[0],i), filename, CPL_BPP_IEEE_FLOAT, NULL, CPL_IO_CREATE);
614  cpl_free(filename);
615  }
616 
617  cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
618 
619 /* cpl_table_dump_structure(timetable,NULL); */
620 /* cpl_table_dump(timetable,0,100,NULL); */
621 /* cpl_table_save(timetable,NULL,NULL,"timetable.fits",CPL_IO_CREATE); */
622 /* cpl_image_dump_window(cpl_imagelist_get(imglst_ABOPEN_ycollapsed[0],10),1,1,172,1,stdout); */
623  }
624 
625  size_fringe=sizeof(wavecalib_prism_hs_frequency)/sizeof(double);
626 
627  dummy_frequency =cpl_array_new(size_fringe, CPL_TYPE_DOUBLE);
628  cpl_array_copy_data_double(dummy_frequency, wavecalib_prism_hs_frequency);
629  frequency=cpl_array_extract(dummy_frequency, llx-1,urx-llx+1);
630  cpl_array_delete(dummy_frequency);
631 
632  fringe=cpl_malloc(cpl_imagelist_get_size(imglst_ABOPEN_ycollapsed[0]) * sizeof(cpl_array *));
633  for (i=0; i<cpl_imagelist_get_size(imglst_ABOPEN_ycollapsed[0]);i=i+1){
634  dummy_fringe =cpl_array_new(size_fringe, CPL_TYPE_DOUBLE);
635  dummy_image_ycollapsed=cpl_image_cast(cpl_imagelist_get(imglst_ABOPEN_ycollapsed[0],i),CPL_TYPE_DOUBLE);
636  cpl_array_copy_data_double(dummy_fringe, cpl_image_get_data_double(dummy_image_ycollapsed));
637  fringe[i]=cpl_array_extract(dummy_fringe, llx-1,urx-llx+1);
638  cpl_image_delete(dummy_image_ycollapsed);
639  cpl_array_delete(dummy_fringe);
640  }
641 
642 /* cpl_msg_info(cpl_func,"frequency: %d fringe: %d ", cpl_array_get_size(frequency), cpl_array_get_size(fringe[1])); */
643 /* for (i=0; i<cpl_array_get_size(fringe[1]);i=i+1){ */
644 /* cpl_msg_info(cpl_func,"frequency, fringe %d %g, %g",i, */
645 /* cpl_array_get_double(frequency,i,NULL), */
646 /* cpl_array_get_double(fringe[1],i,NULL)); */
647 /* } */
648 
649 
650  lomb_out=cpl_malloc(2 * sizeof(cpl_array *));
651 
652  cpl_table_new_column(timetable,"PATH_DIFFERENCE",CPL_TYPE_DOUBLE);
653  cpl_table_new_column(timetable,"LOMB_POWER",CPL_TYPE_DOUBLE);
654  cpl_table_set_column_unit (timetable, "PATH_DIFFERENCE","m");
655  cpl_table_set_column_unit (timetable, "TIME","day");
656 
657 
658  size_imglist_ABOPEN_ycollapsed=cpl_imagelist_get_size(imglst_ABOPEN_ycollapsed[0]);
659  workcounter=0;
660 
661  cpl_msg_info(cpl_func," ");
662  cpl_msg_info(cpl_func,"Deriving the OPD stability based on the paper of Lawson, P.R. 1995:");
663  cpl_msg_info(cpl_func,"J. Opt. Soc. Am. A, Vol. 12, No. 2, p. 366 - 374");
664  cpl_msg_info(cpl_func,"Fringes are analyzed in the frequency domain by the usage of the");
665  cpl_msg_info(cpl_func,"Scargle-Lomb algorithm: ApJ, vol. 263, Dec. 15, 1982, p. 835-853.");
666  cpl_msg_info(cpl_func," ");
667  cpl_msg_info(cpl_func,"The detector-channel to lambda/frequency mapping is not derived");
668  cpl_msg_info(cpl_func,"from the analyzed images, but the values are static to this recipe");
669  cpl_msg_info(cpl_func,"(see variable wavecalib_prism_hs_frequency)");
670  cpl_msg_info(cpl_func," ");
671 
672  for (i=0; i<size_imglist_ABOPEN_ycollapsed;i=i+1){
673 /* for (i=19; i<20;i=i+1){ */
674  lomb_maxpos=0;
675  lomb(fmin,fmax,sampling,frequency,fringe[i],lomb_out);
676  cpl_array_get_maxpos (lomb_out[1], &lomb_maxpos);
677  cpl_table_set_double (timetable, "PATH_DIFFERENCE", i, cpl_array_get_double(lomb_out[0], lomb_maxpos,NULL)/1e6);
678  cpl_table_set_double (timetable, "LOMB_POWER", i, cpl_array_get_max(lomb_out[1]));
679 
680 
681 /* cpl_msg_info(cpl_func,"Time, Power, Frequency: %.15e %.10e %.5e", */
682 /* cpl_table_get_double(timetable, "TIME", i, NULL), */
683 /* cpl_array_get_max(lomb_out[1]), */
684 /* cpl_array_get_double(lomb_out[0], lomb_maxpos,NULL)/1e6); */
685 
686 /* for(j=0;j<cpl_array_get_size(lomb_out[0]);j++){ */
687 /* cpl_msg_info(cpl_func,"frequency, fringe %g, %g", */
688 /* cpl_array_get_double(lomb_out[0],j,NULL), */
689 /* cpl_array_get_double(lomb_out[1],j,NULL)); */
690 
691 /* } */
692  cpl_array_delete(lomb_out[0]);
693  cpl_array_delete(lomb_out[1]);
694 
695  if(i%(int)(size_imglist_ABOPEN_ycollapsed/10) == 0)
696  {
697  cpl_msg_info(cpl_func,"%3d per cent done",workcounter);
698  workcounter+=10;
699  }
700 
701  }
702  cpl_msg_info(cpl_func," All done!");
703 
704 
705 
706 /* Save it to a fits table */
707 
708 
709 /* Propertylist to write to the extension */
710  qclist=cpl_propertylist_new();
711 
712  cpl_propertylist_update_string(qclist, CPL_DFS_PRO_CATG, "MIDI_INTOPD");
713  cpl_propertylist_append_string(qclist, "EXTNAME", "OPD_ACCURACY");
714 
715  /*Derive QC parameters*/
716  midi_intopd_qc_stats(qclist,timetable,"PATH_DIFFERENCE");
717 
718 
719  cpl_dfs_save_table(frameset, NULL, parlist, frameset, NULL, timetable,
720  qclist, "midi_intopd",
721  qclist, NULL,
722  PACKAGE "/" PACKAGE_VERSION,
723  "midi_intopd.fits");
724  cpl_table_delete(intopd_table);
725 
726 
727 /* ---------- Free the memory ---------- */
728 
729  for (i=0; i<cpl_imagelist_get_size(imglst_ABOPEN_ycollapsed[0]);i=i+1){
730  cpl_array_delete(fringe[i]);
731  }
732 
733  for (i=0; i<dimenDATA;i++){
734  while(cpl_imagelist_get_size(imglst_ABOPEN[i])>0){
735  cpl_image_delete(cpl_imagelist_unset(imglst_ABOPEN[i],0));
736  }
737  while(cpl_imagelist_get_size(imglst_ABOPEN_ycollapsed[i])>0){
738  cpl_image_delete(cpl_imagelist_unset(imglst_ABOPEN_ycollapsed[i],0));
739  }
740 
741 
742  cpl_imagelist_delete(imglst_ABOPEN[i]);
743  cpl_imagelist_delete(imglst_ABOPEN_ycollapsed[i]);
744  cpl_image_delete(opdmask[i]);
745  }
746  cpl_table_delete(timetable);
747 
748  cpl_array_delete(frequency);
749  cpl_free(fringe);
750  cpl_free(lomb_out);
751  cpl_propertylist_delete(qclist);
752 
753 
754 /* ---------- Free the memory ---------- */
755 
756 
757  return (int)cpl_error_get_code();
758 }
759 
760 
761 static void midi_intopd_check_parameter(int * llx, int * lly,
762  int * urx, int * ury,
763  double * fmin, double * fmax, int * sampling,
764  cpl_imagelist * imglst_ABOPEN0)
765 {
766  int size_x=0;
767  int size_y=0;
768  size_x=cpl_image_get_size_x(cpl_imagelist_get(imglst_ABOPEN0,1));
769  size_y=cpl_image_get_size_y(cpl_imagelist_get(imglst_ABOPEN0,1));
770 
771  cpl_msg_info(cpl_func, "Checking recipe parameters ...");
772 
773  if (*llx < 1)
774  {
775  *llx=1;
776  cpl_msg_warning(cpl_func, "recipe parameters llx is reset to %d",*llx);
777  }
778  if (*lly < 1 )
779  {
780  *lly=1;
781  cpl_msg_warning(cpl_func, "recipe parameters lly is reset to %d",*lly);
782  }
783  if (*urx <= *llx)
784  {
785  *urx=*llx+1;
786  cpl_msg_warning(cpl_func, "recipe parameters urx is reset to %d",*urx);
787  }
788  if (*ury <= *lly )
789  {
790  *ury=*lly+1;
791  cpl_msg_warning(cpl_func, "recipe parameters ury is reset to %d",*ury);
792  }
793 
794  if (*llx > size_x)
795  {
796  *llx=size_x-1;
797  cpl_msg_warning(cpl_func, "recipe parameters llx is reset to %d",*llx);
798  }
799  if (*lly > size_y)
800  {
801  *lly=size_y-1;
802  cpl_msg_warning(cpl_func, "recipe parameters lly is reset to %d",*lly);
803  }
804 
805  if (*urx > size_x)
806  {
807  *urx=size_x;
808  cpl_msg_warning(cpl_func, "recipe parameters urx is reset to %d",*urx);
809  }
810  if (*ury > size_y)
811  {
812  *ury=size_y;
813  cpl_msg_warning(cpl_func, "recipe parameters ury is reset to %d",*ury);
814  }
815 
816 
817  if (*sampling<1)
818  {
819  *sampling=1;
820  cpl_msg_warning(cpl_func, "recipe parameters sampling is reset to %d",*sampling);
821  }
822 
823  if (*fmin < 0)
824  {
825  *fmin=0.;
826  cpl_msg_warning(cpl_func, "recipe parameters fmin is reset to %g",*fmin);
827  }
828 
829  if (*fmax < *fmin)
830  {
831  *fmax=*fmin+2*DBL_MIN*(*sampling);
832  cpl_msg_warning(cpl_func, "recipe parameters fmax is reset to %g",*fmax);
833  }
834 
835  return;
836 }
837 
838 
839 void save_mask_for_ews(cpl_frameset * frameset, const cpl_parameterlist * parlist,
840  cpl_image ** opdmask ,const char * name, char * first_valid_frame)
841 {
842 
843  char * fitsname;
844  cpl_table * dummy_table=NULL;
845  cpl_propertylist * qclist=NULL;
846  cpl_image * opdmask_float[DIMENDATA]; /* Assumption: HS Data */
847 
848  qclist = cpl_propertylist_new();
849 
850  cpl_propertylist_update_string(qclist, CPL_DFS_PRO_CATG, "MIDI_MASK_DATA1");
851  fitsname = cpl_sprintf("%s%s",name, "_DATA1.fits");
852  if (cpl_dfs_save_image(frameset, NULL, parlist, frameset, NULL, opdmask[0],
853  CPL_BPP_IEEE_FLOAT, name,
854  qclist, NULL,
855  PACKAGE "/" PACKAGE_VERSION,
856  fitsname)) {
857  /* Propagate the error */
858  (void)cpl_error_set_where(cpl_func);
859  }
860  cpl_free(fitsname);
861 
862 
863  cpl_propertylist_update_string(qclist, CPL_DFS_PRO_CATG, "MIDI_MASK_DATA2");
864  fitsname = cpl_sprintf("%s%s",name, "_DATA2.fits");
865  if (cpl_dfs_save_image(frameset, NULL, parlist, frameset, NULL, opdmask[1],
866  CPL_BPP_IEEE_FLOAT, name,
867  qclist, NULL,
868  PACKAGE "/" PACKAGE_VERSION,
869  fitsname)) {
870  /* Propagate the error */
871  (void)cpl_error_set_where(cpl_func);
872  }
873  cpl_free(fitsname);
874 
875 
876 /* Save it to a fits table */
877 
878  dummy_table=cpl_table_new(1);
879 
880  cpl_propertylist_update_string(qclist, CPL_DFS_PRO_CATG, "MIDI_MASK_INTOPD");
881 /* Propertylist to write to the extension */
882  cpl_propertylist_append_string (qclist, "EXTNAME", "IMAGING_DATA");
883 
884  opdmask_float[0]=cpl_image_cast(opdmask[0],CPL_TYPE_FLOAT);
885  opdmask_float[1]=cpl_image_cast(opdmask[1],CPL_TYPE_FLOAT);
886 
887 
888 
889  append_image_to_table(dummy_table,"DATA1",opdmask_float[0],0);
890  append_image_to_table(dummy_table,"DATA2",opdmask_float[1],0);
891 
892 
893  fitsname = cpl_sprintf("%s%s",name, ".fits");
894 
895  cpl_dfs_save_table(frameset, NULL, parlist, frameset, NULL, dummy_table,
896  qclist, name,
897  qclist, NULL,
898  PACKAGE "/" PACKAGE_VERSION,
899  fitsname);
900  cpl_table_delete(dummy_table);
901  cpl_free(fitsname);
902 
903  cpl_image_delete(opdmask_float[0]);
904  cpl_image_delete(opdmask_float[1]);
905  cpl_propertylist_delete(qclist);
906 
907  /* Append the IMAGING_DETECTOR table from the first valid image */
908  /* midi_copy_extension() is a workaround to cpl_table_save() as
909  * the latter is modifiing the content during saving */
910 
911  midi_copy_extension(first_valid_frame, "opdmask.fits", "IMAGING_DETECTOR");
912 
913  return;
914 
915 }
916 
917 
918 /*----------------------------------------------------------------------------*/
926 /*----------------------------------------------------------------------------*/
927 
928 static int midi_copy_extension(const char * infile , const char * outfile, const char * extension_name)
929 {
930 
931 /* cpl_propertylist * pHeader= NULL; */
932 /* cpl_table * pTable= NULL; */
933 /* int ext_imaging_detector=-1; */
934 
935 /* ext_imaging_detector=cpl_fits_find_extension(infile, extension_name); */
936 
937 /* cpl_msg_info(cpl_func,"%d",ext_imaging_detector); */
938 
939 /* pHeader = cpl_propertylist_load(infile, ext_imaging_detector ); */
940 /* pTable = cpl_table_load(infile, ext_imaging_detector, 1 ); */
941 
942 /* if (pHeader ==NULL || pTable==NULL) */
943 /* { */
944 /* cpl_msg_error(cpl_func,"Error loading the extended header or table of %s",infile); */
945 
946 /* cpl_propertylist_delete(pHeader); */
947 /* cpl_table_delete(pTable); */
948 
949 /* return -1; */
950 /* } */
951 
952 /* if (CPL_ERROR_NONE != cpl_table_save(pTable, NULL, pHeader, outfile, CPL_IO_EXTEND )) */
953 /* { */
954 /* cpl_msg_error(cpl_func,"Error when saving Extension: %s %s",cpl_error_get_message(),cpl_error_get_where()); */
955 /* } */
956 
957 
958 /* return 0; */
959 
960 
961  fitsfile * fptrin=NULL;
962  fitsfile * fptrout=NULL;
963  int status=0;
964 
965  fits_open_diskfile(&fptrin, infile, READONLY, &status);
966  fits_open_diskfile(&fptrout, outfile, READWRITE, &status);
967  fits_movnam_hdu(fptrin, ANY_HDU, (char *)extension_name, 0, &status);
968  fits_copy_hdu(fptrin, fptrout, 0, &status);
969  fits_close_file(fptrin, &status);
970  fits_close_file(fptrout, &status);
971 
972  if (status != 0){
973  cpl_msg_error(cpl_func,"A problem occured while copying the EXTENSION: %s", extension_name);
974  return 1;
975  }
976  else{
977  return 0;
978  }
979 }
980 
981 
982 
983 /*----------------------------------------------------------------------------*/
992 /*----------------------------------------------------------------------------*/
993 
994 static int append_image_to_table(cpl_table * table, const char * columname, cpl_image * image, int row)
995 {
996 
997  cpl_array * array_dimension=NULL;
998  cpl_array * array_dummy=NULL;
999 
1000  array_dimension=cpl_array_new(2,CPL_TYPE_INT);
1001  cpl_array_set(array_dimension, 0,cpl_image_get_size_x(image));
1002  cpl_array_set(array_dimension, 1,cpl_image_get_size_y(image));
1003 
1004  cpl_table_new_column_array(table, columname, CPL_TYPE_FLOAT, cpl_image_get_size_x(image)*cpl_image_get_size_y(image));
1005  cpl_table_set_column_dimensions(table,columname,array_dimension);
1006  array_dummy = cpl_array_wrap_float(cpl_image_get_data_float(image), cpl_image_get_size_x(image)*cpl_image_get_size_y(image));
1007  cpl_table_set_array(table, columname, row, array_dummy);
1008  cpl_array_unwrap(array_dummy);
1009 
1010 
1011  cpl_array_delete(array_dimension);
1012 
1013  return 0;
1014 }
1015 
1016 /*----------------------------------------------------------------------------*/
1023 /*----------------------------------------------------------------------------*/
1024 static void midi_intopd_qc_stats(cpl_propertylist * pro_list, cpl_table * table,
1025  const char * column_name)
1026 {
1027  double table_max=0.;
1028  double table_min=0.;
1029  double table_mean=0.;
1030  double table_median=0.;
1031  double table_stdev=0.;
1032 
1033  table_min=cpl_table_get_column_min(table,column_name);
1034  table_max=cpl_table_get_column_max(table,column_name);
1035  table_mean=cpl_table_get_column_mean(table,column_name);
1036  table_median=cpl_table_get_column_median(table,column_name);
1037  table_stdev=cpl_table_get_column_stdev(table,column_name);
1038 
1039  cpl_propertylist_update_double(pro_list, "ESO QC INTOPD MIN",table_min);
1040  cpl_propertylist_update_double(pro_list, "ESO QC INTOPD MAX",table_max);
1041  cpl_propertylist_update_double(pro_list, "ESO QC INTOPD MEAN",table_mean);
1042  cpl_propertylist_update_double(pro_list, "ESO QC INTOPD MEDIAN",table_median);
1043  cpl_propertylist_update_double(pro_list, "ESO QC INTOPD STDEV",table_stdev);
1044 
1045  return;
1046 }
1047