fors_setting.c

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

Generated on Fri Mar 4 09:46:01 2011 for FORS Pipeline Reference Manual by  doxygen 1.4.7