GIRAFFE Pipeline Reference Manual

gimasterbias.c

00001 /* $Id: gimasterbias.c,v 1.39 2009/11/11 08:42:49 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: 2009/11/11 08:42:49 $
00024  * $Revision: 1.39 $
00025  * $Name: giraffe-2_9 $
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                     raw_bias_list[j] = NULL;
00520                 }
00521             }
00522 
00523             cx_free(raw_bias_list);
00524 
00525             giraffe_stacking_config_destroy(stack_config);
00526             stack_config = NULL;
00527 
00528             return -1;
00529 
00530         }
00531         else {
00532             curr_frame = cpl_frameset_find(set, NULL);
00533         }
00534     }
00535 
00536     if (mbias_config.correctbadpixels == TRUE) {
00537 
00538         /* load bad pixel image */
00539 
00540         bad_pixel_frame = cpl_frameset_find(set, GIFRAME_BADPIXEL_MAP);
00541 
00542         cpl_msg_info(fctid, "Bad Pixel Frame is : %s.",
00543                      cpl_frame_get_filename(bad_pixel_frame));
00544 
00545         bad_pixels = giraffe_image_new(CPL_TYPE_INT);
00546 
00547         e_code = giraffe_image_load(bad_pixels,
00548                                     cpl_frame_get_filename(bad_pixel_frame),
00549                                     GIMASTERBIAS_BAD_PIXEL_EXTENSION);
00550 
00551         if (e_code !=0 ) {
00552             cpl_msg_error(fctid, "Could not load Bad Pixel Image [%s], "
00553                           "aborting...",
00554                           cpl_frame_get_filename(bad_pixel_frame));
00555 
00556             for (j = 0; j < raw_bias_count; j++) {
00557                 if (raw_bias_list[j] != NULL) {
00558                     giraffe_image_delete(raw_bias_list[j]);
00559                 }
00560             }
00561 
00562             cx_free(raw_bias_list);
00563 
00564             giraffe_stacking_config_destroy(stack_config);
00565             stack_config = NULL;
00566 
00567             return -1;
00568         }
00569     }
00570 
00571 
00572     /*
00573      *  Stack the bias frames...
00574      */
00575 
00576     master_bias = giraffe_stacking_stack_images(raw_bias_list, stack_config);
00577 
00578     if (master_bias == NULL) {
00579         cpl_msg_error(fctid,"Stacking of raw bias frames failed! "
00580             "No master bias was created, aborting...");
00581 
00582         for (j = 0; j < raw_bias_count; j++) {
00583             if (raw_bias_list[j] != NULL) {
00584                 giraffe_image_delete(raw_bias_list[j]);
00585             }
00586         }
00587 
00588         cx_free(raw_bias_list);
00589 
00590         if (bad_pixels != NULL) {
00591             giraffe_image_delete(bad_pixels);
00592         }
00593 
00594         giraffe_stacking_config_destroy(stack_config);
00595         stack_config = NULL;
00596 
00597         return -1;
00598 
00599     }
00600 
00601     properties = giraffe_image_get_properties(raw_bias_list[0]);
00602     e_code = giraffe_image_set_properties(master_bias, properties);
00603 
00604     giraffe_stacking_config_destroy(stack_config);
00605     stack_config = NULL;
00606 
00607 
00608     /*
00609      *  Bad pixel cleaning on result, if necessary...
00610      */
00611 
00612     if (mbias_config.correctbadpixels == TRUE) {
00613 
00614         cpl_msg_info(fctid, "Cleaning bad pixels on created "
00615                      "master bias image.");
00616 
00617         if (gimasterbias_remove_badpixels(master_bias, bad_pixels) != 0) {
00618 
00619             cpl_msg_error(fctid, "Bad pixel cleaning failed, aborting...");
00620 
00621             for (j = 0; j < raw_bias_count; j++) {
00622                 if (raw_bias_list[j] != NULL) {
00623                     giraffe_image_delete(raw_bias_list[j]);
00624                 }
00625             }
00626 
00627             cx_free(raw_bias_list);
00628 
00629             if (bad_pixels != NULL) {
00630                 giraffe_image_delete(bad_pixels);
00631             }
00632 
00633             if (master_bias != NULL) {
00634                 giraffe_image_delete(master_bias);
00635             }
00636 
00637             return -1;
00638 
00639         }
00640     }
00641 
00642     /*
00643      *  Remove overscans, if necessary...
00644      */
00645 
00646     if (mbias_config.removeoverscan == TRUE) {
00647 
00648         cpl_msg_info(fctid, "Removing overscan areas from "
00649                      "master bias image");
00650 
00651         if (giraffe_trim_raw_areas(master_bias) != 0) {
00652 
00653             cpl_msg_error(fctid, "Removing overscan areas from master "
00654                           "bias failed, aborting...");
00655 
00656             for (j = 0; j < raw_bias_count; j++) {
00657                 if (raw_bias_list[j] != NULL) {
00658                     giraffe_image_delete(raw_bias_list[j]);
00659                 }
00660             }
00661 
00662             cx_free(raw_bias_list);
00663 
00664             if (bad_pixels != NULL) {
00665                 giraffe_image_delete(bad_pixels);
00666             }
00667 
00668             if (master_bias != NULL) {
00669                 giraffe_image_delete(master_bias);
00670             }
00671 
00672             return -1;
00673         }
00674 
00675     }
00676 
00677 
00678     /*
00679      * Update master bias properties, save the master bias frame
00680      * and register it as product.
00681      */
00682 
00683     cpl_msg_info(fctid, "Writing master bias image ...");
00684 
00685     properties = giraffe_image_get_properties(master_bias);
00686     cx_assert(properties != NULL);
00687 
00688     cpl_propertylist_update_double(properties, GIALIAS_CRPIX1, 1.);
00689 
00690     cpl_propertylist_update_double(properties, GIALIAS_EXPTTOT, 0.0);
00691     cpl_propertylist_update_int(properties, GIALIAS_DATANCOM, raw_bias_count);
00692     cpl_propertylist_update_double(properties, GIALIAS_BZERO, 0.0);
00693 
00694     cpl_propertylist_update_double(properties, GIALIAS_BIASVALUE,
00695                                    cpl_image_get_mean(giraffe_image_get(master_bias)));
00696     cpl_propertylist_update_double(properties, GIALIAS_BIASSIGMA,
00697                                    cpl_image_get_stdev(giraffe_image_get(master_bias)));
00698 
00699     cpl_propertylist_erase(properties, GIALIAS_EXPTIME);
00700     cpl_propertylist_erase(properties, GIALIAS_TPLEXPNO);
00701 
00702 
00703     /*
00704      *  Clean up bias list and bad pixels...
00705      */
00706 
00707     for (j = 0; j < raw_bias_count; j++) {
00708         if (raw_bias_list[j] != NULL) {
00709             giraffe_image_delete(raw_bias_list[j]);
00710         }
00711     }
00712 
00713     cx_free(raw_bias_list);
00714     raw_bias_list = NULL;
00715 
00716     if (bad_pixels != NULL) {
00717         giraffe_image_delete(bad_pixels);
00718         bad_pixels = NULL;
00719     }
00720 
00721 
00722     giraffe_image_add_info(master_bias, &info, set);
00723 
00724     product_frame = giraffe_frame_create_image(master_bias,
00725                                                GIFRAME_BIAS_MASTER,
00726                                                CPL_FRAME_LEVEL_FINAL,
00727                                                TRUE, TRUE);
00728 
00729     if (product_frame == NULL) {
00730 
00731         cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
00732 
00733         if (master_bias != NULL) {
00734             giraffe_image_delete(master_bias);
00735         }
00736 
00737         return -1;
00738 
00739     }
00740 
00741     cpl_frameset_insert(set, product_frame);
00742 
00743 
00744     /*
00745      *  Create bad pixel map based on masterbias
00746      *  Very simple algorithm, should be refined later...
00747      */
00748 
00749     if ((mbias_config.bpm.create == TRUE) && (master_bias != NULL)
00750         && (bad_pixel_count == 0)) {
00751 
00752         const cpl_image* _master_bias = giraffe_image_get(master_bias);
00753 
00754         const cxdouble* pd_mbias =
00755                 cpl_image_get_data_double_const(_master_bias);
00756 
00757 
00758         cxint e_code2 = 0;
00759         cxint row_min = 0;
00760         cxint row_max = 0;
00761         cxint ncol = cpl_image_get_size_x(_master_bias);
00762         cxint nrow = cpl_image_get_size_y(_master_bias);
00763         cxint* pi_bpm = NULL;
00764 
00765         cxlong npix = ncol * nrow;
00766         cxlong nbpx = 0L;
00767         cxlong nbpx_max = (cxlong)(mbias_config.bpm.fraction * npix + 0.5);
00768 
00769         cxdouble median = 0.;
00770         cxdouble median_max = CX_MINDOUBLE;
00771         cxdouble median_min = CX_MAXDOUBLE;
00772         cxdouble ron = 0.;
00773         cxdouble tlow = 0.;
00774         cxdouble thigh = 0.;
00775 
00776         GiImage* bpixel = giraffe_image_create(CPL_TYPE_INT, ncol, nrow);
00777 
00778 
00779         cpl_msg_info(fctid, "Creating bad pixel map from master bias "
00780                      "frame ...");
00781 
00782 
00783         /*
00784          * Copy master bias properties to the bad pixel map and
00785          * re-assign the properties' handle.
00786          */
00787 
00788         e_code2 = giraffe_image_set_properties(bpixel, properties);
00789         properties = giraffe_image_get_properties(bpixel);
00790 
00791 
00792         /*
00793          * Get bad pixel map pixel buffer
00794          */
00795 
00796         pi_bpm   = cpl_image_get_data_int(giraffe_image_get(bpixel));
00797 
00798 
00799         /*
00800          * Setup detection thresholds
00801          */
00802 
00803         if ((cpl_propertylist_has(properties, GIALIAS_PRSCX) == TRUE) ||
00804             (cpl_propertylist_has(properties, GIALIAS_OVSCX) == TRUE)) {
00805 
00806             cxint nvalues = 0;
00807             
00808             if (cpl_propertylist_has(properties, GIALIAS_PRSCX) == TRUE) {
00809     
00810                 cxint xsz = cpl_propertylist_get_int(properties,
00811                         GIALIAS_PRSCX);
00812                 
00813                 cxdouble sdev = 0.;
00814                 
00815     
00816                 for (i = 0; i < nrow; ++i) {
00817                     
00818                     register cxint stride = i * ncol;
00819                     
00820                     cxdouble scx_mean = giraffe_array_mean(pd_mbias + stride,
00821                             xsz);
00822                     
00823                     for (j = 0; j < xsz; ++j) {
00824                         sdev += (pd_mbias[stride + j] - scx_mean) *
00825                                 (pd_mbias[stride + j] - scx_mean);
00826                     }
00827                     
00828                 }
00829                 
00830                 ron = sqrt(sdev / (cxdouble)(nrow * xsz - 1));
00831                 ++nvalues;
00832                 
00833             }
00834     
00835             if (cpl_propertylist_has(properties, GIALIAS_OVSCX) == TRUE) {
00836     
00837                 cxint xsz = cpl_propertylist_get_int(properties,
00838                         GIALIAS_OVSCX);
00839     
00840                 cxdouble sdev = 0.;
00841                 
00842     
00843                 for (i = 0; i < nrow; ++i) {
00844                     
00845                     register cxint stride = (i + 1) * ncol - xsz;
00846                     
00847                     cxdouble scx_mean = giraffe_array_mean(pd_mbias + stride,
00848                             xsz);
00849                     
00850                     for (j = 0; j < xsz; ++j) {
00851                         sdev += (pd_mbias[stride + j] - scx_mean) *
00852                                 (pd_mbias[stride + j] - scx_mean);
00853                     }
00854                     
00855                 }
00856                 
00857                 ron += sqrt(sdev / (cxdouble)(nrow * xsz - 1));
00858                 ++nvalues;
00859                 
00860             }
00861 
00862             ron /= (cxdouble)nvalues;
00863             
00864         }
00865         else {
00866 
00867             if (cpl_propertylist_has(properties, GIALIAS_RON)) {
00868 
00869                 ron = cpl_propertylist_get_double(properties, GIALIAS_RON);
00870 
00871                 if (cpl_propertylist_has(properties, GIALIAS_CONAD)) {
00872     
00873                     cxdouble conad = cpl_propertylist_get_double(properties,
00874                                                           GIALIAS_CONAD);
00875     
00876                     if (conad <= 0.) {
00877     
00878                         cpl_msg_error(fctid, "Invalid conversion factor "
00879                                       "property (%s): %.2g!", GIALIAS_CONAD,
00880                                       conad);
00881     
00882                         giraffe_image_delete(bpixel);
00883                         bpixel = NULL;
00884     
00885                         giraffe_image_delete(master_bias);
00886                         master_bias = NULL;
00887     
00888                         return -1;
00889                     }
00890                     else {
00891                         ron /= conad;
00892                     }
00893                 }
00894                 else {
00895                     cpl_msg_error(fctid, "Missing conversion factor property "
00896                             "(%s)!", GIALIAS_CONAD);
00897     
00898                     giraffe_image_delete(bpixel);
00899                     bpixel = NULL;
00900     
00901                     giraffe_image_delete(master_bias);
00902                     master_bias = NULL;
00903     
00904                     return -1;
00905                 }
00906             }
00907             else {
00908                 ron = cpl_image_get_stdev(giraffe_image_get(master_bias));
00909             }
00910             
00911         }
00912 
00913         cpl_msg_info(fctid, "Using local median +/- %.4f [ADU] as "
00914                 "valid pixel value range", ron);
00915 
00916 
00917         for (i = 0; i < nrow; ++i) {
00918 
00919             register cxint stride = i * ncol;
00920             register cxint* bpx_row  = pi_bpm + stride;
00921 
00922             register const cxdouble* bias_row = pd_mbias + stride;
00923 
00924             register cxdouble sdev = 0.;
00925 
00926             median = giraffe_array_median(bias_row, ncol);
00927 
00928             for (j = 0; j < ncol; ++j) {
00929                 sdev += (bias_row[j] - median) * (bias_row[j] - median);
00930             }
00931             sdev = sqrt(sdev / (cxdouble)(ncol - 1));
00932 
00933             if (median < median_min) {
00934                 median_min = median;
00935                 row_min = i;
00936             }
00937 
00938             if (median > median_max) {
00939                 median_max = median;
00940                 row_max = i;
00941             }
00942 
00943             tlow  = median - mbias_config.bpm.factor * ron;
00944             thigh = median + mbias_config.bpm.factor * ron;
00945 
00946             for (j = 0; j < ncol; ++j) {
00947 
00948                 if ((bias_row[j] < tlow) || (bias_row[j] > thigh)) {
00949                     bpx_row[j] = 1;
00950                     ++nbpx;
00951                 }
00952                 else {
00953                     bpx_row[j] = 0;
00954                 }
00955 
00956             }
00957 
00958         }
00959 
00960 
00961         if (nbpx > nbpx_max) {
00962             cpl_msg_warning(fctid, "Number of bad pixels found (%ld) exceeds "
00963                     "maximum number of bad pixels expected (%ld)!", nbpx,
00964                     nbpx_max);
00965         }
00966 
00967         properties = giraffe_image_get_properties(bpixel);
00968 
00969         cpl_propertylist_update_double(properties, GIALIAS_BZERO, 0.);
00970 
00971         cpl_propertylist_update_double(properties,
00972                 GIALIAS_BPM_FRACTION, mbias_config.bpm.fraction);
00973         cpl_propertylist_set_comment(properties, GIALIAS_BPM_FRACTION,
00974                 "Maximum fraction of bad pixels allowed.");
00975 
00976         cpl_propertylist_update_int(properties,
00977                 GIALIAS_BPM_NPIX, nbpx);
00978         cpl_propertylist_set_comment(properties, GIALIAS_BPM_NPIX,
00979                 "Number of pixels flagged as bad.");
00980 
00981         cpl_propertylist_update_double(properties,
00982                 GIALIAS_BPM_MEDIAN_MIN, median_min);
00983         cpl_propertylist_set_comment(properties, GIALIAS_BPM_MEDIAN_MIN,
00984                 "Minimum median pixel value used for bad pixel detection.");
00985 
00986         cpl_propertylist_update_double(properties,
00987                 GIALIAS_BPM_MEDIAN_MAX, median_max);
00988         cpl_propertylist_set_comment(properties, GIALIAS_BPM_MEDIAN_MAX,
00989                 "Maximum median pixel value used for bad pixel detection.");
00990 
00991         cpl_propertylist_update_double(properties,
00992                 GIALIAS_BPM_FACTOR, mbias_config.bpm.factor);
00993         cpl_propertylist_set_comment(properties, GIALIAS_BPM_FACTOR,
00994                 "Noise multiplier defining thresholds for bad pixel "
00995                 "detection.");
00996 
00997         cpl_propertylist_update_double(properties,
00998                 GIALIAS_BPM_NOISE, ron);
00999         cpl_propertylist_set_comment(properties, GIALIAS_BPM_NOISE,
01000                 "Bias noise value [ADU] used for bad pixel detection.");
01001 
01002         giraffe_image_add_info(bpixel, &info, set);
01003 
01004         product_frame = giraffe_frame_create_image(bpixel,
01005                                                    GIFRAME_BADPIXEL_MAP,
01006                                                    CPL_FRAME_LEVEL_FINAL,
01007                                                    TRUE, TRUE);
01008 
01009         if (product_frame == NULL) {
01010 
01011             cpl_msg_error(fctid, "Cannot create local file! Aborting ...");
01012 
01013             if (master_bias != NULL) {
01014                 giraffe_image_delete(master_bias);
01015             }
01016 
01017             if (bpixel != NULL) {
01018                 giraffe_image_delete(bpixel);
01019             }
01020 
01021             return -1;
01022 
01023         }
01024 
01025         cpl_frameset_insert(set, product_frame);
01026 
01027 
01028         /*
01029          * Clean up
01030          */
01031 
01032         if (bpixel != NULL) {
01033             giraffe_image_delete(bpixel);
01034         }
01035 
01036     }
01037 
01038     if (master_bias != NULL) {
01039         giraffe_image_delete(master_bias);
01040     }
01041 
01042     return 0;
01043 
01044 }
01045 
01046 
01047 /*
01048  * The quality control task starts here.
01049  */
01050 
01051 static cxint
01052 giqcmasterbias(cpl_frameset* set)
01053 {
01054 
01055     const cxchar* const fctid = "giqcmasterbias";
01056 
01057 
01058     const cxint wstart = 50;
01059     const cxint wsize = 100;
01060 
01061     cxint i;
01062     cxint j;
01063     cxint k;
01064     cxint nx = 0;
01065     cxint ny = 0;
01066     cxint nvalid = 0;
01067     cxint status = 0;
01068     cxint nsigma = 5;
01069 
01070     const cxdouble low = 100.;
01071     const cxdouble high = 300.;
01072     const cxdouble sthreshold = 2.;
01073 
01074     cxdouble mean = 0.;
01075     cxdouble median = 0.;
01076     cxdouble smean = 0.;
01077     cxdouble sum = 0.;
01078     cxdouble* _mbdata = NULL;
01079     cxdouble* _tdata = NULL;
01080     cxdouble sigma[nsigma];
01081 
01082     cpl_propertylist* properties = NULL;
01083     cpl_propertylist* qclog = NULL;
01084 
01085     cpl_vector* _sigma = NULL;
01086 
01087     cpl_image* _mbias = NULL;
01088     cpl_image* _smbias = NULL;
01089     cpl_image* _test = NULL;
01090 
01091     cpl_frame* rframe = NULL;
01092     cpl_frame* pframe = NULL;
01093 
01094     GiPaf* qc = NULL;
01095 
01096     GiImage* mbias = NULL;
01097     GiImage* bias = NULL;
01098 
01099     GiWindow w;
01100 
01101 
01102     cpl_msg_info(fctid, "Computing QC1 parameters ...");
01103 
01104     qc = giraffe_qclog_open(0);
01105 
01106     if (qc == NULL) {
01107         cpl_msg_error(fctid, "Cannot create QC1 log!");
01108         return 1;
01109     }
01110 
01111     qclog = giraffe_paf_get_properties(qc);
01112     cx_assert(qclog != NULL);
01113 
01114 
01115     /*
01116      * Process master bias
01117      */
01118 
01119     pframe = giraffe_get_frame(set, GIFRAME_BIAS_MASTER,
01120                                CPL_FRAME_GROUP_PRODUCT);
01121 
01122     if (pframe == NULL) {
01123         cpl_msg_error(fctid, "Missing product frame (%s)",
01124                       GIFRAME_BIAS_MASTER);
01125 
01126         giraffe_paf_delete(qc);
01127         qc = NULL;
01128 
01129         return 1;
01130     }
01131 
01132     cpl_msg_info(fctid, "Processing product frame '%s' (%s)",
01133                  cpl_frame_get_filename(pframe), cpl_frame_get_tag(pframe));
01134 
01135     mbias = giraffe_image_new(CPL_TYPE_DOUBLE);
01136     status = giraffe_image_load(mbias, cpl_frame_get_filename(pframe), 0);
01137 
01138     if (status != 0) {
01139         cpl_msg_error(fctid, "Could not load master bias '%s'! Aborting ...",
01140                       cpl_frame_get_filename(pframe));
01141 
01142         giraffe_image_delete(mbias);
01143         mbias = NULL;
01144 
01145         giraffe_paf_delete(qc);
01146         qc = NULL;
01147 
01148         return 1;
01149     }
01150 
01151 
01152     /*
01153      * Load first raw image as reference
01154      */
01155 
01156     rframe = cpl_frameset_find(set, GIFRAME_BIAS);
01157 
01158     if (rframe == NULL) {
01159         cpl_msg_error(fctid, "Missing raw frame (%s)", GIFRAME_BIAS);
01160 
01161         giraffe_image_delete(mbias);
01162         mbias = NULL;
01163 
01164         giraffe_paf_delete(qc);
01165         qc = NULL;
01166 
01167         return 1;
01168     }
01169 
01170     bias = giraffe_image_new(CPL_TYPE_DOUBLE);
01171     status = giraffe_image_load(bias, cpl_frame_get_filename(rframe), 0);
01172 
01173     if (status != 0) {
01174         cpl_msg_error(fctid, "Could not load bias '%s'!",
01175                       cpl_frame_get_filename(rframe));
01176 
01177         giraffe_image_delete(bias);
01178         bias = NULL;
01179 
01180         giraffe_image_delete(mbias);
01181         mbias = NULL;
01182 
01183         giraffe_paf_delete(qc);
01184         qc = NULL;
01185 
01186         return 1;
01187 
01188     }
01189 
01190     properties = giraffe_image_get_properties(bias);
01191     cx_assert(properties != NULL);
01192 
01193     giraffe_propertylist_copy(qclog, "ARCFILE", properties, GIALIAS_ARCFILE);
01194     giraffe_propertylist_copy(qclog, "TPL.ID", properties, GIALIAS_TPLID);
01195 
01196     cpl_propertylist_update_string(qclog, "PRO.CATG",
01197                                    cpl_frame_get_tag(pframe));
01198     cpl_propertylist_set_comment(qclog, "PRO.CATG",
01199                                  "Pipeline product category");
01200 
01201     properties = giraffe_image_get_properties(mbias);
01202     cx_assert(properties != NULL);
01203 
01204     giraffe_propertylist_copy(qclog, "PRO.DATAAVG",
01205                               properties, GIALIAS_DATAMEAN);
01206     giraffe_propertylist_copy(qclog, "PRO.DATARMS",
01207                               properties, GIALIAS_DATASIG);
01208     giraffe_propertylist_copy(qclog, "PRO.DATAMED",
01209                               properties, GIALIAS_DATAMEDI);
01210     giraffe_propertylist_copy(qclog, "PRO.DATANCOM",
01211                               properties, GIALIAS_DATANCOM);
01212 
01213 
01214     /*
01215      * Create screened test image for statistics computation
01216      */
01217 
01218     _mbias = giraffe_image_get(mbias);
01219     _mbdata = cpl_image_get_data(_mbias);
01220 
01221     nx = cpl_image_get_size_x(_mbias);
01222     ny = cpl_image_get_size_y(_mbias);
01223 
01224     nvalid = 0;
01225 
01226     for (i = 0; i < nx * ny; i++) {
01227 
01228         if (_mbdata[i] >= low && _mbdata[i] < high) {
01229             ++nvalid;
01230         }
01231 
01232     }
01233 
01234     _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
01235     _tdata = cpl_image_get_data(_test);
01236 
01237     j = 0;
01238 
01239     for (i = 0; i < nx * ny; i++) {
01240 
01241         if (_mbdata[i] >= low && _mbdata[i] < high) {
01242             _tdata[j++] = _mbdata[i];
01243         }
01244 
01245     }
01246 
01247     cpl_propertylist_update_double(properties, GIALIAS_QCMBIASMED,
01248                                    cpl_image_get_median(_test));
01249     cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASMED,
01250                                  "Median master bias level (ADU)");
01251 
01252     cpl_propertylist_update_double(properties, GIALIAS_QCMBIASAVG,
01253                                    cpl_image_get_mean(_test));
01254     cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASAVG,
01255                                  "Mean master bias level (ADU)");
01256 
01257     cpl_propertylist_update_double(properties, GIALIAS_QCMBIASRMS,
01258                                    cpl_image_get_stdev(_test));
01259     cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASRMS,
01260                                  "RMS of master bias level (ADU)");
01261 
01262     cpl_image_delete(_test);
01263     _test = NULL;
01264 
01265     giraffe_propertylist_copy(qclog, "QC.BIAS.MASTER.MEDIAN",
01266                               properties, GIALIAS_QCMBIASMED);
01267     giraffe_propertylist_copy(qclog, "QC.BIAS.MASTER.MEAN",
01268                               properties, GIALIAS_QCMBIASAVG);
01269     giraffe_propertylist_copy(qclog, "QC.BIAS.MASTER.RMS",
01270                               properties, GIALIAS_QCMBIASRMS);
01271 
01272 
01273     /*
01274      * Compute read out noise on raw frames if at least 2 raw
01275      * biases are available.
01276      */
01277 
01278     if (cpl_frameset_count_tags(set, GIFRAME_BIAS) > 1) {
01279 
01280         cpl_frame* _frame = NULL;
01281 
01282         cpl_image* diff = NULL;
01283 
01284         GiImage* _bias;
01285 
01286 
01287         nsigma = 5;
01288         memset(sigma, 0, nsigma * sizeof(cxdouble));
01289 
01290         _frame = cpl_frameset_find(set, GIFRAME_BIAS);
01291         _frame = cpl_frameset_find(set, NULL);
01292 
01293         _bias = giraffe_image_new(CPL_TYPE_DOUBLE);
01294         status = giraffe_image_load(_bias, cpl_frame_get_filename(_frame), 0);
01295 
01296         if (status != 0) {
01297             cpl_msg_error(fctid, "Could not load bias '%s'! Aborting ...",
01298                           cpl_frame_get_filename(_frame));
01299 
01300             giraffe_image_delete(_bias);
01301             _bias = NULL;
01302 
01303             giraffe_image_delete(mbias);
01304             mbias = NULL;
01305 
01306             giraffe_image_delete(bias);
01307             bias = NULL;
01308 
01309             giraffe_paf_delete(qc);
01310             qc = NULL;
01311 
01312             return 1;
01313         }
01314 
01315         diff = cpl_image_duplicate(giraffe_image_get(bias));
01316 
01317         if (diff == NULL) {
01318             cpl_msg_error(fctid, "Cannot compute bias difference image! "
01319                           "Aborting ...");
01320 
01321             giraffe_image_delete(_bias);
01322             _bias = NULL;
01323 
01324             giraffe_image_delete(mbias);
01325             mbias = NULL;
01326 
01327             giraffe_image_delete(bias);
01328             bias = NULL;
01329 
01330             giraffe_paf_delete(qc);
01331             qc = NULL;
01332 
01333             return 1;
01334         }
01335 
01336         cpl_image_subtract(diff, giraffe_image_get(_bias));
01337 
01338         giraffe_image_delete(_bias);
01339 
01340 
01341         i = 0;
01342 
01343         /* Lower left window */
01344 
01345         w.x0 = wstart;
01346         w.y0 = wstart;
01347         w.x1 = w.x0 + wsize;
01348         w.y1 = w.y0 + wsize;
01349 
01350         giraffe_error_push();
01351 
01352         sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
01353 
01354         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01355             --nsigma;
01356         }
01357 
01358         giraffe_error_pop();
01359 
01360 
01361         /* Lower right window */
01362 
01363         w.x0 = cpl_image_get_size_x(diff) - wstart - wsize;
01364         w.x1 = w.x0 + wsize;
01365 
01366         giraffe_error_push();
01367 
01368         sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
01369 
01370         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01371             --nsigma;
01372         }
01373 
01374         giraffe_error_pop();
01375 
01376 
01377         /* Upper right window */
01378 
01379         w.y0 = cpl_image_get_size_y(diff) - wstart - wsize;
01380         w.y1 = w.y0 + wsize;
01381 
01382         giraffe_error_push();
01383 
01384         sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
01385 
01386         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01387             --nsigma;
01388         }
01389 
01390         giraffe_error_pop();
01391 
01392 
01393         /* Upper left window */
01394 
01395         w.x0 = wstart;
01396         w.x1 = w.x0 + wsize;
01397 
01398         giraffe_error_push();
01399 
01400         sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
01401 
01402         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01403             --nsigma;
01404         }
01405 
01406         giraffe_error_pop();
01407 
01408 
01409         /* Central window */
01410 
01411         w.x0 = 1024;
01412         w.y0 = 1998;
01413         w.x1 = 1124;
01414         w.y1 = 2098;
01415 
01416         giraffe_error_push();
01417 
01418         sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
01419 
01420         if (cpl_error_get_code() != CPL_ERROR_NONE) {
01421             --nsigma;
01422         }
01423 
01424         giraffe_error_pop();
01425 
01426 
01427         for (i = 0; i < nsigma; i++) {
01428             sigma[i] /= sqrt(2.);
01429         }
01430 
01431         if (nsigma < 1) {
01432             cpl_msg_error(fctid, "Could not compute image statistics in any "
01433                           "window! Aborting ...");
01434 
01435             cpl_image_delete(diff);
01436             diff = NULL;
01437 
01438             giraffe_image_delete(mbias);
01439             mbias = NULL;
01440 
01441             giraffe_image_delete(bias);
01442             bias = NULL;
01443 
01444             giraffe_paf_delete(qc);
01445             qc = NULL;
01446 
01447             return 1;
01448         }
01449 
01450 
01451         _sigma = cpl_vector_wrap(nsigma, sigma);
01452 
01453         median = cpl_vector_get_median(_sigma);
01454 
01455         cpl_vector_unwrap(_sigma);
01456         _sigma = NULL;
01457 
01458         cpl_image_delete(diff);
01459         diff = NULL;
01460 
01461 
01462         cpl_propertylist_update_double(properties, GIALIAS_QCRON, median);
01463         cpl_propertylist_set_comment(properties, GIALIAS_QCRON,
01464                                      "Readout noise (raw)");
01465 
01466         giraffe_propertylist_copy(qclog, "QC.OUT1.RON.RAW", properties,
01467                            GIALIAS_QCRON);
01468     }
01469 
01470     giraffe_image_delete(bias);
01471     bias = NULL;
01472 
01473 
01474     /*
01475      * Compute read out noise on master bias frame
01476      */
01477 
01478     k = 0;
01479     nsigma = 5;
01480     memset(sigma, 0, nsigma * sizeof(cxdouble));
01481 
01482 
01483     /* Lower left window */
01484 
01485     w.x0 = wstart;
01486     w.y0 = wstart;
01487     w.x1 = w.x0 + wsize;
01488     w.y1 = w.y0 + wsize;
01489 
01490     _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
01491     _mbdata = cpl_image_get_data(_smbias);
01492 
01493     nvalid  = 0;
01494 
01495     for (i = 0; i < wsize * wsize; i++) {
01496 
01497         if (_mbdata[i] >= low && _mbdata[i] < high) {
01498             ++nvalid;
01499         }
01500 
01501     }
01502 
01503     _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
01504     _tdata = cpl_image_get_data(_test);
01505 
01506     j = 0;
01507 
01508     for (i = 0; i < wsize * wsize; i++) {
01509 
01510         if (_mbdata[i] >= low && _mbdata[i] < high) {
01511             _tdata[j++] = _mbdata[i];
01512         }
01513 
01514     }
01515 
01516     giraffe_error_push();
01517 
01518     sigma[k++] = cpl_image_get_stdev(_test);
01519 
01520     if (cpl_error_get_code() != CPL_ERROR_NONE) {
01521         --nsigma;
01522     }
01523 
01524     giraffe_error_pop();
01525 
01526     cpl_image_delete(_smbias);
01527     _smbias = NULL;
01528 
01529     cpl_image_delete(_test);
01530     _test = NULL;
01531 
01532     /* Lower right window */
01533 
01534     w.x0 = cpl_image_get_size_x(_mbias) - wstart - wsize;
01535     w.x1 = w.x0 + wsize;
01536 
01537     _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
01538     _mbdata = cpl_image_get_data(_smbias);
01539 
01540     nvalid  = 0;
01541 
01542     for (i = 0; i < wsize * wsize; i++) {
01543 
01544         if (_mbdata[i] >= low && _mbdata[i] < high) {
01545             ++nvalid;
01546         }
01547 
01548     }
01549 
01550     _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
01551     _tdata = cpl_image_get_data(_test);
01552 
01553     j = 0;
01554 
01555     for (i = 0; i < wsize * wsize; i++) {
01556 
01557         if (_mbdata[i] >= low && _mbdata[i] < high) {
01558             _tdata[j++] = _mbdata[i];
01559         }
01560 
01561     }
01562 
01563     giraffe_error_push();
01564 
01565     sigma[k++] = cpl_image_get_stdev(_test);
01566 
01567     if (cpl_error_get_code() != CPL_ERROR_NONE) {
01568         --nsigma;
01569     }
01570 
01571     giraffe_error_pop();
01572 
01573     cpl_image_delete(_smbias);
01574     _smbias = NULL;
01575 
01576     cpl_image_delete(_test);
01577     _test = NULL;
01578 
01579     /* Upper right window */
01580 
01581     w.y0 = cpl_image_get_size_y(_mbias) - wstart - wsize;
01582     w.y1 = w.y0 + wsize;
01583 
01584     _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
01585     _mbdata = cpl_image_get_data(_smbias);
01586 
01587     nvalid  = 0;
01588 
01589     for (i = 0; i < wsize * wsize; i++) {
01590 
01591         if (_mbdata[i] >= low && _mbdata[i] < high) {
01592             ++nvalid;
01593         }
01594 
01595     }
01596 
01597     _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
01598     _tdata = cpl_image_get_data(_test);
01599 
01600     j = 0;
01601 
01602     for (i = 0; i < wsize * wsize; i++) {
01603 
01604         if (_mbdata[i] >= low && _mbdata[i] < high) {
01605             _tdata[j++] = _mbdata[i];
01606         }
01607 
01608     }
01609 
01610     giraffe_error_push();
01611 
01612     sigma[k++] = cpl_image_get_stdev(_test);
01613 
01614     if (cpl_error_get_code() != CPL_ERROR_NONE) {
01615         --nsigma;
01616     }
01617 
01618     giraffe_error_pop();
01619 
01620     cpl_image_delete(_smbias);
01621     _smbias = NULL;
01622 
01623     cpl_image_delete(_test);
01624     _test = NULL;
01625 
01626     /* Upper left window */
01627 
01628     w.x0 = wstart;
01629     w.x1 = w.x0 + wsize;
01630 
01631     _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
01632     _mbdata = cpl_image_get_data(_smbias);
01633 
01634     nvalid  = 0;
01635 
01636     for (i = 0; i < wsize * wsize; i++) {
01637 
01638         if (_mbdata[i] >= low && _mbdata[i] < high) {
01639             ++nvalid;
01640         }
01641 
01642     }
01643 
01644     _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
01645     _tdata = cpl_image_get_data(_test);
01646 
01647     j = 0;
01648 
01649     for (i = 0; i < wsize * wsize; i++) {
01650 
01651         if (_mbdata[i] >= low && _mbdata[i] < high) {
01652             _tdata[j++] = _mbdata[i];
01653         }
01654 
01655     }
01656 
01657     giraffe_error_push();
01658 
01659     sigma[k++] = cpl_image_get_stdev(_test);
01660 
01661     if (cpl_error_get_code() != CPL_ERROR_NONE) {
01662         --nsigma;
01663     }
01664 
01665     giraffe_error_pop();
01666 
01667     cpl_image_delete(_smbias);
01668     _smbias = NULL;
01669 
01670     cpl_image_delete(_test);
01671     _test = NULL;
01672 
01673     /* Central window */
01674 
01675     w.x0 = 1024;
01676     w.y0 = 1998;
01677     w.x1 = 1124;
01678     w.y1 = 2098;
01679 
01680     _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
01681     _mbdata = cpl_image_get_data(_smbias);
01682 
01683     nvalid  = 0;
01684 
01685     for (i = 0; i < wsize * wsize; i++) {
01686 
01687         if (_mbdata[i] >= low && _mbdata[i] < high) {
01688             ++nvalid;
01689         }
01690 
01691     }
01692 
01693     _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
01694     _tdata = cpl_image_get_data(_test);
01695 
01696     j = 0;
01697 
01698     for (i = 0; i < wsize * wsize; i++) {
01699 
01700         if (_mbdata[i] >= low && _mbdata[i] < high) {
01701             _tdata[j++] = _mbdata[i];
01702         }
01703 
01704     }
01705 
01706     giraffe_error_push();
01707 
01708     sigma[k++] = cpl_image_get_stdev(_test);
01709 
01710     if (cpl_error_get_code() != CPL_ERROR_NONE) {
01711         --nsigma;
01712     }
01713 
01714     giraffe_error_pop();
01715 
01716     cpl_image_delete(_smbias);
01717     _smbias = NULL;
01718 
01719     cpl_image_delete(_test);
01720     _test = NULL;
01721 
01722     if (nsigma < 1) {
01723         cpl_msg_error(fctid, "Could not compute image statistics in any "
01724                       "window! Aborting ...");
01725 
01726         giraffe_image_delete(mbias);
01727         mbias = NULL;
01728 
01729         giraffe_paf_delete(qc);
01730         qc = NULL;
01731 
01732         return 1;
01733     }
01734 
01735     _sigma = cpl_vector_wrap(nsigma, sigma);
01736 
01737     median = cpl_vector_get_median(_sigma);
01738 
01739     cpl_vector_unwrap(_sigma);
01740     _sigma = NULL;
01741 
01742     cpl_propertylist_update_double(properties, GIALIAS_QCMRON, median);
01743     cpl_propertylist_set_comment(properties, GIALIAS_QCMRON, "Readout noise "
01744                           "(master)");
01745 
01746     giraffe_propertylist_copy(qclog, "QC.OUT1.RON.MASTER", properties,
01747                        GIALIAS_QCMRON);
01748 
01749 
01750     /*
01751      * Compute structure along the x and y axes of the master bias.
01752      */
01753 
01754     _test = cpl_image_collapse_create(_mbias, 0);
01755     cpl_image_divide_scalar(_test, cpl_image_get_size_y(_mbias));
01756 
01757     mean = cpl_image_get_mean(_test);
01758 
01759 
01760     /*
01761      * Compute screened mean value
01762      */
01763 
01764     nvalid = 0;
01765     sum = 0.;
01766 
01767     _tdata = cpl_image_get_data(_test);
01768 
01769     for (i = 0; i < cpl_image_get_size_x(_test); i++) {
01770 
01771         if ((_tdata[i] > mean - sthreshold) &&
01772             (_tdata[i] < mean + sthreshold)) {
01773             sum += _tdata[i];
01774             ++nvalid;
01775         }
01776 
01777     }
01778 
01779     smean = sum / nvalid;
01780 
01781 
01782     /*
01783      * Compute RMS with respect to the screened mean value
01784      */
01785 
01786     nvalid = 0;
01787     sum = 0.;
01788 
01789     for (i = 0; i < cpl_image_get_size_x(_test); i++) {
01790 
01791         if ((_tdata[i] > mean - sthreshold) &&
01792             (_tdata[i] < mean + sthreshold)) {
01793             sum += pow(_tdata[i] - smean, 2.);
01794             ++nvalid;
01795         }
01796 
01797     }
01798 
01799     sum = sqrt(sum / (nvalid - 1));
01800 
01801     cpl_propertylist_update_double(properties, GIALIAS_QCSTRUCTX, sum);
01802     cpl_propertylist_set_comment(properties, GIALIAS_QCSTRUCTX,
01803                                  "Structure along the x axis");
01804 
01805     giraffe_propertylist_copy(qclog, "QC.OUT1.STRUCT.X", properties,
01806                               GIALIAS_QCSTRUCTX);
01807 
01808     cpl_image_delete(_test);
01809     _test = NULL;
01810 
01811 
01812     _test = cpl_image_collapse_create(_mbias, 1);
01813     cpl_image_divide_scalar(_test, cpl_image_get_size_x(_mbias));
01814 
01815     mean = cpl_image_get_mean(_test);
01816 
01817 
01818     /*
01819      * Compute screened mean value
01820      */
01821 
01822     nvalid = 0;
01823     sum = 0.;
01824 
01825     _tdata = cpl_image_get_data(_test);
01826 
01827     for (i = 0; i < cpl_image_get_size_y(_test); i++) {
01828 
01829         if ((_tdata[i] > mean - sthreshold) &&
01830             (_tdata[i] < mean + sthreshold)) {
01831             sum += _tdata[i];
01832             ++nvalid;
01833         }
01834 
01835     }
01836 
01837     smean = sum / nvalid;
01838 
01839 
01840     /*
01841      * Compute RMS with respect to the screened mean value
01842      */
01843 
01844     nvalid = 0;
01845     sum = 0.;
01846 
01847     _tdata = cpl_image_get_data(_test);
01848 
01849     for (i = 0; i < cpl_image_get_size_y(_test); i++) {
01850 
01851         if ((_tdata[i] > mean - sthreshold) &&
01852             (_tdata[i] < mean + sthreshold)) {
01853             sum += pow(_tdata[i] - smean, 2.);
01854             ++nvalid;
01855         }
01856 
01857     }
01858 
01859     sum = sqrt(sum / (nvalid - 1));
01860 
01861     cpl_propertylist_update_double(properties, GIALIAS_QCSTRUCTY, sum);
01862     cpl_propertylist_set_comment(properties, GIALIAS_QCSTRUCTY,
01863                                  "Structure along the y axis");
01864 
01865     giraffe_propertylist_copy(qclog, "QC.OUT1.STRUCT.Y", properties,
01866                        GIALIAS_QCSTRUCTY);
01867 
01868     cpl_image_delete(_test);
01869     _test = NULL;
01870 
01871 
01872     /*
01873      * Write QC1 log and save updated master bias.
01874      */
01875 
01876     giraffe_image_save(mbias, cpl_frame_get_filename(pframe));
01877 
01878     giraffe_image_delete(mbias);
01879     mbias = NULL;
01880 
01881     giraffe_qclog_close(qc);
01882     qc = NULL;
01883 
01884     return 0;
01885 
01886 }
01887 
01888 
01889 /*
01890  * Build table of contents, i.e. the list of available plugins, for
01891  * this module. This function is exported.
01892  */
01893 
01894 int
01895 cpl_plugin_get_info(cpl_pluginlist* list)
01896 {
01897 
01898     cpl_recipe* recipe = cx_calloc(1, sizeof *recipe);
01899     cpl_plugin* plugin = &recipe->interface;
01900 
01901 
01902     cpl_plugin_init(plugin,
01903                     CPL_PLUGIN_API,
01904                     GIRAFFE_BINARY_VERSION,
01905                     CPL_PLUGIN_TYPE_RECIPE,
01906                     "gimasterbias",
01907                     "Creates a master bias image from a set of raw biases.",
01908                     "For detailed information please refer to the "
01909                     "GIRAFFE pipeline user manual.\nIt is available at "
01910                     "http://www.eso.org/pipelines.",
01911                     "Giraffe Pipeline",
01912                     PACKAGE_BUGREPORT,
01913                     giraffe_get_license(),
01914                     gimasterbias_create,
01915                     gimasterbias_exec,
01916                     gimasterbias_destroy);
01917 
01918     cpl_pluginlist_append(list, plugin);
01919 
01920     return 0;
01921 
01922 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.9.0.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Jan 26 14:20:28 2012 by doxygen 1.6.3 written by Dimitri van Heesch, © 1997-2004