00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
00112 cpl_frameset *bias_frames = NULL;
00113 const fors_image_list *bias = NULL;
00114
00115
00116 fors_image *master_bias = NULL;
00117 cpl_propertylist *qc = cpl_propertylist_new();
00118
00119
00120 stack_method *sm = NULL;
00121
00122
00123 fors_setting *setting = NULL;
00124 const char *context = cpl_sprintf("fors.%s", fors_bias_name);
00125
00126
00127 sm = fors_stack_method_new(parameters, context);
00128 assure( !cpl_error_get_code(), return, "Could not get stacking method");
00129
00130
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
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
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
00144 master_bias = fors_stack_const(bias, sm);
00145 assure( !cpl_error_get_code(), return, "Bias stacking failed");
00146
00147
00148 write_qc(qc, setting,
00149 cpl_frameset_get_first(bias_frames),
00150 bias, master_bias, sm);
00151
00152
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
00211
00212
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
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
00277
00278
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 }