irplib_dfs.c

00001 /* $Id: irplib_dfs.c,v 1.28 2007/01/16 09:57:38 yjung Exp $
00002  *
00003  * This file is part of the IRPLIB Package
00004  * Copyright (C) 2002,2003 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: yjung $
00023  * $Date: 2007/01/16 09:57:38 $
00024  * $Revision: 1.28 $
00025  * $Name:  $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                    Includes
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 /* Needed to get irplib_sprintf() */
00049 #include "irplib_utils.h"
00050 #include "irplib_dfs.h"
00051 
00052 /*-----------------------------------------------------------------------------
00053                         Defines and Static variables
00054  -----------------------------------------------------------------------------*/
00055 
00056 /* Use at least this many places when printing the PAF key */
00057 #define PAF_KEY_LEN 21
00058 /* Right justify the PAF key and separate with an extra space */
00059 #define PAF_KEY_FORMAT "%-21s "
00060 
00061 static const char irplib_pro_did[] = "PRO-1.15";
00062 
00063 /*-----------------------------------------------------------------------------
00064                         Private function prototypes
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                               Function codes
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     /* Some ugly, traditional error handling that obscures
00379        the actual functionality (i.e. to fprintf() some strings) */
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         /* Initialization needed in absence of #if for CPL_TYPE_LONG */
00480         cpl_error_code err = CPL_ERROR_UNSUPPORTED_MODE;
00481 
00482 
00483         if (strstr(name, "ESO ") == name) {
00484             /* Drop prefix "ESO " */
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; /* Don't need to modify the key */
00491 
00492         if (qckey != name) {
00493             /* Replace <space> with . */
00494             char * p;
00495             for (p = qckey; *p != '\0'; p++)
00496                 if (*p == ' ') *p = '.';
00497         }
00498 
00499         /* Print the property as PAF */
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)) /* FIXME: Change to #if */
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     /* Create product frame */
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     /* Add any QC parameters here */
00717     if (applist != NULL) error = cpl_propertylist_append(plist, applist);
00718 
00719     /* Add DataFlow keywords */
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         /* Insert the frame of the saved file in the input frameset */
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 }    

Generated on Wed Jan 17 08:33:41 2007 for SINFONI Pipeline Reference Manual by  doxygen 1.4.4