/* $Id: vimos_var.c,v 1.3 2015/08/07 13:07:15 jim Exp $
 *
 * This file is part of the VIMOS Pipeline
 * Copyright (C) 2015 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * $Author: jim $
 * $Date: 2015/08/07 13:07:15 $
 * $Revision: 1.3 $
 * $Name:  $
 */

/* Includes */

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

#include <math.h>
#include <cpl.h>
#include <casu_utils.h>
#include <casu_fits.h>

#include "vimos_var.h"

/**
    \defgroup vimos_var vimos_var
    \ingroup supportroutines

    \brief
    These are routines to create and manipulate variance and inverse 
    variance arrays

    \author
    Jim Lewis, CASU
*/

/**@{*/

/*---------------------------------------------------------------------------*/
/**
    \par Name:
        vimos_var_create
    \par Purpose:
        Create a new variance map 
    \par Description:
        Create a variance map for an input image
    \par Language:
        C
    \param in
        The input image
    \param mask
        A mask marking out where the bad pixels are
    \param readnoise 
        The readnoise (adu) to be used in the variance estimate
    \param gain
        The gain (e-/adu) to be used in the variance estimate
    \returns
        The casu_fits pointer for the variance array
    \author
        Jim Lewis, CASU
 */
/*---------------------------------------------------------------------------*/

casu_fits *vimos_var_create(casu_fits *in, casu_mask *mask, 
                            float readnoise, float gain) {
    int npts,i;
    float var_r,pfac,*vdata;
    unsigned char *bpm;
    cpl_propertylist *p;
    cpl_image *im;
    casu_fits *out;
    const char *fctid = "vimos_var_create";

    /* Readnoise contribution */

    var_r = readnoise*readnoise;

    /* Factor for Poisson contribution */

    pfac = 1.0/gain;

    /* Create a structure for the output variance array */

    out = casu_fits_duplicate(in);
    im = casu_fits_get_image(out);
    vdata = cpl_image_get_data_float(im);
    npts = cpl_image_get_size_x(im)*cpl_image_get_size_y(im);
    bpm = casu_mask_get_data(mask);
    for (i = 0; i < npts; i++) {
        if (bpm[i] == 0)
            vdata[i] = var_r + pfac*fabsf(vdata[i]);
        else
            vdata[i] = 0.0;
    }

    /* Add the given readnoise and gain estimate to the header of the
       output variance array */

    p = casu_fits_get_ehu(out);
    cpl_propertylist_update_float(p,"ESO DRS READNOISE",readnoise);
    cpl_propertylist_set_comment(p,"ESO DRS READNOISE",
                                    "[adu] readnoise estimate used");
    cpl_propertylist_update_float(p,"ESO DRS GAIN",gain);
    cpl_propertylist_set_comment(p,"ESO DRS GAIN",
                                    "[e-/adu] gain estimate used");

    /* Get out of here */

    return(out);
}

/*---------------------------------------------------------------------------*/
/**
    \par Name:
        vimos_var_add
    \par Purpose:
        Propagate the variance of two images that have been added
    \par Description:
        Propagate the variance of two images that have been added. If
        two images have been added, then the variance of the sum is the 
        sum of the variances.
    \par Language:
        C
    \param in1
        The first input variance image
    \param in2
        The second input variance image
    \author
        Jim Lewis, CASU
 */
/*---------------------------------------------------------------------------*/

void vimos_var_add(casu_fits *in1, casu_fits *in2) {
                   cpl_image *im1,*im2;

    /* These should be variances so we can just add them */

    im1 = casu_fits_get_image(in1);
    im2 = casu_fits_get_image(in2);
    cpl_image_add(im1,im2);
}

/*---------------------------------------------------------------------------*/
/**
    \par Name:
        vimos_var_div_im
    \par Purpose:
        Scale the variances of an image that has been divided by a 
        noiseless second image
    \par Description:
        The variance of the first image is scaled by the second image
        which is assumed to be noiseless
    \par Language:
        C
    \param in1
        The input variance image. Result overwrites the input.
    \param in2
        The input divisor image
    \author
        Jim Lewis, CASU
 */
/*---------------------------------------------------------------------------*/

void vimos_var_div_im(casu_fits *in1, casu_fits *in2) {
                      cpl_image *im1,*im2;
    float *d1,*d2;
    int i,n;

    /* Get the images and their data arrays */

    im1 = casu_fits_get_image(in1);
    im2 = casu_fits_get_image(in2);
    n = cpl_image_get_size_x(im1)*cpl_image_get_size_y(im2);
    d1 = cpl_image_get_data_float(im1);
    d2 = cpl_image_get_data_float(im2);

    /* Do the arithmetic */

    for (i = 0; i < n; i++) 
        d1[i] /= d2[i]*d2[i];
}

/*---------------------------------------------------------------------------*/
/**
    \par Name:
        vimos_var_divk
    \par Purpose:
        Scale the variances of an image that has been divided by a 
        constant
    \par Description:
        The variance of the first image is scaled by a constant that
        has been used as a divisor
    \par Language:
        C
    \param in1
        The input variance image. Result overwrites the input values
    \param kscl
        The constant
    \author
        Jim Lewis, CASU
 */
/*---------------------------------------------------------------------------*/

void vimos_var_divk(casu_fits *in, float kscl) {
    cpl_image *im;
    float kscl2;

    /* Do the arithmetic */

    kscl2 = kscl*kscl;
    im = casu_fits_get_image(in);
    cpl_image_divide_scalar(im,kscl2);
}

/*---------------------------------------------------------------------------*/
/**
    \par Name:
        vimos_var_scaledsubt
    \par Purpose:
        Work out the variance for the result of a scaled subtraction
        of two images.
    \par Description:
        The variance second image is scaled and then the variances
        are added.
    \par Language:
        C
    \param in1
        The first input variance image. Result overwrites the input values
    \param in2
        The second input variance image. (The subtracted image)
    \param kscl
        The constant
    \author
        Jim Lewis, CASU
 */
/*---------------------------------------------------------------------------*/

void vimos_var_scaledsubt(casu_fits *in1, casu_fits *in2, float kscl) {
    float kscl2,*data1,*data2;
    int i,n;

    /* Dereference the data arrays */

    data1 = cpl_image_get_data_float(casu_fits_get_image(in1));
    data2 = cpl_image_get_data_float(casu_fits_get_image(in2));
    n = cpl_image_get_size_x(casu_fits_get_image(in1))*
        cpl_image_get_size_y(casu_fits_get_image(in2));

    /* Now do the arithmetic */

    kscl2 = kscl*kscl;
    for (i = 0; i < n; i++) 
        if (data1[i] != 0.0)
            data1[i] += kscl2*data2[i];
}
    
/**@}*/

/*

$Log: vimos_var.c,v $
Revision 1.3  2015/08/07 13:07:15  jim
Fixed copyright to ESO

Revision 1.2  2015/04/30 12:14:29  jim
Added scaled subtract method

Revision 1.1  2015/01/30 12:46:10  jim
new entry


*/
