GRAVI Pipeline Reference Manual  1.2.3
gravi_pfits.c
1 /* $Id: gravi_pfits.c,v 1.12 2011/04/31 06:10:40 nazouaoui Exp $
2  *
3  * This file is part of the GRAVI Pipeline
4  * Copyright (C) 2002,2003 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
32 /*
33  * History :
34  * 10/01/2019 fix Warning : unused parameter : power
35  */
36 /*-----------------------------------------------------------------------------
37  Includes
38  -----------------------------------------------------------------------------*/
39 
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif
43 
44 #include <cpl.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <time.h>
48 #include <math.h>
49 #include <erfa.h>
50 
51 #include "gravi_pfits.h"
52 #include "gravi_utils.h"
53 
54 /*-----------------------------------------------------------------------------
55  Function codes
56  -----------------------------------------------------------------------------*/
57 
58 /*----------------------------------------------------------------------------*/
64 /*----------------------------------------------------------------------------*/
65 
66 int gravi_pfits_get_startx (const cpl_propertylist * plist)
67 {
68  cpl_errorstate prestate = cpl_errorstate_get();
69  int value = cpl_propertylist_get_int(plist, PROFILE_STARTX);
70  cpl_ensure (cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0);
71  return value;
72 }
73 
74 int gravi_pfits_get_fullstartx (const cpl_propertylist * plist)
75 {
76  cpl_errorstate prestate = cpl_errorstate_get();
77  int value = cpl_propertylist_get_int(plist, PROFILE_FULLSTARTX);
78  cpl_ensure (cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0);
79  return value;
80 }
81 
82 int gravi_pfits_get_nx (const cpl_propertylist * plist)
83 {
84  cpl_errorstate prestate = cpl_errorstate_get();
85  int value = cpl_propertylist_get_int(plist, PROFILE_NX);
86  cpl_ensure (cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0);
87  return value;
88 }
89 
90 int gravi_pfits_get_window_start (const cpl_propertylist * plist)
91 {
92  cpl_errorstate prestate = cpl_errorstate_get();
93  int value = cpl_propertylist_get_int(plist, "ESO DET2 FRAM STRX");
94  cpl_ensure (cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
95  return value;
96 }
97 
98 double gravi_pfits_get_diameter (const cpl_propertylist * plist, int type_data)
99 {
100  cpl_errorstate prestate = cpl_errorstate_get();
101  double value = 0.0;
102 
103  const char * keyword = ( type_data == GRAVI_FT ? "ESO FT ROBJ "
104  "DIAMETER" : "ESO INS SOBJ DIAMETER" );
105  if (cpl_propertylist_has (plist, keyword)) {
106  value = cpl_propertylist_get_double( plist, keyword );
107  }
108  else if ( !gravi_pfits_is_calib (plist)) {
109  cpl_msg_warning (cpl_func, "The keyword %s does not "
110  "exist in the propertylist", keyword);
111  }
112 
113  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
114  return value;
115 }
116 
117 double gravi_pfits_get_pmra (const cpl_propertylist * plist)
118 {
119  const char * keyword = "ESO FT ROBJ PMA";
120  double pma = gravi_pfits_get_double_silentdefault (plist, keyword, 0.);
121  return pma; // [as/year]
122 }
123 
124 double gravi_pfits_get_pmdec (const cpl_propertylist * plist)
125 {
126  const char * keyword = "ESO FT ROBJ PMD";
127  double pmd = gravi_pfits_get_double_silentdefault (plist, keyword, 0.);
128  return pmd; // [as/year]
129 }
130 
131 double gravi_pfits_get_plx (const cpl_propertylist * plist)
132 {
133  const char * keyword = "ESO FT ROBJ PARALLAX";
134  double plx = gravi_pfits_get_double_silentdefault (plist, keyword, 0.);
135  return plx; // [as]
136 }
137 
138 const char * gravi_pfits_get_extname (const cpl_propertylist * plist)
139 {
140  cpl_errorstate prestate = cpl_errorstate_get();
141  const char * value = cpl_propertylist_get_string(plist, "EXTNAME");
142  cpl_ensure (cpl_errorstate_is_equal(prestate), cpl_error_get_code(), "");
143  return value;
144 }
145 
146 const char * gravi_pfits_get_dpr_type (const cpl_propertylist * plist)
147 {
148  const char * value = cpl_propertylist_get_string(plist, "ESO DPR TYPE");
149  cpl_ensure (value != NULL, cpl_error_get_code(), NULL);
150  return value;
151 }
152 
153 const char * gravi_pfits_get_resolution (const cpl_propertylist * plist)
154 {
155  const char * value = cpl_propertylist_get_string(plist, "ESO INS FILT2 NAME");
156  cpl_ensure(value != NULL, cpl_error_get_code(), NULL);
157  return value;
158 }
159 
160 const char * gravi_pfits_get_spec_res (const cpl_propertylist * plist)
161 {
162  const char * value = cpl_propertylist_get_string(plist, "ESO INS SPEC RES");
163  cpl_ensure(value != NULL, cpl_error_get_code(), NULL);
164  return value;
165 }
166 
167 const char * gravi_pfits_get_pola_mode (const cpl_propertylist * plist, int type_data )
168 {
169  const char * keyword = ( type_data == GRAVI_FT ? "ESO FT POLA MODE" : "ESO INS POLA MODE");
170  const char * value = cpl_propertylist_get_string(plist, keyword);
171  cpl_ensure (value != NULL, cpl_error_get_code(), NULL);
172  return value;
173 }
174 
175 int gravi_data_frame_get_mode (const cpl_frame * frame)
176 {
177  cpl_ensure (frame, CPL_ERROR_NULL_INPUT, 0);
178  const char * value = cpl_frame_get_tag (frame);
179 
180  cpl_ensure (value != NULL, cpl_error_get_code(), 0);
181  if (strstr(value,"SINGLE")) {
182  return MODE_SINGLE;
183  }
184  if (strstr(value, "DUAL")) {
185  return MODE_DUAL;
186  }
187 
188  return 0;
189 }
190 
191 int gravi_pfits_get_mode (const cpl_propertylist * plist)
192 {
193  const char * type;
194 
195  if (cpl_propertylist_has (plist, "ESO PRO CATG"))
196  type = cpl_propertylist_get_string (plist,"ESO PRO CATG");
197  else if (cpl_propertylist_has (plist, "ESO DPR TYPE"))
198  type = cpl_propertylist_get_string (plist,"ESO DPR TYPE");
199  else return -1;
200 
201  if (strstr (type,"SINGLE")) {
202  return MODE_SINGLE;
203  }
204  if (strstr (type, "DUAL")) {
205  return MODE_DUAL;
206  }
207 
208  return 0;
209 }
210 
211 const char * gravi_pfits_get_mode_name (const cpl_propertylist * plist)
212 {
213  cpl_ensure (plist, CPL_ERROR_NULL_INPUT, NULL);
214  const char * type;
215 
216  if (cpl_propertylist_has (plist, "ESO PRO CATG"))
217  type = cpl_propertylist_get_string (plist,"ESO PRO CATG");
218  else if (cpl_propertylist_has (plist, "ESO DPR TYPE"))
219  type = cpl_propertylist_get_string (plist,"ESO DPR TYPE");
220  else return "UNKNOWN";
221 
222  if (strstr (type,"SINGLE")) {
223  return "SINGLE";
224  }
225  if (strstr (type, "DUAL")) {
226  return "DUAL";
227  }
228 
229  return "UNKNOWN";
230 }
231 
232 int gravi_pfits_get_pola_num (const cpl_propertylist * plist, int type_data )
233 {
234  const char * keyword = ( type_data == GRAVI_FT ? "ESO FT POLA MODE" : "ESO INS POLA MODE");
235  const char * value = cpl_propertylist_get_string(plist, keyword);
236  cpl_ensure (value != NULL, cpl_error_get_code(), 0);
237  return ( !(strcmp(value,"SPLIT")) ? 2 : 1 );
238 }
239 
240 int gravi_pfits_get_extension_type (const cpl_propertylist * plist)
241 {
242  cpl_errorstate prestate = cpl_errorstate_get();
243 
244  const char * value = cpl_propertylist_get_string (plist, "XTENSION");
245  cpl_ensure (value, CPL_ERROR_ILLEGAL_INPUT, 0);
246 
247  int ext_type;
248 
249  if (! strcmp(value, "IMAGE"))
250  ext_type = 3;
251  else if (! strcmp(value, "BINTABLE"))
252  ext_type = 2;
253  else if (! strcmp(value, "TABLE"))
254  ext_type = 2;
255  else {
256  cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
257  "Type extension is incorrect");
258  ext_type = 0;
259  }
260  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
261  return ext_type;
262 }
263 
264 double gravi_pfits_get_metfc_lockmjd (const cpl_propertylist * plist, int tel)
265 {
266  cpl_errorstate prestate = cpl_errorstate_get();
267 
268  char *lock = cpl_sprintf ("ESO OCS MET LKDT_FC%i", tel+1);
269  double value = gravi_convert_to_mjd (cpl_propertylist_get_string (plist, lock));
270 
271  if (!cpl_errorstate_is_equal(prestate)) {
272  cpl_errorstate_set (prestate);
273  cpl_msg_warning (cpl_func, "Cannot read %s", lock);
274  value = 0.0;
275  }
276 
277  cpl_free (lock);
278  return value;
279 }
280 
281 double gravi_pfits_get_met_wavelength_mean (const cpl_propertylist * plist, cpl_table * met_table)
282 {
283  double met_wavelength_ref = gravi_pfits_get_met_wavelength (plist)*1e-9;
284  double lambda_met_mean = met_wavelength_ref +
285  cpl_table_get_column_mean(met_table, "LAMBDA_LASER")*1e-9;
286 
287  return (lambda_met_mean);
288 }
289 
290 double gravi_pfits_get_met_wavelength (const cpl_propertylist * plist)
291 {
292  cpl_errorstate prestate = cpl_errorstate_get();
293 
294  /* double power; */
295  double wavelength;
296 
297  /*
298  * If cannot read MLC laser power
299  */
300  if (cpl_propertylist_has (plist, "ESO INS MLC POWER") == FALSE) {
301  wavelength = gravi_pfits_get_double(plist, "ESO INS MLC WAVELENG");
302  cpl_msg_warning (cpl_func, "Cannot read the laser POWER : use MLC wavelength : %f ", wavelength);
303  }
304  /*
305  * If MLC laser ON
306  */
307  else if (gravi_pfits_get_double(plist, "ESO INS MLC POWER") != 0) {
308  wavelength = gravi_pfits_get_double(plist, "ESO INS MLC WAVELENG");
309  cpl_msg_info(cpl_func, "Using laser MLC wavelength : %f ", wavelength);
310  }
311  /*
312  * If MLAS laser ON
313  */
314  else if (gravi_pfits_get_double(plist, "ESO INS MLAS LPOW") != 0) {
315  /* power=gravi_pfits_get_double(plist, "ESO INS MLAS LPOW"); */
316  wavelength = cpl_propertylist_get_double(plist, "ESO INS MLAS LWAV");
317  cpl_msg_info(cpl_func, "Using laser MLAS wavelength : %f ", wavelength);
318  }
319 
320  if (!cpl_errorstate_is_equal(prestate)) {
321  cpl_msg_warning (cpl_func, "Cannot read the laser wavelength in the header : %s", cpl_error_get_message());
322  cpl_errorstate_set (prestate);
323  wavelength = 0.0;
324  }
325 
326  return wavelength;
327 }
328 
329 double gravi_pfits_get_geolat (const cpl_propertylist * plist)
330 {
331  cpl_errorstate prestate = cpl_errorstate_get();
332  double value = cpl_propertylist_get_double(plist, "ESO ISS GEOLAT");
333  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
334  return value;
335 }
336 
337 double gravi_pfits_get_geolon (const cpl_propertylist * plist)
338 {
339  cpl_errorstate prestate = cpl_errorstate_get();
340  double value = cpl_propertylist_get_double(plist, "ESO ISS GEOLON");
341  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
342  return value;
343 }
344 
345 double gravi_pfits_get_geoelev (const cpl_propertylist * plist)
346 {
347  cpl_errorstate prestate = cpl_errorstate_get();
348  double value = cpl_propertylist_get_double (plist, "ESO ISS GEOELEV");
349  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
350  return value;
351 }
352 
353 const char * gravi_pfits_get_sobj (const cpl_propertylist * plist)
354 {
355  const char * value = gravi_pfits_get_string_default (plist, "ESO INS SOBJ NAME", "UNKNOWN_SC");
356  return value;
357 }
358 
359 double gravi_pfits_get_sobj_diam (const cpl_propertylist * plist)
360 {
361  cpl_errorstate prestate = cpl_errorstate_get();
362  double value = cpl_propertylist_get_double (plist, "ESO INS SOBJ DIAMETER");
363  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
364  return value;
365 }
366 
367 double gravi_pfits_get_sobj_x (const cpl_propertylist * plist)
368 {
369  double value = gravi_pfits_get_double_default (plist, "ESO INS SOBJ X", 0.0);
370  return value;
371 }
372 
373 double gravi_pfits_get_sobj_y (const cpl_propertylist * plist)
374 {
375  double value = gravi_pfits_get_double_default (plist, "ESO INS SOBJ Y", 0.0);
376  return value;
377 }
378 
379 const char * gravi_pfits_get_robj (const cpl_propertylist * plist)
380 {
381  const char * value = gravi_pfits_get_string_default (plist, "ESO FT ROBJ NAME", "UNKNOWN_FT");
382  return value;
383 }
384 
385 double gravi_pfits_get_robj_diam (const cpl_propertylist * plist)
386 {
387  cpl_errorstate prestate = cpl_errorstate_get();
388  double value = cpl_propertylist_get_double(plist, "ESO FT ROBJ DIAMETER");
389  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
390  return value;
391 }
392 
393 
394 /*-----------------------------------------------------------------------------
395  TIMING
396  -----------------------------------------------------------------------------*/
397 
398 double gravi_pfits_get_fddlwindow (const cpl_propertylist * plist)
399 {
400  cpl_errorstate prestate = cpl_errorstate_get();
401  double value = cpl_propertylist_get_double(plist, "ESO INS FDDL WINDOW");
402  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
403  return value;
404 }
405 
406 double gravi_pfits_get_mjd (const cpl_propertylist * plist)
407 {
408  cpl_errorstate prestate = cpl_errorstate_get();
409  double value = cpl_propertylist_get_double(plist, "MJD-OBS");
410  cpl_ensure (cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
411  return value;
412 }
413 
414 const char * gravi_pfits_get_met_ph (const cpl_propertylist * plist)
415 {
416  const char * tim1_start = cpl_propertylist_get_string(plist, "ESO OCS MET PH_DATE");
417  cpl_ensure (tim1_start != NULL, cpl_error_get_code(), NULL);
418  return tim1_start;
419 }
420 
421 int gravi_pfits_has_gdzero (const cpl_propertylist * plist,
422  int tel)
423 {
424  cpl_ensure (plist, CPL_ERROR_NULL_INPUT, 0);
425 
426  int return_val = 0;
427  char name[100];
428 
429  sprintf (name, "ESO QC MET GD_ZERO_FC%i", tel);
430  if (cpl_propertylist_has(plist, name))
431  {
432  return_val = 1;
433  } else {
434  sprintf (name, "ESO PRO MET GD_ZERO_FC%i", tel);
435  if (cpl_propertylist_has(plist, name))
436  return_val = 1;
437  }
438 
439  return return_val;
440 }
441 
442 double gravi_pfits_get_gdzero (const cpl_propertylist * plist,
443  int tel)
444 {
445  cpl_ensure (plist, CPL_ERROR_NULL_INPUT, 0);
446 
447  double output;
448  char name[100];
449 
450  sprintf (name, "ESO QC MET GD_ZERO_FC%i", tel);
451  if (cpl_propertylist_has(plist, name)) {
452  /* Try to read this keyword as a double */
453  output = gravi_pfits_get_double(plist, name);
454  } else {
455  sprintf (name, "ESO PRO MET GD_ZERO_FC%i", tel);
456  if (cpl_propertylist_has(plist, name)) {
457  /* Try to read this keyword as a double */
458  output = gravi_pfits_get_double(plist, name);
459  } else
460  output = 0;
461  }
462 
463  return output;
464 }
465 
466 int gravi_pfits_has_oplzero (const cpl_propertylist * plist,
467  int tel)
468 {
469  cpl_ensure (plist, CPL_ERROR_NULL_INPUT, 0);
470 
471  int return_val = 0;
472  char name[100];
473 
474  sprintf (name, "ESO QC MET OPL_ZERO_FC%i", tel);
475  if (cpl_propertylist_has(plist, name)) {
476  return_val = 1;
477  } else {
478  sprintf (name,"ESO PRO MET OPL_ZERO_FC%i", tel);
479  if (cpl_propertylist_has(plist, name))
480  return_val = 1;
481  }
482 
483  return return_val;
484 }
485 
486 double gravi_pfits_get_oplzero (const cpl_propertylist * plist,
487  int tel)
488 {
489  cpl_ensure (plist, CPL_ERROR_NULL_INPUT, 0);
490 
491  double output;
492  char name[100];
493 
494  sprintf (name, "ESO QC MET OPL_ZERO_FC%i", tel);
495  if (cpl_propertylist_has(plist, name)) {
496  /* Try to read this keyword as a double */
497  output = gravi_pfits_get_double(plist, name);
498  } else {
499  sprintf (name, "ESO PRO MET OPL_ZERO_FC%i", tel);
500  if (cpl_propertylist_has(plist, name)) {
501  /* Try to read this keyword as a double */
502  output = gravi_pfits_get_double(plist, name);
503  } else
504  output = 0;
505  }
506 
507  return output;
508 }
509 
510 
511 const char * gravi_pfits_get_start_sc (const cpl_propertylist * plist)
512 {
513  /* SC = TIM1 = DET2 */
514  const char * tim1_start = cpl_propertylist_get_string(plist, "ESO INS TIM1 START");
515  cpl_ensure (tim1_start != NULL, cpl_error_get_code(), NULL);
516  return tim1_start;
517 }
518 
519 const char * gravi_pfits_get_start_acqcam (const cpl_propertylist * plist)
520 {
521  /* ACQCAM = TIM2 = DET1 */
522  const char * tim1_start = cpl_propertylist_get_string(plist, "ESO INS TIM2 START");
523  cpl_ensure (tim1_start != NULL, cpl_error_get_code(), NULL);
524  return tim1_start;
525 }
526 
527 const char * gravi_pfits_get_start_prcacq (const cpl_propertylist * plist)
528 {
529  /* This is the recording start of RMN tables */
530  const char * acq_start = cpl_propertylist_get_string(plist, "ESO PCR ACQ START");
531  cpl_ensure (acq_start != NULL, cpl_error_get_code(), NULL);
532  return acq_start;
533 }
534 
535 double gravi_pfits_get_dit_acqcam (const cpl_propertylist * plist)
536 {
537  /* ACQCAM = TIM2 = DET1 */
538  cpl_errorstate prestate = cpl_errorstate_get();
539  double value = cpl_propertylist_get_double(plist, "ESO DET1 SEQ1 DIT");
540  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
541  return value;
542 }
543 
544 double gravi_pfits_get_dit_sc (const cpl_propertylist * plist)
545 {
546  /* SC = TIM1 = DET2 */
547  cpl_errorstate prestate = cpl_errorstate_get();
548  double value = cpl_propertylist_get_double(plist, "ESO DET2 SEQ1 DIT");
549  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
550  return value;
551 }
552 
553 double gravi_pfits_get_dit_ft (const cpl_propertylist * plist)
554 {
555  /* FT = PCRACQ = DET3 */
556  cpl_errorstate prestate = cpl_errorstate_get();
557  double value = cpl_propertylist_get_double(plist, "ESO DET3 SEQ1 DIT");
558  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
559  return value;
560 }
561 
562 double gravi_pfits_get_period_sc (const cpl_propertylist * plist)
563 {
564  /* SC = TIM1 = DET2 */
565  cpl_errorstate prestate = cpl_errorstate_get();
566  double value = cpl_propertylist_get_double(plist, "ESO INS TIM1 PERIOD");
567  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
568  return value;
569 }
570 
571 double gravi_pfits_get_period_acqcam (const cpl_propertylist * plist)
572 {
573  /* ACQCAM = TIM2 = DET1 */
574  cpl_errorstate prestate = cpl_errorstate_get();
575  double value = cpl_propertylist_get_double(plist, "ESO INS TIM2 PERIOD");
576  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
577  return value;
578 }
579 
580 /*---------------------------------------------------------------------------*/
588 /*---------------------------------------------------------------------------*/
589 
590 double gravi_pfits_get_time_sc (const cpl_propertylist * header, cpl_size row)
591 {
592  gravi_msg_function_start(0);
593  cpl_ensure (header, CPL_ERROR_NULL_INPUT, 0.0);
594  cpl_errorstate prestate = cpl_errorstate_get();
595 
596  /* Time of the middle of the exposure in
597  * [us] with respect to PRC.ACQ.START. */
598  double window_time = gravi_pfits_get_fddlwindow (header);
599  double period = gravi_pfits_get_period_sc (header);
600 
601  double time = 86400 * 1e6 *
602  (gravi_convert_to_mjd (gravi_pfits_get_start_sc (header)) -
603  gravi_convert_to_mjd (gravi_pfits_get_start_prcacq (header)) ) +
604  (period-window_time)/2. * 1e6 +
605  row * period * 1e6;
606 
607  /* Return 0 if error */
608  cpl_ensure (cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
609 
610  gravi_msg_function_exit(0);
611  return time;
612 }
613 
614 /*---------------------------------------------------------------------------*/
622 /*---------------------------------------------------------------------------*/
623 
624 double gravi_pfits_get_time_acqcam (const cpl_propertylist * header, cpl_size row)
625 {
626  gravi_msg_function_start(0);
627  cpl_ensure (header, CPL_ERROR_NULL_INPUT, 0.0);
628  cpl_ensure (row>=0, CPL_ERROR_ILLEGAL_INPUT, 0.0);
629  cpl_errorstate prestate = cpl_errorstate_get();
630 
631  /* Time of the middle of the exposure in
632  * [us] with respect to PRC.ACQ.START. */
633  double period = gravi_pfits_get_period_acqcam (header);
634 
635  double time = 86400 * 1e6 *
636  (gravi_convert_to_mjd (gravi_pfits_get_start_acqcam (header)) -
637  gravi_convert_to_mjd (gravi_pfits_get_start_prcacq (header)) ) +
638  period/2. * 1e6 +
639  row * period * 1e6;
640 
641  /* Return 0 if error */
642  cpl_ensure (cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
643 
644  gravi_msg_function_exit(0);
645  return time;
646 }
647 
648 double gravi_pfits_get_ptfc_acqcam (const cpl_propertylist * plist, int spot)
649 {
650  cpl_errorstate prestate = cpl_errorstate_get();
651  char name[90];
652  sprintf (name, "ESO ACQ PTFC REFPOS%i", spot);
653  double value = cpl_propertylist_get_double (plist, name);
654  cpl_ensure (cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
655  return value;
656 }
657 
658 double gravi_pfits_get_drotoff (const cpl_propertylist * plist, int tel)
659 {
660  char name[90];
661 
662  /* Angle of binary on ACQ image */
663  sprintf (name, "ESO INS DROTOFF%i", tel+1);
664  double drottoff = cpl_propertylist_get_double (plist, name);
665 
666  return drottoff;
667 }
668 
669 double gravi_pfits_get_fangle_acqcam (const cpl_propertylist * plist, int tel)
670 {
671  double fangle = 0.0;
672 
673  if (cpl_propertylist_has (plist, "ESO INS SOBJ X") &&
674  cpl_propertylist_has (plist, "ESO INS SOBJ Y") ) {
675 
676  /* Angle of binary on ACQ image */
677  char name[90];
678  sprintf (name, "ESO INS DROTOFF%i", tel+1);
679  double drottoff = cpl_propertylist_get_double (plist, name);
680 
681  /* Position angle of binary */
682  double dx = cpl_propertylist_get_double (plist, "ESO INS SOBJ X");
683  double dy = cpl_propertylist_get_double (plist, "ESO INS SOBJ Y");
684 
685  /* If in a mapping template, remove dithering offset */
686  double posangle = 0.0;
687  if (cpl_propertylist_has(plist, "ESO INS SOBJ OFFX") &&
688  cpl_propertylist_has(plist, "ESO INS SOBJ OFFY")) {
689 
690  dx -= gravi_pfits_get_double_default (plist, "ESO INS SOBJ OFFX", 0.0);
691  dy -= gravi_pfits_get_double_default (plist, "ESO INS SOBJ OFFY", 0.0);
692  }
693  if ((fabs(dx)>0.0) || (fabs(dy)>0.0))
694  posangle = atan2 (dx, dy) * CPL_MATH_DEG_RAD;
695 
696  /* Angle of North in ACQ image, from vertical (y+) to right (x+) */
697  fangle = - posangle - drottoff + 270;
698  if (fangle >= 180) fangle -= 360.0;
699  if (fangle < -180) fangle += 360.0;
700  if (fangle >= 180) fangle -= 360.0;
701  if (fangle < -180) fangle += 360.0;
702 
703  cpl_msg_info (cpl_func, "fangle = %.2f [deg] / NorthACQ in Y to X", fangle);
704  } else {
705  cpl_msg_warning (cpl_func, "Cannot compute field angle: fangle = 0.0");
706  }
707 
708  return fangle;
709 }
710 
711 
712 const char * gravi_pfits_get_insname (const cpl_propertylist * plist)
713 {
714  const char * value = cpl_propertylist_get_string(plist, "INSNAME");
715  cpl_ensure (value != NULL, cpl_error_get_code(), NULL);
716  return value;
717 }
718 
719 /*---------------------------------------------------------------------------*/
725 /*---------------------------------------------------------------------------*/
726 
727 double gravi_pfits_get_ft_gain (const cpl_propertylist * plist)
728 {
729  double gain = 0.0;
730 
731  if ( cpl_propertylist_has (plist, "MJD-OBS") &&
732  cpl_propertylist_has (plist, "ESO INS DET3 GAIN") &&
733  cpl_propertylist_get_double (plist, "MJD-OBS") >= 57584.83 &&
734  cpl_propertylist_get_double (plist, "MJD-OBS") < 57617.0) {
735 
736  /* Between 57584.83 and 57617.0, the keyword is valid but written
737  * in [adu/e] and the value 3.0 shall be replaced by 1.7 [adu/e] */
738  gain = cpl_propertylist_get_double (plist, "ESO INS DET3 GAIN");
739  if (gain == 3.0) gain = 1.7;
740  cpl_msg_warning (cpl_func,"Use FT gain of %.3f [adu/e] (wrong units and value in header)", gain);
741  } else if ( cpl_propertylist_has (plist, "MJD-OBS") &&
742  cpl_propertylist_has (plist, "ESO INS DET3 GAIN") &&
743  cpl_propertylist_get_double (plist, "MJD-OBS") >= 57617.0) {
744 
745  /* After 57617.0, the keyword is valid and written in [e/adu] */
746  gain = 1. / cpl_propertylist_get_double (plist, "ESO INS DET3 GAIN");
747  cpl_msg_info (cpl_func,"Use FT gain of %.3f [adu/e] from header", gain);
748  } else {
749  /* The keyword is not valid at all */
750  gain = 25.0;
751  cpl_msg_warning (cpl_func,"Force FT gain to %.3f [adu/e] (wrong value or no value in header)", gain);
752  }
753 
754  /* gain in ADU/e */
755  return gain;
756 }
757 
758 /*---------------------------------------------------------------------------*/
764 /*---------------------------------------------------------------------------*/
765 
766 double gravi_pfits_get_sc_gain (const cpl_propertylist * plist)
767 {
768  double gain = 0.0;
769 
770  if ( cpl_propertylist_has (plist, "MJD-OBS") &&
771  cpl_propertylist_has (plist, "ESO INS DET2 GAIN") &&
772  cpl_propertylist_get_double (plist, "MJD-OBS") > 57617.0) {
773 
774  /* After 57617.0, the keyword is valid and written in [e/adu] */
775  gain = 1. / cpl_propertylist_get_double (plist, "ESO INS DET2 GAIN");
776  cpl_msg_info (cpl_func,"Use SC gain of %.3f [adu/e] from header", gain);
777  } else {
778  /* The keyword is not valid at all */
779  gain = 0.5;
780  cpl_msg_warning (cpl_func,"Force SC gain to %.3f [adu/e]", gain);
781  }
782 
783  /* gain in ADU/e */
784  return gain;
785 }
786 
787 
788 
789 /*-----------------------------------------------------------------------------
790  Extract sub-set of propertylist
791  -----------------------------------------------------------------------------*/
792 
793 /*-----------------------------------------------------------------------------*/
799 /*-----------------------------------------------------------------------------*/
800 
801 cpl_propertylist * gravi_plist_get_oifits_keywords (cpl_propertylist * header)
802 {
803  gravi_msg_function_start(1);
804 
805  cpl_propertylist * o_plist = cpl_propertylist_new ();
806 
807  /* CONTENT */
808  cpl_propertylist_update_string (o_plist, "CONTENT", "OIFITS2");
809  cpl_propertylist_update_string (o_plist, "REFERENC", "2001PASP..112.1133P");
810 
811  /* OBSERVER */
812  const char * observer = gravi_pfits_get_string_default (header, "ESO ISS OPER", "Unknown");
813  cpl_propertylist_update_string (o_plist, "OBSERVER", observer);
814 
815  /* PROG_ID */
816  const char * prog_id = gravi_pfits_get_string_default (header, "ESO OBS PROG ID", "Unknown");
817  cpl_propertylist_update_string (o_plist, "PROG_ID", prog_id);
818 
819  /* PROCSOFT */
820  char * procsoft = cpl_sprintf("GRAVITY pipeline %s", PACKAGE_VERSION);
821  cpl_propertylist_update_string (o_plist, "PROCSOFT", procsoft);
822  FREE (cpl_free, procsoft);
823 
824  /* OBJECT -- may be overwritten by ESO esorex mechanism */
825  const char * sc_object = gravi_pfits_get_sobj (header);
826  const char * ft_object = gravi_pfits_get_robj (header);
827  char * object = cpl_sprintf ("%s,%s", sc_object, ft_object);
828  cpl_propertylist_update_string (o_plist, "OBJECT", object);
829  FREE (cpl_free, object);
830 
831  /* INSMODE */
832  char * mode;
833  mode = cpl_sprintf ("%s,%s,%s,%s",
834  gravi_pfits_get_mode_name (header),
835  gravi_pfits_get_spec_res (header),
836  gravi_pfits_get_pola_mode (header, GRAVI_SC),
837  gravi_pfits_get_pola_mode (header, GRAVI_FT));
838  cpl_propertylist_update_string (o_plist, "INSMODE", mode);
839  FREE (cpl_free, mode);
840 
841  CPLCHECK_NUL ("Cannot fill the OIFITS2 specific keywords");
842 
843  gravi_msg_function_exit(1);
844  return o_plist;
845 }
846 
847 
848 /*-----------------------------------------------------------------------------*/
854 /*-----------------------------------------------------------------------------*/
855 
856 cpl_propertylist * gravi_plist_get_qc (cpl_propertylist * header)
857 {
858  const char * qc = " QC ";
859 
860  /* Check inputs */
861  cpl_ensure (header, CPL_ERROR_NULL_INPUT, NULL);
862 
863  /* Research all the qc parameter inside the primary header of the data */
864  cpl_propertylist * applist = cpl_propertylist_new();
865  cpl_size size = cpl_propertylist_get_size (header);
866  for (cpl_size i = 0; i < size; i++) {
867  cpl_property * p = cpl_propertylist_get (header, i);
868  const char * p_name = cpl_property_get_name (p);
869  if ( (strstr(p_name, qc) != NULL) ||
870  (strstr(p_name, GRAVI_NIGHT_OBS) != NULL) ) {
871  cpl_type type_qc = cpl_property_get_type (p);
872  switch (type_qc) {
873  case CPL_TYPE_FLOAT :
874  if (cpl_property_get_float (p) != NAN)
875  cpl_propertylist_append_property(applist, p);
876  else
877  cpl_msg_warning(cpl_func, "The parameter %s is not correct", cpl_property_get_name (p));
878  break;
879  case CPL_TYPE_DOUBLE :
880  if (cpl_property_get_double (p) != NAN)
881  cpl_propertylist_append_property(applist, p);
882  else
883  cpl_msg_warning(cpl_func, "The parameter %s is not correct", cpl_property_get_name (p));
884  break;
885  case CPL_TYPE_INT :
886  if (cpl_property_get_int (p) != NAN)
887  cpl_propertylist_append_property(applist, p);
888  else
889  cpl_msg_warning(cpl_func, "The parameter %s is not correct", cpl_property_get_name (p));
890  break;
891  case CPL_TYPE_STRING :
892  if (cpl_property_get_string (p))
893  cpl_propertylist_append_property(applist, p);
894  else
895  cpl_msg_warning(cpl_func, "The parameter %s is not correct", cpl_property_get_name (p));
896  break;
897  case CPL_TYPE_CHAR :
898  if (cpl_property_get_char (p))
899  cpl_propertylist_append_property(applist, p);
900  else
901  cpl_msg_warning(cpl_func, "The parameter %s is not correct", cpl_property_get_name (p));
902  break;
903  case CPL_TYPE_BOOL :
904  cpl_propertylist_append_property (applist, p);
905  break;
906  default :
907  cpl_msg_error (cpl_func,"'%s' is an invalid type of property",p_name);
908  cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
909  "invalid type of property");
910  return NULL;
911  }
912  }
913  }
914  return applist;
915 }
916 
917 /*-----------------------------------------------------------------------------
918  Function to convert string
919  -----------------------------------------------------------------------------*/
920 
921 double gravi_convert_to_mjd (const char * start)
922 {
923  cpl_ensure (start, CPL_ERROR_NULL_INPUT, 0.0);
924 
925  /* Cut the string: 2015-04-01T20:36:59.380228
926  * and convert each in int or double */
927  char * str = cpl_strdup (start);
928 
929  str[4] = '\n';
930  str[7] = '\n';
931  str[10] = '\n';
932  str[13] = '\n';
933  str[16] = '\n';
934 
935  int iy = atoi (str+0); // YYYY
936  int im = atoi (str+5); // MM
937  int id = atoi (str+8); // DD
938  double dhr = atof (str+11); // hh
939  double dmin = atof (str+14); // mm
940  double dsec = atof (str+17); // ss.ss
941  cpl_free (str);
942 
943  /* Get the MJD at 00:00 with ERFA [d] */
944  double dmjd0, dmjd;
945  eraCal2jd (iy, im, id, &dmjd0, &dmjd);
946 
947  /* Return the full MJD [d] */
948  return dmjd + (dhr + (dmin + dsec/60.0)/60.0)/24.0;
949 }
950 
951 char * gravi_convert_to_timestamp (double mjd)
952 {
953  int year, month, day, hour, minute;
954  double fraction, second;
955 
956  eraJd2cal (2400000.5, mjd, &year, &month, &day, &fraction);
957 
958  hour = (int)(fraction/3600.0);
959  fraction -= hour*3600.0;
960  minute = (int)(fraction/60.0);
961  fraction -= minute*60.0;
962  second = fraction;
963 
964  return cpl_sprintf ("%04i-%02i-%02iT%02i:%02i:%06.3f", year, month, day, hour, minute, second);
965 }
966 
967 double gravi_pfits_get_decep (const cpl_propertylist * plist, double coef)
968 {
969  cpl_ensure (plist, CPL_ERROR_NULL_INPUT, 0.0);
970  cpl_ensure (coef >= 0 && coef <= 1, CPL_ERROR_ILLEGAL_INPUT, 0.0);
971 
972  /* Get RA and DEC in [rad] */
973  // double raz = gravi_pfits_get_robj_raep (plist);
974  double decz = gravi_pfits_get_robj_decep (plist);
975 
976  /* Get and convert the offsets from [mas] to [rad] */
977  double xi = gravi_pfits_get_sobj_x (plist) / 3600000. * CPL_MATH_RAD_DEG * coef;
978  double eta = gravi_pfits_get_sobj_y (plist) / 3600000. * CPL_MATH_RAD_DEG * coef;
979 
980  double sdecz = sin(decz);
981  double cdecz = cos(decz);
982  double denom = cdecz - eta * sdecz;
983 
984  /* Compute new coordinates in [rad] */
985  double dec = atan2 (sdecz+eta*cdecz, sqrt(xi*xi + denom*denom));
986 
987  /* Return in [rad] */
988  return dec;
989 }
990 
991 double gravi_ra_to_rad (const char *stri)
992 {
993  cpl_ensure (stri, CPL_ERROR_NULL_INPUT, 0.0);
994 
995  /* Assume the format is HH MM SS.SSSS */
996  char * str = cpl_strdup (stri);
997  str[2] = '\0';
998  str[5] = '\0';
999 
1000  /* Ra in [hours] */
1001  double out = 0.0;
1002  out += atof(str+0);
1003  out += atof(str+3) / 60;
1004  out += atof(str+6) / 3600;
1005 
1006  cpl_free (str);
1007  return out / 12 * CPL_MATH_PI;
1008 }
1009 
1010 double gravi_dec_to_rad (const char *stri)
1011 {
1012  cpl_ensure (stri, CPL_ERROR_NULL_INPUT, 0.0);
1013 
1014  /* Assume the format is +DD MM SS.SSSS */
1015  char * str = cpl_strdup (stri);
1016  str[3] = '\0';
1017  str[6] = '\0';
1018 
1019  /* Ra in [hours] */
1020  double out = 0.0;
1021  out += atof(str+1);
1022  out += atof(str+4) / 60;
1023  out += atof(str+7) / 3600;
1024 
1025  out *= (str[0]=='-' ? -1.0 : 1.0);
1026 
1027  cpl_free (str);
1028  return out / 180 * CPL_MATH_PI;
1029 }
1030 
1031 
1032 /*-----------------------------------------------------------------------------
1033  Function to read the target coordinates
1034  -----------------------------------------------------------------------------*/
1035 
1036 double gravi_pfits_get_raep(const cpl_propertylist * plist, double coef)
1037 {
1038  cpl_ensure (plist, CPL_ERROR_NULL_INPUT, 0.0);
1039  cpl_ensure (coef >= 0 && coef <= 1, CPL_ERROR_ILLEGAL_INPUT, 0.0);
1040 
1041  /* Get RA and DEC in [rad] */
1042  double raz = gravi_pfits_get_robj_raep (plist);
1043  double decz = gravi_pfits_get_robj_decep (plist);
1044 
1045  /* Get and convert the offsets from [mas] to [rad] */
1046  double xi = gravi_pfits_get_sobj_x (plist) / 3600000. * CPL_MATH_RAD_DEG * coef;
1047  double eta = gravi_pfits_get_sobj_y (plist) / 3600000. * CPL_MATH_RAD_DEG * coef;
1048 
1049  double sdecz = sin(decz);
1050  double cdecz = cos(decz);
1051  double denom = cdecz - eta * sdecz;
1052 
1053  /* Compute new coordinates in [rad] */
1054  double ra = atan2 (xi,denom) + raz;
1055 
1056  /* Make ra within 0-2pi */
1057  ra = fmod (ra, CPL_MATH_2PI);
1058  if ( ra < 0.0 ) ra += CPL_MATH_2PI;
1059 
1060  /* Return in [rad] */
1061  return ra;
1062 }
1063 
1064 double gravi_pfits_get_robj_raep(const cpl_propertylist * plist)
1065 {
1066  cpl_ensure (plist, CPL_ERROR_NULL_INPUT, 99.);
1067  cpl_errorstate prestate = cpl_errorstate_get();
1068  char tmp[15];
1069 
1070  /* Read the parameter as string */
1071  const char * str_value;
1072  str_value = gravi_pfits_get_string_default (plist, "ESO FT ROBJ ALPHA", "000000.00");
1073 
1074  double value = 99.;
1075 
1076  /* Read of the form '043555.24' */
1077  cpl_msg_debug( cpl_func, "Found '%s'", str_value );
1078 
1079  /* Read 2 first chars */
1080  strncpy(tmp, str_value, 2);
1081  tmp[2] = '\0';
1082  cpl_msg_debug( cpl_func, "Found tmp '%s' -> %f", tmp, atof(tmp) );
1083  value = atof(tmp);
1084 
1085  /* Read 2 more chars */
1086  strncpy(tmp, str_value+2, 4);
1087  tmp[2] = '\0';
1088  cpl_msg_debug( cpl_func, "Found tmp '%s' -> %f", tmp, atof(tmp) );
1089  value += atof(tmp) / 60.0;
1090 
1091  /* Read remaining data */
1092  strcpy(tmp, str_value+4);
1093  cpl_msg_debug( cpl_func, "Found tmp '%s' -> %f", tmp, atof(tmp) );
1094  value += atof(tmp) / 3600.0;
1095 
1096  /* Convert hours to deg */
1097  value *= 360. / 24;
1098 
1099  /* Verbose */
1100  cpl_msg_debug( cpl_func, "Convert RA='%s' into RA=%fdeg", str_value, value);
1101 
1102  if (cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) {
1103  cpl_errorstate_set (prestate);
1104  cpl_msg_warning(cpl_func, "rarp doesn't exist in this file.");
1105  value=0;
1106  }
1107 
1108  /* Check for a change in the CPL error state */
1109  /* - if it did change then propagate the error and return */
1110  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
1111 
1112  /* Convert in [rad] */
1113  return value * CPL_MATH_RAD_DEG;
1114 }
1115 
1116 double gravi_pfits_get_robj_decep (const cpl_propertylist * plist)
1117 {
1118  cpl_ensure (plist, CPL_ERROR_NULL_INPUT, 99.);
1119 
1120  cpl_errorstate prestate = cpl_errorstate_get();
1121  double value = 99.;
1122  char tmp[15];
1123  double sign;
1124 
1125  const char * str_value;
1126  str_value = gravi_pfits_get_string_default (plist, "ESO FT ROBJ DELTA", "+000000.00");
1127 
1128  /* Read of the form '163033.49' -- issue with +/- */
1129  cpl_msg_debug( cpl_func, "Found '%s'", str_value );
1130 
1131  /* Check the first digit is a sign + or -
1132  and discard it */
1133  if ( str_value[0] == '-' ) {
1134  sign = -1.0;
1135  str_value = str_value + 1;
1136  } else if ( str_value[0] == '+' ) {
1137  sign = +1.0;
1138  str_value = str_value + 1;
1139  } else {
1140  sign = +1.0;
1141  }
1142 
1143  /* Read 2 first chars */
1144  strncpy(tmp, str_value, 2);
1145  tmp[2] = '\0';
1146  cpl_msg_debug( cpl_func, "Found tmp '%s' -> %f", tmp, atof(tmp) );
1147  value = atof(tmp);
1148 
1149  /* Read 2 more chars */
1150  strncpy(tmp, str_value+2, 4);
1151  tmp[2] = '\0';
1152  cpl_msg_debug( cpl_func, "Found tmp '%s' -> %f", tmp, atof(tmp) );
1153  value += atof(tmp) / 60.0;
1154 
1155  /* Read remaining data */
1156  strcpy(tmp, str_value+4);
1157  cpl_msg_debug( cpl_func, "Found tmp '%s' -> %f", tmp, atof(tmp) );
1158  value += atof(tmp) / 3600.0;
1159 
1160  /* Apply sign */
1161  value *= sign;
1162 
1163  /* Verbose */
1164  cpl_msg_debug( cpl_func, "Convert DEC='%s' into DEC=%fdeg", str_value, value);
1165 
1166  if (cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) {
1167  cpl_errorstate_set (prestate);
1168  cpl_msg_warning(cpl_func, "decep doesn't exist in this file.");
1169 
1170  value=0;
1171  }
1172 
1173  /* Check for a change in the CPL error state */
1174  /* - if it did change then propagate the error and return */
1175  cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
1176 
1177  /* Convert in [rad] */
1178  return value * CPL_MATH_RAD_DEG;
1179 }
1180 
1181 /*-----------------------------------------------------------------------------
1182  Test function codes
1183  -----------------------------------------------------------------------------*/
1184 
1185 int gravi_pfits_is_calib (const cpl_propertylist * plist)
1186 {
1187  cpl_ensure (plist, CPL_ERROR_NULL_INPUT, 0);
1188  const char * opt1 = "ESO INS OPTI1 NAME";
1189 
1190  if ( !cpl_propertylist_has (plist, opt1) ) return 0;
1191 
1192  const char * value = cpl_propertylist_get_string (plist, opt1);
1193  if ( !strcmp (value,"CALIB") ) return 1;
1194 
1195  return 0;
1196 }
1197 
1198 
1199 /*----------------------------------------------------------------------------
1200  Generic functions to read and set keyword
1201  ----------------------------------------------------------------------------*/
1202 
1203 
1204 /*----------------------------------------------------------------------------*/
1215 /*----------------------------------------------------------------------------*/
1216 
1217 double gravi_pfits_get_double (const cpl_propertylist * self, const char * name)
1218 {
1219  cpl_ensure (self, CPL_ERROR_NULL_INPUT, 0);
1220  cpl_ensure (name, CPL_ERROR_NULL_INPUT, 0);
1221  cpl_ensure (cpl_propertylist_has (self, name), CPL_ERROR_DATA_NOT_FOUND, 0);
1222 
1223  cpl_type type = cpl_propertylist_get_type (self, name);
1224  switch (type) {
1225  case CPL_TYPE_CHAR:
1226  case CPL_TYPE_UCHAR:
1227  case CPL_TYPE_BOOL:
1228  case CPL_TYPE_SHORT:
1229  case CPL_TYPE_USHORT:
1230  case CPL_TYPE_INT:
1231  case CPL_TYPE_UINT:
1232  case CPL_TYPE_LONG:
1233  case CPL_TYPE_LONG_LONG:
1234  case CPL_TYPE_ULONG:
1235  case CPL_TYPE_SIZE:
1236  return cpl_propertylist_get_long(self, name);
1237  case CPL_TYPE_FLOAT:
1238  case CPL_TYPE_DOUBLE:
1239  return cpl_propertylist_get_double(self, name);
1240  case CPL_TYPE_STRING:
1241  cpl_msg_debug (cpl_func,"FITS card %s is string '%s' to double %f",
1242  name,cpl_propertylist_get_string(self, name),atof(cpl_propertylist_get_string(self, name)));
1243  return atof(cpl_propertylist_get_string(self, name));
1244  default:
1245  cpl_error_set(cpl_func, CPL_ERROR_TYPE_MISMATCH);
1246  return 0.;
1247  }
1248  return 0.;
1249 }
1250 
1251 cpl_error_code gravi_pfits_ensure_double (cpl_propertylist * self, const char * name)
1252 {
1253  cpl_ensure_code (self, CPL_ERROR_NULL_INPUT);
1254  cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
1255 
1256  /* Get value and comment */
1257  double value = gravi_pfits_get_double (self, name);
1258  char * comment = cpl_sprintf ("%s", cpl_propertylist_get_comment (self, name));
1259 
1260  /* Delete card and set back to double */
1261  cpl_propertylist_erase (self, name);
1262  cpl_propertylist_append_double (self, name, value );
1263  cpl_propertylist_set_comment (self, name, comment);
1264  cpl_free (comment);
1265 
1266  return cpl_error_get_code();
1267 }
1268 
1269 /*
1270  * Set the header keyword NAME+EXT to value
1271  * protected from nan
1272  */
1273 cpl_error_code gravi_pfits_update_double (cpl_propertylist * plist,
1274  const char * full_name, double value)
1275 {
1276  cpl_error_code code;
1277  cpl_ensure_code (plist, CPL_ERROR_NULL_INPUT);
1278  cpl_ensure_code (full_name, CPL_ERROR_NULL_INPUT);
1279 
1280  /* Set value with check for nan */
1281  if ( isnan(value) )
1282  cpl_propertylist_update_double (plist, full_name, GRAVI_NAN_DOUBLE);
1283  else
1284  cpl_propertylist_update_double (plist, full_name, value);
1285 
1286  /* Check */
1287  if ( (code=cpl_error_get_code()) ) {
1288  cpl_msg_warning (cpl_func, "Cannot set keyword: %s", full_name);
1289  return cpl_error_set_message(cpl_func, code, "Cannot set keyword: %s", full_name);
1290  }
1291 
1292  return CPL_ERROR_NONE;
1293 }
1294 
1295 cpl_error_code gravi_pfits_update_int (cpl_propertylist * plist,
1296  const char * full_name, int value)
1297 {
1298  cpl_error_code code;
1299  cpl_ensure_code (plist, CPL_ERROR_NULL_INPUT);
1300  cpl_ensure_code (full_name, CPL_ERROR_NULL_INPUT);
1301 
1302  /* Set value with check for nan */
1303  if ( isnan((double)value) )
1304  cpl_propertylist_update_int (plist, full_name, GRAVI_NAN_INT);
1305  else
1306  cpl_propertylist_update_int (plist, full_name, value);
1307 
1308  /* Check */
1309  if ( (code=cpl_error_get_code()) ) {
1310  cpl_msg_warning (cpl_func, "Cannot set keyword: %s", full_name);
1311  return cpl_error_set_message(cpl_func, code, "Cannot set keyword: %s", full_name);
1312  }
1313 
1314  return CPL_ERROR_NONE;
1315 }
1316 
1317 const char * gravi_pfits_get_string_default (const cpl_propertylist * plist,
1318  const char *name,
1319  const char *def)
1320 {
1321  cpl_ensure (plist, CPL_ERROR_NULL_INPUT, def);
1322  cpl_ensure (name, CPL_ERROR_NULL_INPUT, def);
1323 
1324  const char *output;
1325 
1326  if (cpl_propertylist_has(plist, name)) {
1327  /* Try to read this keyword */
1328  output = cpl_propertylist_get_string(plist, name);
1329  } else {
1330  /* Get the default and add warning only if not CALIB */
1331  output = def;
1332 
1333  if (!gravi_pfits_is_calib (plist))
1334  cpl_msg_warning (cpl_func, "Can't find keyword %s (use '%s')", name, def);
1335  else
1336  cpl_msg_info (cpl_func, "Can't find keyword %s (use '%s')", name, def);
1337  }
1338 
1339  return output;
1340 }
1341 
1342 double gravi_pfits_get_double_default (const cpl_propertylist * plist,
1343  const char *name,
1344  double def)
1345 {
1346  cpl_ensure (plist, CPL_ERROR_NULL_INPUT, def);
1347  cpl_ensure (name, CPL_ERROR_NULL_INPUT, def);
1348 
1349  double output;
1350 
1351  if (cpl_propertylist_has(plist, name)) {
1352  /* Try to read this keyword as a double */
1353  output = gravi_pfits_get_double(plist, name);
1354  } else {
1355  /* Get the default and add warning only if not CALIB */
1356  output = def;
1357 
1358  if (!gravi_pfits_is_calib (plist))
1359  cpl_msg_warning (cpl_func, "Can't find keyword %s (use '%f')", name, def);
1360  else
1361  cpl_msg_info (cpl_func, "Can't find keyword %s (use '%f')", name, def);
1362  }
1363 
1364  return output;
1365 }
1366 
1367 double gravi_pfits_get_double_silentdefault (const cpl_propertylist * plist,
1368  const char *name,
1369  double def)
1370 {
1371  cpl_ensure (plist, CPL_ERROR_NULL_INPUT, def);
1372  cpl_ensure (name, CPL_ERROR_NULL_INPUT, def);
1373  double output;
1374 
1375  if (cpl_propertylist_has(plist, name))
1376  output = gravi_pfits_get_double (plist, name);
1377  else
1378  output = def;
1379 
1380  return output;
1381 }
1382 
1383 /*---------------------------------------------------------------------------*/
1396 /*---------------------------------------------------------------------------*/
1397 
1398 cpl_error_code gravi_pfits_add_check (cpl_propertylist * header, char *msg)
1399 {
1400  gravi_msg_function_start(0);
1401  cpl_ensure_code (header, CPL_ERROR_NULL_INPUT);
1402  cpl_ensure_code (msg, CPL_ERROR_NULL_INPUT);
1403 
1404  /* Increment counter */
1405  int i = 1;
1406  if (cpl_propertylist_has (header, "ESO QC CHECK FLAGS"))
1407  i = cpl_propertylist_get_int (header, "ESO QC CHECK FLAGS") + 1;
1408 
1409  cpl_propertylist_update_int (header, "ESO QC CHECK FLAGS", i);
1410  CPLCHECK_MSG ("Cannot add check flags...");
1411 
1412  /* Set message */
1413  char qc_name[80];
1414  sprintf (qc_name, "ESO QC CHECK MSG%i", i);
1415 
1416  cpl_msg_warning (cpl_func, "%s = '%s'", qc_name, msg);
1417  cpl_propertylist_append_string (header, qc_name, msg);
1418 
1419  CPLCHECK_MSG ("Cannot add check msg...");
1420 
1421  gravi_msg_function_exit(0);
1422  return CPL_ERROR_NONE;
1423 }
1424 
1425 /*---------------------------------------------------------------------------*/
1436 /*---------------------------------------------------------------------------*/
1437 
1438 cpl_error_code gravi_pfits_add_pipe_build (cpl_propertylist * header)
1439 {
1440  gravi_msg_function_start(0);
1441  cpl_ensure_code (header, CPL_ERROR_NULL_INPUT);
1442 
1443  char name[100];
1444  char value[100];
1445 
1446  /* Increment counter until empty slot */
1447  int i = 0;
1448  do {
1449  i++;
1450  sprintf (name, "ESO PRO REC%i PIPE LAST_BUILD", i);
1451  } while (cpl_propertylist_has (header, name));
1452 
1453  /* Define the last build string */
1454  sprintf (value, "%s %s", __DATE__,__TIME__);
1455  cpl_msg_info (cpl_func, "%s = '%s'", name, value);
1456 
1457  /* Write into header */
1458  cpl_propertylist_update_string (header, name, value);
1459  cpl_propertylist_set_comment (header, name, "Last 'make clean all install'");
1460  CPLCHECK_MSG ("Cannot add PIPE LAST_BUILD...");
1461 
1462  gravi_msg_function_exit(0);
1463  return CPL_ERROR_NONE;
1464 }
1465 
1466 
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_plist_get_qc(cpl_propertylist *header)
Extract QC parameters.
Definition: gravi_pfits.c:856
int gravi_pfits_get_startx(const cpl_propertylist *plist)
find out the name of the propertylist
Definition: gravi_pfits.c:66
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
double gravi_pfits_get_sc_gain(const cpl_propertylist *plist)
SC system gain in [ADU/e].
Definition: gravi_pfits.c:766
cpl_propertylist * gravi_plist_get_oifits_keywords(cpl_propertylist *header)
Create OIFITS keywords to satisfy standar.
Definition: gravi_pfits.c:801
double gravi_pfits_get_double(const cpl_propertylist *self, const char *name)
Get the double value of the given property list entry.
Definition: gravi_pfits.c:1217
double gravi_pfits_get_ft_gain(const cpl_propertylist *plist)
FT system gain in [ADU/e].
Definition: gravi_pfits.c:727
double gravi_pfits_get_time_acqcam(const cpl_propertylist *header, cpl_size row)
Time of the middle of the ACQCAM exposure row in [us], counted from PRC.ACQ.START.
Definition: gravi_pfits.c:624
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