/* $Id: casu_genbpm.c,v 1.2 2015/08/07 13:06:54 jim Exp $
 *
 * This file is part of the CASU Pipeline utilities
 * 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:06:54 $
 * $Revision: 1.2 $
 * $Name:  $
 */

/* Includes */

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

#include <cpl.h>

#include <math.h>

#include "casu_mods.h"
#include "casu_utils.h"
#include "casu_stats.h"

/**@{*/

/*---------------------------------------------------------------------------*/
/**
    \ingroup casu_modules
    \brief Generate a bad pixel mask from a list of dome flats

    \par Name:
        casu_genbpm
    \par Purpose:
        Generate a bad pixel mask from a list of dark corrected dome flat
        images.
    \par Description:
        A list of dark corrected dome flat images is given. A master flat 
        is created from all the input flats in the list. Each input flat
        is then divided by the master. Bad pixels are marked on the new image
        as those that are above or below the threshold (in sigma) in the 
        new image. Any pixel which has been marked as bad for more than a 
        quarter of the input images is defined as bad in the output mask.
    \par Language:
        C
    \param flatlist
        The list of input dark corrected dome flat images. 
    \param nflatlist
        The number of input images
    \param master
        A master flat. If this is NULL then a master will be created from
        the input list
    \param lthr
        The low rejection threshold in units of sigma
    \param hthr
        The high rejection threshold in units of sigma
    \param expkey
        The header keyword for the exposure time.
    \param bpm_array
        The output bad pixel mask
    \param nbad
        The number of bad pixels found
    \param badfrac
        The fraction of pixels in the map that are bad
    \param status
        An input/output status that is the same as the returned values below.
    \retval CASU_OK
        If everything is ok
    \retval CASU_FATAL
        The flat combination failed
    \par QC headers:
        None
    \par DRS headers:
        None
    \author
        Jim Lewis, CASU
 */
/*---------------------------------------------------------------------------*/

extern int casu_genbpm(casu_fits **flatlist, int nflatlist, cpl_image *master,
                       float lthr, float hthr, const char *expkey, 
                       cpl_array **bpm_array, int *nbad, float *badfrac, 
                       int *status) {
    cpl_image *master_img,*im;
    unsigned char *rejmask,*rejplus;
    cpl_propertylist *drs;
    int npi,i,status2,*bpm,k,nbmax;
    float *idata,med,sig,low,high;
    const char *fctid = "casu_genbpm";

    /* Inherited status */

    *nbad = 0;
    *badfrac = 0.0;
    *bpm_array = NULL;
    if (*status != CASU_OK)
        return(*status);

    /* Combine all of the flats into a master if one isn't already provided */

    if (master == NULL) {
        status2 = CASU_OK;
        (void)casu_imcombine(flatlist,NULL,nflatlist,1,3,1,5.0,expkey,
                             &master_img,NULL,&rejmask,&rejplus,&drs,&status2);
        freespace(rejmask);
        freespace(rejplus);
        freepropertylist(drs);
        if (status2 != CASU_OK) {
            cpl_msg_error(fctid,"Flat combination failed");
            *status = CASU_FATAL;
            return(*status);
        }
    } else {
        master_img = cpl_image_duplicate(master);
    }

    /* Divide the resulting image by its median */

    idata = cpl_image_get_data_float(master_img);
    npi = casu_getnpts(master_img);
    casu_medsig(idata,NULL,npi,&med,&sig);
    cpl_image_divide_scalar(master_img,(double)med);
    for (i = 0; i < npi; i++)
        if (idata[i] == 0.0)
            idata[i] = 1.0;

    /* Create and zero the rejection mask */

    bpm = cpl_calloc(npi,sizeof(int));

    /* Now loop for all input images and divide each by the master */

    for (i = 0; i < nflatlist; i++) {
        im = cpl_image_duplicate(casu_fits_get_image(flatlist[i]));
        cpl_image_divide(im,master_img);
        idata = cpl_image_get_data_float(im);
        casu_medmad(idata,NULL,npi,&med,&sig);
        sig *= 1.48;

        /* Divide the resulting image by its median */

        cpl_image_divide_scalar(im,med);

        /* Get the standard deviation of the image */

        low = 1.0 - lthr*sig/med;
        high = 1.0 + hthr*sig/med;

        /* Now define the bad pixels */

        for (k = 0; k < npi; k++)
            if (idata[k] < low || idata[k] > high)
                bpm[k] += 1;
        cpl_image_delete(im);
    }
    cpl_image_delete(master_img);

    /* Go through the rejection mask and if a pixel has been marked bad 
       more than a set number of times, then it is defined as bad */

    nbmax = max(2,nflatlist/4);
    for (i = 0; i < npi; i++) {
        if (bpm[i] >= nbmax) {
            bpm[i] = 1;
            (*nbad)++;
        } else
            bpm[i] = 0;
    }
    *badfrac = (float)(*nbad)/(float)npi;
    *bpm_array = cpl_array_wrap_int(bpm,npi);

    /* Get out of here */

    return(CASU_OK);
}

/**@}*/

/*

$Log: casu_genbpm.c,v $
Revision 1.2  2015/08/07 13:06:54  jim
Fixed copyright to ESO

Revision 1.1.1.1  2015/06/12 10:44:32  jim
Initial import

Revision 1.5  2015/01/29 11:48:15  jim
modified comments

Revision 1.4  2015/01/09 12:13:15  jim
*** empty log message ***

Revision 1.3  2014/12/11 12:23:33  jim
new version

Revision 1.2  2013/11/21 09:38:13  jim
detabbed

Revision 1.1.1.1  2013-08-27 12:07:48  jim
Imported


*/
