/* $Id: hawki_var.c,v 1.5 2015/08/07 13:07:06 jim Exp $
 *
 * This file is part of the HAWKI 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:06 $
 * $Revision: 1.5 $
 * $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 "hawki_var.h"
#include "hawki_pfits.h"

/**
    \defgroup hawki_var hawki_var
    \ingroup supportroutines

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

    \author
    Jim Lewis, CASU
*/

/**@{*/

/*---------------------------------------------------------------------------*/
/**
    \par Name:
        hawki_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
 */
/*---------------------------------------------------------------------------*/

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

    /* Get the header information you need from the primary header */

    p = casu_fits_get_phu(in);
    if (hawki_pfits_get_ndit(p,&ndit) != CASU_OK) {
        cpl_msg_warning(fctid,"No value of NDIT available -- using 1");
        ndit = 1;
    }
    if (hawki_pfits_get_ndsamp(p,&nsamp) != CASU_OK) {
        cpl_msg_warning(fctid,"No value of NDSAMPLES available -- using 2");
        nsamp = 2;
    }

    /* Readnoise contribution */

    var_r = 12.0*readnoise*readnoise*(float)(nsamp-1)/(float)(nsamp*ndit*(nsamp+1));

    /* Factor for Poisson contribution */

    pfac = 1.2*(float)(nsamp*nsamp+1)/(gain*(float)(nsamp*ndit*(nsamp+1)));

    /* 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:
        hawki_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
 */
/*---------------------------------------------------------------------------*/

extern void hawki_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:
        hawki_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
 */
/*---------------------------------------------------------------------------*/

extern void hawki_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:
        hawki_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
 */
/*---------------------------------------------------------------------------*/

extern void hawki_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);
}

/**@}*/

/*

$Log: hawki_var.c,v $
Revision 1.5  2015/08/07 13:07:06  jim
Fixed copyright to ESO

Revision 1.4  2015/03/12 09:16:51  jim
Modified to remove some compiler moans

Revision 1.3  2015/01/29 12:00:16  jim
Modified comments + removed redundant routines

Revision 1.2  2014/12/12 21:45:28  jim
added a few more routines

Revision 1.1  2014/12/11 12:26:21  jim
new entry


*/
