fors_qc.c

00001 /* $Id: fors_qc.c,v 1.7 2007/11/05 15:57:40 jmlarsen Exp $
00002  *
00003  * This file is part of the FORS Library
00004  * Copyright (C) 2002-2006 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  02110-1301 USA
00019  */
00020 
00021 /*
00022  * $Author: jmlarsen $
00023  * $Date: 2007/11/05 15:57:40 $
00024  * $Revision: 1.7 $
00025  * $Name:  $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <ctype.h>
00035 #include <string.h>
00036 #include <unistd.h>
00037 #include <math.h>
00038 
00039 #include <cpl.h>
00040 #include <fors_utils.h>
00041 #include <fors_paf.h>
00042 #include <fors_dfs.h>
00043 #include <fors_qc.h>
00044 
00045 #define DICT_LINE_LENGTH    (80)
00046 #define MAX_PAF_NAME_LENGTH (80)
00047 #define PAF_ROOT_NAME       "qc"
00048 
00056 const char *const fors_qc_dic_version = "2.0";
00057 
00058 static ForsPAF *pafFile = NULL;
00059 static int     pafIndex = 0;
00060 
00061 
00077 cpl_error_code fors_qc_start_group(cpl_propertylist *header,
00078                                    const char *qcdic_version, 
00079                                    const char *instrument)
00080 {
00081     char pafName[MAX_PAF_NAME_LENGTH];
00082 
00083     if (pafFile)
00084         return cpl_error_set("fors_qc_start_group", CPL_ERROR_FILE_ALREADY_OPEN);
00085 
00086     sprintf(pafName, "%s%.4d.paf", PAF_ROOT_NAME, pafIndex);
00087 
00088     if (!(pafFile = newForsPAF(pafName, "QC1 parameters", NULL, NULL)))
00089         return cpl_error_set("fors_qc_start_group", CPL_ERROR_FILE_NOT_CREATED);
00090     
00091     fors_qc_write_qc_string(header, 
00092                             "QC.DID", qcdic_version, "QC1 dictionary",
00093                             instrument);
00094 
00095     return CPL_ERROR_NONE;
00096 
00097 }
00098 
00099 #undef cleanup
00100 #define cleanup \
00101 do { \
00102     cpl_propertylist_delete(header); \
00103 } while(0)
00104 
00115 void fors_qc_write_group_heading(const cpl_frame *raw_frame,
00116                                  const char *pro_catg,
00117                                  const char *instrument)
00118 {
00119     cpl_propertylist *header = NULL;
00120     assure( raw_frame != NULL, return, NULL );
00121     assure( cpl_frame_get_filename(raw_frame) != NULL, return, NULL );
00122 
00123     header = cpl_propertylist_load(cpl_frame_get_filename(raw_frame), 0);
00124     assure( !cpl_error_get_code(), return, "Could not load %s header",
00125             cpl_frame_get_filename(raw_frame));
00126     
00127     fors_qc_write_string("PRO.CATG", pro_catg,
00128                          "Product category", instrument);
00129     assure( !cpl_error_get_code(), return, "Cannot write product category to "
00130             "QC log file");
00131     
00132     fors_qc_keyword_to_paf(header, "ESO DPR TYPE", NULL, 
00133                            "DPR type", instrument);
00134     assure( !cpl_error_get_code(), return, "Missing keyword DPR TYPE in raw "
00135             "frame header");
00136     
00137     fors_qc_keyword_to_paf(header, "ESO TPL ID", NULL, 
00138                            "Template", instrument);
00139     assure( !cpl_error_get_code(), return, "Missing keyword TPL ID in raw "
00140             "frame header");
00141     
00142     if (cpl_propertylist_has(header, "ESO INS FILT1 NAME")) {
00143         fors_qc_keyword_to_paf(header, "ESO INS FILT1 NAME", NULL,
00144                                "Filter name", instrument);
00145         assure( !cpl_error_get_code(), return, "Failed to write ESO INS FILT1 NAME");
00146     }
00147     
00148     fors_qc_keyword_to_paf(header, "ESO INS COLL NAME", NULL,
00149                            "Collimator name", instrument);
00150     assure( !cpl_error_get_code(), return, "Missing keyword INS COLL NAME in raw "
00151             "frame header");
00152     
00153     fors_qc_keyword_to_paf(header, "ESO DET CHIP1 ID", NULL,
00154                            "Chip identifier", instrument);
00155     assure( !cpl_error_get_code(), return, "Missing keyword DET CHIP1 ID in raw "
00156             "frame header");
00157     
00158     fors_qc_keyword_to_paf(header, "ESO DET WIN1 BINX", NULL,    
00159                            "Binning factor along X", instrument);
00160     assure( !cpl_error_get_code(), return, "Missing keyword ESO DET WIN1 BINX "
00161             "in raw frame header");
00162     
00163     fors_qc_keyword_to_paf(header, "ESO DET WIN1 BINY", NULL,
00164                            "Binning factor along Y", instrument);
00165     assure( !cpl_error_get_code(), return, "Missing keyword ESO DET WIN1 BINY "
00166             "in raw frame header");
00167     
00168     fors_qc_keyword_to_paf(header, "ARCFILE", NULL,
00169                            "Archive name of input data", 
00170                            instrument);
00171     assure( !cpl_error_get_code(), return, "Missing keyword ARCFILE in raw "
00172             "frame header");
00173     
00174     {
00175         char *pipefile = dfs_generate_filename(pro_catg);
00176         fors_qc_write_string("PIPEFILE", pipefile, 
00177                              "Pipeline product name", instrument);
00178         cpl_free(pipefile); pipefile = NULL;
00179         assure( !cpl_error_get_code(), return, "Cannot write PIPEFILE to QC log file");
00180     }
00181 
00182     cleanup;
00183     return;
00184 }
00185 
00186 
00187 
00200 cpl_error_code fors_qc_end_group(void)
00201 {
00202 
00203     if (!pafFile)
00204         return cpl_error_set("fors_qc_end_group", CPL_ERROR_DATA_NOT_FOUND);
00205 
00206     if (!forsPAFIsEmpty(pafFile)) {
00207         forsPAFWrite(pafFile);
00208         pafIndex++;
00209     }
00210 
00211     deleteForsPAF(pafFile);
00212     pafFile = NULL;
00213 
00214     return CPL_ERROR_NONE;
00215 
00216 }
00217 
00218 
00235 cpl_error_code fors_qc_write_string(const char *name, const char *value, 
00236                                 const char *comment, const char *instrument)
00237 {
00238 
00239     int status;
00240     int   length = strlen(instrument) + 3;
00241     char *allComment;
00242 
00243 
00244     if (comment == NULL || name == NULL || instrument == NULL)
00245         return cpl_error_set("fors_qc_write_string", CPL_ERROR_NULL_INPUT);
00246 
00247     length += strlen(comment) + 1;
00248 
00249     allComment = cpl_malloc(length * sizeof(char));
00250 
00251     sprintf(allComment, "%s [%s]", comment, instrument);
00252 
00253     status = forsPAFAppendString(pafFile, name, value, allComment);
00254 
00255     cpl_free(allComment);
00256 
00257     if (status)
00258         cpl_msg_error("fors_qc_write_string", 
00259                       "Cannot write parameter %s to QC1 PAF", name);
00260 
00261     /* Write QC parameters of type string only at the debug level;
00262        they tend to be less interesting (often duplicates of FITS keys). */
00263     cpl_msg_debug(cpl_func, "%s [%s] = '%s'", comment, name, value);
00264 
00265     return CPL_ERROR_NONE;
00266 
00267 }
00268 
00269 
00291 cpl_error_code fors_qc_write_double(const char *name, double value, 
00292                                 const char *unit, const char *comment,
00293                                 const char *instrument)
00294 {
00295 
00296     cpl_error_code status;
00297     int   length = strlen(instrument) + 3;
00298     char *allComment;
00299 
00300 
00301     if (comment == NULL || name == NULL || instrument == NULL)
00302         return cpl_error_set("fors_qc_write_double", CPL_ERROR_NULL_INPUT);
00303 
00304     length += strlen(comment) + 1;
00305 
00306     if (unit)
00307       length += strlen(unit) + 3;
00308 
00309     allComment = cpl_malloc(length * sizeof(char));
00310 
00311     if (unit)
00312       sprintf(allComment, "%s (%s) [%s]", comment, unit, instrument);
00313     else
00314       sprintf(allComment, "%s [%s]", comment, instrument);
00315 
00316     status = forsPAFAppendDouble(pafFile, name, value, allComment);
00317 
00318     cpl_free(allComment);
00319 
00320     if (status)
00321         cpl_msg_error("fors_qc_write_double", 
00322                       "Cannot write parameter %s to QC1 PAF", name);
00323 
00324     cpl_msg_info(cpl_func, "%s [%s] = %f %s", 
00325                  comment, name, value, (unit != NULL) ? unit : "");
00326 
00327     return CPL_ERROR_NONE;
00328 
00329 }
00330 
00331 
00332 cpl_error_code fors_qc_write_int(const char *name, int value, const char *unit, 
00333                              const char *comment, const char *instrument)
00334 {
00335 
00336     cpl_error_code status;
00337     int   length = strlen(instrument) + 3;
00338     char *allComment;
00339 
00340 
00341     if (comment == NULL || name == NULL || instrument == NULL)
00342         return cpl_error_set("fors_qc_write_int", CPL_ERROR_NULL_INPUT);
00343 
00344     length += strlen(comment) + 1;
00345 
00346     if (unit)
00347       length += strlen(unit) + 3;
00348 
00349     allComment = cpl_malloc(length * sizeof(char));
00350 
00351     if (unit)
00352       sprintf(allComment, "%s (%s) [%s]", comment, unit, instrument);
00353     else
00354       sprintf(allComment, "%s [%s]", comment, instrument);
00355 
00356     status = forsPAFAppendInt(pafFile, name, value, allComment);
00357 
00358     cpl_free(allComment);
00359 
00360     if (status)
00361         cpl_msg_error("fors_qc_write_int", 
00362                       "Cannot write parameter %s to QC1 PAF", name);
00363 
00364     cpl_msg_info(cpl_func, "%s [%s] = %d %s", 
00365                  comment, name, value, (unit != NULL) ? unit : "");
00366  
00367     return CPL_ERROR_NONE;
00368 
00369 }
00370 
00371 
00395 cpl_error_code fors_qc_keyword_to_paf(cpl_propertylist *header, 
00396                                      const char *name, const char *unit, 
00397                                      const char *comment, 
00398                                      const char *instrument)
00399 {
00400 
00401   const char func[] = "fors_qc_keyword_to_paf";
00402 
00403   char            *keyName;
00404   char            *keep;
00405   char            *pos;
00406   int              ivalue;
00407   float            fvalue;
00408   double           dvalue;
00409   char            *svalue = NULL;
00410   int              status;
00411   int              i;
00412 
00413 
00414   if (header == NULL) {
00415     cpl_msg_error(func, "Empty header");
00416     return cpl_error_set(func, CPL_ERROR_NULL_INPUT);
00417   }
00418 
00419   if (!cpl_propertylist_has(header, name)) {
00420     cpl_msg_error(func, "Keyword %s not found", name);
00421     return cpl_error_set(func, CPL_ERROR_DATA_NOT_FOUND);
00422   }
00423 
00424   switch (cpl_propertylist_get_type(header, name)) {
00425   case CPL_TYPE_INT :
00426     ivalue = cpl_propertylist_get_int(header, name);
00427     break;
00428   case CPL_TYPE_FLOAT :
00429     fvalue = cpl_propertylist_get_float(header, name);
00430     break;
00431   case CPL_TYPE_DOUBLE :
00432     dvalue = cpl_propertylist_get_double(header, name);
00433     break;
00434   case CPL_TYPE_STRING :
00435     svalue = (char *)cpl_propertylist_get_string(header, name);
00436     break;
00437   default :
00438     cpl_msg_error(func, "Unsupported keyword type");
00439     return cpl_error_set(func, CPL_ERROR_INVALID_TYPE);
00440   }
00441 
00442 
00443   /*
00444    *  Construct entry name for PAF
00445    */
00446 
00447   keep = keyName = cpl_strdup(name);
00448 
00449   pos = strstr(keyName, "ESO ");
00450 
00451   if (pos == keyName)
00452     keyName += 4;
00453 
00454   for (i = 0; keyName[i] != '\0'; i++)
00455     if (keyName[i] == ' ')
00456       keyName[i] = '.';
00457 
00458   /*
00459    *  Now write entry to PAF object.
00460    */
00461 
00462   switch (cpl_propertylist_get_type(header, name)) {
00463   case CPL_TYPE_INT :
00464     status = fors_qc_write_int(keyName, ivalue, unit, comment, instrument);
00465     break;
00466   case CPL_TYPE_FLOAT :
00467     dvalue = fvalue;
00468   case CPL_TYPE_DOUBLE :
00469     status = fors_qc_write_double(keyName, dvalue, unit, comment, instrument);
00470     break;
00471   default :    /* CPL_TYPE_STRING */
00472     status = fors_qc_write_string(keyName, svalue, comment, instrument);
00473   }
00474 
00475   if (status)
00476     cpl_msg_error(func, "Could not copy keyword value to QC1 PAF!");
00477 
00478   cpl_free(keep);
00479 
00480   return status;
00481 
00482 }
00483 
00505 cpl_error_code fors_qc_write_qc_string(cpl_propertylist *header,
00506                                        const char *name, const char *value, 
00507                                        const char *comment, const char *instrument)
00508 {
00509     const char func[] = "fors_qc_write_qc_string";
00510 
00511     char *header_name;
00512     int   i;
00513 
00514     if (fors_qc_write_string(name, value, comment, instrument)) {
00515         cpl_error_set_where(func);
00516         return cpl_error_get_code();
00517     }
00518 
00519     header_name = cpl_malloc((strlen(name) + 6) * sizeof(char *));
00520 
00521     strcpy(header_name, "ESO ");
00522     strcat(header_name, name);
00523 
00524     for (i = 0; header_name[i] != '\0'; i++)
00525         if (header_name[i] == '.')
00526             header_name[i] = ' ';
00527 
00528     if (cpl_propertylist_update_string(header, header_name, value)) {
00529         cpl_free(header_name);
00530         cpl_error_set_where(func);
00531         return cpl_error_get_code();
00532     }
00533 
00534     cpl_propertylist_set_comment(header, header_name, comment);
00535 
00536     cpl_free(header_name);
00537 
00538     return CPL_ERROR_NONE;
00539 }
00540 
00565 cpl_error_code fors_qc_write_qc_double(cpl_propertylist *header, double value, 
00566                                       const char *name, const char *unit, 
00567                                       const char *comment,
00568                                       const char *instrument)
00569 {
00570 
00571   const char func[] = "fors_qc_write_qc_double";
00572 
00573   char *header_name;
00574   int   i;
00575 
00576 
00577   if (fors_qc_write_double(name, value, unit, comment, instrument)) {
00578       cpl_error_set_where(func);
00579       return cpl_error_get_code();
00580   }
00581 
00582   header_name = cpl_malloc((strlen(name) + 6) * sizeof(char *));
00583 
00584   strcpy(header_name, "ESO ");
00585   strcat(header_name, name);
00586 
00587   for (i = 0; header_name[i] != '\0'; i++)
00588     if (header_name[i] == '.')
00589       header_name[i] = ' ';
00590 
00591   if (cpl_propertylist_update_double(header, header_name, value)) {
00592       cpl_free(header_name);
00593       cpl_error_set_where(func);
00594       return cpl_error_get_code();
00595   }
00596 
00597   cpl_propertylist_set_comment(header, header_name, comment);
00598 
00599   cpl_free(header_name);
00600 
00601   return CPL_ERROR_NONE;
00602 
00603 }
00604 
00605 
00606 cpl_error_code fors_qc_write_qc_int(cpl_propertylist *header, int value,
00607                                    const char *name, const char *unit,
00608                                    const char *comment,
00609                                    const char *instrument)
00610 {
00611 
00612   const char func[] = "fors_qc_write_qc_int";
00613 
00614   char *header_name;
00615   int   i;
00616 
00617 
00618   if (fors_qc_write_int(name, value, unit, comment, instrument)) {
00619       cpl_error_set_where(func);
00620       return cpl_error_get_code();
00621   }
00622 
00623   header_name = cpl_malloc((strlen(name) + 6) * sizeof(char *));
00624 
00625   strcpy(header_name, "ESO ");
00626   strcat(header_name, name);
00627 
00628   for (i = 0; header_name[i] != '\0'; i++)
00629     if (header_name[i] == '.')
00630       header_name[i] = ' ';
00631 
00632   if (cpl_propertylist_update_int(header, header_name, value)) {
00633       cpl_free(header_name);
00634       cpl_error_set_where(func);
00635       return cpl_error_get_code();
00636   }
00637 
00638   cpl_propertylist_set_comment(header, header_name, comment);
00639 
00640   cpl_free(header_name);
00641 
00642   return CPL_ERROR_NONE;
00643 
00644 }
00645 
00646 /*
00647  * @brief
00648  *   Write an integer value to the active QC1 PAF object and to a header.
00649  *
00650  * @return @c CPL_ERROR_NONE on success
00651  *
00652  * @param filnam  Name of existing FITS file.
00653  * @param value   Value to write.
00654  * @param name    QC1 PAF entry name.
00655  * @param unit    Optional unit to be associated to value.
00656  * @param comment Optional comment to be associated to value.
00657  *
00658  * @doc
00659  *   This function writes the header entries directly to the header 
00660  *   of the FITS file written to disk, using the qfits_replace_card() call.
00661  *   An entry with the specified @em name is written to the current QC1 PAF 
00662  *   object. From the entry @em name, the name of the QC keyword that
00663  *   should be written to header is derived prepending the string "ESO "
00664  *   and replacing all '.' with a blank (e.g., "QC.BIAS.MASTER.MEAN"
00665  *   becomes "ESO QC BIAS MASTER MEAN"). Finally, the new keyword
00666  *   is written to the header. Note that before calling this funtion 
00667  *   a QC1 PAF object must be created with a call to fors_qc_start_group().
00668  */
00669 
00670 /*
00671 cpl_error_code fors_qc_write_qc_int(char *filnam, int value, const char *name,
00672                                const char *unit, const char *comment,
00673                                const char *instrument)
00674 {
00675 
00676   const char func[] = "fors_qc_write_qc_int";
00677 
00678   char             line[81];
00679   char             val[81];
00680   char            *descName;
00681   int              i;
00682 
00683 
00684   if (fors_qc_write_int(name, value, unit, comment, instrument)) {
00685     cpl_msg_error(func, "Could not copy value to QC1 PAF!");
00686     cpl_error_set_where(func);
00687     return cpl_error_get_code();
00688   }
00689 
00690   descName = cpl_malloc((strlen(name) + 15) * sizeof(char *));
00691 
00692   strcpy(descName, "HIERARCH ESO ");
00693   strcat(descName, name);
00694 
00695   for (i = 0; descName[i] != '\0'; i++)
00696     if (descName[i] == '.')
00697       descName[i] = ' ';
00698 
00699   sprintf(val, "%d", value);
00700   keytuple2str(line, descName, val, (char *)comment);
00701   qfits_replace_card(filnam, descName, line);
00702 
00703   cpl_free(descName);
00704 
00705   return CPL_ERROR_NONE;
00706 
00707 }
00708 
00709 
00710 cpl_error_code fors_qc_write_qc_double(char *filnam, double value, 
00711                                       const char *name, const char *unit, 
00712                                       const char *comment,
00713                                       const char *instrument)
00714 {
00715 
00716   const char func[] = "fors_qc_write_qc_double";
00717 
00718   char             line[81];
00719   char             val[81];
00720   char            *descName;
00721   int              i;
00722 
00723 
00724   if (fors_qc_write_double(name, value, unit, comment, instrument)) {
00725     cpl_msg_error(func, "Could not copy value to QC1 PAF!");
00726     cpl_error_set_where(func);
00727     return cpl_error_get_code();
00728   }
00729 
00730   descName = cpl_malloc((strlen(name) + 15) * sizeof(char *));
00731 
00732   strcpy(descName, "HIERARCH ESO ");
00733   strcat(descName, name);
00734 
00735   for (i = 0; descName[i] != '\0'; i++)
00736     if (descName[i] == '.')
00737       descName[i] = ' ';
00738 
00739   sprintf(val, "%1.6e", value);
00740   keytuple2str(line, descName, val, (char *)comment);
00741   qfits_replace_card(filnam, descName, line);
00742 
00743   cpl_free(descName);
00744 
00745   return CPL_ERROR_NONE;
00746 
00747 }
00748 
00749 */
00750 

Generated on Wed Jun 24 14:11:17 2009 for FORS Pipeline Reference Manual by  doxygen 1.4.7