FORS Pipeline Reference Manual 4.9.20
|
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_9_20 $ 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