GRAVI Pipeline Reference Manual  1.2.3
gravi_data.c
1 /* $Id: gravi_data_3.c, 2011/05/18 15:21:53 nazouaoui Exp $
2  *
3  * This file is part of the ESO Common Pipeline Library
4  * Copyright (C) 2001-2005 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 
35 /*
36  * History :
37  * ekw 10/01/2019 Remove x in int gravi_data_get_dark_pos(cpl_table * detector_table, int reg, int x);
38  */
39 /*-----------------------------------------------------------------------------
40  Includes
41  -----------------------------------------------------------------------------*/
42 
43 #include <cpl.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <config.h>
47 #include <ctype.h>
48 #include <time.h>
49 #include <math.h>
50 #include <regex.h>
51 
52 #include "gravi_dfs.h"
53 #include "gravi_data.h"
54 #include "gravi_pfits.h"
55 #include "gravi_utils.h"
56 #include "gravi_cpl.h"
57 
58 /*-----------------------------------------------------------------------------
59  Defines
60  -----------------------------------------------------------------------------*/
61 
62 #define GRAVI_DATA_SIZE 30
63 
64 struct _gravi_data_{
65  cpl_propertylist * primary_hdr;
66  int nb_ext;
67  cpl_propertylist ** exts_hdrs;
68  cpl_imagelist ** exts_imgl;
69  cpl_table ** exts_tbs;
70 };
71 
72 /* ----------------------------------------------------------------------------
73  Private prototypes
74  ---------------------------------------------------------------------------- */
75 
76 int gravi_data_is_oi_ext (cpl_propertylist * hdr);
77 cpl_error_code gravi_data_check_savetypes(cpl_propertylist * hdr, cpl_table * oi_table);
78 int gravi_data_get_dark_pos(cpl_table * detector_table, int reg);
79 
80 /*-----------------------------------------------------------------------------
81  Functions code
82  -----------------------------------------------------------------------------*/
83 
84 /*----------------------------------------------------------------------------*/
100 /*----------------------------------------------------------------------------*/
101 
102 gravi_data * gravi_data_new (int nb_ext)
103 {
104  gravi_msg_function_start(0);
105  cpl_ensure (nb_ext==0, CPL_ERROR_ILLEGAL_INPUT, NULL);
106 
107  gravi_data *self = cpl_malloc (sizeof (gravi_data));
108  self->primary_hdr = cpl_propertylist_new ();
109  self->nb_ext = 0;
110 
111  self->exts_hdrs = cpl_malloc (GRAVI_DATA_SIZE * sizeof(cpl_propertylist*));
112  self->exts_tbs = cpl_malloc (GRAVI_DATA_SIZE * sizeof(cpl_table*));
113  self->exts_imgl = cpl_malloc (GRAVI_DATA_SIZE * sizeof(cpl_imagelist*));
114 
115  for(int i = 0; i < GRAVI_DATA_SIZE; i++){
116  self->exts_tbs[i] = NULL;
117  self->exts_hdrs[i] = NULL;
118  self->exts_imgl[i] = NULL;
119  }
120 
121  gravi_msg_function_exit(0);
122  return self;
123 }
124 
125 /*----------------------------------------------------------------------------*/
135 /*----------------------------------------------------------------------------*/
136 
137 void gravi_data_delete (gravi_data *self)
138 {
139  gravi_msg_function_start(0);
140 
141  if (self) {
142  /* Delete main header */
143  FREE (cpl_propertylist_delete, self->primary_hdr);
144  /* Delete data */
145  FREELOOP (cpl_propertylist_delete, self->exts_hdrs, GRAVI_DATA_SIZE);
146  FREELOOP (cpl_table_delete, self->exts_tbs, GRAVI_DATA_SIZE);
147  FREELOOP (cpl_imagelist_delete, self->exts_imgl, GRAVI_DATA_SIZE);
148  /* Delete structure */
149  FREE (cpl_free, self);
150  }
151 
152  gravi_msg_function_exit(0);
153  return;
154 }
155 
156 /*----------------------------------------------------------------------------*/
160 /*----------------------------------------------------------------------------*/
161 
162 int gravi_data_is_oi_ext (cpl_propertylist * hdr)
163 {
164  if (hdr==NULL) { return 0; }
165  if (!cpl_propertylist_has (hdr, "EXTNAME")) { return 0; }
166  if (strncmp (gravi_pfits_get_extname (hdr), "OI_", 3)) { return 0; }
167  return 1;
168 }
169 
170 /*----------------------------------------------------------------------------*/
184 /*----------------------------------------------------------------------------*/
185 
186 cpl_error_code gravi_data_check_savetypes (cpl_propertylist * hdr, cpl_table * oi_table)
187 {
188  cpl_ensure_code (hdr, CPL_ERROR_NULL_INPUT);
189  cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
190 
191  /* If not an OI_FITS table, nothing to do */
192  if (!gravi_data_is_oi_ext (hdr)) return CPL_ERROR_NONE;
193 
194  if ( cpl_table_has_column (oi_table, "FLAG") ) {
195  cpl_table_set_column_savetype(oi_table, "FLAG", CPL_TYPE_BOOL);
196  }
197 
198  if ( cpl_table_has_column (oi_table, "STA_INDEX") ) {
199  cpl_table_set_column_savetype(oi_table, "STA_INDEX", CPL_TYPE_SHORT);
200  }
201 
202  if ( cpl_table_has_column (oi_table, "TARGET_ID") ) {
203  cpl_table_set_column_savetype(oi_table, "TARGET_ID", CPL_TYPE_SHORT);
204  }
205 
206  if ( cpl_table_has_column (oi_table, "MNT_STA") ) {
207  cpl_table_set_column_savetype(oi_table, "MNT_STA", CPL_TYPE_SHORT);
208  }
209 
210  /* Check errors */
211  if ( cpl_error_get_code() != CPL_ERROR_NONE ) {
212  cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
213  "Cannot reinstall the savetypes");
214  return cpl_error_get_code();
215  }
216 
217  return CPL_ERROR_NONE;
218 }
219 
220 /*----------------------------------------------------------------------------*/
234 /*----------------------------------------------------------------------------*/
235 
236 gravi_data * gravi_data_duplicate (const gravi_data *self)
237 {
238  gravi_msg_function_start(1);
239  cpl_ensure (self, CPL_ERROR_NULL_INPUT, NULL);
240 
241  gravi_data * copy = gravi_data_new(0);
242  copy->nb_ext = self->nb_ext;
243 
244  if (self->primary_hdr) {
245  cpl_propertylist_delete (copy->primary_hdr);
246  copy->primary_hdr = cpl_propertylist_duplicate(self->primary_hdr);
247  } else {
248  cpl_msg_warning (cpl_func,"a data without header shall not exist");
249  }
250 
251  CPLCHECK_NUL ("Cannot duplicate header");
252 
253  for (int i = 0; i < copy->nb_ext ; i++){
254  if (self->exts_hdrs[i])
255  copy->exts_hdrs[i] = cpl_propertylist_duplicate(self->exts_hdrs[i]);
256  if (self->exts_tbs[i]) {
257  copy->exts_tbs[i] = cpl_table_duplicate(self->exts_tbs[i]);
258  gravi_data_check_savetypes (copy->exts_hdrs[i], copy->exts_tbs[i]);
259  }
260  if (self->exts_imgl[i])
261  copy->exts_imgl[i] = cpl_imagelist_duplicate(self->exts_imgl[i]);
262 
263  CPLCHECK_NUL ("Cannot duplicate extension");
264  }
265 
266  gravi_msg_function_exit(1);
267  return copy;
268 }
269 
270 
271 /*----------------------------------------------------------------------------*/
288 /*----------------------------------------------------------------------------*/
289 
290 cpl_error_code gravi_data_append (gravi_data * first, const gravi_data * second, int force)
291 {
292  gravi_msg_function_start(1);
293  cpl_ensure_code (first, CPL_ERROR_NULL_INPUT);
294  cpl_ensure_code (second, CPL_ERROR_NULL_INPUT);
295  cpl_ensure_code (first->nb_ext == second->nb_ext, CPL_ERROR_INCOMPATIBLE_INPUT);
296 
297  cpl_msg_warning (cpl_func, "Append data: keep only the HEADER of the first data");
298  cpl_msg_warning (cpl_func, "Append data: FIXME: only works for OIFITS data");
299 
300  for (int i = 0; i < first->nb_ext ; i++) {
301 
302  /* Check EXTNAME */
303  const char * name1 = gravi_pfits_get_extname (first->exts_hdrs[i]);
304  const char * name2 = gravi_pfits_get_extname (second->exts_hdrs[i]);
305  cpl_ensure_code (!strcmp (name1, name2), CPL_ERROR_INCOMPATIBLE_INPUT);
306 
307  /* These tables shall not be merged, but shall be equal */
308  if ( !strcmp (name1,"OI_WAVELENGTH") ||
309  !strcmp (name1, "OI_TARGET") ||
310  !strcmp (name1, "OI_ARRAY") ||
311  !strcmp (name1, "IMAGING_DETECTOR_SC") ||
312  !strcmp (name1, "IMAGING_DETECTOR_FT") ||
313  !strcmp (name1, "ARRAY_DESCRIPTION") ||
314  !strcmp (name1, "ARRAY_GEOMETRY") ||
315  !strcmp (name1, "OPTICAL_TRAIN") ) {
316  if (force) {
317  cpl_msg_info (cpl_func,"Don't check table %s", name1);
318  continue;
319  }
320 
321  cpl_msg_info (cpl_func,"Check table %s", name1);
322  if ( !gravi_table_are_equal (first->exts_tbs[i], second->exts_tbs[i]) ) {
323  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT, "Tables %s are different", name1);
324  return 0;
325  }
326  continue;
327  }
328 
329  /* Append as table */
330  if ( first->exts_tbs[i] != NULL ) {
331  cpl_msg_info (cpl_func,"Merge table %s", name1);
332  cpl_table_insert (first->exts_tbs[i], second->exts_tbs[i], CPL_SIZE_MAX);
333 
334  CPLCHECK_MSG ("Cannot append table");
335  continue;
336  }
337 
338  /* Append as imagelist (duplicate each image) */
339  if ( first->exts_imgl[i] != NULL ) {
340  cpl_msg_info (cpl_func,"Merge imglist %s", name1);
341  cpl_size n_first = cpl_imagelist_get_size (first->exts_imgl[i]);
342  cpl_size n_second = cpl_imagelist_get_size (second->exts_imgl[i]);
343  CPLCHECK_MSG ("Cannot get the size of imglist");
344 
345  for (cpl_size iimg = 0; iimg < n_second; iimg++) {
346  cpl_image * img = cpl_image_duplicate (cpl_imagelist_get (second->exts_imgl[i], iimg));
347  cpl_imagelist_set (first->exts_imgl[i], img, n_first + iimg);
348  }
349 
350  CPLCHECK_MSG ("Cannot append imglist");
351  continue;
352  }
353 
354  CPLCHECK_MSG ("Cannot append data");
355  }
356 
357  gravi_msg_function_exit(1);
358  return CPL_ERROR_NONE;
359 }
360 
361 /*----------------------------------------------------------------------------*/
374 /*----------------------------------------------------------------------------*/
375 
376 gravi_data * gravi_data_load (const char * filename)
377 {
378  gravi_msg_function_start(0);
379  cpl_ensure (filename, CPL_ERROR_NULL_INPUT, NULL);
380 
381  cpl_msg_debug (cpl_func, "Load file : %s", filename);
382 
383  /* Find a number of extension on the FITS file */
384  int nb_ext = cpl_fits_count_extensions (filename);
385  if (nb_ext == -1){
386  cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT, "no extension in this file");
387  return NULL;
388  }
389 
390  /* Create data */
391  gravi_data * self = gravi_data_new (0);
392 
393  /* Load primary header */
394  cpl_propertylist * header = cpl_propertylist_load (filename, 0);
395  cpl_propertylist_append (self->primary_hdr, header);
396  FREE (cpl_propertylist_delete, header);
397 
398  /* Loop on extensions */
399  for (int i = 0; i < nb_ext ; i++ ){
400 
401  /* Load header of this extension */
402  self->exts_hdrs[i] = cpl_propertylist_load (filename, i+1);
403  CPLCHECK_NUL ("Cannot load header");
404 
405  /* Load extension as table */
406  if (gravi_pfits_get_extension_type (self->exts_hdrs[i]) == 2) {
407  self->exts_tbs[i] = cpl_table_load (filename, i+1, 0);
408  gravi_data_check_savetypes (self->exts_hdrs[i], self->exts_tbs[i]);
409  CPLCHECK_NUL ("Cannot load bintable");
410  }
411  /* Load extension as imagelist */
412  else if (gravi_pfits_get_extension_type (self->exts_hdrs[i]) == 3) {
413  self->exts_imgl[i] = cpl_imagelist_load (filename,CPL_TYPE_DOUBLE,i+1);
414  CPLCHECK_NUL ("Cannot load imagelist");
415  }
416  /* error */
417  else {
418  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT, "The dimension of the extension is wrong");
419  gravi_data_delete (self);
420  return NULL;
421  }
422 
423  self->nb_ext ++;
424  }
425 
426  gravi_msg_function_exit(0);
427  return self;
428 }
429 
430 /*----------------------------------------------------------------------------*/
447 /*----------------------------------------------------------------------------*/
448 gravi_data * gravi_data_load_ext(const char * filename,
449  const char * extensions_regexp)
450 {
451  gravi_msg_function_start(0);
452  cpl_ensure (filename, CPL_ERROR_NULL_INPUT, NULL);
453 
454  cpl_msg_debug (cpl_func, "Load file : %s", filename);
455 
456  /* Find a number of extension on the FITS file */
457  int nb_ext = cpl_fits_count_extensions (filename);
458  if (nb_ext == -1){
459  cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT, "no extension in this file");
460  return NULL;
461  }
462 
463  /* Create data */
464  gravi_data * self = gravi_data_new (0);
465 
466  /* Load primary header */
467  cpl_propertylist * header = cpl_propertylist_load (filename, 0);
468  cpl_propertylist_append (self->primary_hdr, header);
469  FREE (cpl_propertylist_delete, header);
470 
471  //Compile regular expression
472  regex_t filter;
473  int status = regcomp(&filter, extensions_regexp, REG_EXTENDED | REG_NOSUB);
474  if(status) {
475  cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
476  "Cannot interpret extension regular expression");
477  return NULL;
478  }
479 
480  /* Loop on extensions */
481  int iext = 0;
482  for (int i = 0; i < nb_ext ; i++ ){
483 
484  //Read the extension header
485  cpl_propertylist *proplist = cpl_propertylist_load (filename, i+1);
486  const char *extname = cpl_propertylist_get_string (proplist, "EXTNAME");
487  CPLCHECK_NUL ("Cannot load header");
488 
489  //Check whether it is one of the required extensions
490  if (regexec(&filter, extname, 0, NULL, 0) == REG_NOMATCH)
491  {
492  cpl_propertylist_delete(proplist);
493  continue;
494  }
495  /* Load header of this extension */
496  self->exts_hdrs[iext] = proplist;
497 
498  /* Load extension as table */
499  if (gravi_pfits_get_extension_type (self->exts_hdrs[iext]) == 2) {
500  self->exts_tbs[iext] = cpl_table_load (filename, i+1, 0);
501  gravi_data_check_savetypes (self->exts_hdrs[iext], self->exts_tbs[iext]);
502  CPLCHECK_NUL ("Cannot load bintable");
503  }
504  /* Load extension as imagelist */
505  else if (gravi_pfits_get_extension_type (self->exts_hdrs[iext]) == 3) {
506  self->exts_imgl[iext] = cpl_imagelist_load (filename,CPL_TYPE_DOUBLE,i+1);
507  CPLCHECK_NUL ("Cannot load imagelist");
508  }
509  /* error */
510  else {
511  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT, "The dimension of the extension is wrong");
512  gravi_data_delete (self);
513  regfree(&filter);
514  return NULL;
515  }
516 
517  self->nb_ext ++;
518  iext++;
519  }
520 
521  regfree(&filter);
522  gravi_msg_function_exit(0);
523  return self;
524 }
525 
526 /*----------------------------------------------------------------------------*/
537 /*----------------------------------------------------------------------------*/
538 
539 cpl_error_code gravi_data_dump_mode (gravi_data * data)
540 {
541  cpl_ensure_code (data, CPL_ERROR_NULL_INPUT);
542  cpl_errorstate prestate = cpl_errorstate_get();
543 
544  /* Dump minimum info */
545  cpl_propertylist * header = gravi_data_get_header (data);
546  const char * res = gravi_pfits_get_spec_res (header);
547  const char * scpol = gravi_pfits_get_pola_mode (header, GRAVI_SC);
548  const char * ftpol = gravi_pfits_get_pola_mode (header, GRAVI_FT);
549 
550  if (cpl_errorstate_is_equal(prestate)) {
551  cpl_msg_info (cpl_func, "(insmode: %s %s %s)", res, scpol, ftpol);
552  } else {
553  cpl_errorstate_set (prestate);
554  }
555 
556  return CPL_ERROR_NONE;
557 }
558 
559 /*----------------------------------------------------------------------------*/
571 /*----------------------------------------------------------------------------*/
572 
573 gravi_data * gravi_data_load_frame (cpl_frame * frame,
574  cpl_frameset * used_frameset)
575 {
576  cpl_ensure (frame, CPL_ERROR_NULL_INPUT, NULL);
577 
578  const char * filename = cpl_frame_get_filename (frame);
579 
580  cpl_msg_info (cpl_func, "Load file %s (%s)", FILESHORT(filename), cpl_frame_get_tag (frame));
581 
582  if (used_frameset) cpl_frameset_insert (used_frameset, cpl_frame_duplicate (frame));
583 
584  /* Load data */
585  gravi_data * data = gravi_data_load (filename);
586  CPLCHECK_NUL ("Cannot load data");
587 
588  /* Dump minimum info */
589  gravi_data_dump_mode (data);
590 
591  return data;
592 }
593 
594 /*----------------------------------------------------------------------------*/
607 /*----------------------------------------------------------------------------*/
608 
609 int gravi_data_patch (gravi_data * file_to_patch,
610  cpl_frameset * patch_frameset)
611 {
612  cpl_ensure (file_to_patch, CPL_ERROR_NULL_INPUT, 0);
613 
614  cpl_frame * patch_frame = NULL;
615 
616  if ( !cpl_frameset_is_empty (patch_frameset) )
617  patch_frame = cpl_frameset_get_position(patch_frameset, 0);
618 
619  if (patch_frame) {
620  const char * filename = cpl_frame_get_filename (patch_frame);
621  CPLCHECK_INT("Cannot get finelame");
622  cpl_msg_info (cpl_func, "Patch the input file with %s", FILESHORT(filename));
623  cpl_propertylist * plist_patch = cpl_propertylist_load (filename, 0);
624  CPLCHECK_INT("Cannot load patch");
625  cpl_propertylist * plist_file_to_patch = gravi_data_get_plist_x(file_to_patch, 0);
626  CPLCHECK_INT("Cannot load data");
627 
628  for (int i=0; i<cpl_propertylist_get_size(plist_patch); i++){
629  cpl_property * keyword = cpl_propertylist_get(plist_patch, i);
630  cpl_type type = cpl_property_get_type(keyword);
631  const char * p_name = cpl_property_get_name (keyword);
632  if ( (strstr(p_name, " QC ") != NULL) ||
633  (strstr(p_name, " TPL ") != NULL) ||
634  (strstr(p_name, " OCS ") != NULL) ||
635  (strstr(p_name, " OBS ") != NULL) ||
636  (strstr(p_name, " MET ") != NULL) ||
637  (strstr(p_name, " ISS ") != NULL) ||
638  (strstr(p_name, " INS ") != NULL) ||
639  (strstr(p_name, " FT ") != NULL) ||
640  (strstr(p_name, " FDDL ") != NULL) ||
641  (strstr(p_name, " ACQ ") != NULL) ) {
642  cpl_msg_info (cpl_func, "Patch the keyword %s", p_name);
643  switch (type) {
644  case CPL_TYPE_FLOAT :
645  cpl_propertylist_update_float(plist_file_to_patch, p_name, cpl_property_get_float(keyword));
646  break;
647  case CPL_TYPE_DOUBLE :
648  cpl_propertylist_update_double(plist_file_to_patch, p_name, cpl_property_get_double(keyword));
649  break;
650  case CPL_TYPE_INT :
651  cpl_propertylist_update_int(plist_file_to_patch, p_name, cpl_property_get_int(keyword));
652  break;
653  case CPL_TYPE_STRING :
654  cpl_propertylist_update_string(plist_file_to_patch, p_name, cpl_property_get_string(keyword));
655  break;
656  case CPL_TYPE_CHAR :
657  cpl_propertylist_update_char(plist_file_to_patch, p_name, cpl_property_get_char(keyword));
658  break;
659  case CPL_TYPE_BOOL :
660  cpl_propertylist_update_bool(plist_file_to_patch, p_name, cpl_property_get_bool(keyword));
661  break;
662  default :
663  cpl_msg_error (cpl_func,"'%s' is an invalid type of property",p_name);
664  cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
665  "invalid type of property");
666  return 0;
667  }
668  }
669  }
670  FREE (cpl_propertylist_delete, plist_patch);
671  }
672 return 1;
673 }
674 
675 /*----------------------------------------------------------------------------*/
688 /*----------------------------------------------------------------------------*/
689 
690 gravi_data * gravi_data_load_rawframe (cpl_frame * frame,
691  cpl_frameset * used_frameset)
692 {
693  cpl_ensure (frame, CPL_ERROR_NULL_INPUT, NULL);
694 
695  const char * filename = cpl_frame_get_filename (frame);
696  cpl_msg_info (cpl_func, "Load RAW file %s (%s)", FILESHORT(filename), cpl_frame_get_tag (frame));
697 
698  if (used_frameset) cpl_frameset_insert (used_frameset, cpl_frame_duplicate (frame));
699 
700  /* Load data */
701  gravi_data * data = gravi_data_load (filename);
702  CPLCHECK_NUL ("Cannot load data");
703 
704  /* Dump minimum info */
705  gravi_data_dump_mode (data);
706 
707  /* Check consistency */
709  CPLCHECK_NUL ("Cannot check data consistency");
710 
711  /* Delete unused data so far */
712  // gravi_data_erase (data, GRAVI_IMAGING_DATA_ACQ_EXT);
713  // gravi_data_erase (data, "ACQ_ABS_REF_POSITION");
714  // CPLCHECK_NUL ("Cannot erase useless data");
715 
716  return data;
717 }
718 
719 /*----------------------------------------------------------------------------*/
733 /*----------------------------------------------------------------------------*/
734 gravi_data * gravi_data_load_rawframe_ext (cpl_frame * frame,
735  cpl_frameset * used_frameset,
736  char * extensions_regexp)
737 {
738  cpl_ensure (frame, CPL_ERROR_NULL_INPUT, NULL);
739 
740  const char * filename = cpl_frame_get_filename (frame);
741  cpl_msg_info (cpl_func, "Load RAW file %s (%s)", FILESHORT(filename), cpl_frame_get_tag (frame));
742 
743  if (used_frameset) cpl_frameset_insert (used_frameset, cpl_frame_duplicate (frame));
744 
745  /* Load data */
746  gravi_data * data = gravi_data_load_ext(filename, extensions_regexp);
747  CPLCHECK_NUL ("Cannot load data");
748 
749  /* Dump minimum info */
750  gravi_data_dump_mode (data);
751 
752  /* Check consistency */
753  //TODO: If not all extensions are loaded the consistency cannot be checked
754  //gravi_data_check_consistency (data);
755  CPLCHECK_NUL ("Cannot check data consistency");
756 
757  return data;
758 }
759 
760 /*----------------------------------------------------------------------------*/
768 /*----------------------------------------------------------------------------*/
769 
770 cpl_error_code gravi_data_dump (gravi_data *self)
771 {
772  cpl_ensure_code (self, CPL_ERROR_NULL_INPUT);
773 
774  cpl_msg_info (cpl_func,"-------------------------");
775  cpl_msg_info (cpl_func,"POINTER: %p", self);
776  cpl_msg_info (cpl_func,"HEADER: %p", self->primary_hdr);
777  cpl_msg_info (cpl_func,"nb_ext = %i",self->nb_ext);
778 
779  for (int i=0; i<self->nb_ext; i++){
780  cpl_msg_info (cpl_func,"%i: %s - %p %p %p", i,
781  gravi_pfits_get_extname (self->exts_hdrs[i]),
782  self->exts_hdrs[i],
783  self->exts_tbs[i],
784  self->exts_imgl[i]);
785  }
786  cpl_msg_info (cpl_func,"-------------------------");
787 
788  return CPL_ERROR_NONE;
789 }
790 
791 /*----------------------------------------------------------------------------*/
800 /*----------------------------------------------------------------------------*/
801 
802 int gravi_data_get_size(const gravi_data *self)
803 {
804  cpl_ensure (self, CPL_ERROR_ILLEGAL_INPUT, 0L);
805  return (int)self->nb_ext;
806 }
807 
808 
809 /*----------------------------------------------------------------------------*/
828 /*----------------------------------------------------------------------------*/
829 
830 cpl_error_code gravi_data_save_data(gravi_data * self,
831  const char * filename,
832  unsigned mode)
833 {
834  cpl_ensure_code (self, CPL_ERROR_NULL_INPUT);
835  cpl_ensure_code (filename, CPL_ERROR_NULL_INPUT);
836 
837  /* Create the file and save the first property list and table field with
838  * primary header entries. */
839  if (self->exts_tbs[0] != NULL)
840  cpl_table_save(self->exts_tbs[0], self->primary_hdr,
841  self->exts_hdrs[0], filename, mode);
842  else if (self->exts_imgl[0] != NULL){
843  cpl_propertylist_save (self->primary_hdr, filename, mode);
844  cpl_imagelist_save (self->exts_imgl[0], filename,
845  CPL_TYPE_DOUBLE, self->exts_hdrs[0], CPL_IO_EXTEND);
846  }
847  else {
848  cpl_error_set_message(cpl_func, CPL_ERROR_NULL_INPUT,
849  "one of the inputs at least is NULL");
850  return CPL_ERROR_NULL_INPUT;
851  }
852 
853 
854  /* Save the remainging extension */
855  for (int i = 1; i < self->nb_ext; i++){
856 
857  if (gravi_pfits_get_extension_type (self->exts_hdrs[i]) == 2)
858  cpl_table_save(self->exts_tbs[i], NULL,
859  self->exts_hdrs[i], filename, CPL_IO_EXTEND);
860  else if (gravi_pfits_get_extension_type (self->exts_hdrs[i]) == 3)
861  cpl_imagelist_save (self->exts_imgl[i], filename,
862  CPL_TYPE_DOUBLE, self->exts_hdrs[i], CPL_IO_EXTEND);
863  else {
864  cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
865  "The dimension of the extension is wrong");
866  gravi_data_delete(self);
867  return CPL_ERROR_ILLEGAL_INPUT;
868  }
869  }
870 
871  return CPL_ERROR_NONE;
872 }
873 
874 /*----------------------------------------------------------------------------*/
894 /*----------------------------------------------------------------------------*/
895 
896 cpl_error_code gravi_data_save_new (gravi_data * self,
897  cpl_frameset * allframes,
898  const char * filename,
899  const char * suffix,
900  const cpl_parameterlist * parlist,
901  cpl_frameset * usedframes,
902  cpl_frame * frame,
903  const char * recipe,
904  cpl_propertylist * applist,
905  const char * proCatg)
906 {
907  gravi_msg_function_start(0);
908  cpl_ensure_code (filename || frame, CPL_ERROR_NULL_INPUT);
909  cpl_ensure_code (self, CPL_ERROR_NULL_INPUT);
910  cpl_ensure_code (proCatg, CPL_ERROR_NULL_INPUT);
911 
912  cpl_frameset * frameset;
913  int ext, i = 0, j = 0;
914 
915  /* If the optional propertylist is not given, we simply
916  * extract the QC parameters from the saved product. */
917  if (applist == NULL) {
918  applist = gravi_data_get_qc (self);
919  CPLCHECK_MSG ("Cannot get QC parameters");
920  } else {
921  applist = cpl_propertylist_duplicate (applist);
922  }
923 
924  /* Add the product CATG to the header */
925  cpl_propertylist_append_string (applist, CPL_DFS_PRO_CATG, proCatg);
926  CPLCHECK_MSG ("Cannot add the CATG parameter");
927 
928  /* Copy the DATE-OBS and NIGHT-OBS parameters if present */
929  cpl_propertylist * hdr = gravi_data_get_header (self);
930  if ( cpl_propertylist_has (hdr, GRAVI_NIGHT_OBS) ) {
931  cpl_propertylist_copy_property (applist, hdr, GRAVI_NIGHT_OBS);
932  CPLCHECK_MSG ("Cannot set NIGHT_OBS");
933  }
934  if ( cpl_propertylist_has (hdr, "DATE-OBS") ) {
935  cpl_propertylist_copy_property (applist, hdr, "DATE-OBS");
936  CPLCHECK_MSG ("Cannot DATE-OBS");
937  }
938 
939  /* Create keywords for OIFITS comliancy if VIS product */
940  if (strstr (proCatg,"VIS") || strstr (proCatg,"TF")) {
941  cpl_propertylist * tmp = gravi_plist_get_oifits_keywords (hdr);
942  cpl_propertylist_append (applist, tmp);
943  FREE (cpl_propertylist_delete, tmp);
944  }
945 
946  /* Add the PIPE LAST_BUILD keyword */
947  gravi_pfits_add_pipe_build (applist);
948 
949  /* Select the name extension depending on this catg */
950  char catg_ext[800];
951  for(i = 0; proCatg[i]; i++) if (proCatg[i]!='_') { catg_ext[j] = tolower(proCatg[i]); j++; }
952  catg_ext[j] = '\0';
953 
954 
955  /* If filename is NULL */
956  if (filename == NULL && frame != NULL) {
957  filename = cpl_frame_get_filename (frame);
958  } else if (filename == NULL && frame == NULL) {
959  cpl_error_set_message(cpl_func, CPL_ERROR_NULL_INPUT, "Need a frame if filename is void");
960  return CPL_ERROR_NULL_INPUT;
961  }
962 
963  /* Use either the input filename or a name based on recipe */
964  char * product_name = NULL;
965 
966  if ( cpl_parameterlist_find_const (parlist,"gravity.dfs.static-name") &&
967  gravi_param_get_bool (parlist,"gravity.dfs.static-name")) {
968 
969  /* Use the recipe name and add the selected catg_ext */
970  if(suffix != NULL)
971  product_name = cpl_sprintf ("%s_%s_%s.fits", recipe, catg_ext, suffix);
972  else
973  product_name = cpl_sprintf ("%s_%s.fits", recipe, catg_ext);
974  }
975  else {
976 
977  /* Remove the extension (last '.') and add the selected catg_ext */
978  char * filenoext = cpl_strdup (FILESHORT(filename));
979  char * lastdot = strrchr (filenoext, '.');
980  if (lastdot != NULL) *lastdot = '\0';
981  product_name = cpl_sprintf ("%s_%s.fits", filenoext, catg_ext);
982  FREE (cpl_free, filenoext);
983  }
984 
985  cpl_msg_info (cpl_func, "Save file to %s", product_name);
986 
987  if (usedframes && frame==NULL) {
988  /* frameset is only the usedframes */
989  frameset = cpl_frameset_duplicate (usedframes);
990  }
991  else if (usedframes && frame) {
992  /* frameset is the usedframes, and
993  * frame is ensured to be the first */
994  frameset = cpl_frameset_new ();
995  cpl_frameset_insert (frameset, cpl_frame_duplicate (frame));
996  for (int f = 0; f < cpl_frameset_get_size (usedframes); f++)
997  if (strcmp (cpl_frame_get_filename (cpl_frameset_get_position (usedframes, f)), cpl_frame_get_filename (frame)))
998  cpl_frameset_insert (frameset, cpl_frame_duplicate (cpl_frameset_get_position (usedframes, f)));
999  }
1000  else if (usedframes==NULL && frame) {
1001  /* frameset is only the frame */
1002  frameset = cpl_frameset_new ();
1003  cpl_frameset_insert (frameset, cpl_frame_duplicate (frame));
1004  }
1005  else {
1006  /* This shall not happen */
1007  cpl_error_set_message(cpl_func, CPL_ERROR_NULL_INPUT, "Bug: need a frame or a usedframes");
1008  return CPL_ERROR_NULL_INPUT;
1009  }
1010 
1011  /* Save the primary header */
1012  cpl_dfs_save_propertylist (allframes, NULL, parlist,
1013  frameset, frame, recipe, applist,
1014  NULL, PACKAGE_STRING, product_name);
1015  CPLCHECK_MSG("Cannot save the first extension primary header");
1016 
1017  /* Save the extensions */
1018  for (ext = 0; ext < self->nb_ext; ext ++)
1019  {
1020  if (self->exts_tbs[ext] != NULL)
1021  cpl_table_save (self->exts_tbs[ext], NULL,
1022  self->exts_hdrs[ext], product_name, CPL_IO_EXTEND);
1023  else if (self->exts_imgl[ext] != NULL)
1024  cpl_imagelist_save (self->exts_imgl[ext], product_name,
1025  cpl_image_get_type (cpl_imagelist_get (self->exts_imgl[ext], 0)),
1026  self->exts_hdrs[ext], CPL_IO_EXTEND);
1027  CPLCHECK_MSG("Cannot save the extension");
1028  }
1029 
1030  FREE (cpl_frameset_delete, frameset);
1031  FREE (cpl_free, product_name);
1032  FREE (cpl_propertylist_delete, applist);
1033 
1034  gravi_msg_function_exit(0);
1035  return CPL_ERROR_NONE;
1036 }
1037 
1038 /*----------------------------------------------------------------------------*/
1049 /*----------------------------------------------------------------------------*/
1050 int gravi_data_get_dark_pos(cpl_table * detector_table, int reg)
1051 {
1052  cpl_ensure_code (detector_table, CPL_ERROR_NULL_INPUT);
1053 
1054  /* TODO, FIXME must use the new LEFT HALFLEFT
1055  * RIGHT HALFRIGHT column to interpolate the position */
1056  // int ref0_x = gravi_table_get_value (detector_table, "CENTER", reg, 0);
1057  int ref0_y = gravi_table_get_value (detector_table, "CENTER", reg, 1);
1058  int ref1_y = gravi_table_get_value (detector_table, "CENTER", reg+1, 1);
1059 
1060  return (ref0_y+ref1_y)/2;
1061 }
1062 
1063 
1064 
1065 /*----------------------------------------------------------------------------*/
1084 /*----------------------------------------------------------------------------*/
1085 
1086 cpl_error_code gravi_data_detector_cleanup (gravi_data * data,
1087  const cpl_parameterlist * parlist)
1088 {
1089  gravi_msg_function_start(1);
1090  cpl_ensure_code (data, CPL_ERROR_NULL_INPUT);
1091 
1092  int nv = 0;
1093 
1094  /* Read header and number of regions */
1095  cpl_propertylist * header = gravi_data_get_header (data);
1096  cpl_table * detector_table = gravi_data_get_table (data, GRAVI_IMAGING_DETECTOR_SC_EXT);
1097  cpl_size nreg = cpl_table_get_nrow (detector_table);
1098  const char * resolution = gravi_pfits_get_resolution (header);
1099 
1100  CPLCHECK_MSG ("Cannot get data");
1101 
1102  /* Get the data as imagelist */
1103  cpl_imagelist * imglist = gravi_data_get_cube (data, GRAVI_IMAGING_DATA_SC_EXT);
1104  cpl_size nframe = cpl_imagelist_get_size (imglist);
1105  cpl_size nx = cpl_image_get_size_x (cpl_imagelist_get (imglist, 0));
1106  cpl_size ny = cpl_image_get_size_y (cpl_imagelist_get (imglist, 0));
1107 
1108  CPLCHECK_MSG ("Cannot get data");
1109 
1110  /* To save the list of bias correction */
1111  cpl_vector * bias_list = cpl_vector_new (nframe);
1112 
1113  /* Some hardcoded information */
1114  cpl_size nx_bias_hr = 4;
1115  cpl_size ny_reg_mr = (ny - 1) / nreg;
1116  cpl_size n_bias_line = 5;
1117 
1118  // cpl_msg_info (cpl_func, "nreg=%lli, nx=%lli, ny=%lli, ny_reg_mr=%lli", nreg, nx, ny, ny_reg_mr);
1119 
1120  if ( !strcmp(resolution, "HIGH") && !strcmp (gravi_param_get_string_default (parlist,
1121  "gravity.preproc.bias-method","MEDIAN"),
1122  "MEDIAN_PER_COLUMN")) {
1123  /* TODO High - the n first lines of Image is bias
1124  * Use the median of the bias-pixel
1125  * per column !! not correct should do like for MED and LOW */
1126 
1127  gravi_msg_warning ("FIXME","Remove bias per column is experimental (HIGH)");
1128 
1129  cpl_vector * bias = cpl_vector_new (nx);
1130  cpl_vector * bias_column = cpl_vector_new (n_bias_line*2);
1131 
1132  /* Loop on frames */
1133  for (cpl_size f = 0; f < nframe; f++) {
1134  cpl_image * frame = cpl_imagelist_get (imglist, f);
1135 
1136  /* Loop on columns */
1137  for (cpl_size x = 0; x < nx; x++) {
1138  cpl_size bias_index=0;
1139 
1140  /* Get the bias pixels of the first lines */
1141  for (cpl_size y = 0; y < n_bias_line; y++) {
1142  double value = cpl_image_get (frame, x+1, y+1, &nv);
1143  cpl_vector_set (bias_column, bias_index++, value);
1144  CPLCHECK_MSG ("Cannot get the bias pixels");
1145  }
1146 
1147  /* Get the bias pixels of the last lines */
1148  for (cpl_size y = 0; y < n_bias_line; y++) {
1149  double value = cpl_image_get (frame, x+1, ny-y, &nv);
1150  cpl_vector_set (bias_column, bias_index++, value);
1151  CPLCHECK_MSG ("Cannot get the bias pixels");
1152  }
1153 
1154  /* Compute the bias of this column, and save it */
1155  double bias_med = cpl_vector_get_median (bias_column);
1156  cpl_vector_set (bias, x, bias_med);
1157 
1158  /* Remove the bias from this column */
1159  for (cpl_size y = 0; y < ny; y++) {
1160  double value = cpl_image_get (frame, x+1, y+1, &nv);
1161  cpl_image_set (frame, x+1, y+1, value - bias_med);
1162  CPLCHECK_MSG ("Cannot set the bias corrected pixels");
1163  }
1164  } /* End loop on columns */
1165 
1166  /* Remove the median of bias pixels to image */
1167  double bias_mean = cpl_vector_get_mean (bias);
1168  cpl_vector_set (bias_list, f, bias_mean);
1169  }
1170  FREE (cpl_vector_delete, bias);
1171  FREE (cpl_vector_delete, bias_column);
1172  }
1173  else if ( !strcmp(resolution, "HIGH") ) {
1174  /* High Resolution - the first 4 columns
1175  * are for bias. FIXME: make sure this is also true in
1176  * in HIGH-COMBINED */
1177 
1178  cpl_vector * bias = cpl_vector_new (nx_bias_hr * ny);
1179 
1180  /* Loop on frames */
1181  for (cpl_size f = 0; f < nframe; f++) {
1182  cpl_image * frame = cpl_imagelist_get (imglist, f);
1183 
1184  /* Get the bias pixels */
1185  for (cpl_size x = 0; x < nx_bias_hr; x++)
1186  for (cpl_size y = 0; y < ny; y++) {
1187  cpl_vector_set (bias, x * ny + y, cpl_image_get (frame, x+1, y+1, &nv));
1188  CPLCHECK_MSG ("Cannot get the bias pixels");
1189  }
1190 
1191  /* Remove the median of bias pixels to image */
1192  double bias_med = cpl_vector_get_median (bias);
1193  cpl_vector_set (bias_list, f, bias_med);
1194  cpl_image_subtract_scalar (frame, bias_med);
1195  CPLCHECK_MSG ("Cannot subtract bias");
1196  }
1197  FREE (cpl_vector_delete, bias);
1198  }
1199  else if ( !strcmp (gravi_param_get_string_default (parlist,
1200  "gravity.preproc.bias-method","MEDIAN"),
1201  "MEDIAN_PER_COLUMN")) {
1202  /* Low and Medium - the n_bias_line between
1203  * each region is bias. Use the median of the bias-pixel
1204  * per column !!*/
1205 
1206  gravi_msg_warning ("FIXME","Remove bias per column is experimental (LOW, MEDIUM)");
1207 
1208  cpl_vector * bias = cpl_vector_new (nx);
1209 // cpl_vector * bias_column = cpl_vector_new (nreg);
1210  cpl_vector * bias_column = cpl_vector_new ((nreg-1)*n_bias_line);
1211  cpl_vector * bias_coord = cpl_vector_new ((nreg-1)*n_bias_line);
1212 
1213  /* Loop on frames */
1214  for (cpl_size f = 0; f < nframe; f++) {
1215  cpl_image * frame = cpl_imagelist_get (imglist, f);
1216 
1217  /* Loop on columns */
1218  for (cpl_size x = 0; x < nx; x++) {
1219  cpl_size bias_index=0;
1220 
1221  /* Get the bias pixels of this column */
1222 /* commented to try a new implementation
1223  for (cpl_size y = 0; y < nreg; y++) {
1224  double value = cpl_image_get (frame, x+1, (y+1)*ny_reg_mr+1, &nv);
1225  cpl_vector_set (bias_column, y, value);
1226  CPLCHECK_MSG ("Cannot get the bias pixels");
1227  }
1228 */
1229  for (cpl_size reg = 0; reg < nreg-1; reg++) {
1230  int starty=gravi_data_get_dark_pos(detector_table, reg)-n_bias_line/2;
1231  for (cpl_size y = 0; y < n_bias_line; y++){
1232  double value = cpl_image_get (frame, x+1, starty+y+1, &nv);
1233  cpl_vector_set (bias_column, bias_index, value);
1234  cpl_vector_set (bias_coord, bias_index++, starty+y);
1235  }
1236  CPLCHECK_MSG ("Cannot get the bias pixels");
1237  }
1238 
1239  /* Compute the bias of this column, and save it */
1240  double bias_med = gravi_vector_get_mean_clip (bias_column, 0.05, 3.0);
1241  cpl_vector_set (bias, x, bias_med);
1242 
1243  /* Remove the bias from this column */
1244  for (cpl_size y = 0; y < ny; y++) {
1245  double value = cpl_image_get (frame, x+1, y+1, &nv);
1246  cpl_image_set (frame, x+1, y+1, value - bias_med);
1247  CPLCHECK_MSG ("Cannot set the bias corrected pixels");
1248  }
1249  } /* End loop on columns */
1250 
1251  /* Remove the median of bias pixels to image */
1252  double bias_mean = cpl_vector_get_mean (bias);
1253  cpl_vector_set (bias_list, f, bias_mean);
1254  }
1255  FREE (cpl_vector_delete, bias);
1256  FREE (cpl_vector_delete, bias_column);
1257  }
1258  else {
1259  /* Low and Medium - the first line of
1260  * each region is bias */
1261 
1262  cpl_vector * bias = cpl_vector_new (nx * nreg);
1263 
1264  /* Loop on frames */
1265  for (cpl_size f = 0; f < nframe; f++) {
1266  cpl_image * frame = cpl_imagelist_get (imglist, f);
1267 
1268  /* Get the bias pixels */
1269  for (cpl_size x = 0; x < nx; x++)
1270  for (cpl_size y = 0; y < nreg; y++) {
1271  cpl_vector_set (bias, x * nreg + y, cpl_image_get (frame, x+1, (y+1)*ny_reg_mr+1, &nv));
1272  CPLCHECK_MSG ("Cannot get the bias pixels");
1273  }
1274 
1275  /* Remove the median of bias pixels to image */
1276  double bias_med = cpl_vector_get_median (bias);
1277  cpl_vector_set (bias_list, f, bias_med);
1278  cpl_image_subtract_scalar (frame, bias_med);
1279  CPLCHECK_MSG ("Cannot subtract bias");
1280  }
1281  FREE (cpl_vector_delete, bias);
1282  }
1283 
1284  /* Add some QC */
1285  cpl_propertylist_update_double (header, "ESO QC PIXBIAS AVG", cpl_vector_get_mean (bias_list));
1286  cpl_propertylist_set_comment (header, "ESO QC PIXBIAS AVG", "[adu] avg over the bias pixel");
1287 
1288  cpl_propertylist_update_double (header, "ESO QC PIXBIAS RMS", cpl_vector_get_stdev (bias_list));
1289  cpl_propertylist_set_comment (header, "ESO QC PIXBIAS RMS", "[adu] rms over frames");
1290  cpl_vector_delete (bias_list);
1291 
1292  gravi_msg_function_exit(1);
1293  return CPL_ERROR_NONE;
1294 }
1295 
1296 /*----------------------------------------------------------------------------*/
1297 
1298 /* Return the first extension exactly matching EXTNAME=name */
1299 inline static int _gravi_data_find (const gravi_data *self, const char *name)
1300 {
1301  int ext = 0;
1302  while (ext < self->nb_ext){
1303  cpl_propertylist *p = self->exts_hdrs[ext];
1304  const char *key = cpl_propertylist_get_string (p, "EXTNAME");
1305  if (strcmp(key, name) == 0) break;
1306  ext ++;
1307  }
1308  return ext;
1309 }
1310 
1311 /*---------------------------------------------------------------------------*/
1323 /*---------------------------------------------------------------------------*/
1324 
1325 cpl_error_code gravi_data_copy_ext (gravi_data * output,
1326  gravi_data * input,
1327  const char * name)
1328 {
1329  cpl_ensure_code (output, CPL_ERROR_NULL_INPUT);
1330  cpl_ensure_code (input, CPL_ERROR_NULL_INPUT);
1331  cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
1332 
1333  int n = gravi_data_get_size (input);
1334  for (int j = 0; j < n; j++){
1335 
1336  cpl_propertylist * plist = gravi_data_get_plist_x (input, j);
1337  const char * plist_name = gravi_pfits_get_extname (plist);
1338 
1339  CPLCHECK_MSG ("Cannot get input data");
1340 
1341  if (plist_name == NULL) continue;
1342 
1343  if (!(strcmp (plist_name, name))) {
1344  int type_data = gravi_pfits_get_extension_type (plist);
1345 
1346  if (type_data == 2) {
1347  gravi_data_add_table (output, cpl_propertylist_duplicate (plist), NULL,
1348  cpl_table_duplicate (gravi_data_get_table_x (input, j)));
1349  }
1350  else if (type_data == 3) {
1351  gravi_data_add_cube (output, cpl_propertylist_duplicate (plist), NULL,
1352  cpl_imagelist_duplicate (gravi_data_get_cube_x (input, j)));
1353  }
1354 
1355  CPLCHECK_MSG ("Cannot copy extension");
1356  }
1357  }
1358 
1359  return CPL_ERROR_NONE;
1360 }
1361 
1362 /*---------------------------------------------------------------------------*/
1374 /*---------------------------------------------------------------------------*/
1375 
1376 cpl_error_code gravi_data_move_ext (gravi_data * output,
1377  gravi_data * input,
1378  const char * name)
1379 {
1380  gravi_msg_function_start(0);
1381  cpl_ensure_code (output, CPL_ERROR_NULL_INPUT);
1382  cpl_ensure_code (input, CPL_ERROR_NULL_INPUT);
1383  cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
1384 
1385  int n = gravi_data_get_size (input);
1386 
1387  int jnew = 0;
1388  for (int j = 0; j < n; j++){
1389 
1390  cpl_propertylist * plist = gravi_data_get_plist_x (input, j);
1391  const char * plist_name = gravi_pfits_get_extname (plist);
1392  CPLCHECK_MSG ("Cannot get input");
1393 
1394  /* Case we need to move this extension */
1395  if ( (plist_name!=NULL) &&
1396  !(strcmp (plist_name, name))) {
1397 
1398  cpl_msg_info (cpl_func, "Move extension %s", plist_name);
1399  int type_data = gravi_pfits_get_extension_type (plist);
1400  if (type_data == 2) {
1401  gravi_data_add_table (output, plist, NULL,
1402  gravi_data_get_table_x (input, j));
1403  }
1404  else if (type_data == 3) {
1405  gravi_data_add_cube (output, plist, NULL,
1406  gravi_data_get_cube_x (input, j));
1407  }
1408  CPLCHECK_MSG ("Cannot move extension");
1409 
1410  } else {
1411 
1412  /* Move pointer in the input */
1413  input->exts_hdrs[jnew] = input->exts_hdrs[j];
1414  input->exts_imgl[jnew] = input->exts_imgl[j];
1415  input->exts_tbs[jnew] = input->exts_tbs[j];
1416  jnew ++;
1417  }
1418 
1419  } /* End loop on extension */
1420 
1421  /* Cleanup input further away */
1422  input->nb_ext = jnew;
1423  for (int j = input->nb_ext; j < GRAVI_DATA_SIZE; j++) {
1424  input->exts_hdrs[j] = NULL;
1425  input->exts_imgl[j] = NULL;
1426  input->exts_tbs[j] = NULL;
1427  }
1428 
1429  gravi_msg_function_exit(0);
1430  return CPL_ERROR_NONE;
1431 }
1432 
1433 /*---------------------------------------------------------------------------*/
1441 /*---------------------------------------------------------------------------*/
1442 
1443 int gravi_data_has_extension (gravi_data * raw_calib, const char * ext_name)
1444 {
1445  cpl_ensure (raw_calib, CPL_ERROR_NULL_INPUT, 0);
1446  cpl_ensure (ext_name, CPL_ERROR_NULL_INPUT, 0);
1447 
1448  int test = 1;
1449  int ext = _gravi_data_find (raw_calib, ext_name);
1450 
1451  if (ext == raw_calib->nb_ext) {
1452  test = 0;
1453  }
1454 
1455  return test;
1456 }
1457 
1458 /*---------------------------------------------------------------------------*/
1466 /*---------------------------------------------------------------------------*/
1467 
1468 int gravi_data_has_type (gravi_data * self, const char * type)
1469 {
1470  cpl_ensure (self, CPL_ERROR_NULL_INPUT, -1);
1471  cpl_ensure (type, CPL_ERROR_NULL_INPUT, -1);
1472  cpl_ensure (strlen (type)>1, CPL_ERROR_ILLEGAL_INPUT, -1);
1473 
1474  int counter = 0;
1475 
1476  /* Loop on extension */
1477  for (int ext = 0; ext < gravi_data_get_size (self) ; ext ++) {
1478 
1479  cpl_propertylist * plist = gravi_data_get_plist_x (self, ext);
1480 
1481  /* Check if EXTNAME or INSNAME contains the 'type'
1482  * Warning that the number of extension is changed in the loop */
1483  if ( (cpl_propertylist_has (plist, "INSNAME") &&
1484  strstr (gravi_pfits_get_insname (plist), type) ) ||
1485  (cpl_propertylist_has (plist, "EXTNAME") &&
1486  strstr (gravi_pfits_get_extname (plist), type) ) )
1487  {
1488  cpl_msg_debug (cpl_func,"Find '%s' ", gravi_pfits_get_extname (plist));
1489  counter ++;
1490  }
1491  }
1492  return counter;
1493 }
1494 
1495 /*---------------------------------------------------------------------------*/
1509 /*---------------------------------------------------------------------------*/
1510 
1511 cpl_propertylist * gravi_data_get_plist_x (gravi_data* self, int i)
1512 {
1513  cpl_ensure (self, CPL_ERROR_NULL_INPUT, NULL);
1514  cpl_ensure (i>=0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1515  cpl_ensure (i<self->nb_ext, CPL_ERROR_ILLEGAL_INPUT, NULL);
1516 
1517  return self->exts_hdrs[i];
1518 }
1519 
1520 /*---------------------------------------------------------------------------*/
1534 /*---------------------------------------------------------------------------*/
1535 
1536 cpl_table * gravi_data_get_table_x (gravi_data* self, int i)
1537 {
1538  cpl_ensure (self, CPL_ERROR_NULL_INPUT, NULL);
1539  cpl_ensure (i>=0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1540  cpl_ensure (i<self->nb_ext, CPL_ERROR_ILLEGAL_INPUT, NULL);
1541 
1542  return self->exts_tbs[i];
1543 }
1544 
1545 /*---------------------------------------------------------------------------*/
1559 /*---------------------------------------------------------------------------*/
1560 
1561 cpl_imagelist * gravi_data_get_cube_x (gravi_data* self, int i)
1562 {
1563  cpl_ensure (self, CPL_ERROR_NULL_INPUT, NULL);
1564  cpl_ensure (i>=0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1565  cpl_ensure (i<self->nb_ext, CPL_ERROR_ILLEGAL_INPUT, NULL);
1566 
1567  return self->exts_imgl[i];
1568 }
1569 
1570 /*---------------------------------------------------------------------------*/
1585 /*---------------------------------------------------------------------------*/
1586 
1587 cpl_table * gravi_data_get_oi_table (gravi_data * self,
1588  const char * extname,
1589  const char * insname)
1590 {
1591  cpl_ensure (self, CPL_ERROR_NULL_INPUT, NULL);
1592  cpl_ensure (extname, CPL_ERROR_NULL_INPUT, NULL);
1593  cpl_ensure (insname, CPL_ERROR_NULL_INPUT, NULL);
1594 
1595  int nb_ext = self->nb_ext;
1596  int pos = -1;
1597  for (int i = 0; i < nb_ext; i++){
1598 
1599  if (cpl_propertylist_has (self->exts_hdrs[i], "INSNAME")){
1600  if ((!strcmp (gravi_pfits_get_insname (self->exts_hdrs[i]), insname)) &&
1601  (!strcmp (gravi_pfits_get_extname (self->exts_hdrs[i]), extname))){
1602  pos = i;
1603  break;
1604  }
1605  }
1606  }
1607 
1608  if (pos < 0){
1609  cpl_msg_warning(cpl_func, "The extention %s doesn't exist "
1610  "with the insname %s",
1611  extname, insname);
1612  return NULL;
1613  }
1614 
1615  return self->exts_tbs[pos];
1616 }
1617 
1618 /*---------------------------------------------------------------------------*/
1634 /*---------------------------------------------------------------------------*/
1635 
1636 cpl_propertylist * gravi_data_get_oi_plist (gravi_data * self,
1637  const char * extname,
1638  const char * insname)
1639 {
1640  cpl_ensure (self, CPL_ERROR_NULL_INPUT, NULL);
1641  cpl_ensure (extname, CPL_ERROR_NULL_INPUT, NULL);
1642  cpl_ensure (insname, CPL_ERROR_NULL_INPUT, NULL);
1643 
1644  int nb_ext = self->nb_ext;
1645  int pos = -1;
1646  for (int i = 0; i < nb_ext; i++){
1647  if (cpl_propertylist_has (self->exts_hdrs[i], "INSNAME")){
1648  if ((!strcmp (gravi_pfits_get_insname (self->exts_hdrs[i]), insname)) &&
1649  (!strcmp (gravi_pfits_get_extname (self->exts_hdrs[i]), extname))){
1650  pos = i;
1651  break;
1652  }
1653  }
1654  }
1655 
1656  if (pos < -1){
1657  cpl_msg_warning(cpl_func, "The extention %s doesn't exist "
1658  "with the insname %s",
1659  extname, insname);
1660  return NULL;
1661  }
1662 
1663  return self->exts_hdrs[pos];
1664 }
1665 
1666 /*---------------------------------------------------------------------------*/
1682 /*---------------------------------------------------------------------------*/
1683 
1684 cpl_propertylist * gravi_data_get_plist (gravi_data * self,
1685  const char * extname)
1686 {
1687  cpl_ensure (self, CPL_ERROR_NULL_INPUT, NULL);
1688  cpl_ensure (extname, CPL_ERROR_NULL_INPUT, NULL);
1689 
1690  if (!strcmp(extname, GRAVI_PRIMARY_HDR_EXT))
1691  return self->primary_hdr;
1692 
1693  int pos = _gravi_data_find(self, extname);
1694 
1695  cpl_ensure (pos<self->nb_ext, CPL_ERROR_ILLEGAL_INPUT, NULL);
1696 
1697  return self->exts_hdrs[pos];
1698 }
1699 
1700 /*---------------------------------------------------------------------------*/
1714 /*---------------------------------------------------------------------------*/
1715 
1716 cpl_table * gravi_data_get_table (gravi_data* self, const char * extname)
1717 {
1718  cpl_ensure (self, CPL_ERROR_NULL_INPUT, NULL);
1719  cpl_ensure (extname, CPL_ERROR_NULL_INPUT, NULL);
1720 
1721  int pos = _gravi_data_find(self, extname);
1722 
1723  cpl_ensure (pos<self->nb_ext, CPL_ERROR_ILLEGAL_INPUT, NULL);
1724 
1725  if ((self->exts_tbs[pos] == NULL) ||
1726  (gravi_pfits_get_extension_type (self->exts_hdrs[pos]) != 2)){
1727  cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1728  "No BINTABLE at the extension %s", extname);
1729  return NULL;
1730  }
1731 
1732  return self->exts_tbs[pos];
1733 }
1734 
1735 /*---------------------------------------------------------------------------*/
1749 /*---------------------------------------------------------------------------*/
1750 
1751 cpl_imagelist * gravi_data_get_cube (gravi_data* self, const char * extname)
1752 {
1753  cpl_ensure (self, CPL_ERROR_NULL_INPUT, NULL);
1754  cpl_ensure (extname, CPL_ERROR_NULL_INPUT, NULL);
1755 
1756  int pos = _gravi_data_find(self, extname);
1757 
1758  cpl_ensure (pos<self->nb_ext, CPL_ERROR_ILLEGAL_INPUT, NULL);
1759 
1760  if ((self->exts_imgl[pos] == NULL) ||
1761  (gravi_pfits_get_extension_type (self->exts_hdrs[pos]) != 3)){
1762  cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1763  "No IMAGE at the extension %s", extname);
1764  return NULL;
1765  }
1766 
1767  return self->exts_imgl[pos];
1768 }
1769 
1770 /*----------------------------------------------------------------------------*/
1779 /*----------------------------------------------------------------------------*/
1780 
1781 cpl_error_code gravi_data_erase_x (gravi_data * self, int pos)
1782 {
1783  cpl_ensure_code (self, CPL_ERROR_NULL_INPUT);
1784  cpl_ensure_code (pos>-1, CPL_ERROR_ILLEGAL_INPUT);
1785 
1786  /* Delete data or move pointers */
1787  int comp = 0;
1788  for (int i = 0; i < self->nb_ext; i++) {
1789  if (i != pos){
1790  self->exts_hdrs[comp] = self->exts_hdrs[i];
1791  self->exts_tbs[comp] = self->exts_tbs[i];
1792  self->exts_imgl[comp] = self->exts_imgl[i];
1793  comp++;
1794  }
1795  else{
1796  if ((gravi_pfits_get_extension_type (self->exts_hdrs[pos]) == 2))
1797  FREE (cpl_table_delete, self->exts_tbs[i]);
1798  else if (gravi_pfits_get_extension_type (self->exts_hdrs[pos]) == 3)
1799  FREE (cpl_imagelist_delete, self->exts_imgl[i]);
1800  CPLCHECK_MSG("Cannot delete data");
1801 
1802  FREE (cpl_propertylist_delete, self->exts_hdrs[i]);
1803  CPLCHECK_MSG("Cannot delete header");
1804  }
1805  }
1806 
1807  /* Cleanup further away */
1808  for (int i = comp ; i<GRAVI_DATA_SIZE; i++) {
1809  self->exts_hdrs[i] = NULL;
1810  self->exts_tbs[i] = NULL;
1811  self->exts_imgl[i] = NULL;
1812  }
1813 
1814  /* Change number of extension */
1815  self->nb_ext = comp;
1816 
1817  return CPL_ERROR_NONE;
1818 }
1819 
1820 /*----------------------------------------------------------------------------*/
1830 /*----------------------------------------------------------------------------*/
1831 
1832 cpl_error_code gravi_data_erase (gravi_data * self, const char * extname)
1833 {
1834  cpl_ensure_code (self, CPL_ERROR_NULL_INPUT);
1835  cpl_ensure_code (extname, CPL_ERROR_NULL_INPUT);
1836 
1837  /* Find the position of the property list */
1838  int pos = _gravi_data_find(self, extname);
1839 
1840  /* Check pos */
1841  if (pos == self->nb_ext) {
1842  cpl_msg_info (cpl_func,"Cannot delete '%s' (not found)",extname);
1843  return CPL_ERROR_NONE;
1844  } else {
1845  cpl_msg_info (cpl_func,"Delete '%s' found in ext[%i] (over %i) ",extname, pos, self->nb_ext);
1846  }
1847 
1848  /* Erase */
1849  gravi_data_erase_x (self, pos);
1850 
1851  CPLCHECK_MSG ("Cannot erase this extension name");
1852  return CPL_ERROR_NONE;
1853 }
1854 
1855 /*----------------------------------------------------------------------------*/
1865 /*----------------------------------------------------------------------------*/
1866 
1867 cpl_error_code gravi_data_erase_type (gravi_data * self, const char * type)
1868 {
1869  cpl_ensure_code (self, CPL_ERROR_NULL_INPUT);
1870  cpl_ensure_code (type, CPL_ERROR_NULL_INPUT);
1871  cpl_ensure_code (strlen (type)>1, CPL_ERROR_ILLEGAL_INPUT);
1872 
1873  /* Loop on extension */
1874  for (int ext = 0; ext < gravi_data_get_size (self) ; ext ++) {
1875 
1876  cpl_propertylist * plist = gravi_data_get_plist_x (self, ext);
1877 
1878  /* Check if EXTNAME or INSNAME contains the 'type'
1879  * Warning that the number of extension is changed in the loop */
1880  if ( (cpl_propertylist_has (plist, "INSNAME") &&
1881  strstr (gravi_pfits_get_insname (plist), type) ) ||
1882  (cpl_propertylist_has (plist, "EXTNAME") &&
1883  strstr (gravi_pfits_get_extname (plist), type) ) )
1884  {
1885  cpl_msg_info (cpl_func,"Delete '%s' ", gravi_pfits_get_extname (plist));
1886  gravi_data_erase_x (self, ext);
1887  ext--;
1888 
1889  CPLCHECK_MSG ("Cannot erase this type");
1890  }
1891  }
1892  return CPL_ERROR_NONE;
1893 }
1894 
1895 /*----------------------------------------------------------------------------*/
1907 /*----------------------------------------------------------------------------*/
1908 
1909 cpl_error_code gravi_data_add_table (gravi_data * self,
1910  cpl_propertylist * plist,
1911  const char * extname,
1912  cpl_table * table)
1913 {
1914  cpl_ensure_code (self, CPL_ERROR_NULL_INPUT);
1915  cpl_ensure_code (table, CPL_ERROR_NULL_INPUT);
1916 
1917  /* Set the header */
1918  if (plist == NULL) plist = cpl_propertylist_new ();
1919  if (extname != NULL) cpl_propertylist_update_string (plist, "EXTNAME", extname);
1920 
1921  /* Add header */
1922  cpl_propertylist_update_string (plist, "XTENSION", "BINTABLE");
1923  self->exts_hdrs[self->nb_ext] = plist;
1924 
1925  /* Add an EXTNAME to UNKNOWN */
1926  if (!cpl_propertylist_has(plist, "EXTNAME") ) {
1927  cpl_msg_error (cpl_func,"FIXME: set a table without EXTNAME !!");
1928  cpl_propertylist_update_string (plist, "EXTNAME", "UNKNOWN");
1929  }
1930 
1931  /* OIFITS: add OI_REVN to OI_* tables */
1932  const char * plist_name = 0;
1933  if (cpl_propertylist_has (plist, "EXTNAME"))
1934  plist_name = gravi_pfits_get_extname (plist);
1935 
1936  if (plist_name && !(strcmp(plist_name, GRAVI_OI_ARRAY_EXT) &&
1937  strcmp (plist_name, GRAVI_OI_TARGET_EXT) &&
1938  strcmp (plist_name, GRAVI_OI_WAVELENGTH_EXT) &&
1939  strcmp (plist_name, GRAVI_OI_FLUX_EXT) &&
1940  strcmp (plist_name, GRAVI_OI_T3_EXT) &&
1941  strcmp (plist_name, GRAVI_OI_VIS2_EXT) &&
1942  strcmp (plist_name, GRAVI_OI_VIS_EXT))) {
1943  cpl_propertylist_update_int (plist, "OI_REVN", 1);
1944  }
1945 
1946  /* OIFITS: check is saved as short */
1947  gravi_data_check_savetypes (plist, table);
1948 
1949  self->exts_tbs[self->nb_ext] = table;
1950  self->exts_imgl[self->nb_ext] = NULL;
1951 
1952  self->nb_ext ++;
1953 
1954  CPLCHECK_MSG ("Cannot add the table");
1955  return CPL_ERROR_NONE;
1956 }
1957 
1958 /*----------------------------------------------------------------------------*/
1970 /*----------------------------------------------------------------------------*/
1971 
1972 cpl_error_code gravi_data_add_cube (gravi_data * self,
1973  cpl_propertylist * plist,
1974  const char * extname,
1975  cpl_imagelist * imglist)
1976 {
1977 
1978  cpl_ensure_code (self, CPL_ERROR_NULL_INPUT);
1979  cpl_ensure_code (imglist, CPL_ERROR_NULL_INPUT);
1980 
1981  if (plist == NULL) plist = cpl_propertylist_new ();
1982  if (extname != NULL) cpl_propertylist_update_string (plist, "EXTNAME", extname);
1983 
1984  /* Add header */
1985  self->exts_hdrs[self->nb_ext] = plist;
1986  cpl_propertylist_update_string (self->exts_hdrs[self->nb_ext],"XTENSION", "IMAGE");
1987 
1988  /* Add data */
1989  self->exts_imgl[self->nb_ext] = (imglist);
1990  self->exts_tbs[self->nb_ext] = NULL;
1991 
1992  self->nb_ext ++;
1993 
1994  CPLCHECK_MSG ("Cannot add the cube");
1995  return CPL_ERROR_NONE;
1996 
1997 }
1998 
1999 /*----------------------------------------------------------------------------*/
2011 /*----------------------------------------------------------------------------*/
2012 
2013 cpl_error_code gravi_data_add_img (gravi_data * self,
2014  cpl_propertylist * plist,
2015  const char * extname,
2016  cpl_image * image) {
2017 
2018  cpl_ensure_code (self, CPL_ERROR_NULL_INPUT);
2019  cpl_ensure_code (image, CPL_ERROR_NULL_INPUT);
2020 
2021  if (plist == NULL) plist = cpl_propertylist_new ();
2022  if (extname != NULL) cpl_propertylist_update_string (plist, "EXTNAME", extname);
2023 
2024  /* Add header */
2025  self->exts_hdrs[self->nb_ext] = plist;
2026  cpl_propertylist_update_string (self->exts_hdrs[self->nb_ext],"XTENSION", "IMAGE");
2027 
2028  /* Convert to imagelist */
2029  cpl_imagelist * imglist = cpl_imagelist_new ();
2030  cpl_imagelist_set (imglist, image, 0);
2031 
2032  /* Add data */
2033  self->exts_imgl[self->nb_ext] = (imglist);
2034  self->exts_tbs[self->nb_ext] = NULL;
2035 
2036  self->nb_ext ++;
2037 
2038  CPLCHECK_MSG ("Cannot add the image");
2039  return CPL_ERROR_NONE;
2040 }
2041 
2042 /*---------------------------------------------------------------------------*/
2052 /*---------------------------------------------------------------------------*/
2053 
2054 cpl_error_code gravi_data_clean_for_astro (gravi_data * data)
2055 {
2056  gravi_msg_function_start(1);
2057  cpl_ensure_code (data, CPL_ERROR_NULL_INPUT);
2058 
2059  /* Loop on extension in file ?? */
2060  for (int i = 0; i < gravi_data_get_size (data); i++) {
2061 
2062  /* Keep OI_ARRAY and OI_TARGET */
2063  cpl_propertylist * plist = gravi_data_get_plist_x (data, i);
2064  const char * plist_name = gravi_pfits_get_extname (plist);
2065  if (!(strcmp (plist_name, GRAVI_OI_ARRAY_EXT)) ||
2066  !(strcmp (plist_name, GRAVI_OI_TARGET_EXT)) ) {
2067  cpl_msg_debug (cpl_func,"NAME: %s kept", plist_name);
2068  continue;
2069  }
2070 
2071  /* Keep all INSNAME_SC */
2072  if (cpl_propertylist_has (plist, "INSNAME") &&
2073  ( (!strcmp (gravi_pfits_get_insname (plist), INSNAME_SC_P1)) ||
2074  (!strcmp (gravi_pfits_get_insname (plist), INSNAME_SC_P2)) ||
2075  (!strcmp (gravi_pfits_get_insname (plist), INSNAME_SC)) ) ) {
2076  cpl_msg_debug (cpl_func,"NAME: %s kept", plist_name);
2077  continue;
2078  }
2079 
2080  /* Delete */
2081  cpl_msg_debug (cpl_func,"NAME: %s deleted", plist_name);
2082  FREE (cpl_propertylist_delete, data->exts_hdrs[i]);
2083  FREE (cpl_table_delete, data->exts_tbs[i]);
2084  FREE (cpl_imagelist_delete, data->exts_imgl[i]);
2085  }
2086 
2087  /* Loop on extension in file to move the
2088  * extension consecutively */
2089  int j = 0;
2090  for (int i = 0; i < gravi_data_get_size (data); i++) {
2091  /* This one exist, copy in last place */
2092  if (data->exts_hdrs[i] || data->exts_tbs[i] || data->exts_imgl[i]) {
2093  if ( i!=j ) {
2094  data->exts_hdrs[j] = data->exts_hdrs[i]; data->exts_hdrs[i] = NULL;
2095  data->exts_tbs[j] = data->exts_tbs[i]; data->exts_tbs[i] = NULL;
2096  data->exts_imgl[j] = data->exts_imgl[i]; data->exts_imgl[i] = NULL;
2097  }
2098  j++;
2099  }
2100  }
2101 
2102  data->nb_ext = j;
2103 
2104  gravi_msg_function_exit(1);
2105  return CPL_ERROR_NONE;
2106 }
2107 
2108 /*---------------------------------------------------------------------------*/
2119 /*---------------------------------------------------------------------------*/
2120 
2121 cpl_error_code gravi_data_check_consistency (gravi_data * data)
2122 {
2123  gravi_msg_function_start(0);
2124  cpl_ensure_code (data, CPL_ERROR_NULL_INPUT);
2125 
2126  char qc_msg[80];
2127 
2128  /* Add the QC parameter, start with 0 warning */
2129  cpl_propertylist * header = gravi_data_get_header (data);
2130  cpl_propertylist_append_int (header, "ESO QC CHECK FLAGS", 0);
2131 
2132  /* Check number of extensions */
2133  int nb_ext = 12;
2134  const char *extname[] = {"ARRAY_DESCRIPTION", "ARRAY_GEOMETRY", "OPTICAL_TRAIN",
2135  "IMAGING_DATA_ACQ", "ACQ_ABS_REF_POSITION",
2136  "OPDC", "FDDL", "METROLOGY",
2137  "IMAGING_DATA_SC","IMAGING_DETECTOR_SC",
2138  "IMAGING_DATA_FT","IMAGING_DETECTOR_FT"};
2139 
2140  for (int ext = 0; ext< nb_ext; ext++) {
2141 
2142  /* Check if existing */
2143  if ( !gravi_data_has_extension (data, extname[ext]) ) {
2144  sprintf (qc_msg, "%s is missing", extname[ext]);
2145  gravi_pfits_add_check (header, qc_msg);
2146  continue;
2147  }
2148 
2149  cpl_propertylist * plist;
2150  plist = gravi_data_get_plist (data, extname[ext]);
2151 
2152  /* Check the frame counter if it has one */
2153  if (cpl_propertylist_has (plist, "ESO DET FRAM NO")) {
2154  int frame_no = cpl_propertylist_get_int (plist, "ESO DET FRAM NO");
2155  int naxis_3 = cpl_propertylist_get_int (plist, "NAXIS3");
2156  if ( frame_no != naxis_3) {
2157  sprintf (qc_msg, "%s is missing DITs", extname[ext]);
2158  gravi_pfits_add_check (header, qc_msg);
2159  }
2160  }
2161  }
2162 
2163  CPLCHECK_MSG ("Cannot check consistency of tables...");
2164 
2165 
2166 
2167  /* Build the time of the first and last frame of SC in
2168  * [us] with respect to PRC.ACQ.START. We need RMN data over
2169  * the entire first and last DITs of SC */
2170  int ndit = cpl_propertylist_get_int (header, "ESO DET2 NDIT");
2171  double scdit = gravi_pfits_get_dit_sc (header);
2172  double start_sc = gravi_pfits_get_time_sc (header, 0) - scdit/2. * 1e6;
2173  double end_sc = gravi_pfits_get_time_sc (header, ndit-1) + scdit/2. * 1e6;
2174 
2175  cpl_msg_debug (cpl_func,"start = %8.0f and end = %10.0f (%s [us] from PCR.ACQ.START)",
2176  start_sc, end_sc, "SC");
2177 
2178  /* Check the TIME content of RMN tables */
2179  int nb_ext_rmn = 4;
2180  const char *ext_rmn[] = {"OPDC", "FDDL", "METROLOGY", "IMAGING_DATA_FT"};
2181 
2182  for (int ext = 0; ext< nb_ext_rmn; ext++) {
2183 
2184  /* Get this RMN table */
2185  if (!gravi_data_has_extension (data, ext_rmn[ext])) continue;
2186  cpl_table * table = gravi_data_get_table (data, ext_rmn[ext]);
2187 
2188  /* Get the first and last time sample, in [us] */
2189  double min_table = cpl_table_get_column_min (table, "TIME");
2190  double max_table = cpl_table_get_column_max (table, "TIME");
2191 
2192  cpl_msg_debug (cpl_func,"start = %8.0f and end = %10.0f (%s [us] from PCR.ACQ.START)",
2193  min_table, max_table, ext_rmn[ext]);
2194 
2195  /* Check if it covers the SC data */
2196  if ( min_table > start_sc) {
2197  sprintf (qc_msg, "%s starts *after* the science exposure", ext_rmn[ext]);
2198  gravi_pfits_add_check (header, qc_msg);
2199  }
2200  if ( max_table < end_sc) {
2201  sprintf (qc_msg, "%s finish *before* the science exposure", ext_rmn[ext]);
2202  gravi_pfits_add_check (header, qc_msg);
2203  }
2204 
2205  /* Get data */
2206  cpl_size nrow = cpl_table_get_nrow (table);
2207  int * time = cpl_table_get_data_int (table, "TIME");
2208  CPLCHECK_MSG ("Cannot get data");
2209 
2210  /* Compute the median step, over the first 10000 samples */
2211  cpl_size nsamp = CPL_MIN (10000, nrow-1);
2212  cpl_array * delta = cpl_array_new (nsamp, CPL_TYPE_INT);
2213  for (cpl_size row = 0; row < nsamp ; row++) {
2214  cpl_array_set_int (delta, row, time[row+1] - time[row]);
2215  }
2216  double median_delta = cpl_array_get_median (delta);
2217  FREE (cpl_array_delete, delta);
2218 
2219  /* Check missing samples (delta > 1.5 * median) */
2220  int nwrong = 0;
2221  for (cpl_size row = 0; row < nrow-1 ; row++) {
2222  double current_delta = time[row+1] - time[row];
2223  if (current_delta > 1.5 * median_delta) nwrong ++;
2224  }
2225 
2226  if (nwrong) {
2227  sprintf (qc_msg, "%s has %i wrong steps", ext_rmn[ext], nwrong);
2228  gravi_pfits_add_check (header, qc_msg);
2229  }
2230 
2231  } /* End loop on RMN tables */
2232 
2233  CPLCHECK_MSG ("Cannot check consistency of RMN tables...");
2234 
2235  gravi_msg_function_exit(0);
2236  return CPL_ERROR_NONE;
2237 }
2238 
2239 /*---------------------------------------------------------------------------*/
2251 /*---------------------------------------------------------------------------*/
2252 
2253 cpl_table ** gravi_data_get_oiwave_tables (gravi_data * data, int type_data, int npol)
2254 {
2255  cpl_ensure (data, CPL_ERROR_NULL_INPUT, NULL);
2256  cpl_ensure (npol == 1 || npol == 2, CPL_ERROR_ILLEGAL_INPUT, NULL);
2257  cpl_ensure (type_data == GRAVI_SC || type_data == GRAVI_FT, CPL_ERROR_ILLEGAL_INPUT, NULL);
2258 
2259  cpl_table ** oiwave_tables = cpl_calloc (npol, sizeof(cpl_table *));
2260  for (int pol = 0; pol < npol; pol++)
2261  oiwave_tables[pol] = gravi_data_get_oi_wave (data, type_data, pol, npol);
2262 
2263  return oiwave_tables;
2264 }
2265 
2266 
2267 
gravi_data * gravi_data_new(int nb_ext)
Create an empty gravi_data.
Definition: gravi_data.c:102
double gravi_pfits_get_time_sc(const cpl_propertylist *header, cpl_size row)
Time of the middle of the SC exposure row in [us], counted from PRC.ACQ.START.
Definition: gravi_pfits.c:590
cpl_propertylist * gravi_data_get_oi_plist(gravi_data *self, const char *extname, const char *insname)
Get the propertylist from EXTNAME and INSNAME.
Definition: gravi_data.c:1636
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
gravi_data * gravi_data_load(const char *filename)
Low-level function to load FITS file.
Definition: gravi_data.c:376
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_propertylist * gravi_data_get_plist_x(gravi_data *self, int i)
Get the propertylist of an extension by position.
Definition: gravi_data.c:1511
cpl_error_code gravi_data_erase_type(gravi_data *self, const char *type)
Erase all extension related to an instrument (SC, FT, MET...)
Definition: gravi_data.c:1867
int gravi_data_has_extension(gravi_data *raw_calib, const char *ext_name)
Check if data has extension with given EXTNAME.
Definition: gravi_data.c:1443
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
gravi_data * gravi_data_load_ext(const char *filename, const char *extensions_regexp)
Low-level function to load FITS file.
Definition: gravi_data.c:448
cpl_error_code gravi_pfits_add_check(cpl_propertylist *header, char *msg)
Add a QC.CHECK keyword to the header.
Definition: gravi_pfits.c:1398
cpl_error_code gravi_data_move_ext(gravi_data *output, gravi_data *input, const char *name)
Move extensions from one data to another.
Definition: gravi_data.c:1376
cpl_error_code gravi_data_save_data(gravi_data *self, const char *filename, unsigned mode)
Save a gravi data in a FITS file.
Definition: gravi_data.c:830
cpl_propertylist * gravi_plist_get_oifits_keywords(cpl_propertylist *header)
Create OIFITS keywords to satisfy standar.
Definition: gravi_pfits.c:801
cpl_table ** gravi_data_get_oiwave_tables(gravi_data *data, int type_data, int npol)
Get pointer to the OI_WAVELENGTH tables of both polarisations.
Definition: gravi_data.c:2253
int gravi_data_is_oi_ext(cpl_propertylist *hdr)
Check if EXTNAME starts with &#39;OI_&#39; (OIFITS extension)
Definition: gravi_data.c:162
cpl_error_code gravi_data_erase_x(gravi_data *self, int pos)
Erase an extension by its position.
Definition: gravi_data.c:1781
int gravi_table_are_equal(cpl_table *first, cpl_table *second)
Check if two tables have the same content.
Definition: gravi_cpl.c:1358
cpl_table * gravi_data_get_table(gravi_data *self, const char *extname)
Return a pointer on a table extension by its EXTNAME.
Definition: gravi_data.c:1716
cpl_error_code gravi_data_check_consistency(gravi_data *data)
Verify the integrity of RAW data.
Definition: gravi_data.c:2121
cpl_imagelist * gravi_data_get_cube_x(gravi_data *self, int i)
Get the cube of an extension by position.
Definition: gravi_data.c:1561
cpl_error_code gravi_pfits_add_pipe_build(cpl_propertylist *header)
Add the ESO PRO REC# PIPE LAST_BUILD in header.
Definition: gravi_pfits.c:1438
cpl_error_code gravi_data_dump(gravi_data *self)
Dump the overall structure of a gravi_data in stdout.
Definition: gravi_data.c:770
cpl_error_code gravi_data_check_savetypes(cpl_propertylist *hdr, cpl_table *oi_table)
Set the savetypes of the OIFITS table.
Definition: gravi_data.c:186
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_error_code gravi_data_dump_mode(gravi_data *data)
Dump some information about data in messagin.
Definition: gravi_data.c:539
double gravi_vector_get_mean_clip(cpl_vector *vector_in, double percent, double nsigma)
Return the mean of a vector after extrema and RMS clipping.
Definition: gravi_cpl.c:2207
int gravi_data_has_type(gravi_data *self, const char *type)
Return the number of ext whose EXTNAME and INSNAME match &#39;type&#39;.
Definition: gravi_data.c:1468
cpl_error_code gravi_data_clean_for_astro(gravi_data *data)
Clean the data to keep only OIFITS extensions related to SC.
Definition: gravi_data.c:2054
cpl_propertylist * gravi_data_get_plist(gravi_data *self, const char *extname)
Get the propertylist from EXTNAME.
Definition: gravi_data.c:1684
cpl_table * gravi_data_get_table_x(gravi_data *self, int i)
Get the table of an extension by position.
Definition: gravi_data.c:1536
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_data_add_cube(gravi_data *self, cpl_propertylist *plist, const char *extname, cpl_imagelist *imglist)
Add an IMAGE (imagelist) extension in gravi_data.
Definition: gravi_data.c:1972
gravi_data * gravi_data_load_rawframe_ext(cpl_frame *frame, cpl_frameset *used_frameset, char *extensions_regexp)
Load a RAW FITS file and create a gravi_data from specified extensions.
Definition: gravi_data.c:734
cpl_error_code gravi_data_add_table(gravi_data *self, cpl_propertylist *plist, const char *extname, cpl_table *table)
Add a BINTABLE extension in gravi_data.
Definition: gravi_data.c:1909
void gravi_data_delete(gravi_data *self)
Delete a gravi data.
Definition: gravi_data.c:137
gravi_data * gravi_data_duplicate(const gravi_data *self)
Create a copy of the gravi data.
Definition: gravi_data.c:236
int gravi_data_patch(gravi_data *file_to_patch, cpl_frameset *patch_frameset)
Load a RAW FITS file and create a gravi_data.
Definition: gravi_data.c:609
cpl_error_code gravi_data_erase(gravi_data *self, const char *extname)
Erase an extension by its EXTNAME.
Definition: gravi_data.c:1832
cpl_error_code gravi_data_append(gravi_data *first, const gravi_data *second, int force)
Append a gravi_data into another existing one.
Definition: gravi_data.c:290
cpl_error_code gravi_data_add_img(gravi_data *self, cpl_propertylist *plist, const char *extname, cpl_image *image)
Add an IMAGE (single image) extension in gravi_data.
Definition: gravi_data.c:2013
int gravi_data_get_dark_pos(cpl_table *detector_table, int reg)
retrun the position of the dark line on top of the region at x position
Definition: gravi_data.c:1050
int gravi_data_get_size(const gravi_data *self)
Get the number of extension in a gravi_data.
Definition: gravi_data.c:802
cpl_table * gravi_data_get_oi_table(gravi_data *self, const char *extname, const char *insname)
Get an OI_FITS table from EXTNAME and INSNAME.
Definition: gravi_data.c:1587