GIRAFFE Pipeline Reference Manual

gimasterbias.c

00001 /* $Id: gimasterbias.c,v 1.38 2008/04/24 14:06:26 rpalsa Exp $
00002  *
00003  * This file is part of the GIRAFFE Pipeline
00004  * Copyright (C) 2002-2006 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: rpalsa $
00023  * $Date: 2008/04/24 14:06:26 $
00024  * $Revision: 1.38 $
00025  * $Name: giraffe-2_8_1 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #  include <config.h>
00030 #endif
00031 
00032 #include <math.h>
00033 
00034 #include <cxmessages.h>
00035 #include <cxmemory.h>
00036 
00037 #include <cpl_recipe.h>
00038 #include <cpl_plugininfo.h>
00039 #include <cpl_parameterlist.h>
00040 #include <cpl_frameset.h>
00041 #include <cpl_propertylist.h>
00042 #include <cpl_vector.h>
00043 #include <cpl_msg.h>
00044 
00045 #include "gialias.h"
00046 #include "gierror.h"
00047 #include "giarray.h"
00048 #include "giframe.h"
00049 #include "giimage.h"
00050 #include "giwindow.h"
00051 #include "gifibers.h"
00052 #include "gibias.h"
00053 #include "gimath.h"
00054 #include "gistacking.h"
00055 #include "giqclog.h"
00056 #include "giutils.h"
00057 
00058 
00059 #define GIMASTERBIAS_BIAS_EXTENSION_IMG 0
00060 #define GIMASTERBIAS_BIAS_EXTENSION_PL 0
00061 #define GIMASTERBIAS_BAD_PIXEL_EXTENSION 0
00062 
00063 
00064 struct GiMasterbiasConfig {
00065 
00066     cxbool removeoverscan;
00067     cxbool correctbadpixels;
00068 
00069     struct {
00070         cxbool create;
00071         cxdouble factor;
00072         cxdouble fraction;
00073     } bpm;
00074     cxbool crebadpixmap;
00075 };
00076 
00077 typedef struct GiMasterbiasConfig GiMasterbiasConfig;
00078 
00079 static cxint gimasterbias(cpl_parameterlist*, cpl_frameset*);
00080 static cxint giqcmasterbias(cpl_frameset*);
00081 
00082 
00083 /*
00084  * Maximum fraction of pixels which may be bad.
00085  */
00086 
00087 static cxdouble max_bpx_fraction = 0.15;
00088 
00089 
00090 /*
00091  * Create the recipe instance, i.e. setup the parameter list for this
00092  * recipe and make it availble to the application using the interface.
00093  */
00094 
00095 static cxint
00096 gimasterbias_create(cpl_plugin* plugin)
00097 {
00098 
00099     cpl_recipe* recipe = (cpl_recipe*)plugin;
00100 
00101     cpl_parameter* p;
00102 
00103 
00104     giraffe_error_init();
00105 
00106 
00107     /*
00108      * We have to provide the option we accept to the application. We
00109      * need to setup our parameter list and hook it into the recipe
00110      * interface.
00111      */
00112 
00113     recipe->parameters = cpl_parameterlist_new();
00114     cx_assert(recipe->parameters != NULL);
00115 
00116     /*
00117      * Fill the parameter list.
00118      */
00119 
00120     /* Stacking */
00121 
00122     giraffe_stacking_config_add(recipe->parameters);
00123 
00124     /* Masterbias */
00125 
00126     p = cpl_parameter_new_value("giraffe.masterbias.overscan.remove",
00127                                 CPL_TYPE_BOOL,
00128                                 "Remove pre- and over-scan regions from "
00129                                 "the created master bias image.",
00130                                 "giraffe.masterbias.overscan",
00131                                 FALSE);
00132     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "mbias-oscremove");
00133     cpl_parameterlist_append(recipe->parameters, p);
00134 
00135     p = cpl_parameter_new_value("giraffe.masterbias.badpixel.clean",
00136                                 CPL_TYPE_BOOL,
00137                                 "Correct master bias image for bad pixels",
00138                                 "giraffe.masterbias.badpixel",
00139                                 FALSE);
00140     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "mbias-bpxclean");
00141     cpl_parameterlist_append(recipe->parameters, p);
00142 
00143     p = cpl_parameter_new_value("giraffe.masterbias.bpm.create",
00144                                 CPL_TYPE_BOOL,
00145                                 "Create bad pixel map using a simple "
00146                                 "thresholding algorithm. (temporary!)",
00147                                 "giraffe.masterbias.bpm",
00148                                 TRUE);
00149     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "bpm-create");
00150     cpl_parameterlist_append(recipe->parameters, p);
00151 
00152     p = cpl_parameter_new_value("giraffe.masterbias.bpm.factor",
00153                                 CPL_TYPE_DOUBLE,
00154                                 "Readout noise multiplier defining the "
00155                                 "valid range of pixel values for searching "
00156                                 "bad pixels.",
00157                                 "giraffe.masterbias.bpm",
00158                                 5.0);
00159     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "bpm-factor");
00160     cpl_parameterlist_append(recipe->parameters, p);
00161 
00162     p = cpl_parameter_new_value("giraffe.masterbias.bpm.fraction",
00163                                 CPL_TYPE_DOUBLE,
00164                                 "Maximum fraction of pixels which may be "
00165                                 "flagged as 'bad. If more pixels are "
00166                                 "found to be 'bad a warning is issued.",
00167                                 "giraffe.masterbias.bpm",
00168                                 max_bpx_fraction);
00169     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "bpm-frac");
00170     cpl_parameterlist_append(recipe->parameters, p);
00171 
00172     return 0;
00173 
00174 }
00175 
00176 /*
00177  * Execute the plugin instance given by the interface.
00178  */
00179 
00180 static cxint
00181 gimasterbias_exec(cpl_plugin* plugin)
00182 {
00183 
00184     cpl_recipe* recipe = (cpl_recipe*)plugin;
00185 
00186     cxint status = 0;
00187 
00188 
00189     if (recipe->parameters == NULL || recipe->frames == NULL) {
00190         return 1;
00191     }
00192 
00193     status = gimasterbias(recipe->parameters, recipe->frames);
00194 
00195     if (status != 0) {
00196         return 1;
00197     }
00198 
00199     status = giqcmasterbias(recipe->frames);
00200 
00201     if (status != 0) {
00202         return 1;
00203     }
00204 
00205     return 0;
00206 
00207 }
00208 
00209 
00210 static cxint
00211 gimasterbias_destroy(cpl_plugin* plugin)
00212 {
00213 
00214     cpl_recipe* recipe = (cpl_recipe*)plugin;
00215 
00216 
00217     /*
00218      * We just destroy what was created during the plugin initialization
00219      * phase, i.e. the parameter list. The frame set is managed by the
00220      * application which called us, so we must not touch it,
00221      */
00222 
00223     cpl_parameterlist_delete(recipe->parameters);
00224 
00225     giraffe_error_clear();
00226 
00227     return 0;
00228 
00229 }
00230 
00231 /*
00232  * Remove bad pixels from a Image using a bad pixel map
00233  */
00234 
00235 static cxint
00236 gimasterbias_remove_badpixels(GiImage* img, GiImage* img_badpixels)
00237 {
00238 
00239     const cxchar* const fctid = "gimasterbias_remove_badpixels";
00240 
00241 
00242     cxbool found_first;
00243 
00244     register cxint j;
00245     register cxint k;
00246     register cxint nr_pairs;
00247     register cxint d;
00248     register cxint sign;
00249 
00250     cxint ncol_bp;
00251     cxint nrow_bp;
00252     cxint badx;
00253     cxint bady;
00254     cxint cx;
00255     cxint cy;
00256     cxint search_horizon = 100;
00257 
00258     cxint* pi_bp  = NULL;
00259 
00260     cxint sx[] = { 0, 1, 1, 1 };
00261     cxint sy[] = { 1,-1, 0, 1 };
00262 
00263     cxlong npix_bp;
00264     cxlong nr_bad_pixels = 0L;
00265     cxlong n;
00266 
00267     cxdouble sumd;
00268     cxdouble save = 0.;
00269 
00270     cxdouble* pd_img = NULL;
00271 
00272     cxdouble estimate[4];
00273 
00274 
00275 
00276     if (!img) {
00277         cpl_msg_error(fctid, "NULL Image as input, aborting..." );
00278         return -1;
00279     }
00280 
00281     if (!img_badpixels) {
00282         cpl_msg_error(fctid, "NULL Bad Pixel Image as input, aborting..." );
00283         return -1;
00284     }
00285 
00286     ncol_bp = cpl_image_get_size_x(giraffe_image_get(img_badpixels));
00287     nrow_bp = cpl_image_get_size_y(giraffe_image_get(img_badpixels));
00288     npix_bp = ncol_bp * nrow_bp;
00289     pi_bp   = cpl_image_get_data_int(giraffe_image_get(img_badpixels));
00290 
00291     pd_img  = cpl_image_get_data_double(giraffe_image_get(img));
00292 
00293     for (n=0; n<npix_bp; n++) {
00294         if (pi_bp[n]!=0)
00295             nr_bad_pixels++;
00296     }
00297 
00298     if (((cxdouble)nr_bad_pixels / (cxdouble)npix_bp) >= max_bpx_fraction) {
00299         cpl_msg_error(fctid, "Too many bad pixels, aborting..." );
00300         return -1;
00301     }
00302 
00303     /************************************************************************
00304                                      PROCESSING
00305     ************************************************************************/
00306 
00307     for (badx=0; badx<ncol_bp; badx++) {
00308         for (bady=0; bady<nrow_bp; bady++) {
00309             if (pi_bp[badx + bady * ncol_bp]==1) {
00310                 nr_pairs = 0;
00311                 for (j=0; j<4; j++) {
00312                     estimate[nr_pairs] = 0.0;
00313                     sumd = 0.0;
00314                     found_first = FALSE;
00315                     for (k=0; k<2; k++) {
00316                         sign = 2 * k - 1;
00317                         d = 0;
00318                         cx = badx;
00319                         cy = bady;
00320                         do {
00321                             cx += sign * sx[j];
00322                             cy += sign * sy[j];
00323                             if (cx<0 || cx>=ncol_bp || cy<0 || cy>=nrow_bp)
00324                                 break;
00325                             d++;
00326                         } while (pi_bp[cx+cy*ncol_bp] && (d<search_horizon));
00327 
00328                         if (cx>=0 && cx<ncol_bp && cy>=0 && cy<nrow_bp &&
00329                             (d<search_horizon)                             )
00330                         {
00331                             save = pd_img[cx+cy*ncol_bp];
00332                             estimate[nr_pairs] += save / d;
00333                             sumd += 1.0 / (cxdouble) d;
00334                             if (k) {
00335                                 estimate[nr_pairs] /= sumd;
00336                                 nr_pairs++;
00337                             } else {
00338                                 found_first = TRUE;
00339                             }
00340                         } else {
00341                             if (k) {
00342                                 if (found_first) {
00343                                     estimate[nr_pairs] = save;
00344                                     nr_pairs++;
00345                                     if (nr_pairs>2) {
00346 
00347                                         cpl_vector* _estimate =
00348                                             cpl_vector_wrap(nr_pairs,
00349                                                             estimate);
00350 
00351                                         pd_img[badx+bady*ncol_bp] =
00352                                             cpl_vector_get_median(_estimate);
00353 
00354                                         cpl_vector_unwrap(_estimate);
00355                                         _estimate = NULL;
00356 
00357                                     } else if (nr_pairs==2) {
00358                                         pd_img[badx+bady*ncol_bp] =
00359                                             (estimate[0]+estimate[1]) * 0.5;
00360                                     } else if (nr_pairs==1) {
00361                                         pd_img[badx+bady*ncol_bp] =
00362                                             estimate[0];
00363                                     } else {
00364                                         cpl_msg_warning(
00365                                             fctid,
00366                                             "Can't correct badpixel [%d,%d]",
00367                                             badx,
00368                                             bady
00369                                         );
00370                                     }
00371                                 }
00372                             }
00373                         }
00374                     }
00375 
00376                 }
00377             }
00378         }
00379     }
00380 
00381     return 0;
00382 
00383 }
00384 
00385 
00386 /*
00387  * The actual recipe starts here.
00388  */
00389 
00390 static cxint
00391 gimasterbias(cpl_parameterlist* config, cpl_frameset* set)
00392 {
00393 
00394     const cxchar* const fctid = "gimasterbias";
00395 
00396 
00397     cxint raw_bias_count  = 0;
00398     cxint bad_pixel_count = 0;
00399     cxint e_code          = 0;
00400 
00401     cxlong i = 0;
00402     cxlong j = 0;
00403 
00404     cpl_propertylist* properties = NULL;
00405 
00406     cpl_frame* curr_frame = NULL;
00407     cpl_frame* bad_pixel_frame = NULL;
00408     cpl_frame* product_frame = NULL;
00409 
00410     cpl_parameter* p = NULL;
00411 
00412     GiImage** raw_bias_list = NULL;
00413     GiImage* bad_pixels = NULL;
00414     GiImage* master_bias = NULL;
00415 
00416     GiMasterbiasConfig mbias_config;
00417 
00418     GiStackingConfig* stack_config = NULL;
00419 
00420     GiRecipeInfo info = {(cxchar*)fctid, 1, NULL};
00421 
00422     GiGroupInfo groups[] = {
00423         {GIFRAME_BIAS, CPL_FRAME_GROUP_RAW},
00424         {GIFRAME_BADPIXEL_MAP, CPL_FRAME_GROUP_CALIB},
00425         {NULL, CPL_FRAME_GROUP_NONE}
00426     };
00427 
00428 
00429     /************************************************************************
00430                                     PREPROCESSING
00431     ************************************************************************/
00432 
00433     p = cpl_parameterlist_find(config, "giraffe.masterbias.overscan.remove");
00434     mbias_config.removeoverscan = cpl_parameter_get_bool(p);
00435 
00436     p = cpl_parameterlist_find(config, "giraffe.masterbias.badpixel.clean");
00437     mbias_config.correctbadpixels = cpl_parameter_get_bool(p);
00438 
00439     p = cpl_parameterlist_find(config, "giraffe.masterbias.bpm.create");
00440     mbias_config.bpm.create = cpl_parameter_get_bool(p);
00441 
00442     p = cpl_parameterlist_find(config, "giraffe.masterbias.bpm.factor");
00443     mbias_config.bpm.factor = cpl_parameter_get_double(p);
00444 
00445     p = cpl_parameterlist_find(config, "giraffe.masterbias.bpm.fraction");
00446     mbias_config.bpm.fraction = cpl_parameter_get_double(p);
00447 
00448 
00449     e_code = giraffe_frameset_set_groups(set, groups);
00450 
00451     if (e_code != 0) {
00452         cpl_msg_error(fctid, "Setting frame group information failed!");
00453         return 1;
00454     }
00455 
00456 
00457     /************************************************************************
00458                                      PROCESSING
00459     ************************************************************************/
00460 
00461     stack_config = giraffe_stacking_config_create(config);
00462 
00463     /* check number of images */
00464     raw_bias_count = cpl_frameset_count_tags(set, GIFRAME_BIAS);
00465 
00466     if (raw_bias_count < stack_config->min_nr_frames) {
00467         cpl_msg_error(fctid, "Not enough raw bias Images [%d, need %d], "
00468                       "aborting...", raw_bias_count,
00469                       stack_config->min_nr_frames);
00470 
00471         giraffe_stacking_config_destroy(stack_config);
00472         stack_config = NULL;
00473 
00474         return -1;
00475     }
00476 
00477     bad_pixel_count = cpl_frameset_count_tags(set, GIFRAME_BADPIXEL_MAP);
00478 
00479     if (mbias_config.correctbadpixels == TRUE) {
00480         if (bad_pixel_count != 1) {
00481             cpl_msg_error(fctid, "Invalid number of bad pixel Images "
00482                           "[%d instead of 1], aborting...", bad_pixel_count);
00483 
00484             giraffe_stacking_config_destroy(stack_config);
00485             stack_config = NULL;
00486 
00487             return -1;
00488         }
00489     }
00490 
00491     cpl_msg_info(fctid, "Creating master bias from %d bias frames ...",
00492                  raw_bias_count);
00493 
00494 
00495     /* load images */
00496 
00497     raw_bias_list = (GiImage**)cx_calloc(raw_bias_count + 1, sizeof(GiImage*));
00498 
00499     raw_bias_list[raw_bias_count] = NULL;
00500 
00501     curr_frame = cpl_frameset_find(set, GIFRAME_BIAS);
00502 
00503     for (i = 0; i < raw_bias_count; i++) {
00504 
00505         raw_bias_list[i] = giraffe_image_new(CPL_TYPE_DOUBLE);
00506 
00507         e_code = giraffe_image_load(raw_bias_list[i],
00508                                     cpl_frame_get_filename(curr_frame),
00509                                     GIMASTERBIAS_BIAS_EXTENSION_IMG);
00510 
00511         if (e_code != 0) {
00512 
00513             cpl_msg_error(fctid, "Could not load raw Bias Image [%s], "
00514                           "aborting...", cpl_frame_get_filename(curr_frame));
00515 
00516             for (j = 0; j < i; j++) {
00517                 if (raw_bias_list[j] != NULL) {
00518                     giraffe_image_delete(raw_bias_list[j]);
00519                 }
00520             }
00521 
00522             cx_free(raw_bias_list);
00523 
00524             giraffe_stacking_config_destroy(stack_config);
00525             stack_config = NULL;
00526 
00527             return -1;
00528 
00529         }
00530         else {
00531             curr_frame = cpl_frameset_find(set, NULL);
00532         }
00533     }
00534 
00535     if (mbias_config.correctbadpixels == TRUE) {
00536 
00537         /* load bad pixel image */
00538 
00539         bad_pixel_frame = cpl_frameset_find(set, GIFRAME_BADPIXEL_MAP);
00540 
00541         cpl_msg_info(fctid, "Bad Pixel Frame is : %s.",
00542                      cpl_frame_get_filename(bad_pixel_frame));
00543 
00544         bad_pixels = giraffe_image_new(CPL_TYPE_INT);
00545 
00546         e_code = giraffe_image_load(bad_pixels,
00547                                     cpl_frame_get_filename(bad_pixel_frame),
00548                                     GIMASTERBIAS_BAD_PIXEL_EXTENSION);
00549 
00550         if (e_code !=0 ) {
00551             cpl_msg_error(fctid, "Could not load Bad Pixel Image [%s], "
00552                           "aborting...",
00553                           cpl_frame_get_filename(bad_pixel_frame));
00554 
00555             for (j = 0; j < raw_bias_count; j++) {
00556                 if (raw_bias_list[j] != NULL) {
00557                     giraffe_image_delete(raw_bias_list[j]);
00558                 }
00559             }
00560 
00561             cx_free(raw_bias_list);
00562 
00563             giraffe_stacking_config_destroy(stack_config);
00564             stack_config = NULL;
00565 
00566             return -1;
00567         }
00568     }
00569 
00570 
00571     /*
00572      *  Stack the bias frames...
00573      */
00574 
00575     master_bias = giraffe_stacking_stack_images(raw_bias_list, stack_config);
00576 
00577     if (master_bias == NULL) {
00578         cpl_msg_error(fctid,"Stacking of raw bias frames failed! "
00579             "No master bias was created, aborting...");
00580 
00581         for (j = 0; j < raw_bias_count; j++) {
00582             if (raw_bias_list[j] != NULL) {
00583                 giraffe_image_delete(raw_bias_list[j]);
00584             }
00585         }
00586 
00587         cx_free(raw_bias_list);
00588 
00589         if (bad_pixels != NULL) {
00590             giraffe_image_delete(bad_pixels);
00591         }
00592 
00593         giraffe_stacking_config_destroy(stack_config);
00594         stack_config = NULL;
00595 
00596         return -1;
00597 
00598     }
00599 
00600     properties = giraffe_image_get_properties(raw_bias_list[0]);
00601     e_code = giraffe_image_set_properties(master_bias, properties);
00602 
00603     giraffe_stacking_config_destroy(stack_config);
00604     stack_config = NULL;
00605 
00606 
00607     /*
00608      *  Bad pixel cleaning on result, if necessary...
00609      */
00610 
00611     if (mbias_config.correctbadpixels == TRUE) {
00612 
00613         cpl_msg_info(fctid, "Cleaning bad pixels on created "
00614                      "master bias image.");
00615 
00616         if (gimasterbias_remove_badpixels(master_bias, bad_pixels) != 0) {
00617 
00618             cpl_msg_error(fctid, "Bad pixel cleaning failed, aborting...");
00619 
00620             for (j = 0; j < raw_bias_count; j++) {
00621                 if (raw_bias_list[j] != NULL) {
00622                     giraffe_image_delete(raw_bias_list[j]);
00623                 }
00624             }
00625 
00626             cx_free(raw_bias_list);
00627 
00628             if (bad_pixels != NULL) {
00629                 giraffe_image_delete(bad_pixels);
00630             }
00631 
00632             if (master_bias != NULL) {
00633                 giraffe_image_delete(master_bias);
00634             }
00635 
00636             return -1;
00637 
00638         }
00639     }
00640 
00641     /*
00642      *  Remove overscans, if necessary...
00643      */
00644 
00645     if (mbias_config.removeoverscan == TRUE) {
00646 
00647         cpl_msg_info(fctid, "Removing overscan areas from "
00648                      "master bias image");
00649 
00650         if (giraffe_trim_raw_areas(master_bias) != 0) {
00651 
00652             cpl_msg_error(fctid, "Removing overscan areas from master "
00653                           "bias failed, aborting...");
00654 
00655             for (j = 0; j < raw_bias_count; j++) {
00656                 if (raw_bias_list[j] != NULL) {
00657                     giraffe_image_delete(raw_bias_list[j]);
00658                 }
00659             }
00660 
00661             cx_free(raw_bias_list);
00662 
00663             if (bad_pixels != NULL) {
00664                 giraffe_image_delete(bad_pixels);
00665             }
00666 
00667             if (master_bias != NULL) {
00668                 giraffe_image_delete(master_bias);
00669             }
00670 
00671             return -1;
00672         }
00673 
00674     }
00675 
00676 
00677     /*
00678      * Update master bias properties, save the master bias frame
00679      * and register it as product.
00680      */
00681 
00682     cpl_msg_info(fctid, "Writing master bias image ...");
00683 
00684     properties = giraffe_image_get_properties(master_bias);
00685     cx_assert(properties != NULL);
00686 
00687     cpl_propertylist_update_double(properties, GIALIAS_CRPIX1, 1.);
00688 
00689     cpl_propertylist_update_double(properties, GIALIAS_EXPTTOT, 0.0);
00690     cpl_propertylist_update_int(properties, GIALIAS_DATANCOM, raw_bias_count);
00691     cpl_propertylist_update_double(properties, GIALIAS_BZERO, 0.0);
00692 
00693     cpl_propertylist_update_double(properties, GIALIAS_BIASVALUE,
00694                                    cpl_image_get_mean(giraffe_image_get(master_bias)));
00695     cpl_propertylist_update_double(properties, GIALIAS_BIASSIGMA,
00696                                    cpl_image_get_stdev(giraffe_image_get(master_bias)));
00697 
00698     cpl_propertylist_erase(properties, GIALIAS_EXPTIME);
00699     cpl_propertylist_erase(properties, GIALIAS_TPLEXPNO);
00700 
00701 
00702     /*
00703      *  Clean up bias list and bad pixels...
00704      */
00705 
00706     for (j = 0; j < raw_bias_count; j++) {
00707         if (raw_bias_list[j] != NULL) {
00708             giraffe_image_delete(raw_bias_list[j]);
00709         }
00710     }
00711 
00712     cx_free(raw_bias_list);
00713     raw_bias_list = NULL;
00714 
00715     if (bad_pixels != NULL) {
00716         giraffe_image_delete(bad_pixels);
00717         bad_pixels = NULL;
00718     }
00719 
00720 
00721     giraffe_image_add_info(master_bias, &info, set);
00722 
00723     product_frame = giraffe_frame_create_image(master_bias,
00724                                                GIFRAME_BIAS_MASTER,
00725                                                CPL_FRAME_LEVEL_FINAL,
00726                                                TRUE, TRUE);
00727 
00728     if (product_frame == NULL) {
00729 
00730         cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
00731 
00732         if (master_bias != NULL) {
00733             giraffe_image_delete(master_bias);
00734         }
00735 
00736         return -1;
00737 
00738     }
00739 
00740     cpl_frameset_insert(set, product_frame);
00741 
00742 
00743     /*
00744      *  Create bad pixel map based on masterbias
00745      *  Very simple algorithm, should be refined later...
00746      */
00747 
00748     if ((mbias_config.bpm.create == TRUE) && (master_bias != NULL)
00749         && (bad_pixel_count == 0)) {
00750 
00751         const cpl_image* _master_bias = giraffe_image_get(master_bias);
00752 
00753         const cxdouble* pd_mbias =
00754                 cpl_image_get_data_double_const(_master_bias);
00755 
00756 
00757         cxint e_code2 = 0;
00758         cxint row_min = 0;
00759         cxint row_max = 0;
00760         cxint ncol = cpl_image_get_size_x(_master_bias);
00761         cxint nrow = cpl_image_get_size_y(_master_bias);
00762         cxint* pi_bpm = NULL;
00763 
00764         cxlong npix = ncol * nrow;
00765         cxlong nbpx = 0L;
00766         cxlong nbpx_max = (cxlong)(mbias_config.bpm.fraction * npix + 0.5);
00767 
00768         cxdouble median = 0.;
00769         cxdouble median_max = CX_MINDOUBLE;
00770         cxdouble median_min = CX_MAXDOUBLE;
00771         cxdouble ron = 0.;
00772         cxdouble tlow = 0.;
00773         cxdouble thigh = 0.;
00774 
00775         GiImage* bpixel = giraffe_image_create(CPL_TYPE_INT, ncol, nrow);
00776 
00777 
00778         cpl_msg_info(fctid, "Creating bad pixel map from master bias "
00779                      "frame ...");
00780 
00781 
00782         /*
00783          * Copy master bias properties to the bad pixel map and
00784          * re-assign the properties' handle.
00785          */
00786 
00787         e_code2 = giraffe_image_set_properties(bpixel, properties);
00788         properties = giraffe_image_get_properties(bpixel);
00789 
00790 
00791         /*
00792          * Get bad pixel map pixel buffer
00793          */
00794 
00795         pi_bpm   = cpl_image_get_data_int(giraffe_image_get(bpixel));
00796 
00797 
00798         /*
00799          * Setup detection thresholds
00800          */
00801 
00802         if ((cpl_propertylist_has(properties, GIALIAS_PRSCX) == TRUE) ||
00803             (cpl_propertylist_has(properties, GIALIAS_OVSCX) == TRUE)) {
00804 
00805             cxint nvalues = 0;
00806             
00807             if (cpl_propertylist_has(properties, GIALIAS_PRSCX) == TRUE) {
00808     
00809                 cxint xsz = cpl_propertylist_get_int(properties,
00810                         GIALIAS_PRSCX);
00811                 
00812                 cxdouble sdev = 0.;
00813                 
00814     
00815                 for (i = 0; i < nrow; ++i) {
00816                     
00817                     register cxint stride = i * ncol;
00818                     
00819                     cxdouble scx_mean = giraffe_array_mean(pd_mbias + stride,
00820                             xsz);
00821                     
00822                     for (j = 0; j < xsz; ++j) {
00823                         sdev += (pd_mbias[stride + j] - scx_mean) *
00824                                 (pd_mbias[stride + j] - scx_mean);
00825                     }
00826                     
00827                 }
00828                 
00829                 ron = sqrt(sdev / (cxdouble)(nrow * xsz - 1));
00830                 ++nvalues;
00831                 
00832             }
00833     
00834             if (cpl_propertylist_has(properties, GIALIAS_OVSCX) == TRUE) {
00835     
00836                 cxint xsz = cpl_propertylist_get_int(properties,
00837                         GIALIAS_OVSCX);
00838     
00839                 cxdouble sdev = 0.;
00840                 
00841     
00842                 for (i = 0; i < nrow; ++i) {
00843                     
00844                     register cxint stride = (i + 1) * ncol - xsz;
00845                     
00846                     cxdouble scx_mean = giraffe_array_mean(pd_mbias + stride,
00847                             xsz);
00848                     
00849                     for (j = 0; j < xsz; ++j) {
00850                         sdev += (pd_mbias[stride + j] - scx_mean) *
00851                                 (pd_mbias[stride + j] - scx_mean);
00852                     }
00853                     
00854                 }
00855                 
00856                 ron += sqrt(sdev / (cxdouble)(nrow * xsz - 1));
00857                 ++nvalues;
00858                 
00859             }
00860 
00861             ron /= (cxdouble)nvalues;
00862             
00863         }
00864         else {
00865 
00866             if (cpl_propertylist_has(properties, GIALIAS_RON)) {
00867 
00868                 ron = cpl_propertylist_get_double(properties, GIALIAS_RON);
00869 
00870                 if (cpl_propertylist_has(properties, GIALIAS_CONAD)) {
00871     
00872                     cxdouble conad = cpl_propertylist_get_double(properties,
00873                                                           GIALIAS_CONAD);
00874     
00875                     if (conad <= 0.) {
00876     
00877                         cpl_msg_error(fctid, "Invalid conversion factor "
00878                                       "property (%s): %.2g!", GIALIAS_CONAD,
00879                                       conad);
00880     
00881                         giraffe_image_delete(bpixel);
00882                         bpixel = NULL;
00883     
00884                         giraffe_image_delete(master_bias);
00885                         master_bias = NULL;
00886     
00887                         return -1;
00888                     }
00889                     else {
00890                         ron /= conad;
00891                     }
00892                 }
00893                 else {
00894                     cpl_msg_error(fctid, "Missing conversion factor property "
00895                             "(%s)!", GIALIAS_CONAD);
00896     
00897                     giraffe_image_delete(bpixel);
00898                     bpixel = NULL;
00899     
00900                     giraffe_image_delete(master_bias);
00901                     master_bias = NULL;
00902     
00903                     return -1;
00904                 }
00905             }
00906             else {
00907                 ron = cpl_image_get_stdev(giraffe_image_get(master_bias));
00908             }
00909             
00910         }
00911 
00912         cpl_msg_info(fctid, "Using local median +/- %.4f [ADU] as "
00913                 "valid pixel value range", ron);
00914 
00915 
00916         for (i = 0; i < nrow; ++i) {
00917 
00918             register cxint stride = i * ncol;
00919             register cxint* bpx_row  = pi_bpm + stride;
00920 
00921             register const cxdouble* bias_row = pd_mbias + stride;
00922 
00923             register cxdouble sdev = 0.;
00924 
00925             median = giraffe_array_median(bias_row, ncol);
00926 
00927             for (j = 0; j < ncol; ++j) {
00928                 sdev += (bias_row[j] - median) * (bias_row[j] - median);
00929             }
00930             sdev = sqrt(sdev / (cxdouble)(ncol - 1));
00931 
00932             if (median < median_min) {
00933                 median_min = median;
00934                 row_min = i;
00935             }
00936 
00937             if (median > median_max) {
00938                 median_max = median;
00939                 row_max = i;
00940             }
00941 
00942             tlow  = median - mbias_config.bpm.factor * ron;
00943             thigh = median + mbias_config.bpm.factor * ron;
00944 
00945             for (j = 0; j < ncol; ++j) {
00946 
00947                 if ((bias_row[j] < tlow) || (bias_row[j] > thigh)) {
00948                     bpx_row[j] = 1;
00949                     ++nbpx;
00950                 }
00951                 else {
00952                     bpx_row[j] = 0;
00953                 }
00954 
00955             }
00956 
00957         }
00958 
00959 
00960         if (nbpx > nbpx_max) {
00961             cpl_msg_warning(fctid, "Number of bad pixels found (%ld) exceeds "
00962                     "maximum number of bad pixels expected (%ld)!", nbpx,
00963                     nbpx_max);
00964         }
00965 
00966         properties = giraffe_image_get_properties(bpixel);
00967 
00968         cpl_propertylist_update_double(properties, GIALIAS_BZERO, 0.);
00969 
00970         cpl_propertylist_update_double(properties,
00971                 GIALIAS_BPM_FRACTION, mbias_config.bpm.fraction);
00972         cpl_propertylist_set_comment(properties, GIALIAS_BPM_FRACTION,
00973                 "Maximum fraction of bad pixels allowed.");
00974 
00975         cpl_propertylist_update_int(properties,
00976                 GIALIAS_BPM_NPIX, nbpx);
00977         cpl_propertylist_set_comment(properties, GIALIAS_BPM_NPIX,
00978                 "Number of pixels flagged as bad.");
00979 
00980         cpl_propertylist_update_double(properties,
00981                 GIALIAS_BPM_MEDIAN_MIN, median_min);
00982         cpl_propertylist_set_comment(properties, GIALIAS_BPM_MEDIAN_MIN,
00983                 "Minimum median pixel value used for bad pixel detection.");
00984 
00985         cpl_propertylist_update_double(properties,
00986                 GIALIAS_BPM_MEDIAN_MAX, median_max);
00987         cpl_propertylist_set_comment(properties, GIALIAS_BPM_MEDIAN_MAX,
00988                 "Maximum median pixel value used for bad pixel detection.");
00989 
00990         cpl_propertylist_update_double(properties,
00991                 GIALIAS_BPM_FACTOR, mbias_config.bpm.factor);
00992         cpl_propertylist_set_comment(properties, GIALIAS_BPM_FACTOR,
00993                 "Noise multiplier defining thresholds for bad pixel "
00994                 "detection.");
00995 
00996         cpl_propertylist_update_double(properties,
00997                 GIALIAS_BPM_NOISE, ron);
00998         cpl_propertylist_set_comment(properties, GIALIAS_BPM_NOISE,
00999                 "Bias noise value [ADU] used for bad pixel detection.");
01000 
01001         giraffe_image_add_info(bpixel, &info, set);
01002 
01003         product_frame = giraffe_frame_create_image(bpixel,
01004                                                    GIFRAME_BADPIXEL_MAP,
01005                                                    CPL_FRAME_LEVEL_FINAL,
01006                                                    TRUE, TRUE);
01007 
01008         if (product_frame == NULL) {
01009 
01010             cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
01011 
01012             if (master_bias != NULL) {
01013                 giraffe_image_delete(master_bias);
01014             }
01015 
01016             if (bpixel != NULL) {
01017                 giraffe_image_delete(bpixel);
01018             }
01019 
01020             return -1;
01021 
01022         }
01023 
01024         cpl_frameset_insert(set, product_frame);
01025 
01026 
01027         /*
01028          * Clean up
01029          */
01030 
01031         if (bpixel != NULL) {
01032             giraffe_image_delete(bpixel);
01033         }
01034 
01035     }
01036 
01037     if (master_bias != NULL) {
01038         giraffe_image_delete(master_bias);
01039     }
01040 
01041     return 0;
01042 
01043 }
01044 
01045 
01046 /*
01047  * The quality control task starts here.
01048  */
01049 
01050 static cxint
01051 giqcmasterbias(cpl_frameset* set)
01052 {
01053 
01054     const cxchar* const fctid = "giqcmasterbias";
01055 
01056 
01057     const cxint wstart = 50;
01058     const cxint wsize = 100;
01059 
01060     cxint i;
01061     cxint j;
01062     cxint k;
01063     cxint nx = 0;
01064     cxint ny = 0;
01065     cxint nvalid = 0;
01066     cxint status = 0;
01067     cxint nsigma = 5;
01068 
01069     const cxdouble low = 100.;
01070     const cxdouble high = 300.;
01071     const cxdouble sthreshold = 2.;
01072 
01073     cxdouble mean = 0.;
01074     cxdouble median = 0.;
01075     cxdouble smean = 0.;
01076     cxdouble sum = 0.;
01077     cxdouble* _mbdata = NULL;
01078     cxdouble* _tdata = NULL;
01079     cxdouble sigma[nsigma];
01080 
01081     cpl_propertylist* properties = NULL;
01082     cpl_propertylist* qclog = NULL;
01083 
01084     cpl_vector* _sigma = NULL;
01085 
01086     cpl_image* _mbias = NULL;
01087     cpl_image* _smbias = NULL;
01088     cpl_image* _test = NULL;
01089 
01090     cpl_frame* rframe = NULL;
01091     cpl_frame* pframe = NULL;
01092 
01093     GiPaf* qc = NULL;
01094 
01095     GiImage* mbias = NULL;
01096     GiImage* bias = NULL;
01097 
01098     GiWindow w;
01099 
01100 
01101     cpl_msg_info(fctid, "Computing QC1 parameters ...");
01102 
01103     qc = giraffe_qclog_open(0);
01104 
01105     if (qc == NULL) {
01106         cpl_msg_error(fctid, "Cannot create QC1 log!");
01107         return 1;
01108     }
01109 
01110     qclog = giraffe_paf_get_properties(qc);
01111     cx_assert(qclog != NULL);
01112 
01113 
01114     /*
01115      * Process master bias
01116      */
01117 
01118     pframe = giraffe_get_frame(set, GIFRAME_BIAS_MASTER,
01119                                CPL_FRAME_GROUP_PRODUCT);
01120 
01121     if (pframe == NULL) {
01122         cpl_msg_error(fctid, "Missing product frame (%s)",
01123                       GIFRAME_BIAS_MASTER);
01124 
01125         giraffe_paf_delete(qc);
01126         qc = NULL;
01127 
01128         return 1;
01129     }
01130 
01131     cpl_msg_info(fctid, "Processing product frame '%s' (%s)",
01132                  cpl_frame_get_filename(pframe), cpl_frame_get_tag(pframe));
01133 
01134     mbias = giraffe_image_new(CPL_TYPE_DOUBLE);
01135     status = giraffe_image_load(mbias, cpl_frame_get_filename(pframe), 0);
01136 
01137     if (status != 0) {
01138         cpl_msg_error(fctid, "Could not load master bias '%s'! Aborting ...",
01139                       cpl_frame_get_filename(pframe));
01140 
01141         giraffe_image_delete(mbias);
01142         mbias = NULL;
01143 
01144         giraffe_paf_delete(qc);
01145         qc = NULL;
01146 
01147         return 1;
01148     }
01149 
01150 
01151     /*
01152      * Load first raw image as reference
01153      */
01154 
01155     rframe = cpl_frameset_find(set, GIFRAME_BIAS);
01156 
01157     if (rframe == NULL) {
01158         cpl_msg_error(fctid, "Missing raw frame (%s)", GIFRAME_BIAS);
01159 
01160         giraffe_image_delete(mbias);
01161         mbias = NULL;
01162 
01163         giraffe_paf_delete(qc);
01164         qc = NULL;
01165 
01166         return 1;
01167     }
01168 
01169     bias = giraffe_image_new(CPL_TYPE_DOUBLE);
01170     status = giraffe_image_load(bias, cpl_frame_get_filename(rframe), 0);
01171 
01172     if (status != 0) {
01173         cpl_msg_error(fctid, "Could not load bias '%s'!",
01174                       cpl_frame_get_filename(rframe));
01175 
01176         giraffe_image_delete(bias);
01177         bias = NULL;
01178 
01179         giraffe_image_delete(mbias);
01180         mbias = NULL;
01181 
01182         giraffe_paf_delete(qc);
01183         qc = NULL;
01184 
01185         return 1;
01186 
01187     }
01188 
01189     properties = giraffe_image_get_properties(bias);
01190     cx_assert(properties != NULL);
01191 
01192     giraffe_propertylist_copy(qclog, "ARCFILE", properties, GIALIAS_ARCFILE);
01193     giraffe_propertylist_copy(qclog, "TPL.ID", properties, GIALIAS_TPLID);
01194 
01195     cpl_propertylist_update_string(qclog, "PRO.CATG",
01196                                    cpl_frame_get_tag(pframe));
01197     cpl_propertylist_set_comment(qclog, "PRO.CATG",
01198                                  "Pipeline product category");
01199 
01200     properties = giraffe_image_get_properties(mbias);
01201     cx_assert(properties != NULL);
01202 
01203     giraffe_propertylist_copy(qclog, "PRO.DATAAVG",
01204                               properties, GIALIAS_DATAMEAN);
01205     giraffe_propertylist_copy(qclog, "PRO.DATARMS",
01206                               properties, GIALIAS_DATASIG);
01207     giraffe_propertylist_copy(qclog, "PRO.DATAMED",
01208                               properties, GIALIAS_DATAMEDI);
01209     giraffe_propertylist_copy(qclog, "PRO.DATANCOM",
01210                               properties, GIALIAS_DATANCOM);
01211 
01212 
01213     /*
01214      * Create screened test image for statistics computation
01215      */
01216 
01217     _mbias = giraffe_image_get(mbias);
01218     _mbdata = cpl_image_get_data(_mbias);
01219 
01220     nx = cpl_image_get_size_x(_mbias);
01221     ny = cpl_image_get_size_y(_mbias);
01222 
01223     nvalid = 0;
01224 
01225     for (i = 0; i < nx * ny; i++) {
01226 
01227         if (_mbdata[i] >= low && _mbdata[i] < high) {
01228             ++nvalid;
01229         }
01230 
01231     }
01232 
01233     _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
01234     _tdata = cpl_image_get_data(_test);
01235 
01236     j = 0;
01237 
01238     for (i = 0; i < nx * ny; i++) {
01239 
01240         if (_mbdata[i] >= low && _mbdata[i] < high) {
01241             _tdata[j++] = _mbdata[i];
01242         }
01243 
01244     }
01245 
01246     cpl_propertylist_update_double(properties, GIALIAS_QCMBIASMED,
01247                                    cpl_image_get_median(_test));
01248     cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASMED,
01249                                  "Median master bias level (ADU)");
01250 
01251     cpl_propertylist_update_double(properties, GIALIAS_QCMBIASAVG,
01252                                    cpl_image_get_mean(_test));
01253     cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASAVG,
01254                                  "Mean master bias level (ADU)");
01255 
01256     cpl_propertylist_update_double(properties, GIALIAS_QCMBIASRMS,
01257                                    cpl_image_get_stdev(_test));
01258     cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASRMS,
01259                                  "RMS of master bias level (ADU)");
01260 
01261     cpl_image_delete(_test);
01262     _test = NULL;
01263 
01264     giraffe_propertylist_copy(qclog, "QC.BIAS.MASTER.MEDIAN",
01265                               properties, GIALIAS_QCMBIASMED);
01266     giraffe_propertylist_copy(qclog, "QC.BIAS.MASTER.MEAN",
01267                               properties, GIALIAS_QCMBIASAVG);
01268     giraffe_propertylist_copy(qclog, "QC.BIAS.MASTER.RMS",
01269                               properties, GIALIAS_QCMBIASRMS);
01270 
01271 
01272     /*
01273      * Compute read out noise on raw frames if at least 2 raw
01274      * biases are available.
01275      */
01276 
01277     if (cpl_frameset_count_tags(set, GIFRAME_BIAS) > 1) {
01278 
01279         cpl_frame* _frame = NULL;
01280 
01281         cpl_image* diff = NULL;
01282 
01283         GiImage* _bias;
01284 
01285 
01286         nsigma = 5;
01287         memset(sigma, 0, nsigma * sizeof(cxdouble));
01288 
01289         _frame = cpl_frameset_find(set, GIFRAME_BIAS);
01290         _frame = cpl_frameset_find(set, NULL);
01291 
01292         _bias = giraffe_image_new(CPL_TYPE_DOUBLE);
01293         status = giraffe_image_load(_bias, cpl_frame_get_filename(_frame), 0);
01294 
01295         if (status != 0) {
01296             cpl_msg_error(fctid, "Could not load bias '%s'! Aborting ...",
01297                           cpl_frame_get_filename(_frame));
01298 
01299             giraffe_image_delete(_bias);
01300             _bias = NULL;
01301 
01302             giraffe_image_delete(mbias);
01303             mbias = NULL;
01304 
01305             giraffe_image_delete(bias);
01306             bias = NULL;
01307 
01308             giraffe_paf_delete(qc);
01309             qc = NULL;
01310 
01311             return 1;
01312         }
01313 
01314         diff = cpl_image_duplicate(giraffe_image_get(bias));
01315 
01316         if (diff == NULL) {
01317             cpl_msg_error(fctid, "Cannot compute bias difference image! "
01318                           "Aborting ...");
01319 
01320             giraffe_image_delete(_bias);
01321             _bias = NULL;
01322 
01323             giraffe_image_delete(mbias);
01324             mbias = NULL;
01325 
01326             giraffe_image_delete(bias);
01327             bias = NULL;
01328 
01329             giraffe_paf_delete(qc);
01330             qc = NULL;
01331 
01332             return 1;
01333         }
01334 
01335         cpl_image_subtract(diff, giraffe_image_get(_bias));
01336 
01337         giraffe_image_delete(_bias);
01338 
01339 
01340         i = 0;
01341 
01342         /* Lower left window */
01343 
01344         w.x0 = wstart;
01345         w.y0 = wstart;
01346         w.x1 = w.x0 + wsize;
01347         w.y1 = w.y0 + wsize;
01348 
01349         giraffe_error_push();
01350 
01351         sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
01352 
01353         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01354             --nsigma;
01355         }
01356 
01357         giraffe_error_pop();
01358 
01359 
01360         /* Lower right window */
01361 
01362         w.x0 = cpl_image_get_size_x(diff) - wstart - wsize;
01363         w.x1 = w.x0 + wsize;
01364 
01365         giraffe_error_push();
01366 
01367         sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
01368 
01369         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01370             --nsigma;
01371         }
01372 
01373         giraffe_error_pop();
01374 
01375 
01376         /* Upper right window */
01377 
01378         w.y0 = cpl_image_get_size_y(diff) - wstart - wsize;
01379         w.y1 = w.y0 + wsize;
01380 
01381         giraffe_error_push();
01382 
01383         sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
01384 
01385         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01386             --nsigma;
01387         }
01388 
01389         giraffe_error_pop();
01390 
01391 
01392         /* Upper left window */
01393 
01394         w.x0 = wstart;
01395         w.x1 = w.x0 + wsize;
01396 
01397         giraffe_error_push();
01398 
01399         sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
01400 
01401         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01402             --nsigma;
01403         }
01404 
01405         giraffe_error_pop();
01406 
01407 
01408         /* Central window */
01409 
01410         w.x0 = 1024;
01411         w.y0 = 1998;
01412         w.x1 = 1124;
01413         w.y1 = 2098;
01414 
01415         giraffe_error_push();
01416 
01417         sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
01418 
01419         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01420             --nsigma;
01421         }
01422 
01423         giraffe_error_pop();
01424 
01425 
01426         for (i = 0; i < nsigma; i++) {
01427             sigma[i] /= sqrt(2.);
01428         }
01429 
01430         if (nsigma < 1) {
01431             cpl_msg_error(fctid, "Could not compute image statistics in any "
01432                           "window! Aborting ...");
01433 
01434             cpl_image_delete(diff);
01435             diff = NULL;
01436 
01437             giraffe_image_delete(mbias);
01438             mbias = NULL;
01439 
01440             giraffe_image_delete(bias);
01441             bias = NULL;
01442 
01443             giraffe_paf_delete(qc);
01444             qc = NULL;
01445 
01446             return 1;
01447         }
01448 
01449 
01450         _sigma = cpl_vector_wrap(nsigma, sigma);
01451 
01452         median = cpl_vector_get_median(_sigma);
01453 
01454         cpl_vector_unwrap(_sigma);
01455         _sigma = NULL;
01456 
01457         cpl_image_delete(diff);
01458         diff = NULL;
01459 
01460 
01461         cpl_propertylist_update_double(properties, GIALIAS_QCRON, median);
01462         cpl_propertylist_set_comment(properties, GIALIAS_QCRON,
01463                                      "Readout noise (raw)");
01464 
01465         giraffe_propertylist_copy(qclog, "QC.OUT1.RON.RAW", properties,
01466                            GIALIAS_QCRON);
01467     }
01468 
01469     giraffe_image_delete(bias);
01470     bias = NULL;
01471 
01472 
01473     /*
01474      * Compute read out noise on master bias frame
01475      */
01476 
01477     k = 0;
01478     nsigma = 5;
01479     memset(sigma, 0, nsigma * sizeof(cxdouble));
01480 
01481 
01482     /* Lower left window */
01483 
01484     w.x0 = wstart;
01485     w.y0 = wstart;
01486     w.x1 = w.x0 + wsize;
01487     w.y1 = w.y0 + wsize;
01488 
01489     _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
01490     _mbdata = cpl_image_get_data(_smbias);
01491 
01492     nvalid  = 0;
01493 
01494     for (i = 0; i < wsize * wsize; i++) {
01495 
01496         if (_mbdata[i] >= low && _mbdata[i] < high) {
01497             ++nvalid;
01498         }
01499 
01500     }
01501 
01502     _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
01503     _tdata = cpl_image_get_data(_test);
01504 
01505     j = 0;
01506 
01507     for (i = 0; i < wsize * wsize; i++) {
01508 
01509         if (_mbdata[i] >= low && _mbdata[i] < high) {
01510             _tdata[j++] = _mbdata[i];
01511         }
01512 
01513     }
01514 
01515     giraffe_error_push();
01516 
01517     sigma[k++] = cpl_image_get_stdev(_test);
01518 
01519     if (cpl_error_get_code() != CPL_ERROR_NONE) {
01520         --nsigma;
01521     }
01522 
01523     giraffe_error_pop();
01524 
01525     cpl_image_delete(_smbias);
01526     _smbias = NULL;
01527 
01528     cpl_image_delete(_test);
01529     _test = NULL;
01530 
01531     /* Lower right window */
01532 
01533     w.x0 = cpl_image_get_size_x(_mbias) - wstart - wsize;
01534     w.x1 = w.x0 + wsize;
01535 
01536     _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
01537     _mbdata = cpl_image_get_data(_smbias);
01538 
01539     nvalid  = 0;
01540 
01541     for (i = 0; i < wsize * wsize; i++) {
01542 
01543         if (_mbdata[i] >= low && _mbdata[i] < high) {
01544             ++nvalid;
01545         }
01546 
01547     }
01548 
01549     _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
01550     _tdata = cpl_image_get_data(_test);
01551 
01552     j = 0;
01553 
01554     for (i = 0; i < wsize * wsize; i++) {
01555 
01556         if (_mbdata[i] >= low && _mbdata[i] < high) {
01557             _tdata[j++] = _mbdata[i];
01558         }
01559 
01560     }
01561 
01562     giraffe_error_push();
01563 
01564     sigma[k++] = cpl_image_get_stdev(_test);
01565 
01566     if (cpl_error_get_code() != CPL_ERROR_NONE) {
01567         --nsigma;
01568     }
01569 
01570     giraffe_error_pop();
01571 
01572     cpl_image_delete(_smbias);
01573     _smbias = NULL;
01574 
01575     cpl_image_delete(_test);
01576     _test = NULL;
01577 
01578     /* Upper right window */
01579 
01580     w.y0 = cpl_image_get_size_y(_mbias) - wstart - wsize;
01581     w.y1 = w.y0 + wsize;
01582 
01583     _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
01584     _mbdata = cpl_image_get_data(_smbias);
01585 
01586     nvalid  = 0;
01587 
01588     for (i = 0; i < wsize * wsize; i++) {
01589 
01590         if (_mbdata[i] >= low && _mbdata[i] < high) {
01591             ++nvalid;
01592         }
01593 
01594     }
01595 
01596     _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
01597     _tdata = cpl_image_get_data(_test);
01598 
01599     j = 0;
01600 
01601     for (i = 0; i < wsize * wsize; i++) {
01602 
01603         if (_mbdata[i] >= low && _mbdata[i] < high) {
01604             _tdata[j++] = _mbdata[i];
01605         }
01606 
01607     }
01608 
01609     giraffe_error_push();
01610 
01611     sigma[k++] = cpl_image_get_stdev(_test);
01612 
01613     if (cpl_error_get_code() != CPL_ERROR_NONE) {
01614         --nsigma;
01615     }
01616 
01617     giraffe_error_pop();
01618 
01619     cpl_image_delete(_smbias);
01620     _smbias = NULL;
01621 
01622     cpl_image_delete(_test);
01623     _test = NULL;
01624 
01625     /* Upper left window */
01626 
01627     w.x0 = wstart;
01628     w.x1 = w.x0 + wsize;
01629 
01630     _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
01631     _mbdata = cpl_image_get_data(_smbias);
01632 
01633     nvalid  = 0;
01634 
01635     for (i = 0; i < wsize * wsize; i++) {
01636 
01637         if (_mbdata[i] >= low && _mbdata[i] < high) {
01638             ++nvalid;
01639         }
01640 
01641     }
01642 
01643     _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
01644     _tdata = cpl_image_get_data(_test);
01645 
01646     j = 0;
01647 
01648     for (i = 0; i < wsize * wsize; i++) {
01649 
01650         if (_mbdata[i] >= low && _mbdata[i] < high) {
01651             _tdata[j++] = _mbdata[i];
01652         }
01653 
01654     }
01655 
01656     giraffe_error_push();
01657 
01658     sigma[k++] = cpl_image_get_stdev(_test);
01659 
01660     if (cpl_error_get_code() != CPL_ERROR_NONE) {
01661         --nsigma;
01662     }
01663 
01664     giraffe_error_pop();
01665 
01666     cpl_image_delete(_smbias);
01667     _smbias = NULL;
01668 
01669     cpl_image_delete(_test);
01670     _test = NULL;
01671 
01672     /* Central window */
01673 
01674     w.x0 = 1024;
01675     w.y0 = 1998;
01676     w.x1 = 1124;
01677     w.y1 = 2098;
01678 
01679     _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
01680     _mbdata = cpl_image_get_data(_smbias);
01681 
01682     nvalid  = 0;
01683 
01684     for (i = 0; i < wsize * wsize; i++) {
01685 
01686         if (_mbdata[i] >= low && _mbdata[i] < high) {
01687             ++nvalid;
01688         }
01689 
01690     }
01691 
01692     _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
01693     _tdata = cpl_image_get_data(_test);
01694 
01695     j = 0;
01696 
01697     for (i = 0; i < wsize * wsize; i++) {
01698 
01699         if (_mbdata[i] >= low && _mbdata[i] < high) {
01700             _tdata[j++] = _mbdata[i];
01701         }
01702 
01703     }
01704 
01705     giraffe_error_push();
01706 
01707     sigma[k++] = cpl_image_get_stdev(_test);
01708 
01709     if (cpl_error_get_code() != CPL_ERROR_NONE) {
01710         --nsigma;
01711     }
01712 
01713     giraffe_error_pop();
01714 
01715     cpl_image_delete(_smbias);
01716     _smbias = NULL;
01717 
01718     cpl_image_delete(_test);
01719     _test = NULL;
01720 
01721     if (nsigma < 1) {
01722         cpl_msg_error(fctid, "Could not compute image statistics in any "
01723                       "window! Aborting ...");
01724 
01725         giraffe_image_delete(mbias);
01726         mbias = NULL;
01727 
01728         giraffe_paf_delete(qc);
01729         qc = NULL;
01730 
01731         return 1;
01732     }
01733 
01734     _sigma = cpl_vector_wrap(nsigma, sigma);
01735 
01736     median = cpl_vector_get_median(_sigma);
01737 
01738     cpl_vector_unwrap(_sigma);
01739     _sigma = NULL;
01740 
01741     cpl_propertylist_update_double(properties, GIALIAS_QCMRON, median);
01742     cpl_propertylist_set_comment(properties, GIALIAS_QCMRON, "Readout noise "
01743                           "(master)");
01744 
01745     giraffe_propertylist_copy(qclog, "QC.OUT1.RON.MASTER", properties,
01746                        GIALIAS_QCMRON);
01747 
01748 
01749     /*
01750      * Compute structure along the x and y axes of the master bias.
01751      */
01752 
01753     _test = cpl_image_collapse_create(_mbias, 0);
01754     cpl_image_divide_scalar(_test, cpl_image_get_size_y(_mbias));
01755 
01756     mean = cpl_image_get_mean(_test);
01757 
01758 
01759     /*
01760      * Compute screened mean value
01761      */
01762 
01763     nvalid = 0;
01764     sum = 0.;
01765 
01766     _tdata = cpl_image_get_data(_test);
01767 
01768     for (i = 0; i < cpl_image_get_size_x(_test); i++) {
01769 
01770         if ((_tdata[i] > mean - sthreshold) &&
01771             (_tdata[i] < mean + sthreshold)) {
01772             sum += _tdata[i];
01773             ++nvalid;
01774         }
01775 
01776     }
01777 
01778     smean = sum / nvalid;
01779 
01780 
01781     /*
01782      * Compute RMS with respect to the screened mean value
01783      */
01784 
01785     nvalid = 0;
01786     sum = 0.;
01787 
01788     for (i = 0; i < cpl_image_get_size_x(_test); i++) {
01789 
01790         if ((_tdata[i] > mean - sthreshold) &&
01791             (_tdata[i] < mean + sthreshold)) {
01792             sum += pow(_tdata[i] - smean, 2.);
01793             ++nvalid;
01794         }
01795 
01796     }
01797 
01798     sum = sqrt(sum / (nvalid - 1));
01799 
01800     cpl_propertylist_update_double(properties, GIALIAS_QCSTRUCTX, sum);
01801     cpl_propertylist_set_comment(properties, GIALIAS_QCSTRUCTX,
01802                                  "Structure along the x axis");
01803 
01804     giraffe_propertylist_copy(qclog, "QC.OUT1.STRUCT.X", properties,
01805                               GIALIAS_QCSTRUCTX);
01806 
01807     cpl_image_delete(_test);
01808     _test = NULL;
01809 
01810 
01811     _test = cpl_image_collapse_create(_mbias, 1);
01812     cpl_image_divide_scalar(_test, cpl_image_get_size_x(_mbias));
01813 
01814     mean = cpl_image_get_mean(_test);
01815 
01816 
01817     /*
01818      * Compute screened mean value
01819      */
01820 
01821     nvalid = 0;
01822     sum = 0.;
01823 
01824     _tdata = cpl_image_get_data(_test);
01825 
01826     for (i = 0; i < cpl_image_get_size_y(_test); i++) {
01827 
01828         if ((_tdata[i] > mean - sthreshold) &&
01829             (_tdata[i] < mean + sthreshold)) {
01830             sum += _tdata[i];
01831             ++nvalid;
01832         }
01833 
01834     }
01835 
01836     smean = sum / nvalid;
01837 
01838 
01839     /*
01840      * Compute RMS with respect to the screened mean value
01841      */
01842 
01843     nvalid = 0;
01844     sum = 0.;
01845 
01846     _tdata = cpl_image_get_data(_test);
01847 
01848     for (i = 0; i < cpl_image_get_size_y(_test); i++) {
01849 
01850         if ((_tdata[i] > mean - sthreshold) &&
01851             (_tdata[i] < mean + sthreshold)) {
01852             sum += pow(_tdata[i] - smean, 2.);
01853             ++nvalid;
01854         }
01855 
01856     }
01857 
01858     sum = sqrt(sum / (nvalid - 1));
01859 
01860     cpl_propertylist_update_double(properties, GIALIAS_QCSTRUCTY, sum);
01861     cpl_propertylist_set_comment(properties, GIALIAS_QCSTRUCTY,
01862                                  "Structure along the y axis");
01863 
01864     giraffe_propertylist_copy(qclog, "QC.OUT1.STRUCT.Y", properties,
01865                        GIALIAS_QCSTRUCTY);
01866 
01867     cpl_image_delete(_test);
01868     _test = NULL;
01869 
01870 
01871     /*
01872      * Write QC1 log and save updated master bias.
01873      */
01874 
01875     giraffe_image_save(mbias, cpl_frame_get_filename(pframe));
01876 
01877     giraffe_image_delete(mbias);
01878     mbias = NULL;
01879 
01880     giraffe_qclog_close(qc);
01881     qc = NULL;
01882 
01883     return 0;
01884 
01885 }
01886 
01887 
01888 /*
01889  * Build table of contents, i.e. the list of available plugins, for
01890  * this module. This function is exported.
01891  */
01892 
01893 int
01894 cpl_plugin_get_info(cpl_pluginlist* list)
01895 {
01896 
01897     cpl_recipe* recipe = cx_calloc(1, sizeof *recipe);
01898     cpl_plugin* plugin = &recipe->interface;
01899 
01900 
01901     cpl_plugin_init(plugin,
01902                     CPL_PLUGIN_API,
01903                     GIRAFFE_BINARY_VERSION,
01904                     CPL_PLUGIN_TYPE_RECIPE,
01905                     "gimasterbias",
01906                     "Creates a master bias image from a set of raw biases.",
01907                     "For detailed information please refer to the "
01908                     "GIRAFFE pipeline user manual.\nIt is available at "
01909                     "http://www.eso.org/pipelines.",
01910                     "Giraffe Pipeline",
01911                     PACKAGE_BUGREPORT,
01912                     giraffe_get_license(),
01913                     gimasterbias_create,
01914                     gimasterbias_exec,
01915                     gimasterbias_destroy);
01916 
01917     cpl_pluginlist_append(list, plugin);
01918 
01919     return 0;
01920 
01921 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.8.1.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Mon Aug 3 13:13:33 2009 by doxygen 1.5.1 written by Dimitri van Heesch, © 1997-2004