fors_setting.c

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

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