FORS Pipeline Reference Manual 4.9.20
|
00001 /* $Id: fors_bias_impl.c,v 1.29 2012/11/06 09:42:15 cgarcia 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: cgarcia $ 00023 * $Date: 2012/11/06 09:42:15 $ 00024 * $Revision: 1.29 $ 00025 * $Name: fors-4_9_20 $ 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_header.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_header_write_string(qc, 00184 "QC.DID", 00185 "2.0", 00186 "QC1 dictionary"); 00187 00188 00189 assure( !cpl_error_get_code(), return, "Could not write %s QC parameters", 00190 MASTER_BIAS); 00191 00192 fors_header_write_double(qc, 00193 fors_image_get_median(first_raw, NULL), 00194 "QC.BIAS.LEVEL", 00195 "ADU", 00196 "Bias level"); 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_header_write_double(qc, 00227 ron, 00228 "QC.RON", 00229 "ADU", 00230 "Readout noise"); 00231 00232 fors_header_write_double(qc, 00233 fpn, 00234 "QC.BIAS.FPN", 00235 "ADU", 00236 "Bias fixed pattern noise"); 00237 00238 double structure = fors_image_get_stdev_robust(first_raw, 50, NULL); 00239 if (structure*structure >= ron*ron + fpn*fpn) { 00240 structure = sqrt(structure*structure - ron*ron - fpn*fpn); 00241 } 00242 else { 00243 cpl_msg_warning(cpl_func, 00244 "Overall bias standard deviation (%f ADU) is less " 00245 "than combined readout and fixed pattern noise " 00246 "(%f ADU), setting structure to zero", 00247 structure , sqrt(ron*ron + fpn*fpn)); 00248 structure = 0; 00249 } 00250 00251 00252 fors_header_write_double(qc, 00253 structure, 00254 "QC.BIAS.STRUCT", 00255 "ADU", 00256 "Bias structure"); 00257 00258 /* Master bias QC */ 00259 00260 fors_header_write_double(qc, 00261 fors_image_get_median(master_bias, NULL), 00262 "QC.MBIAS.LEVEL", 00263 "ADU", 00264 "Master bias level"); 00265 00266 double ron_expect = -1; 00267 if (ron > 0) { 00268 00269 int N = fors_image_list_size(bias); 00270 00271 /* 00272 When median stacking and N >= 3, we need to 00273 take into account the fact that the median is more noisy than 00274 the mean. 00275 */ 00276 00277 if (sm->method == MEDIAN) { 00278 ron_expect = fors_utils_median_corr(N) * ron / sqrt(N); 00279 } 00280 else { 00281 ron_expect = ron / sqrt(N); 00282 } 00283 } 00284 else cpl_msg_warning(cpl_func, 00285 "Cannot compute expected master bias readout noise"); 00286 00287 fors_header_write_double(qc, 00288 ron_expect, 00289 "QC.MBIAS.RONEXP", 00290 "ADU", 00291 "Expected master bias readout noise"); 00292 00293 double mbias_noise = -1; 00294 if (ron_expect > 0) { 00295 mbias_noise = 00296 fors_image_get_stdev_robust(master_bias, 3*ron_expect, NULL); 00297 } 00298 else { 00299 mbias_noise = -1; 00300 } 00301 00302 fors_header_write_double(qc, 00303 mbias_noise, 00304 "QC.MBIAS.NOISE", 00305 "ADU", 00306 "Master bias readout noise"); 00307 00308 fors_header_write_double(qc, 00309 mbias_noise / ron_expect, 00310 "QC.MBIAS.NRATIO", 00311 NULL, 00312 "Master bias observed/expected noise"); 00313 00314 double mbias_struct = fors_image_get_stdev(master_bias, NULL); 00315 00316 if (mbias_struct * mbias_struct > mbias_noise * mbias_noise) { 00317 00318 cpl_msg_debug(cpl_func, "Overall standard deviation is %f ADU", 00319 mbias_struct); 00320 00321 mbias_struct = sqrt(mbias_struct * mbias_struct - 00322 mbias_noise * mbias_noise); 00323 } 00324 else { 00325 cpl_msg_warning(cpl_func, 00326 "Master bias overall standard deviation (%f ADU) is " 00327 "greater than master bias noise (%f ADU), " 00328 "cannot compute master bias structure", 00329 mbias_struct, mbias_noise); 00330 mbias_struct = -1; 00331 } 00332 00333 fors_header_write_double(qc, 00334 mbias_struct, 00335 "QC.MBIAS.STRUCT", 00336 "ADU", 00337 "Structure of master bias"); 00338 00339 00340 cleanup; 00341 return; 00342 }