GIRAFFE Pipeline Reference Manual

gimasterbias.c

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

This file is part of the GIRAFFE Pipeline Reference Manual 2.5.2.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Fri Jun 13 14:36:22 2008 by doxygen 1.4.6 written by Dimitri van Heesch, © 1997-2004