/* $Id: xsh_qc_handling.c,v 1.9 2009-09-27 10:39:36 amodigli Exp $
 *
 * This file is part of the IRPLIB Package
 * 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 St, Fifth Floor, Boston, MA  02111-1307  USA
 */

/*
 * $Author: amodigli $
 * $Date: 2009-09-27 10:39:36 $
 * $Revision: 1.9 $
 */

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

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

#include <cpl.h>

#include <regex.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <fnmatch.h>
#include <string.h>
#include <assert.h>

#include "xsh_msg.h"
#include "xsh_qc_handling.h"
#include "xsh_qc_definition.h"
#include "xsh_pfits_qc.h"


/*-----------------------------------------------------------------------------
                        Defines and Static variables
 -----------------------------------------------------------------------------*/
#define USE_REGEXP 
/*----------------------------------------------------------------------------*/
/**
 * @defgroup xsh_qc_handling    QC Structure Functions
 *
 */
/*----------------------------------------------------------------------------*/

/**@{*/

/*-----------------------------------------------------------------------------
                              Function codes
 -----------------------------------------------------------------------------*/

/* Functions */

qc_description * xsh_get_qc_desc_by_kw( const char *kw )
{
  qc_description * current ;

  for( current = (qc_description *)qc_table ; current->kw_name != NULL ;
       current++ )
    if ( strcmp( current->kw_name, kw ) == 0 ) return current ;
  return NULL ;
}


qc_description * xsh_get_qc_desc_by_pro_catg( const char * pro_catg )
{
  qc_description * current ;
#if defined(USE_REGEXP)
  regex_t reg ;
  int err ;

  for( current = (qc_description *)qc_table ; current->kw_name != NULL ;
       current++ ) {
    if ( current->pro_catg == NULL ) continue ;
    err = regcomp( &reg, current->pro_catg, REG_EXTENDED | REG_ICASE ) ;
    if ( err != 0 ) continue ;
    err = regexec( &reg, pro_catg, 0, 0, 0 ) ;
    regfree( &reg ) ;
    if ( err == 0 ) return current ;
  }
#else
  for( current = (qc_description *)qc_table ; current->kw_name != NULL ;
       current++ ) {
    if ( current->pro_catg == NULL ) return current ;
    if ( fnmatch( current->pro_catg, pro_catg, 0 ) == 0 )
      return current ;
  }
#endif
  return NULL ;
}

int xsh_qc_in_recipe( qc_description * pqc, xsh_instrument * instrument )
{
  if ( ( pqc->kw_recipes != NULL &&
	 strstr( pqc->kw_recipes, instrument->recipe_id ) != NULL ) ||
       ( pqc->kw_recipes_tbw != NULL &&
	 strstr( pqc->kw_recipes_tbw, instrument->recipe_id ) != NULL ) ) return 0 ;

  return -1 ;
}

qc_description * xsh_get_qc_desc_by_recipe( const char *recipe,
					    qc_description *prev )
{
  qc_description * current ;

  if ( prev == NULL ) {
    current = (qc_description *)qc_table ;
  }
  else current = prev+1 ;

  for( ; current->kw_name != NULL ; current++ ) {
    if ( ((current->kw_recipes != NULL &&
	 strstr( current->kw_recipes, recipe ) != NULL) ||
	 (current->kw_recipes_tbw != NULL &&
	  strstr( current->kw_recipes_tbw, recipe ) != NULL)) &&
	 current->kw_type != CPL_TYPE_INVALID )
      return current ;
  }
  return NULL ;
}


qc_description * xsh_get_qc_desc_by_function( char *function,
					      qc_description *prev )
{
  qc_description * current ;

  if ( prev == NULL ) {
    current = (qc_description *)qc_table ;
  }
  else current = prev+1 ;

  for( ; current->kw_name != NULL ; current++ ) {
    if ( (current->kw_function != NULL &&
	  strstr( current->kw_function, function ) != NULL) )
      return current ;
  }
  return NULL ;
}

