00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include <string.h>
00037 #include <strings.h>
00038 #include <sys/types.h>
00039 #include <regex.h>
00040 #include <assert.h>
00041
00042 #ifdef HAVE_QFITS
00043 #include <qfits.h>
00044 #endif
00045
00046 #include <cpl.h>
00047
00048
00049 #include "irplib_utils.h"
00050 #include "irplib_dfs.h"
00051
00052
00053
00054
00055
00056
00057 #define PAF_KEY_LEN 21
00058
00059 #define PAF_KEY_FORMAT "%-21s "
00060
00061 static const char irplib_pro_did[] = "PRO-1.15";
00062
00063
00064
00065
00066
00067 static FILE * irplib_paf_init(const char *, const char *, const char *)
00068 #if defined __GNUC__ && __GNUC__ >= 4
00069 __attribute__((nonnull))
00070 #endif
00071 ;
00072
00073 static cpl_error_code irplib_paf_dump(const cpl_propertylist *, FILE *)
00074 #if defined __GNUC__ && __GNUC__ >= 4
00075 __attribute__((nonnull))
00076 #endif
00077 ;
00078
00079 static cpl_error_code irplib_paf_dump_string(const char *, const char *,
00080 const char *, FILE *);
00081 static cpl_error_code irplib_paf_dump_double(const char *, double, const char *,
00082 FILE *);
00083 static cpl_error_code irplib_paf_dump_int(const char *, int, const char *,
00084 FILE *);
00085
00086 static cpl_error_code irplib_product_save(cpl_frameset *,
00087 const cpl_parameterlist *,
00088 const cpl_frameset *,
00089 const cpl_image *,
00090 cpl_type_bpp,
00091 const cpl_table *,
00092 const cpl_propertylist *,
00093 const char *,
00094 const char *,
00095 const cpl_propertylist *,
00096 const char *,
00097 const char *,
00098 const char *);
00099
00100
00101
00106
00107
00110
00111
00112
00113
00114 #ifdef HAVE_QFITS
00115
00122
00123 cpl_error_code irplib_dfs_update_frameset(cpl_frameset * self)
00124 {
00125
00126 const char * fitskey = "DATAMD5";
00127 const cpl_frame * frame;
00128 int nupdate = 0;
00129
00130
00131 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00132
00133 for (frame = cpl_frameset_get_first(self);
00134 frame != NULL;
00135 frame = cpl_frameset_get_next(self)) {
00136
00137 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_PRODUCT) {
00138
00139 const cpl_frame_type type = cpl_frame_get_type(frame);
00140
00141 if (type == CPL_FRAME_TYPE_TABLE || type == CPL_FRAME_TYPE_IMAGE) {
00142
00143 const char * filename = cpl_frame_get_filename(frame);
00144 const char * md5sum = qfits_datamd5(filename);
00145
00146 char * newcard = irplib_sprintf("%s = '%s' / MD5 checksum",
00147 fitskey, md5sum);
00148
00149 const int error = qfits_replace_card(filename, fitskey,
00150 newcard);
00151
00152 cpl_free(newcard);
00153
00154 if (error) {
00155 cpl_msg_error(cpl_func, "Could not update FITS card with "
00156 "key '%s' to value '%s' in file %s: %d",
00157 fitskey, md5sum, filename, error);
00158 cpl_ensure_code(0, CPL_ERROR_FILE_IO);
00159 }
00160 nupdate++;
00161 }
00162 }
00163 }
00164
00165 cpl_msg_info(cpl_func, "Updated the FITS card with key '%s' in the primary "
00166 "FITS header of %d product(s)", fitskey, nupdate);
00167
00168 return CPL_ERROR_NONE;
00169
00170 }
00171 #endif
00172
00173
00192
00193 cpl_error_code irplib_image_save(cpl_frameset * allframes,
00194 const cpl_parameterlist * parlist,
00195 const cpl_frameset * usedframes,
00196 const cpl_image * image,
00197 cpl_type_bpp bpp,
00198 const char * recipe,
00199 const char * procat,
00200 const cpl_propertylist * applist,
00201 const char * remregexp,
00202 const char * pipe_id,
00203 const char * filename)
00204 {
00205 const cpl_error_code error =
00206 irplib_product_save(allframes, parlist, usedframes, image, bpp, NULL,
00207 NULL, recipe, procat, applist, remregexp, pipe_id,
00208 filename);
00209
00210 cpl_ensure_code(!error, error);
00211
00212 return CPL_ERROR_NONE;
00213
00214 }
00215
00216
00217
00235
00236 cpl_error_code irplib_table_save(cpl_frameset * allframes,
00237 const cpl_parameterlist * parlist,
00238 const cpl_frameset * usedframes,
00239 const cpl_table * table,
00240 const cpl_propertylist * tablelist,
00241 const char * recipe,
00242 const char * procat,
00243 const cpl_propertylist * applist,
00244 const char * remregexp,
00245 const char * pipe_id,
00246 const char * filename)
00247 {
00248
00249 cpl_error_code error;
00250
00251 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
00252
00253 error = irplib_product_save(allframes, parlist, usedframes, NULL,
00254 CPL_BPP_DEFAULT, table, tablelist, recipe,
00255 procat, applist, remregexp, pipe_id, filename);
00256
00257 cpl_ensure_code(!error, error);
00258
00259 return CPL_ERROR_NONE;
00260 }
00261
00262
00263
00293
00294 cpl_error_code irplib_paf_save(const char * instrume, const char *recipe,
00295 const cpl_propertylist * paflist,
00296 const char * filename)
00297 {
00298
00299 FILE * paf;
00300 cpl_error_code status;
00301
00302
00303 cpl_ensure_code(instrume != NULL, CPL_ERROR_NULL_INPUT);
00304 cpl_ensure_code(recipe != NULL, CPL_ERROR_NULL_INPUT);
00305 cpl_ensure_code(paflist != NULL, CPL_ERROR_NULL_INPUT);
00306 cpl_ensure_code(filename != NULL, CPL_ERROR_NULL_INPUT);
00307
00308
00309 paf = irplib_paf_init(instrume, recipe, filename);
00310
00311 cpl_ensure_code(paf != NULL, cpl_error_get_code());
00312
00313 status = irplib_paf_dump(paflist, paf);
00314 if (status == CPL_ERROR_NONE && fprintf(paf, "\n") != 1)
00315 status = CPL_ERROR_FILE_IO;
00316
00317 if (status == CPL_ERROR_NONE) {
00318 cpl_ensure_code(fclose(paf) == 0, CPL_ERROR_FILE_IO);
00319 } else {
00320 (void)fclose(paf);
00321 }
00322
00323 return status;
00324
00325 }
00326
00329
00349
00350 static FILE * irplib_paf_init(const char * instrume,
00351 const char * recipe,
00352 const char * filename)
00353 {
00354 FILE * paf = NULL;
00355 char * paf_id = NULL;
00356 const char paf_desc[] = "QC file";
00357 int nlen;
00358 cpl_error_code error;
00359
00360
00361 cpl_ensure(instrume != NULL, CPL_ERROR_NULL_INPUT, NULL);
00362 cpl_ensure(recipe != NULL, CPL_ERROR_NULL_INPUT, NULL);
00363 cpl_ensure(filename != NULL, CPL_ERROR_NULL_INPUT, NULL);
00364
00365
00366 cpl_msg_info(cpl_func, "Writing PAF: %s" , filename);
00367
00368 paf_id = irplib_sprintf("%s/%s", instrume, recipe);
00369 assert( paf_id != NULL);
00370
00371 paf = fopen(filename, "w");
00372
00373 if (paf == NULL) {
00374 cpl_free(paf_id);
00375 cpl_ensure(0, CPL_ERROR_FILE_IO, NULL);
00376 }
00377
00378
00379
00380
00381 error = CPL_ERROR_NONE;
00382
00383 if (!error) {
00384 nlen = fprintf(paf, "PAF.HDR.START ;# start of header\n");
00385 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
00386 }
00387
00388 if (!error) {
00389 nlen = fprintf(paf, "PAF.TYPE \"pipeline product\" ;\n");
00390 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
00391 }
00392
00393 if (!error) {
00394 nlen = fprintf(paf, "PAF.ID \"%s\"\n", paf_id);
00395 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
00396 }
00397
00398 if (!error) {
00399 nlen = fprintf(paf, "PAF.NAME \"%s\"\n", filename);
00400 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
00401 }
00402
00403 if (!error) {
00404 nlen = fprintf(paf, "PAF.DESC \"%s\"\n", paf_desc);
00405 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
00406 }
00407
00408 if (!error) {
00409 nlen = fprintf(paf, "PAF.CHCK.CHECKSUM \"\"\n");
00410 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
00411 }
00412
00413 if (!error) {
00414 nlen = fprintf(paf, "PAF.HDR.END ;# end of header\n");
00415 if (nlen <= PAF_KEY_LEN) error = CPL_ERROR_FILE_IO;
00416 }
00417
00418 if (!error) {
00419 nlen = fprintf(paf, "\n");
00420 if (nlen != 1) error = CPL_ERROR_FILE_IO;
00421 }
00422
00423 cpl_free(paf_id);
00424
00425 if (error) {
00426 (void)fclose(paf);
00427 cpl_msg_error(cpl_func, "Could not write PAF: %s", filename);
00428 cpl_ensure(0, error, NULL);
00429 }
00430
00431 return paf;
00432
00433 }
00434
00435
00464
00465 static cpl_error_code irplib_paf_dump(const cpl_propertylist * self, FILE * paf)
00466 {
00467 int i;
00468
00469
00470 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00471 cpl_ensure_code(paf, CPL_ERROR_NULL_INPUT);
00472
00473 for (i=0; i < cpl_propertylist_get_size(self); i++) {
00474 const cpl_property * prop = cpl_propertylist_get((cpl_propertylist *)
00475 self, i);
00476 const char * name = cpl_property_get_name(prop);
00477 const char * comment = cpl_property_get_comment(prop);
00478 char * qckey;
00479
00480 cpl_error_code err = CPL_ERROR_UNSUPPORTED_MODE;
00481
00482
00483 if (strstr(name, "ESO ") == name) {
00484
00485 qckey = cpl_malloc(strlen(name) - 3);
00486 memcpy(qckey, name+4, strlen(name) - 3);
00487 } else if (strstr(name, " "))
00488 qckey = cpl_strdup(name);
00489 else
00490 qckey = (char *)name;
00491
00492 if (qckey != name) {
00493
00494 char * p;
00495 for (p = qckey; *p != '\0'; p++)
00496 if (*p == ' ') *p = '.';
00497 }
00498
00499
00500
00501 switch (cpl_property_get_type(prop)) {
00502 case CPL_TYPE_CHAR:
00503 err = irplib_paf_dump_int(qckey, cpl_property_get_char(prop),
00504 comment, paf);
00505 case CPL_TYPE_INT:
00506 err = irplib_paf_dump_int(qckey, cpl_property_get_int(prop),
00507 comment, paf);
00508 break;
00509 case CPL_TYPE_LONG:
00510 if (sizeof(long) == sizeof(int))
00511 err = irplib_paf_dump_int(qckey, cpl_property_get_long(prop),
00512 comment, paf);
00513 break;
00514 case CPL_TYPE_FLOAT:
00515 err = irplib_paf_dump_double(qckey, cpl_property_get_float(prop),
00516 comment, paf);
00517 break;
00518 case CPL_TYPE_DOUBLE:
00519 err = irplib_paf_dump_double(qckey, cpl_property_get_double(prop),
00520 comment, paf);
00521 break;
00522 case CPL_TYPE_STRING:
00523 err = irplib_paf_dump_string(qckey, cpl_property_get_string(prop),
00524 comment, paf);
00525 break;
00526 default:
00527 err = CPL_ERROR_UNSUPPORTED_MODE;
00528 }
00529
00530 if (qckey != name) cpl_free(qckey);
00531
00532 cpl_ensure_code(!err, err);
00533
00534 }
00535
00536 return CPL_ERROR_NONE;
00537 }
00538
00539
00552
00553 static cpl_error_code irplib_paf_dump_string(const char * key,
00554 const char * value,
00555 const char * comment, FILE * paf)
00556 {
00557 cpl_ensure_code(paf, CPL_ERROR_NULL_INPUT);
00558 cpl_ensure_code(key, CPL_ERROR_NULL_INPUT);
00559 cpl_ensure_code(value, CPL_ERROR_NULL_INPUT);
00560
00561 if (comment == NULL)
00562 cpl_ensure_code(fprintf(paf, PAF_KEY_FORMAT "\"%s\"\n",
00563 key, value) > PAF_KEY_LEN,
00564 CPL_ERROR_FILE_IO);
00565 else
00566 cpl_ensure_code(fprintf(paf, PAF_KEY_FORMAT "\"%s\" ; # %s\n",
00567 key, value, comment) > PAF_KEY_LEN,
00568 CPL_ERROR_FILE_IO);
00569
00570 return CPL_ERROR_NONE;
00571 }
00572
00573
00574
00585
00586 static cpl_error_code irplib_paf_dump_double(const char * key,
00587 double value,
00588 const char * comment, FILE * paf)
00589 {
00590 cpl_ensure_code(paf, CPL_ERROR_NULL_INPUT);
00591 cpl_ensure_code(key, CPL_ERROR_NULL_INPUT);
00592
00593 if (comment == NULL)
00594 cpl_ensure_code(fprintf(paf, PAF_KEY_FORMAT "%.10g\n",
00595 key, value) > PAF_KEY_LEN,
00596 CPL_ERROR_FILE_IO);
00597 else
00598 cpl_ensure_code(fprintf(paf, PAF_KEY_FORMAT "%.10g ; # %s\n",
00599 key, value, comment) > PAF_KEY_LEN,
00600 CPL_ERROR_FILE_IO);
00601
00602 return CPL_ERROR_NONE;
00603
00604 }
00605
00606
00617
00618 static cpl_error_code irplib_paf_dump_int(const char * key,
00619 int value,
00620 const char * comment, FILE * paf)
00621 {
00622 cpl_ensure_code(paf, CPL_ERROR_NULL_INPUT);
00623 cpl_ensure_code(key, CPL_ERROR_NULL_INPUT);
00624
00625 if (comment == NULL)
00626 cpl_ensure_code(fprintf(paf, PAF_KEY_FORMAT "%d\n",
00627 key, value) > PAF_KEY_LEN,
00628 CPL_ERROR_FILE_IO);
00629 else
00630 cpl_ensure_code(fprintf(paf, PAF_KEY_FORMAT "%d ; # %s\n",
00631 key, value, comment) > PAF_KEY_LEN,
00632 CPL_ERROR_FILE_IO);
00633
00634 return CPL_ERROR_NONE;
00635
00636 }
00637
00638
00639
00640
00641
00663
00664
00665 static cpl_error_code irplib_product_save(cpl_frameset * allframes,
00666 const cpl_parameterlist * parlist,
00667 const cpl_frameset * usedframes,
00668 const cpl_image * image,
00669 cpl_type_bpp bpp,
00670 const cpl_table * table,
00671 const cpl_propertylist * tablelist,
00672 const char * recipe,
00673 const char * procat,
00674 const cpl_propertylist * applist,
00675 const char * remregexp,
00676 const char * pipe_id,
00677 const char * filename) {
00678
00679 cpl_propertylist * plist;
00680 cpl_frame * product_frame;
00681 const cpl_boolean is_image = table == NULL ? CPL_TRUE : CPL_FALSE;
00682 cpl_error_code error = CPL_ERROR_NONE;
00683
00684
00685 assert(table == NULL || image == NULL);
00686 assert(tablelist == NULL || image == NULL);
00687
00688 cpl_ensure_code(allframes != NULL, CPL_ERROR_NULL_INPUT);
00689 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
00690 cpl_ensure_code(usedframes != NULL, CPL_ERROR_NULL_INPUT);
00691 cpl_ensure_code(recipe != NULL, CPL_ERROR_NULL_INPUT);
00692 cpl_ensure_code(procat != NULL, CPL_ERROR_NULL_INPUT);
00693 cpl_ensure_code(pipe_id != NULL, CPL_ERROR_NULL_INPUT);
00694 cpl_ensure_code(filename != NULL, CPL_ERROR_NULL_INPUT);
00695
00696 cpl_msg_info(cpl_func, "Writing FITS %s product(%s): %s",
00697 is_image ? "image" : "table", procat, filename);
00698
00699 product_frame = cpl_frame_new();
00700
00701
00702 error |= cpl_frame_set_filename(product_frame, filename);
00703 error |= cpl_frame_set_tag(product_frame, procat);
00704 error |= cpl_frame_set_type(product_frame,
00705 is_image ? CPL_FRAME_TYPE_IMAGE : CPL_FRAME_TYPE_TABLE);
00706 error |= cpl_frame_set_group(product_frame, CPL_FRAME_GROUP_PRODUCT);
00707 error |= cpl_frame_set_level(product_frame, CPL_FRAME_LEVEL_FINAL);
00708
00709 if (error) {
00710 cpl_frame_delete(product_frame);
00711 return cpl_error_get_code();
00712 }
00713
00714 plist = cpl_propertylist_new();
00715
00716
00717 if (applist != NULL) error = cpl_propertylist_append(plist, applist);
00718
00719
00720 if (!error)
00721 error = cpl_dfs_setup_product_header(plist, product_frame, usedframes,
00722 parlist, recipe, pipe_id,
00723 irplib_pro_did);
00724
00725 if (remregexp != NULL && !error)
00726 error = cpl_propertylist_erase_regexp(plist, remregexp, 0);
00727
00728 if (!error) {
00729 if (is_image) {
00730 error = cpl_image_save(image, filename, bpp, plist,
00731 CPL_IO_DEFAULT);
00732 } else {
00733
00734 error = cpl_table_save(table, plist, tablelist, filename,
00735 CPL_IO_DEFAULT);
00736
00737 }
00738 }
00739
00740 if (!error) {
00741
00742
00743 error = cpl_frameset_insert(allframes, product_frame);
00744
00745 } else {
00746 cpl_frame_delete(product_frame);
00747 }
00748
00749 cpl_propertylist_delete(plist);
00750
00751 return error;
00752
00753 }