fors_setting.c

00001 /* $Id: fors_setting.c,v 1.16 2008/06/23 11:56:15 cizzo 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: cizzo $
00023  * $Date: 2008/06/23 11:56:15 $
00024  * $Revision: 1.16 $
00025  * $Name:  $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 #include <fors_setting.h>
00033 
00034 #include <fors_dfs.h>
00035 #include <fors_pfits.h>
00036 #include <fors_utils.h>
00037 
00038 #include <cpl.h>
00039 #include <stdbool.h>
00040 #include <string.h>
00041 #include <math.h>
00042 
00043 /*----------------------------------------------------------------------------*/
00047 /*----------------------------------------------------------------------------*/
00048 
00051 static fors_setting *
00052 fors_setting_new_level(const cpl_frame *raw, cpl_msg_severity level);
00053 
00054 
00062 fors_setting *
00063 fors_setting_new(const cpl_frame *raw)
00064 {
00065     return fors_setting_new_level(raw, CPL_MSG_INFO);
00066 }
00067 
00068 #undef cleanup
00069 #define cleanup \
00070 do { \
00071     cpl_propertylist_delete(header); \
00072 } while (0)
00073 
00080 static fors_setting *
00081 fors_setting_new_level(const cpl_frame *raw, cpl_msg_severity level)
00082 {
00083     fors_setting *s = NULL;
00084     const char *filename;
00085     cpl_propertylist *header = NULL;
00086 
00087     assure( raw != NULL, return NULL, NULL );
00088 
00089     fors_msg(level, "Instrument setting:");
00090     cpl_msg_indent_more();
00091 
00092     /* Load header */
00093     filename = cpl_frame_get_filename(raw);
00094     assure( filename != NULL, return NULL, "Missing frame filename" );
00095     header = cpl_propertylist_load(filename, 0);
00096     assure( !cpl_error_get_code(), return NULL, 
00097             "Could not read %s primary header", filename );
00098 
00099     cpl_msg_debug(cpl_func, "Reading setting from %s", filename );
00100         
00101     /* Read relevant contents */
00102     s = cpl_malloc(sizeof(*s));
00103 
00104     s->binx = cpl_propertylist_get_int(header, FORS_PFITS_BINX);
00105     if (CPL_ERROR_TYPE_MISMATCH == cpl_error_get_code()) {
00106         cpl_msg_error(cpl_func, 
00107                       "Keyword %s is not an integer", FORS_PFITS_BINX);
00108     }
00109     assure( !cpl_error_get_code(), return s,
00110             "Could not read %s from %s header", 
00111             FORS_PFITS_BINX, filename);
00112     
00113     fors_msg(level, "Detector x-binning (%s) = %d", FORS_PFITS_BINX, s->binx);
00114 
00115     s->biny = cpl_propertylist_get_int(header, FORS_PFITS_BINY);
00116     if (CPL_ERROR_TYPE_MISMATCH == cpl_error_get_code()) {
00117         cpl_msg_error(cpl_func, 
00118                       "Keyword %s is not an integer", FORS_PFITS_BINY);
00119     }
00120     assure( !cpl_error_get_code(), return s,
00121             "Could not read %s from %s header", 
00122             FORS_PFITS_BINY, filename);
00123 
00124     fors_msg(level, "Detector y-binning (%s) = %d", FORS_PFITS_BINY, s->biny);
00125 
00126     
00127     if (cpl_propertylist_has(header, FORS_PFITS_PRESCANX)) {
00128         
00129         s->prescan_x = cpl_propertylist_get_int(header, FORS_PFITS_PRESCANX);
00130         if (CPL_ERROR_TYPE_MISMATCH == cpl_error_get_code()) {
00131             cpl_msg_error(cpl_func, 
00132                           "Keyword %s is not an integer", FORS_PFITS_PRESCANX);
00133         }
00134         assure( !cpl_error_get_code(), return s,
00135                 "Could not read %s from %s header", 
00136                 FORS_PFITS_PRESCANX, filename);
00137         
00138     }
00139     else {
00140         s->prescan_x = 0;
00141     }
00142     
00143     fors_msg(level, "Detector x-prescan (%s) = %d",
00144              FORS_PFITS_PRESCANX, s->prescan_x);
00145 
00146 
00147     if (cpl_propertylist_has(header, FORS_PFITS_PRESCANY)) {
00148         
00149         s->prescan_y = cpl_propertylist_get_int(header, FORS_PFITS_PRESCANY);
00150         if (CPL_ERROR_TYPE_MISMATCH == cpl_error_get_code()) {
00151             cpl_msg_error(cpl_func, 
00152                           "Keyword %s is not an integer", FORS_PFITS_PRESCANY);
00153         }
00154         assure( !cpl_error_get_code(), return s,
00155                 "Could not read %s from %s header", 
00156                 FORS_PFITS_PRESCANY, filename);
00157         
00158     }
00159     else {
00160         s->prescan_y = 0;
00161     }
00162     
00163     fors_msg(level, "Detector y-prescan (%s) = %d",
00164              FORS_PFITS_PRESCANY, s->prescan_y);
00165 
00166 
00167     if (cpl_propertylist_has(header, FORS_PFITS_FILTER_NAME)) {
00168         
00169         s->filter_name = cpl_propertylist_get_string(header, 
00170                                                      FORS_PFITS_FILTER_NAME);
00171         if (CPL_ERROR_TYPE_MISMATCH == cpl_error_get_code()) {
00172             cpl_msg_error(cpl_func, 
00173                           "Keyword %s is not a string", 
00174                           FORS_PFITS_FILTER_NAME);
00175         }
00176         assure( !cpl_error_get_code(), return s,
00177                 "Could not read %s from %s header", 
00178                 FORS_PFITS_FILTER_NAME, filename);
00179     
00180         /* Allocate new string (after the check for NULL and
00181            before deallocating the cpl_propertylist) */
00182         s->filter_name = cpl_strdup(s->filter_name);
00183 
00184         fors_msg(level, "Filter name (%s) = %s", 
00185                      FORS_PFITS_FILTER_NAME, s->filter_name);
00186         
00187         bool recognized = false;
00188         unsigned i;
00189         for (i = 0; 
00190              i < sizeof(FORS_DATA_FILTERLIST) / sizeof(*FORS_DATA_FILTERLIST);
00191              i++) {
00192             
00193             if (strcmp(s->filter_name, FORS_DATA_FILTERLIST[i].name) == 0) {
00194                 s->filter = FORS_DATA_FILTERLIST[i].filter;
00195                 recognized = true;
00196             }
00197         }
00198         
00199 /* %%% New part...  */
00200 
00201         if (!recognized) {
00202             cpl_msg_warning(cpl_func, "Non-standard filter...");
00203             s->filter = FILTER_U; //fixme
00204             s->filter_name = NULL;
00205         }
00206 
00207 /***
00208         assure( recognized, return s, "%s: %s: Unrecognized filter name: '%s'",
00209                 filename, FORS_PFITS_FILTER_NAME, s->filter_name );
00210 ***/
00211 
00212     }
00213     else {
00214         /* No raw frame filter (e.g. rawbias) */
00215         s->filter = FILTER_U; //fixme
00216         s->filter_name = NULL;
00217     }
00218     
00219     if (cpl_propertylist_has(header, FORS_PFITS_EXPOSURE_TIME)) {
00220         s->exposure_time = cpl_propertylist_get_double(header, 
00221                            FORS_PFITS_EXPOSURE_TIME);
00222         if (CPL_ERROR_TYPE_MISMATCH == cpl_error_get_code()) {
00223             cpl_msg_error(cpl_func, 
00224                           "Keyword %s is not a double precision type", 
00225                           FORS_PFITS_EXPOSURE_TIME);
00226         }
00227         assure( !cpl_error_get_code(), return s, 
00228                 "Could not read %s from %s header", 
00229                 FORS_PFITS_EXPOSURE_TIME, filename);
00230         
00231         fors_msg(level, "Exposure time (%s) = %f s", 
00232                      FORS_PFITS_EXPOSURE_TIME, s->exposure_time);
00233     }
00234     else {
00235         cpl_msg_debug(cpl_func, "%s: Missing keyword '%s'",
00236                       filename, FORS_PFITS_EXPOSURE_TIME);
00237     }
00238 
00239     s->pixel_scale = cpl_propertylist_get_double(header, FORS_PFITS_PIXSCALE);
00240     if (CPL_ERROR_TYPE_MISMATCH == cpl_error_get_code()) {
00241         cpl_msg_error(cpl_func, 
00242                       "Keyword %s is not a double precision type", 
00243                       FORS_PFITS_PIXSCALE);
00244     }
00245     assure( !cpl_error_get_code(), return s, 
00246             "Could not read %s from %s header", 
00247             FORS_PFITS_PIXSCALE, filename);
00248 
00249     fors_msg(level, "Pixel scale (%s) = %f arcsec/pixel", 
00250                  FORS_PFITS_PIXSCALE, s->pixel_scale);
00251 
00252     assure( s->pixel_scale > 0, return s,
00253             "%s: %s is non-positive (%f arcsec/pixel)",
00254             filename, FORS_PFITS_PIXSCALE, s->pixel_scale);
00255     
00256     s->version = fors_dfs_pipeline_version(header, &(s->instrument));
00257     assure( !cpl_error_get_code(), return s,
00258             "Could not read instrument version from %s header", 
00259             filename);
00260 
00261     fors_msg(level, "Instrument (%s) = %s", 
00262              FORS_PFITS_INSTRUME, s->instrument);
00263 
00264     {
00265     int outputs = cpl_propertylist_get_int(header, FORS_PFITS_OUTPUTS);
00266         if (CPL_ERROR_TYPE_MISMATCH == cpl_error_get_code()) {
00267             cpl_msg_error(cpl_func, 
00268                           "Keyword %s is not integer", 
00269                           FORS_PFITS_OUTPUTS);
00270         }
00271     assure( !cpl_error_get_code(), return s, 
00272         "Could not read %s from %s header", 
00273         FORS_PFITS_OUTPUTS, filename);
00274 
00275     fors_msg(level, "Output ports (%s) = %d", 
00276          FORS_PFITS_OUTPUTS, outputs);
00277     
00278     /* Support only new and old FORS data, where the approximation
00279        about using average ron/conad is fine. 
00280     */
00281     assure( outputs == 1 || outputs == 4, return s,
00282         "1 or 4 output ports required");
00283 
00284     int i;
00285     s->average_gain = 0;
00286     s->ron = 0;
00287     for(i = 0; i < outputs; i++) {
00288         
00289         double conad = cpl_propertylist_get_double(header, 
00290                                                        FORS_PFITS_CONAD[i]);
00291             if (CPL_ERROR_TYPE_MISMATCH == cpl_error_get_code()) {
00292                 cpl_msg_error(cpl_func, 
00293                               "Keyword %s is not a double precision type", 
00294                               FORS_PFITS_CONAD[i]);
00295             }
00296         assure( !cpl_error_get_code(), return s, 
00297             "Could not read %s from %s header", 
00298             FORS_PFITS_CONAD[i], filename);
00299         
00300         fors_msg(level, "Gain factor (%s) = %.2f e-/ADU", 
00301              FORS_PFITS_CONAD[i], conad);
00302         
00303         assure( conad > 0, return s, "%s: Illegal %s: %f, must be positive",
00304             filename, FORS_PFITS_CONAD[i], conad);
00305         
00306         double ron = cpl_propertylist_get_double(header, FORS_PFITS_RON[i]);
00307             if (CPL_ERROR_TYPE_MISMATCH == cpl_error_get_code()) {
00308                 cpl_msg_error(cpl_func, 
00309                               "Keyword %s is not a double precision type", 
00310                               FORS_PFITS_RON[i]);
00311             }
00312         assure( !cpl_error_get_code(), return s, 
00313             "Could not read %s from %s header", 
00314             FORS_PFITS_RON[i], filename);
00315         
00316         assure( ron > 0, return s,
00317             "%s: Illegal %s: %f, must be positive",
00318             filename, FORS_PFITS_RON[i], ron);
00319         
00320         ron /= conad; /* electrons -> ADU */
00321 
00322         fors_msg(level, "Read-out-noise (%s) = %.2f ADU", 
00323              FORS_PFITS_RON[i], ron);
00324 
00325         /* accumulate */
00326         s->ron += ron;
00327         s->average_gain += 1.0/conad;
00328     }
00329 
00330     /* get average */
00331     s->ron          /= outputs;
00332     s->average_gain /= outputs;
00333 
00334     if (outputs > 1) {
00335         fors_msg(level, "Average gain factor = %.2f e-/ADU", 
00336              1.0/s->average_gain);
00337 
00338         fors_msg(level, "Read-out-noise = %.2f ADU", 
00339              s->ron);
00340     }
00341     }
00342     
00343     s->read_clock = cpl_propertylist_get_string(header, FORS_PFITS_READ_CLOCK);
00344     if (CPL_ERROR_TYPE_MISMATCH == cpl_error_get_code()) {
00345         cpl_msg_error(cpl_func, 
00346                       "Keyword %s is not a string", 
00347                       FORS_PFITS_READ_CLOCK);
00348     }
00349     assure( !cpl_error_get_code(), return s, 
00350             "Could not read %s from %s header", 
00351             FORS_PFITS_READ_CLOCK, filename);
00352 
00353     s->read_clock = cpl_strdup(s->read_clock);
00354 
00355     fors_msg(level, "Readout clock pattern (%s) = %s", 
00356                  FORS_PFITS_READ_CLOCK, s->read_clock);
00357     
00358 
00359     s->chip_id = cpl_propertylist_get_string(header, FORS_PFITS_CHIP_ID);
00360     if (CPL_ERROR_TYPE_MISMATCH == cpl_error_get_code()) {
00361         cpl_msg_error(cpl_func, 
00362                       "Keyword %s is not a string", 
00363                       FORS_PFITS_CHIP_ID);
00364     }
00365     assure( !cpl_error_get_code(), return s, 
00366             "Could not read %s from %s header", 
00367             FORS_PFITS_CHIP_ID, filename);
00368 
00369     s->chip_id = cpl_strdup(s->chip_id);
00370 
00371 
00372     fors_msg(level, "Chip ID (%s) = %s", 
00373                  FORS_PFITS_CHIP_ID, s->chip_id);
00374 
00375     cpl_msg_indent_less();
00376     
00377     cleanup;
00378     return s;
00379 }
00380 
00381 #undef cleanup
00382 #define cleanup \
00383 do { \
00384     fors_setting_delete(&input_setting); \
00385 } while (0)
00386 
00396 void
00397 fors_setting_verify(const fors_setting *ref_setting, const cpl_frame *frame,
00398             fors_setting **setting)
00399 {
00400     fors_setting *input_setting = NULL;
00401 
00402     assure( ref_setting != NULL, return, NULL );
00403     assure( frame       != NULL, return, NULL );
00404     assure( cpl_frame_get_filename(frame) != NULL, return, NULL );
00405 
00406     input_setting = fors_setting_new_level(frame, CPL_MSG_DEBUG);
00407 
00408     assure( !cpl_error_get_code(), return, 
00409             "Could not get %s instrument setting",
00410             cpl_frame_get_filename(frame));
00411     
00412 
00413     if (ref_setting->binx != input_setting->binx ||
00414         ref_setting->biny != input_setting->biny) {
00415         cpl_msg_warning(cpl_func, "Incompatible CCD binning: %dx%d",
00416                         input_setting->binx, input_setting->biny);
00417     }
00418 
00419     if (ref_setting->filter_name != NULL && 
00420         input_setting->filter_name != NULL &&
00421         strcmp(ref_setting->filter_name, input_setting->filter_name) != 0) {
00422         cpl_msg_warning(cpl_func, "Incompatible filter names: '%s'",
00423                         input_setting->filter_name);
00424     }
00425 
00426     if ((ref_setting->prescan_x != input_setting->prescan_x &&
00427          input_setting->prescan_x != 0) ||
00428         (ref_setting->prescan_y != input_setting->prescan_y &&
00429          input_setting->prescan_y != 0)) {
00430         cpl_msg_warning(cpl_func, "Incompatible CCD x-prescan areas: %dx%d",
00431                         input_setting->prescan_x,
00432                         input_setting->prescan_y);
00433     }
00434 
00435     /* no check on exposure time */
00436 
00437     if (fabs((ref_setting->average_gain - input_setting->average_gain) /
00438              ref_setting->average_gain) > 0.01) {
00439 
00440         cpl_msg_warning(cpl_func, "Incompatible gain factor: %f e-/ADU",
00441                         input_setting->average_gain);
00442     }
00443 
00444 
00445     if (fabs((ref_setting->ron - input_setting->ron) /
00446              ref_setting->ron) > 0.01) {
00447         cpl_msg_warning(cpl_func, "Incompatible read-out-noise: %f ADU",
00448                         input_setting->ron);
00449     }
00450 
00451     if (fabs((ref_setting->pixel_scale - input_setting->pixel_scale) /
00452              ref_setting->pixel_scale) > 0.01) {
00453         cpl_msg_warning(cpl_func, "Incompatible pixel scale: %f arcsec/pixel",
00454                         input_setting->pixel_scale);
00455     }
00456 
00457     if (strcmp(ref_setting->chip_id, input_setting->chip_id) != 0) {
00458         cpl_msg_warning(cpl_func, "Incompatible chip ID: '%s'",
00459                         input_setting->chip_id);
00460     }
00461 
00462     if (strcmp(ref_setting->read_clock, input_setting->read_clock) != 0) {
00463         cpl_msg_warning(cpl_func, "Incompatible readout clock pattern: '%s'",
00464                         input_setting->read_clock);
00465     }
00466 
00467     if (strcmp(ref_setting->instrument, input_setting->instrument) != 0) {
00468         cpl_msg_warning(cpl_func, "Incompatible instrument name: '%s'",
00469                         input_setting->instrument);
00470     }
00471 
00472     if (strcmp(ref_setting->version, input_setting->version) != 0) {
00473         cpl_msg_warning(cpl_func, "Incompatible version: '%s'",
00474                         input_setting->version);
00475     }   
00476 
00477     /* Return setting if requested */
00478     if (setting != NULL) {
00479         *setting = input_setting;
00480         input_setting = NULL;
00481     }
00482 
00483     cleanup;
00484     return;
00485 
00486 }
00487 
00488 
00489 
00494 void fors_setting_delete(fors_setting **s)
00495 {
00496     if (s && *s) {
00497         if ((*s)->filter_name != NULL) cpl_free((void *)((*s)->filter_name));
00498         cpl_free((void *)((*s)->read_clock));
00499         cpl_free((void *)((*s)->chip_id));
00500         cpl_free((void *)((*s)->version));
00501         cpl_free((void *)((*s)->instrument));
00502         cpl_free(*s); *s = NULL;
00503     }
00504     return;
00505 }
00506 

Generated on Wed Sep 10 07:31:52 2008 for FORS Pipeline Reference Manual by  doxygen 1.4.6