X-shooter Pipeline Reference Manual 3.8.15
xsh_paf_save.c
Go to the documentation of this file.
1/* $Id: xsh_paf_save.c,v 1.30 2012-12-18 16:09:54 amodigli Exp $
2 *
3 * This file is part of the IRPLIB Package
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., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: amodigli $
23 * $Date: 2012-12-18 16:09:54 $
24 * $Revision: 1.30 $
25 * $Name: not supported by cvs2svn $
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31
32/*-----------------------------------------------------------------------------
33 Includes
34 -----------------------------------------------------------------------------*/
35
36#include <cpl.h>
37
38#include <string.h>
39#include <strings.h>
40#include <sys/types.h>
41#include <regex.h>
42#include <assert.h>
43
44#include "xsh_data_instrument.h"
45#include "xsh_qc_handling.h"
46#include "xsh_msg.h"
47#include "xsh_paf_save.h"
48#include "xsh_error.h"
49
50
51/*-----------------------------------------------------------------------------
52 Defines and Static variables
53 -----------------------------------------------------------------------------*/
54
55/* Use at least this many places when printing the PAF key */
56#define PAF_KEY_LEN 21
57/* Right justify the PAF key and separate with an extra space */
58#define PAF_KEY_FORMAT "%-21s "
59
60/*----------------------------------------------------------------------------*/
66/*----------------------------------------------------------------------------*/
67
70/*-----------------------------------------------------------------------------
71 Function codes
72 -----------------------------------------------------------------------------*/
73static FILE * irplib_paf_init(const xsh_instrument * instrume,
74 const char * recipe,
75 const char * filename,
76 const cpl_propertylist* primary_header) ;
77static cpl_error_code irplib_paf_dump( qc_description *pqc,
78 const char * kwnamw, const cpl_propertylist * paflist,
79 FILE *paf ) ;
80static cpl_error_code irplib_paf_dump_int( char *kw, int value,
81 const char *comment, FILE *paf ) ;
82static cpl_error_code irplib_paf_dump_double( char *kw, double value,
83 const char *comment, FILE *paf ) ;
84static cpl_error_code irplib_paf_dump_string( char *kw, const char * value,
85 const char *comment, FILE *paf ) ;
86/*----------------------------------------------------------------------------*/
87
103/*----------------------------------------------------------------------------*/
104cpl_error_code xsh_paf_save( const xsh_instrument * instrument,
105 const char *recipe,
106 const cpl_propertylist * paflist,
107 const char * filename,
108 const char * pro_catg )
109{
110 qc_description * pqc ;
111 FILE *paf = NULL ;
112 const char * arm ;
113
115 XSH_ASSURE_NOT_NULL( recipe ) ;
116 XSH_ASSURE_NOT_NULL( paflist ) ;
117 XSH_ASSURE_NOT_NULL( filename ) ;
118
120 xsh_msg_dbg_low( "=====>>>>> paf_save (%s, %s, %s)", recipe,
121 arm, pro_catg ) ;
122
123 paf = irplib_paf_init( instrument, recipe, filename, paflist ) ;
124
125 pqc = NULL ;
126 /*
127 Find all QC relevant for this product and check if they are
128 present in the FITS header. Print a message for each missing QC
129 */
130 while ( (pqc = xsh_get_qc_desc_by_recipe( recipe, pqc )) != NULL ) {
131 xsh_msg_dbg_low( " Found KW: %s\n", pqc->kw_name ) ;
132 /*
133 Check that the QC is relevant for this pro_catg
134 */
135#if 1
136 if ( xsh_is_qc_for_pro_catg( pro_catg, pqc ) == 0 ) {
137 // No, ignore it
138 xsh_msg_dbg_low( "QC '%s' not for PRO.CATG '%s'", pqc->kw_name,
139 pro_catg ) ;
140 continue ;
141 }
142#endif
143 /*
144 Check that the QC is relevant for this arm
145 */
146 if ( xsh_is_qc_for_arm( arm, pqc ) == 0 ) {
147 /* No, ignore it */
148 xsh_msg_dbg_low( "QC '%s' not for arm '%s'", pqc->kw_name, arm ) ;
149 continue ;
150 }
151 /* Check if kw is in the propertylist
152 There is a special case if the keyword contains the letter 'i':
153 in this case one should search for all the KW in the propertylist
154 by replacing i by 0, 1, 2, ... untill not found
155 */
156 if ( strchr( pqc->kw_name, 'i' ) != NULL ) {
157 /* Special multiple kw with 0, 1, 2, .. */
158 char kformat[256];
159 const char *pk;
160 char* pm;
161 int i ;
162 xsh_msg_dbg_low( " ++++ Multiple KW '%s'", pqc->kw_name ) ;
163
164 for( i = 0, pk = pqc->kw_name, pm = kformat ; *pk != '\0' ; i++, pk++ )
165 if ( *pk == 'i' ) {
166 strcpy( pm, "%d" ) ;
167 pm += 2 ;
168 }
169 else *pm++ = *pk ;
170 *pm = '\0' ;
171 for( i = 0 ; i<10 ; i++ ) {
172 char curname[256] ;
173 sprintf( curname, kformat, i ) ;
174 xsh_msg_dbg_low( " %d --> '%s'", i, curname ) ;
175 if ( cpl_propertylist_has( paflist, curname ) ) {
176 xsh_msg_dbg_low( "QC Parameter \"%s\" is in propertylist",
177 curname ) ;
178 /* Dump data to PAF */
179 irplib_paf_dump( pqc, curname, paflist, paf ) ;
180 }
181 else break ;
182 }
183 if ( i == 0 ) xsh_msg( "QC Parameter \"%s\" NOT in propertylist",
184 pqc->kw_name ) ;
185 }
186 else if ( cpl_propertylist_has( paflist, pqc->kw_name ) ) {
187 xsh_msg_dbg_low( "QC Parameter \"%s\" is in propertylist",
188 pqc->kw_name ) ;
189 /* Dump data to PAF */
190 irplib_paf_dump( pqc, pqc->kw_name, paflist, paf ) ;
191 }
192 else xsh_msg_debug( "QC Parameter \"%s\" NOT in propertylist",
193 pqc->kw_name ) ;
194
195 }
196
197 /* Close PAF */
198 fclose( paf ) ;
199
200 cleanup:
201 return cpl_error_get_code() ;
202
203}
204
225/*----------------------------------------------------------------------------*/
227 const char * recipe,
228 const char * filename,
229 const cpl_propertylist* primary_header)
230{
231 FILE * paf = NULL;
232 char * paf_id = NULL;
233 const char paf_desc[] = "QC file";
234 int nlen;
235 cpl_error_code error;
236 const char* key_value = NULL;
237
238
239 cpl_ensure(instrument != NULL, CPL_ERROR_NULL_INPUT, NULL);
240 cpl_ensure(recipe != NULL, CPL_ERROR_NULL_INPUT, NULL);
241 cpl_ensure(filename != NULL, CPL_ERROR_NULL_INPUT, NULL);
242
243#if 0
244 paf_id = cpl_malloc(sizeof(char) *
245 (strlen(instrument) + strlen("/") + strlen(recipe) + 1));
246 assert( paf_id != NULL);
247 strcpy(paf_id, instrument);
248 strcat(paf_id, "/");
249 strcat(paf_id, recipe);
250#else
251 paf_id = xsh_stringcat_any( recipe, (void*)NULL ) ;
252#endif
253 paf = fopen(filename, "w");
254
255 if (paf == NULL) {
256 cpl_free(paf_id);
257 cpl_ensure(0, CPL_ERROR_FILE_IO, NULL);
258 return NULL;
259 }
260
261 /* Some ugly, traditional error handling that obscures
262 the actual functionality (i.e. to fprintf() some strings) */
263
264 error = CPL_ERROR_NONE;
265
266 if (!error) {
267 nlen = fprintf(paf, "PAF.HDR.START ;# start of header\n");
268 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
269 }
270
271 if (!error) {
272 nlen = fprintf(paf, "PAF.TYPE \"pipeline product\" ;\n");
273 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
274 }
275
276 if (!error) {
277 nlen = fprintf(paf, "PAF.ID \"%s\"\n", paf_id);
278 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
279 }
280
281 if (!error) {
282 nlen = fprintf(paf, "PAF.NAME \"%s\"\n", filename);
283 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
284 }
285
286 if (!error) {
287 nlen = fprintf(paf, "PAF.DESC \"%s\"\n", paf_desc);
288 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
289 }
290
291 if (!error) {
292 nlen = fprintf(paf, "PAF.CHCK.CHECKSUM \"\"\n");
293 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
294 }
295
296 if (!error) {
297 nlen = fprintf(paf, "PAF.HDR.END ;# end of header\n");
298 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
299 }
300
301
302 if(cpl_propertylist_has(primary_header,"ARCFILE")) {
303 key_value=cpl_propertylist_get_string(primary_header,"ARCFILE");
304 } else {
305 key_value="ARCFILE_NOT_FOUND";
306 }
307 if (!error) {
308 nlen = fprintf(paf, "ARCFILE \"%s\";# archive file name\n",key_value);
309 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
310 }
311
312 if(cpl_propertylist_has(primary_header,"PIPEFILE")) {
313 key_value=cpl_propertylist_get_string(primary_header,"PIPEFILE");
314 } else {
315 key_value="PIPEFILE_NOT_FOUND";
316 }
317 if (!error) {
318 nlen = fprintf(paf, "PIPEFILE \"%s\";# File name of data product\n",key_value);
319 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
320 }
321
322
323 if(cpl_propertylist_has(primary_header,"PRO.REC1.PIPE.ID")) {
324 key_value=cpl_propertylist_get_string(primary_header,"PRO.REC1.PIPE.ID");
325 } else {
326 key_value="PRO_REC1_PIPE_ID_NOT_FOUND";
327 }
328 if (!error) {
329 nlen = fprintf(paf, "PRO.REC1.PIPE.ID \"%s\";# Pipeline (unique) identifier\n",key_value);
330 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
331 }
332
333
334
335
336 if (!error) {
337 nlen = fprintf(paf, "PRO.TYPE \"REDUCED\";# Product type\n");
338 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
339 }
340
341
342
343 if (!error) {
344 nlen = fprintf(paf, "\n");
345 if (nlen != 1) error = CPL_ERROR_FILE_IO;
346 }
347
348 cpl_free(paf_id);
349
350
351 fflush( paf ) ;
352
353 if(paf != NULL) {
354 return paf;
355 }
356
357 if (error) {
358 cpl_msg_error(cpl_func, "Could not write PAF: %s", filename);
359 fclose(paf);
360 cpl_ensure(0, error, NULL);
361 }
362
363 return NULL;
364}
365
366static void no_space( char * str )
367{
368 for( ; *str != '\0' ; str++ )
369 if ( *str == ' ' ) *str = '.' ;
370}
371
401static cpl_error_code irplib_paf_dump( qc_description *pqc, const char *kwname,
402 const cpl_propertylist * paflist,
403 FILE *paf )
404{
405 cpl_error_code err=CPL_ERROR_NONE;
406 char * keydot = NULL, *pk ;
407
408 keydot = cpl_strdup( kwname ) ;
409 pk = keydot ;
410 /* Replace spaces by dots */
411 no_space( keydot ) ;
412 if ( strncmp( keydot, "ESO.", 4 ) == 0 ) pk += 4 ;
413 xsh_msg_dbg_low( "irplib_dump: '%s'", pk ) ;
414
415 switch( cpl_propertylist_get_type( paflist, kwname ) ) {
416 case CPL_TYPE_CHAR:
417 err = irplib_paf_dump_int(pk,
418 cpl_propertylist_get_char( paflist, kwname),
419 pqc->kw_help, paf);
420 break ;
421 case CPL_TYPE_INT:
422 err = irplib_paf_dump_int(pk,
423 cpl_propertylist_get_int( paflist, kwname),
424 pqc->kw_help, paf);
425 break;
426 case CPL_TYPE_LONG:
427 if (sizeof(long) == sizeof(int)) /* FIXME: Change to #if */
428 err = irplib_paf_dump_int(pk,
429 cpl_propertylist_get_long( paflist,
430 kwname),
431 pqc->kw_help, paf);
432 break;
433 case CPL_TYPE_FLOAT:
434 err = irplib_paf_dump_double(pk,
435 cpl_propertylist_get_float( paflist,
436 kwname),
437 pqc->kw_help, paf);
438 break;
439 case CPL_TYPE_DOUBLE:
440 err = irplib_paf_dump_double(pk,
441 cpl_propertylist_get_double( paflist,
442 kwname),
443 pqc->kw_help, paf);
444 break;
445 case CPL_TYPE_STRING:
446 err = irplib_paf_dump_string(pk,
447 cpl_propertylist_get_string( paflist,
448 kwname),
449 pqc->kw_help, paf);
450 break;
451 default:
452 err = CPL_ERROR_UNSUPPORTED_MODE;
453 }
454 cpl_free(keydot);
455 return err ;
456}
457
468static cpl_error_code irplib_paf_dump_int( char *key, int value,
469 const char *comment, FILE *paf )
470{
471 cpl_ensure_code(paf, CPL_ERROR_NULL_INPUT);
472 cpl_ensure_code(key, CPL_ERROR_NULL_INPUT);
473
474 if (comment == NULL)
475 cpl_ensure_code(fprintf(paf, PAF_KEY_FORMAT "%d\n",
476 key, value) > PAF_KEY_LEN,
477 CPL_ERROR_FILE_IO);
478 else
479 cpl_ensure_code(fprintf(paf, PAF_KEY_FORMAT "%d ; # %s\n",
480 key, value, comment) > PAF_KEY_LEN,
481 CPL_ERROR_FILE_IO);
482
483 return CPL_ERROR_NONE;
484}
485
496static cpl_error_code irplib_paf_dump_double( char *key, double value,
497 const char *comment, FILE *paf )
498{
499 cpl_ensure_code(paf, CPL_ERROR_NULL_INPUT);
500 cpl_ensure_code(key, CPL_ERROR_NULL_INPUT);
501
502 if (comment == NULL)
503 cpl_ensure_code(fprintf(paf, PAF_KEY_FORMAT "%.10g\n",
504 key, value) > PAF_KEY_LEN,
505 CPL_ERROR_FILE_IO);
506 else
507 cpl_ensure_code(fprintf(paf, PAF_KEY_FORMAT "%.10g ; # %s\n",
508 key, value, comment) > PAF_KEY_LEN,
509 CPL_ERROR_FILE_IO);
510
511 return CPL_ERROR_NONE;
512}
513
526static cpl_error_code irplib_paf_dump_string( char *key, const char * value,
527 const char *comment, FILE *paf )
528{
529 cpl_ensure_code(paf, CPL_ERROR_NULL_INPUT);
530 cpl_ensure_code(key, CPL_ERROR_NULL_INPUT);
531 cpl_ensure_code(value, CPL_ERROR_NULL_INPUT);
532
533 if (comment == NULL)
534 cpl_ensure_code(fprintf(paf, PAF_KEY_FORMAT "\"%s\"\n",
535 key, value) > PAF_KEY_LEN,
536 CPL_ERROR_FILE_IO);
537 else
538 cpl_ensure_code(fprintf(paf, PAF_KEY_FORMAT "\"%s\" ; # %s\n",
539 key, value, comment) > PAF_KEY_LEN,
540 CPL_ERROR_FILE_IO);
541
542 return CPL_ERROR_NONE;
543}
544
545
static xsh_instrument * instrument
#define XSH_ASSURE_NOT_NULL(pointer)
Definition: xsh_error.h:99
const char * xsh_instrument_arm_tostring(xsh_instrument *i)
Get the string associated with an arm.
#define xsh_msg_debug(...)
Print a debug message.
Definition: xsh_msg.h:99
#define xsh_msg(...)
Print a message on info level.
Definition: xsh_msg.h:121
#define xsh_msg_dbg_low(...)
Definition: xsh_msg.h:48
static FILE * irplib_paf_init(const xsh_instrument *instrume, const char *recipe, const char *filename, const cpl_propertylist *primary_header)
Open a new PAF file, output a default header.
Definition: xsh_paf_save.c:226
static cpl_error_code irplib_paf_dump_double(char *kw, double value, const char *comment, FILE *paf)
Print a double-property as PAF.
Definition: xsh_paf_save.c:496
static cpl_error_code irplib_paf_dump(qc_description *pqc, const char *kwnamw, const cpl_propertylist *paflist, FILE *paf)
Print a propertylist as PAF.
Definition: xsh_paf_save.c:401
cpl_error_code xsh_paf_save(const xsh_instrument *instrument, const char *recipe, const cpl_propertylist *paflist, const char *filename, const char *pro_catg)
Create a new PAF file.
Definition: xsh_paf_save.c:104
static cpl_error_code irplib_paf_dump_string(char *kw, const char *value, const char *comment, FILE *paf)
Print a string-property as PAF.
Definition: xsh_paf_save.c:526
static void no_space(char *str)
Definition: xsh_paf_save.c:366
static cpl_error_code irplib_paf_dump_int(char *kw, int value, const char *comment, FILE *paf)
Print an int-property as PAF.
Definition: xsh_paf_save.c:468
int xsh_is_qc_for_arm(const char *arm, qc_description *pqc)
qc_description * xsh_get_qc_desc_by_recipe(const char *recipe, qc_description *prev)
int xsh_is_qc_for_pro_catg(const char *pro_catg, qc_description *pqc)
char * xsh_stringcat_any(const char *s,...)
Concatenate an arbitrary number of strings.
Definition: xsh_utils.c:1925
const char * kw_help
const char * kw_name
#define PAF_KEY_FORMAT
Definition: xsh_paf_save.c:58
#define PAF_KEY_LEN
Definition: xsh_paf_save.c:56