/** 
 * Check if the ARM is in the list of arms of the QC descriptor.
 * If yes or the list of arms is NULL, returns TRUE (1), returns 0 otherwise.
 * Is used for somw WC parameters that are relevant only for some specific
 * arm(s) such as BP-MAP NOISYPIX (calculated in xsh_mdark).
 * 
 * @param arm Name of the arm (NIR, UVB, VIS)
 * @param pqc Pointer to QC parameter description
 * 
 * @return 1 if the arm is in the qc.arms string or qc.arms is null, 0 otherwise
 */
int xsh_is_qc_for_arm( const char * arm, qc_description * pqc )
{
  if ( pqc->arms == NULL ||
       strstr( pqc->arms, arm ) != NULL ) return 1 ;
  return 0 ;
}

/** 
 * Check if the PRO.CATG is in the list of arms of the QC descriptor.
 * If yes or the list of pro.catg is NULL, returns TRUE (1), returns 0 otherwise.
 * 
 * @param pro_catg PRO.CATG string
 * @param pqc Pointer to QC parameter description
 * 
 * @return 1 if the arm is in the qc.pro_catg string or qc.pro_catg is null,
 * 0 otherwise.
 */
int xsh_is_qc_for_pro_catg( const char * pro_catg, qc_description * pqc )
{
#if defined(USE_REGEXP)
  regex_t reg ;
  int err ;

  if ( pqc == NULL || pqc->pro_catg == NULL ) return 1 ;

  err = regcomp( &reg, pqc->pro_catg, REG_EXTENDED | REG_ICASE ) ;
  if ( err != 0 ) return 0 ;
  err = regexec( &reg, pro_catg, 0, 0, 0 ) ;
  regfree( &reg ) ;
  if ( err == 0 ) return 1 ;

#else
  if( pqc->pro_catg == NULL || fnmatch( pqc->pro_catg, pro_catg, 0 )  == 0 ) {
    if ( pqc->pro_catg == NULL ) {
      xsh_msg_dbg_high( "++++++++ QC '%s' has a NULL PRO.CATG",
			pqc->kw_name ) ;
    }
    else {
      xsh_msg_dbg_high( "++++++++ QC '%s' found for PRO.CATG '%s'",
			pqc->kw_name, pqc->pro_catg ) ;
    }
    return 1 ;
  }
#endif
  return 0 ;
}



/**
 * Calculates and set the QC parameters relevant for Cosmic Rays.
 *
 * @param pre Pointer to XSH_PRE Structure
 * @param nbcrh Total umber of cosmics found
 * @param nframes Number of frames used to remove cosmics
 */
void xsh_add_qc_crh (xsh_pre* pre, int nbcrh, int nframes)
{
  double qc_crrate = 0.0;
  float nbcr_avg ;        /**< Average of cosmics per frame */

  XSH_ASSURE_NOT_NULL(pre);
  XSH_ASSURE_NOT_ILLEGAL(pre->pszx >0. && pre->pszy > 0);
  XSH_ASSURE_NOT_ILLEGAL(pre->exptime > 0);
  /*
    QC.CRRATE = avg_nb_of_crh_per_frame/(exposure_time*size_of_detector_in_cm2)
    Nb of Cosmics per cm2 per second.
    The whole size of the image in cm2 is given by pszx and pszy. These
    values are in MICRONS.
  */
  xsh_msg_dbg_medium( "add_qc_crh - Exptime = %f", pre->exptime ) ;
  qc_crrate =
    (double) nbcrh / (((double) nframes) * (pre->exptime *
    (pre->pszx / 10000.0) * (pre->pszy /10000.0) * pre->nx * pre->ny)) ;
  nbcr_avg = nbcrh/nframes ;

  /*
    Now set QC KW
  */
  check( xsh_pfits_set_qc_crrate( pre->data_header,qc_crrate) ) ;
  check( xsh_pfits_set_qc_ncrh( pre->data_header,nbcrh) ) ;
  check( xsh_pfits_set_qc_ncrh_mean( pre->data_header,nbcr_avg) ) ;
  /* Same thing for the qual header */
  check( xsh_pfits_set_qc_crrate( pre->qual_header,qc_crrate) ) ;
  check( xsh_pfits_set_qc_ncrh( pre->qual_header,nbcrh) ) ;
  check( xsh_pfits_set_qc_ncrh_mean( pre->qual_header,nbcr_avg) ) ;
  cleanup:
    return ;
}






/**@}*/
