FORS Pipeline Reference Manual 4.9.9
|
00001 /* $Id: fors_bias_impl.c,v 1.27 2010/09/14 07:49:30 cizzo Exp $ 00002 * 00003 * This file is part of the FORS Data Reduction Pipeline 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.27 $ 00025 * $Name: fors-4_9_9 $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 #include <fors_bias_impl.h> 00033 00034 #include <fors_stack.h> 00035 #include <fors_qc.h> 00036 #include <fors_tools.h> 00037 #include <fors_dfs.h> 00038 #include <fors_utils.h> 00039 #include <moses.h> 00040 00041 #include <cpl.h> 00042 00043 #include <string.h> 00044 #include <math.h> 00045 00052 const char *const fors_bias_name = "fors_bias"; 00053 const char *const fors_bias_description_short = "Compute the master bias frame"; 00054 const char *const fors_bias_author = "Jonas M. Larsen, Carlo Izzo"; 00055 const char *const fors_bias_email = PACKAGE_BUGREPORT; 00056 const char *const fors_bias_description = 00057 "This recipe is used to combine input raw BIAS frames into a master bias\n" 00058 "frame. The overscan regions, if present, are removed from the result.\n\n" 00059 "Input files:\n\n" 00060 " DO category: Type: Explanation: Required:\n" 00061 " BIAS Raw Bias frame Y\n\n" 00062 "Output files:\n\n" 00063 " DO category: Data type: Explanation:\n" 00064 " MASTER_BIAS FITS image Master bias frame\n\n"; 00065 00066 00067 static void 00068 write_qc(cpl_propertylist *qc, 00069 const fors_setting *setting, 00070 const cpl_frame *first_bias, 00071 const fors_image_list *bias, 00072 const fors_image *master_bias, 00073 const stack_method *sm); 00078 void fors_bias_define_parameters(cpl_parameterlist *parameters) 00079 { 00080 const char *context = cpl_sprintf("fors.%s", fors_bias_name); 00081 00082 fors_stack_define_parameters(parameters, context, "minmax"); 00083 00084 cpl_free((void *)context); 00085 00086 return; 00087 } 00088 00089 #undef cleanup 00090 #define cleanup \ 00091 do { \ 00092 cpl_frameset_delete(bias_frames); \ 00093 fors_stack_method_delete(&sm); \ 00094 cpl_free((void *)context); \ 00095 fors_image_list_delete_const(&bias, fors_image_delete); \ 00096 fors_image_delete(&master_bias); \ 00097 fors_setting_delete(&setting); \ 00098 cpl_propertylist_delete(qc); \ 00099 } while (0) 00100 00109 void fors_bias(cpl_frameset *frames, const cpl_parameterlist *parameters) 00110 { 00111 /* Raw */ 00112 cpl_frameset *bias_frames = NULL; 00113 const fors_image_list *bias = NULL; 00114 00115 /* Product */ 00116 fors_image *master_bias = NULL; 00117 cpl_propertylist *qc = cpl_propertylist_new(); 00118 00119 /* Parameters */ 00120 stack_method *sm = NULL; 00121 00122 /* Other */ 00123 fors_setting *setting = NULL; 00124 const char *context = cpl_sprintf("fors.%s", fors_bias_name); 00125 00126 /* Get parameters */ 00127 sm = fors_stack_method_new(parameters, context); 00128 assure( !cpl_error_get_code(), return, "Could not get stacking method"); 00129 00130 /* Find raw */ 00131 bias_frames = fors_frameset_extract(frames, BIAS); 00132 assure( cpl_frameset_get_size(bias_frames) > 0, return, 00133 "No %s provided", BIAS); 00134 00135 /* Get instrument setting */ 00136 setting = fors_setting_new(cpl_frameset_get_first(bias_frames)); 00137 assure( !cpl_error_get_code(), return, "Could not get instrument setting" ); 00138 00139 /* Load bias */ 00140 bias = fors_image_load_list_const(bias_frames, NULL, setting, NULL); 00141 assure( !cpl_error_get_code(), return, "Could not load bias images"); 00142 00143 /* Stack */ 00144 master_bias = fors_stack_const(bias, sm); 00145 assure( !cpl_error_get_code(), return, "Bias stacking failed"); 00146 00147 /* QC */ 00148 write_qc(qc, setting, 00149 cpl_frameset_get_first(bias_frames), 00150 bias, master_bias, sm); 00151 00152 /* Save product */ 00153 fors_dfs_save_image(frames, master_bias, MASTER_BIAS, 00154 qc, parameters, fors_bias_name, 00155 cpl_frameset_get_first(bias_frames)); 00156 assure( !cpl_error_get_code(), return, "Saving %s failed", 00157 MASTER_BIAS); 00158 00159 cleanup; 00160 return; 00161 } 00162 00163 00164 #undef cleanup 00165 #define cleanup \ 00166 do { \ 00167 fors_image_delete(&image); \ 00168 } while (0) 00169 00170 00171 static void 00172 write_qc(cpl_propertylist *qc, 00173 const fors_setting *setting, 00174 const cpl_frame *first_bias, 00175 const fors_image_list *bias, 00176 const fors_image *master_bias, 00177 const stack_method *sm) 00178 { 00179 const fors_image *first_raw = fors_image_list_first_const(bias); 00180 const fors_image *second_raw = fors_image_list_next_const(bias); 00181 fors_image *image = NULL; 00182 00183 fors_qc_start_group(qc, fors_qc_dic_version, setting->instrument); 00184 00185 fors_qc_write_group_heading(first_bias, 00186 MASTER_BIAS, 00187 setting->instrument); 00188 assure( !cpl_error_get_code(), return, "Could not write %s QC parameters", 00189 MASTER_BIAS); 00190 00191 fors_qc_write_qc_double(qc, 00192 fors_image_get_median(first_raw, NULL), 00193 "QC.BIAS.LEVEL", 00194 "ADU", 00195 "Bias level", 00196 setting->instrument); 00197 double ron; 00198 double fpn; 00199 if (second_raw != NULL) { 00200 00201 image = fors_image_duplicate(first_raw); 00202 fors_image_subtract(image, second_raw); 00203 00204 ron = fors_image_get_stdev_robust(image, 50, NULL) / sqrt(2.0); 00205 00206 fpn = fors_fixed_pattern_noise_bias(first_raw, 00207 second_raw, 00208 ron); 00209 /* 00210 fpn = fors_fixed_pattern_noise(first_raw, 00211 1.0, 00212 ron); 00213 */ 00214 assure( !cpl_error_get_code(), return, 00215 "Could not compute fixed pattern noise" ); 00216 } 00217 else { 00218 cpl_msg_warning(cpl_func, 00219 "Only %d bias frame(s) provided, " 00220 "cannot compute readout noise", 00221 fors_image_list_size(bias)); 00222 ron = -1; 00223 fpn = -1; 00224 } 00225 00226 fors_qc_write_qc_double(qc, 00227 ron, 00228 "QC.RON", 00229 "ADU", 00230 "Readout noise", 00231 setting->instrument); 00232 00233 fors_qc_write_qc_double(qc, 00234 fpn, 00235 "QC.BIAS.FPN", 00236 "ADU", 00237 "Bias fixed pattern noise", 00238 setting->instrument); 00239 00240 double structure = fors_image_get_stdev_robust(first_raw, 50, NULL); 00241 if (structure*structure >= ron*ron + fpn*fpn) { 00242 structure = sqrt(structure*structure - ron*ron - fpn*fpn); 00243 } 00244 else { 00245 cpl_msg_warning(cpl_func, 00246 "Overall bias standard deviation (%f ADU) is less " 00247 "than combined readout and fixed pattern noise " 00248 "(%f ADU), setting structure to zero", 00249 structure , sqrt(ron*ron + fpn*fpn)); 00250 structure = 0; 00251 } 00252 00253 00254 fors_qc_write_qc_double(qc, 00255 structure, 00256 "QC.BIAS.STRUCT", 00257 "ADU", 00258 "Bias structure", 00259 setting->instrument); 00260 00261 /* Master bias QC */ 00262 00263 fors_qc_write_qc_double(qc, 00264 fors_image_get_median(master_bias, NULL), 00265 "QC.MBIAS.LEVEL", 00266 "ADU", 00267 "Master bias level", 00268 setting->instrument); 00269 00270 double ron_expect = -1; 00271 if (ron > 0) { 00272 00273 int N = fors_image_list_size(bias); 00274 00275 /* 00276 When median stacking and N >= 3, we need to 00277 take into account the fact that the median is more noisy than 00278 the mean. 00279 */ 00280 00281 if (sm->method == MEDIAN) { 00282 ron_expect = fors_utils_median_corr(N) * ron / sqrt(N); 00283 } 00284 else { 00285 ron_expect = ron / sqrt(N); 00286 } 00287 } 00288 else cpl_msg_warning(cpl_func, 00289 "Cannot compute expected master bias readout noise"); 00290 00291 fors_qc_write_qc_double(qc, 00292 ron_expect, 00293 "QC.MBIAS.RONEXP", 00294 "ADU", 00295 "Expected master bias readout noise", 00296 setting->instrument); 00297 00298 double mbias_noise = -1; 00299 if (ron_expect > 0) { 00300 mbias_noise = 00301 fors_image_get_stdev_robust(master_bias, 3*ron_expect, NULL); 00302 } 00303 else { 00304 mbias_noise = -1; 00305 } 00306 00307 fors_qc_write_qc_double(qc, 00308 mbias_noise, 00309 "QC.MBIAS.NOISE", 00310 "ADU", 00311 "Master bias readout noise", 00312 setting->instrument); 00313 00314 fors_qc_write_qc_double(qc, 00315 mbias_noise / ron_expect, 00316 "QC.MBIAS.NRATIO", 00317 NULL, 00318 "Master bias observed/expected noise", 00319 setting->instrument); 00320 00321 double mbias_struct = fors_image_get_stdev(master_bias, NULL); 00322 00323 if (mbias_struct * mbias_struct > mbias_noise * mbias_noise) { 00324 00325 cpl_msg_debug(cpl_func, "Overall standard deviation is %f ADU", 00326 mbias_struct); 00327 00328 mbias_struct = sqrt(mbias_struct * mbias_struct - 00329 mbias_noise * mbias_noise); 00330 } 00331 else { 00332 cpl_msg_warning(cpl_func, 00333 "Master bias overall standard deviation (%f ADU) is " 00334 "greater than master bias noise (%f ADU), " 00335 "cannot compute master bias structure", 00336 mbias_struct, mbias_noise); 00337 mbias_struct = -1; 00338 } 00339 00340 fors_qc_write_qc_double(qc, 00341 mbias_struct, 00342 "QC.MBIAS.STRUCT", 00343 "ADU", 00344 "Structure of master bias", 00345 setting->instrument); 00346 00347 fors_qc_end_group(); 00348 00349 cleanup; 00350 return; 00351 }