/* $Id: hawki_variance.c,v 1.3 2013-03-25 11:35:10 cgarcia Exp $
 *
 * This file is part of the HAWKI Pipeline
 * Copyright (C) 2002,2003 European Southern Observatory
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/*
 * $Author: cgarcia $
 * $Date: 2013-03-25 11:35:10 $
 * $Revision: 1.3 $
 * $Name: not supported by cvs2svn $
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

/*-----------------------------------------------------------------------------
                                   Includes
 -----------------------------------------------------------------------------*/

#include <float.h>
#include <string.h>
#include <math.h>
#include <cpl.h>

#include "hawki_variance.h"

/*----------------------------------------------------------------------------*/
/**
 * @defgroup hawki_variance       Variance estimation for raw images.
 */
/*----------------------------------------------------------------------------*/

/**@{*/
 
/*----------------------------------------------------------------------------*/
/**
  @brief    Create the associated variance of a raw image
  @param    image      the raw image
  @param    gain       the gain of the detector (e-/ADU)
  @param    ron        the ron for one read of the detector (ADU)
  @param    ndit       the number of total integrations.
  @param    ndsamples  the number of non-destructive readouts.
  @return   The variance image if suceed. NULL elsewhere.

   The variance is computed with the following 
   equation:
   \f[ \sigma^{2}(i,j) = \frac{6 S(i,j)}{5 g n_{nds} n_{dit}} (\frac{n_{nds}^{2} + 1}{n_{nds} + 1}) + \frac{12 RON^{2}(i,j)}{g^{2} n_{nds} n_{dit}} (\frac{n_{nds}-1}{n_{nds}+1})\f]
   where: \f$\sigma^{2}(i,j)\f$ is the total variance in (ADU\f$^{2}\f$),
   \f$S(i,j)\f$ is the signal in ADU of electrons in the pixel potencial 
   well, so to the measured ADU we must first remove the bias,
   \f$g\f$ is the gain of the  detector (in electrons/ADU),
   \f$n_{nds}\f$ is the number of non-denstructive reads (<i>ndsamples</i>),
   \f$n_{ndit}\f$ is the number of total integrations (<i>ndit</i>)
   and \f$RON(i,j)\f$ is the readout noise of a single readout of the
   detector (in ADU).
   Note that the dimensional inconsistency of the previous
   expression is only apparent.
   The expression used, however is only approximate, and is valid for
   RON  << S(i,j). For low signal levels there may be significant
   deviations

 */
/*----------------------------------------------------------------------------*/
cpl_image * hawki_image_create_variance
(const cpl_image * image,
 double            gain,
 double            ron,
 int               ndit,
 int               ndsamples)
{
    cpl_image    * variance;
    float        * variance_p;
    const float  * image_p;
    int            pix;
    int            npix;
    double         poisson_contrib;
    double         poisson_factor;
    double         ron_contrib;
    

    /* Test entries */
    if (image == NULL) return NULL;

    /* Create new image */
    variance = cpl_image_duplicate(image);

    /* Loop on pixels */
    variance_p = cpl_image_get_data(variance);
    image_p = cpl_image_get_data_const(image);
    npix = cpl_image_get_size_x(image) * cpl_image_get_size_y(image); 
    /* TODO: There is a Delta_t factor that appears in the Vacca article
     * that is not reflexed here! */ 
    ron_contrib = 12 * ron * ron / (gain * gain * ndsamples * ndit) *
        (ndsamples - 1) / (ndsamples + 1);
    poisson_factor = 6. / (5. * gain * ndsamples * ndit) * 
        (ndsamples * ndsamples + 1) / (ndsamples + 1);
    for(pix = 0; pix < npix; ++pix)
    {
        /* TODO: Include the effect of saturation in the TLI mode used by HAWK-I */
        poisson_contrib = poisson_factor * fabs(image_p[pix]);
        variance_p[pix] = poisson_contrib + ron_contrib;
    }
    
    /* Return */
    return variance;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Create the associated variance of raw imagelist
  @param    imagelist_raw  the raw imagelist
  @param    gain           the gain of the detector (e-/ADU)
  @param    ron            the ron for one read of the detector (ADU)
  @param    ndit           the number of total integrations.
  @param    ndsamples      the number of non-destructive readouts.
  @return   The variance imagelist if suceed. NULL elsewhere.

   The original imagelist_raw is empty after the process. This is so in order
   not to duplicate the amount of memory needed. However it will still have to
   be deleted with cpl_imagelist_delete. Also the returned pointer have
   to be deleted with cpl_imagelist_delete, of course.

   The variance is computed with the following 
   equation:
   \f[ \sigma^{2}(i,j) = \frac{6 S(i,j)}{5 g n_{nds} n_{dit}} (\frac{n_{nds}^{2} + 1}{n_{nds} + 1}) + \frac{12 RON^{2}(i,j)}{g^{2} n_{nds} n_{dit}} (\frac{n_{nds}-1}{n_{nds}+1})\f]
   where: \f$\sigma^{2}(i,j)\f$ is the total variance in (ADU\f$^{2}\f$),
   \f$S(i,j)\f$ is the signal in ADU of electrons in the pixel potencial 
   well, so to the measured ADU we must first remove the bias,
   \f$g\f$ is the gain of the  detector (in electrons/ADU),
   \f$n_{nds}\f$ is the number of non-denstructive reads (<i>ndsamples</i>),
   \f$n_{ndit}\f$ is the number of total integrations (<i>ndit</i>)
   and \f$RON(i,j)\f$ is the readout noise of a single readout of the
   detector (in ADU).
   Note that the dimensional inconsistency of the previous
   expression is only apparent.
   The expression used, however is only approximate, and is valid for
   RON  << S(i,j). For low signal levels there may be significant
   deviations.
   
 */
/*----------------------------------------------------------------------------*/
cpl_imagelist * hawki_imglist_create_variances_and_delete
(cpl_imagelist * imagelist_raw, 
 double          gain,
 double          ron,
 int             ndit,
 int             ndsamples)
{
    cpl_imagelist  * variances;
    
    variances = cpl_imagelist_new();
    /* Loop on the frames */
    while(cpl_imagelist_get_size(imagelist_raw) > 0)
    {
        cpl_image * variance;
            
        variance = hawki_image_create_variance
            (cpl_imagelist_get(imagelist_raw, 0), gain, ron, ndit, ndsamples);
        cpl_imagelist_set(variances, variance, 
                          cpl_imagelist_get_size(variances));
        cpl_image_delete(cpl_imagelist_unset(imagelist_raw, 0));
    }
    return variances;
}


/**@}*/
