FORS Pipeline Reference Manual 4.9.20
fors_bias_impl.c
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 }