/*                                                                           *
 *   This file is part of the ESO X-shooter Pipeline                         *
 *   Copyright (C) 2006 European Southern Observatory                        *
 *                                                                           *
 *   This library 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, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA    *
 *                                                                           */

/*
 * $Author: amodigli $
 * $Date: 2013-04-26 10:44:01 $
 * $Revision: 1.16 $
 * $Name: not supported by cvs2svn $
 */

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

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


#include <xsh_dump.h>
#include <xsh_utils.h>
#include <xsh_error.h>
#include <xsh_msg.h>
#include <xsh_qc_handling.h>
#include <xsh_data_instrument.h>
#include <xsh_pfits.h>
#include <string.h>
#include <cpl.h>
#include <stdbool.h>
#include <xsh_pfits_qc.h>

/*---------------------------------------------------------------------------*/
/**
 * @defgroup xsh_pfits_qc FITS header QC access
 * @ingroup xsh_pfits
 *
 */
/*---------------------------------------------------------------------------*/

/**@{*/

/*----------------------------------------------------------------------------
                               Function prototypes
 ----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------
                               Function implementation
 ----------------------------------------------------------------------------*/

/**
  @brief
    Find out the QC NCRH value
  @param plist
    The property list to read from
  @return
    The requested value
 */
int xsh_pfits_get_qc_ncrh( const cpl_propertylist * plist)
{
  int returnvalue = -1 ;

  check_msg( xsh_get_property_value( plist, XSH_QC_CRH_NUMBER,
				     CPL_TYPE_INT, &returnvalue ),
	     "Error reading Keyword '%s'", XSH_QC_CRH_NUMBER ) ;
  cleanup:
    return returnvalue ;
}

/**
  @brief
    Find out the QC NCRH value
  @param plist
    The property list to read from
  @return
    The requested value
 */
double xsh_pfits_get_qc_ncrh_mean( const cpl_propertylist * plist)
{
  double returnvalue = -1 ;

  check_msg( xsh_get_property_value( plist, XSH_QC_CRH_NUMBER_MEAN,
				     CPL_TYPE_DOUBLE, &returnvalue ),
	     "Error reading Keyword '%s'", XSH_QC_CRH_NUMBER_MEAN ) ;
  cleanup:
    return returnvalue ;
}



/*--------------------------------------------------------------------------- */
/**
  @brief    find out the QC.MBIASAVG value
  @param    plist    Property list to read from
  @return   double the requested value   
 */
/*--------------------------------------------------------------------------- */
double
xsh_pfits_get_qc_mbiasavg (const cpl_propertylist * plist)
{
  double returnvalue = 0.0;

  check_msg (xsh_get_property_value (plist, XSH_QC_MASTER_BIAS_MEAN,
    CPL_TYPE_DOUBLE, &returnvalue),
    "Error reading keyword '%s'", XSH_QC_MASTER_BIAS_MEAN);

cleanup:
  return returnvalue;
}


/**
  @brief    find out the QC.MBIASMED value
  @param    plist    Property list to read from
  @return   double the requested value   
 */
/*--------------------------------------------------------------------------- */
double
xsh_pfits_get_qc_mbiasmed (const cpl_propertylist * plist)
{
  double returnvalue = 0.0;

  check_msg (xsh_get_property_value (plist, XSH_QC_MASTER_BIAS_MEDIAN,
    CPL_TYPE_DOUBLE, &returnvalue),
    "Error reading keyword '%s'", XSH_QC_MASTER_BIAS_MEDIAN);

cleanup:
  return returnvalue;
}


/**
  @brief    find out the QC.MBIASRMS value
  @param    plist    Property list to read from
  @return   double the requested value   
 */
/*--------------------------------------------------------------------------- */
double
xsh_pfits_get_qc_mbiasrms (const cpl_propertylist * plist)
{
  double returnvalue = 0.0;

  check_msg (xsh_get_property_value (plist, XSH_QC_MASTER_BIAS_RMS,
    CPL_TYPE_DOUBLE, &returnvalue),
    "Error reading keyword '%s'", XSH_QC_MASTER_BIAS_RMS);

cleanup:
  return returnvalue;
}


/**
  @brief    find out the QC.NHPIX value
  @param    plist    Property list to read from
  @return   double the requested value   
 */
/*--------------------------------------------------------------------------- */
int
xsh_pfits_get_qc_nhpix (const cpl_propertylist * plist)
{
  int returnvalue = 0.0;
  cpl_type type;

  type = cpl_propertylist_get_type (plist, XSH_QC_NHPIX);

  check_msg (xsh_get_property_value (plist, XSH_QC_NHPIX,
				     type, &returnvalue),
	     "Error reading keyword '%s'", XSH_QC_NHPIX);

cleanup:
  return returnvalue;
}


/**
  @brief    find out the QC.MBIASSLOPE value
  @param    plist    Property list to read from
  @return   double the requested value   
 */
/*--------------------------------------------------------------------------- */
double
xsh_pfits_get_qc_mbiasslope (const cpl_propertylist * plist)
{
  double returnvalue = 0.0;
  cpl_type type;

  type = cpl_propertylist_get_type (plist, XSH_QC_MBIASSLOPE);

  check_msg (xsh_get_property_value (plist, XSH_QC_MBIASSLOPE,
				     type, &returnvalue),
	     "Error reading keyword '%s'", XSH_QC_MBIASSLOPE);

cleanup:
  return returnvalue;
}

/*-------------------------------------------------------------------------- */
 /*
   @brief
     Find out the QC STRUCT X value
   @param    plist
     The property list to read from
   @return
     The requested value
 */
/*-------------------------------------------------------------------------- */
double xsh_pfits_get_qc_structx( const cpl_propertylist * plist)
 {
   double returnvalue = 0;

   check_msg( xsh_get_property_value( plist, XSH_QC_STRUCT_X_REG1,
     CPL_TYPE_DOUBLE, &returnvalue),
     "Error reading keyword '%s'", XSH_QC_STRUCT_X_REG1);

 cleanup:
   return returnvalue;
}

/*-------------------------------------------------------------------------- */
/*
   @brief
     Find out the QC STRUCTY value
   @param    plist
     The property list to read from
   @return
     The requested value
*/
/*-------------------------------------------------------------------------- */
double xsh_pfits_get_qc_structy( const cpl_propertylist * plist)
{
   double returnvalue = 0;

   check_msg( xsh_get_property_value( plist, XSH_QC_STRUCT_Y_REG1,
     CPL_TYPE_DOUBLE, &returnvalue),
     "Error reading keyword '%s'", XSH_QC_STRUCT_Y_REG1);

cleanup:
   return returnvalue;
}


/*-------------------------------------------------------------------------- */
/*
   @brief
     Find out the QC RON value
   @param    plist
     The property list to read from
   @return
     The requested value
*/
/*-------------------------------------------------------------------------- */
double xsh_pfits_get_qc_ron( const cpl_propertylist * plist)
{
 double returnvalue = 0;

   check_msg( xsh_get_property_value( plist, XSH_QC_RON_REG1,
     CPL_TYPE_DOUBLE, &returnvalue),
     "Error reading keyword '%s'", XSH_QC_RON_REG1);

cleanup:
   return returnvalue;
}


/**
  @brief    Write the QC.RON.MASTER value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_ron_master (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist,XSH_QC_MASTER_RON,value),
             "Error writing keyword '%s'", XSH_QC_MASTER_RON);
  cpl_propertylist_set_comment(plist,XSH_QC_MASTER_RON,XSH_QC_MASTER_RON_C);

cleanup:
  return;
}

/**
  @brief    Write the QC.FPN.MASTER value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_fpn_master (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist,XSH_QC_MASTER_FPN,value),
             "Error writing keyword '%s'", XSH_QC_MASTER_FPN);
  cpl_propertylist_set_comment(plist,XSH_QC_MASTER_FPN,XSH_QC_MASTER_FPN_C);

cleanup:
  return;
}

/**
  @brief    Write the QC.FPN value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_fpn(cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist,XSH_QC_FPN,value),
             "Error writing keyword '%s'", XSH_QC_FPN);
  cpl_propertylist_set_comment(plist,XSH_QC_FPN,XSH_QC_FPN_C);

cleanup:
  return;
}


/**
  @brief    Write the QC.FPN value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_fpn_err(cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist,XSH_QC_FPN_ERR,value),
             "Error writing keyword '%s'", XSH_QC_FPN_ERR);
  cpl_propertylist_set_comment(plist,XSH_QC_FPN_ERR,XSH_QC_FPN_ERR_C);

cleanup:
  return;
}


/**
  @brief    Write the QC.NORMFPN value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_norm_fpn(cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist,XSH_QC_NORM_FPN,value),
             "Error writing keyword '%s'", XSH_QC_NORM_FPN);
  cpl_propertylist_set_comment(plist,XSH_QC_NORM_FPN,XSH_QC_NORM_FPN_C);

cleanup:
  return;
}

/**
  @brief    Write the QC.NORMFPN.ERR value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_norm_fpn_err(cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist,XSH_QC_NORM_FPN_ERR,value),
             "Error writing keyword '%s'", XSH_QC_NORM_FPN_ERR);
  cpl_propertylist_set_comment(plist,XSH_QC_NORM_FPN_ERR,XSH_QC_NORM_FPN_ERR_C);

cleanup:
  return;
}


/**
  @brief    Write the QC.STRUCTX value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_reg1_structx (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist,XSH_QC_STRUCT_X_REG1,value),
             "Error writing keyword '%s'", XSH_QC_STRUCT_X_REG1);
  cpl_propertylist_set_comment(plist,XSH_QC_STRUCT_X_REG1,XSH_QC_STRUCT_X_REG1_C);

cleanup:
  return;
}

/**
  @brief    Write the QC.STRUCTY value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_reg1_structy (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist,XSH_QC_STRUCT_Y_REG1, value),
             "Error writing keyword '%s'",XSH_QC_STRUCT_Y_REG1);
  cpl_propertylist_set_comment(plist,XSH_QC_STRUCT_Y_REG1,XSH_QC_STRUCT_Y_REG1_C);

cleanup:
  return;
}



/**
  @brief    Write the QC.STRUCTX value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_reg2_structx (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist,XSH_QC_STRUCT_X_REG2, value),
             "Error writing keyword '%s'", XSH_QC_STRUCT_X_REG2);
  cpl_propertylist_set_comment(plist,XSH_QC_STRUCT_X_REG2,XSH_QC_STRUCT_X_REG2_C);

cleanup:
  return;
}

/**
  @brief    Write the QC.STRUCTY value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_reg2_structy (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist,XSH_QC_STRUCT_Y_REG2, value),
             "Error writing keyword '%s'",XSH_QC_STRUCT_Y_REG2);
  cpl_propertylist_set_comment(plist,XSH_QC_STRUCT_Y_REG2,XSH_QC_STRUCT_Y_REG2_C);

cleanup:
  return;
}

/*--------------------------------------------------------------------------- */
/*
  @brief
    Write the QC RON value
  @param plist
    The property list to write to
  @param value
    The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_ron( cpl_propertylist * plist, double value)
{
  check_msg( cpl_propertylist_update_double( plist,XSH_QC_RON, value),
    "Error writing keyword '%s'",XSH_QC_RON);
  cpl_propertylist_set_comment( plist,XSH_QC_RON,XSH_QC_RON_C);

cleanup:
  return;
}


/*--------------------------------------------------------------------------- */
/*
  @brief
    Write the QC RON ERR value
  @param plist
    The property list to write to
  @param value
    The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_ron_err( cpl_propertylist * plist, double value)
{
  check_msg( cpl_propertylist_update_double( plist,XSH_QC_RON_ERR, value),
    "Error writing keyword '%s'",XSH_QC_RON_ERR);
  cpl_propertylist_set_comment( plist,XSH_QC_RON_ERR,XSH_QC_RON_ERR_C);

cleanup:
  return;
}

/*--------------------------------------------------------------------------- */
/*
  @brief
    Write the QC RON value
  @param plist
    The property list to write to
  @param value
    The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_ron1( cpl_propertylist * plist, double value)
{
  check_msg( cpl_propertylist_update_double( plist,XSH_QC_RON_REG1, value),
    "Error writing keyword '%s'",XSH_QC_RON_REG1);
  cpl_propertylist_set_comment( plist,XSH_QC_RON_REG1,XSH_QC_RON_REG1_C);

cleanup:
  return;
}


/*--------------------------------------------------------------------------- */
/*
  @brief
    Write the QC RON value
  @param plist
    The property list to write to
  @param value
    The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_ron2( cpl_propertylist * plist, double value)
{
  check_msg( cpl_propertylist_update_double( plist,XSH_QC_RON_REG2, value),
    "Error writing keyword '%s'",XSH_QC_RON_REG2);
  cpl_propertylist_set_comment( plist,XSH_QC_RON_REG2,XSH_QC_RON_REG2_C);

cleanup:
  return;
}



/*--------------------------------------------------------------------------- */
/*
  @brief
    Write the QC RON value
  @param plist
    The property list to write to
  @param value
    The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_ron1_err( cpl_propertylist * plist, double value)
{
  check_msg( cpl_propertylist_update_double( plist,XSH_QC_RON_REG1_ERR, value),
    "Error writing keyword '%s'",XSH_QC_RON_REG1_ERR);
  cpl_propertylist_set_comment( plist,XSH_QC_RON_REG1_ERR,XSH_QC_RON_REG1_ERR_C);

cleanup:
  return;
}


/*--------------------------------------------------------------------------- */
/*
  @brief
    Write the QC RON ERR value
  @param plist
    The property list to write to
  @param value
    The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_ron2_err( cpl_propertylist * plist, double value)
{
  check_msg( cpl_propertylist_update_double( plist,XSH_QC_RON_REG2_ERR, value),
    "Error writing keyword '%s'",XSH_QC_RON_REG2_ERR);
  cpl_propertylist_set_comment( plist,XSH_QC_RON_REG2_ERR,XSH_QC_RON_REG2_ERR_C);

cleanup:
  return;
}


void xsh_pfits_set_qc_nlinecat(cpl_propertylist * plist, double value)
{
check_msg (cpl_propertylist_update_double (plist, XSH_QC_NLINE_CAT, value),
             "Error writing keyword '%s'", XSH_QC_NLINE_CAT);
cpl_propertylist_set_comment (plist, XSH_QC_NLINE_CAT,XSH_QC_NLINE_CAT_C);
cleanup:
  return;
}


void xsh_pfits_set_qc_nlinecat_clean(cpl_propertylist * plist, double value)
{
check_msg (cpl_propertylist_update_double (plist, XSH_QC_NLINE_CAT_CLEAN, value),
             "Error writing keyword '%s'", XSH_QC_NLINE_CAT_CLEAN);
cpl_propertylist_set_comment (plist, XSH_QC_NLINE_CAT_CLEAN,XSH_QC_NLINE_CAT_CLEAN_C);
cleanup:
  return;
}


void xsh_pfits_set_qc_nlinefound_fib4(cpl_propertylist * plist, double value)
{
check_msg (cpl_propertylist_update_double (plist, XSH_QC_NLINE4_FOUND, value),
             "Error writing keyword '%s'", XSH_QC_NLINE4_FOUND);
cpl_propertylist_set_comment (plist, XSH_QC_NLINE4_FOUND,XSH_QC_NLINE4_FOUND_C);
cleanup:
  return;
}

void xsh_pfits_set_qc_nlinefound_clean_fib4(cpl_propertylist * plist, double value)
{
check_msg (cpl_propertylist_update_double (plist, XSH_QC_NLINE4_FOUND_CLEAN, value),
             "Error writing keyword '%s'", XSH_QC_NLINE4_FOUND_CLEAN);
cpl_propertylist_set_comment (plist, XSH_QC_NLINE4_FOUND_CLEAN,XSH_QC_NLINE4_FOUND_CLEAN_C);
cleanup:
  return;
}


void xsh_pfits_set_qc_nlinefound(cpl_propertylist * plist, double value)
{
check_msg (cpl_propertylist_update_double (plist, XSH_QC_NLINE_FOUND, value),
             "Error writing keyword '%s'", XSH_QC_NLINE_FOUND);
cpl_propertylist_set_comment (plist, XSH_QC_NLINE_FOUND,XSH_QC_NLINE_FOUND_C);
cleanup:
  return;
}

void xsh_pfits_set_qc_nlinefound_clean(cpl_propertylist * plist, double value)
{
check_msg (cpl_propertylist_update_double (plist, XSH_QC_NLINE_FOUND_CLEAN, value),
             "Error writing keyword '%s'", XSH_QC_NLINE_FOUND_CLEAN);
cpl_propertylist_set_comment (plist, XSH_QC_NLINE_FOUND_CLEAN,XSH_QC_NLINE_FOUND_CLEAN_C);
cleanup:
  return;
}

/**
  @brief    Write the QC.MBIASAVG value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_mbiasavg (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist,XSH_QC_MASTER_BIAS_MEAN, value),
	     "Error writing keyword '%s'",XSH_QC_MASTER_BIAS_MEAN);
  cpl_propertylist_set_comment(plist,XSH_QC_MASTER_BIAS_MEAN,XSH_QC_MASTER_BIAS_MEAN_C);

cleanup:
  return;
}

/**
  @brief    Write the QC.MBIASMED value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_mbiasmed (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist,XSH_QC_MASTER_BIAS_MEDIAN, value),
	     "Error writing keyword '%s'",XSH_QC_MASTER_BIAS_MEDIAN);
  cpl_propertylist_set_comment(plist,XSH_QC_MASTER_BIAS_MEDIAN,XSH_QC_MASTER_BIAS_MEDIAN_C);

cleanup:
  return;
}


/**
  @brief    Write the QC.MBIASRMS value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_mbiasrms (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist,XSH_QC_MASTER_BIAS_RMS, value),
	     "Error writing keyword '%s'",XSH_QC_MASTER_BIAS_RMS);
  cpl_propertylist_set_comment(plist,XSH_QC_MASTER_BIAS_RMS,XSH_QC_MASTER_BIAS_RMS_C);

cleanup:
  return;
}

/**
  @brief    Write the QC.NHPIX value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_nhpix (cpl_propertylist * plist, int value)
{
  check_msg (cpl_propertylist_update_int (plist, XSH_QC_NHPIX, value),
	     "Error writing keyword '%s'", XSH_QC_NHPIX);

cleanup:
  return;
}


/**
  @brief    Write the QC.NHPIX value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_noisepix (cpl_propertylist * plist, int value)
{
  check_msg (cpl_propertylist_update_int (plist, XSH_QC_BP_MAP_PICKUP_NOISE_PIX, value),
	     "Error writing keyword '%s'", XSH_QC_BP_MAP_PICKUP_NOISE_PIX);

cleanup:
  return;
}


/**
  @brief    Write the QC.MBIASSLOPE value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_mbiasslope (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist, XSH_QC_MBIASSLOPE, value),
	     "Error writing keyword '%s'", XSH_QC_MBIASSLOPE);

cleanup:
  return;
}


/**
  @brief    Write the QC.NCRH value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_ncrh (cpl_propertylist * plist, int value)
{
  check_msg (cpl_propertylist_update_int (plist, XSH_QC_CRH_NUMBER, value),
	     "Error writing keyword '%s'", XSH_QC_CRH_NUMBER);
  cpl_propertylist_set_comment(plist, XSH_QC_CRH_NUMBER,XSH_QC_CRH_NUMBER_C);

cleanup:
  return;
}

/**
  @brief    Write the QC.NCRH.AVG value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_ncrh_mean (cpl_propertylist * plist, const double value)
{
  check_msg (cpl_propertylist_update_double (plist, XSH_QC_CRH_NUMBER_MEAN, value),
	     "Error writing keyword '%s'", XSH_QC_CRH_NUMBER_MEAN);
  cpl_propertylist_set_comment(plist, XSH_QC_CRH_NUMBER_MEAN,XSH_QC_CRH_NUMBER_MEAN_C);

cleanup:
  return;
}

/**
  @brief    Write the QC.NCRH.TOT value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_ncrh_tot (cpl_propertylist * plist, const int value)
{
  check_msg (cpl_propertylist_update_int (plist, XSH_QC_CRH_NUMBER_TOT, value),
	     "Error writing keyword '%s'", XSH_QC_CRH_NUMBER_TOT);
  cpl_propertylist_set_comment(plist, XSH_QC_CRH_NUMBER_TOT,XSH_QC_CRH_NUMBER_TOT_C);

cleanup:
  return;
}

/**
  @brief    Write the QC.CRRATE value
  @param    plist      Property list to write to
  @param    value      The value to write (double)
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_crrate (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_float (plist, XSH_QC_CRH_RATE, value),
	     "Error writing keyword '%s'", XSH_QC_CRH_RATE);
  cpl_propertylist_set_comment(plist,XSH_QC_CRH_RATE,XSH_QC_CRH_RATE_C);

cleanup:
  return;
}

/**
  @brief    Write the QC.MDARKMED value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_mdarkmed (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist, XSH_QC_MASTER_DARK_MEDIAN, value),
	     "Error writing keyword '%s'", XSH_QC_MASTER_DARK_MEDIAN);
  cpl_propertylist_set_comment(plist, XSH_QC_MASTER_DARK_MEDIAN,XSH_QC_MASTER_DARK_MEDIAN_C);

cleanup:
  return;
}

/**
  @brief    Read the QC.MDARKMED value
  @param    plist      Property list to write to
  @return   value      The value read
 */
/*-------------------------------------------------------------------------- */
double
xsh_pfits_get_qc_mdarkmed (cpl_propertylist * plist)
{

  double returnvalue = 0.0;

  check_msg (xsh_get_property_value (plist, XSH_QC_MASTER_DARK_MEDIAN,
    CPL_TYPE_DOUBLE, &returnvalue),
    "Error reading keyword '%s'", XSH_QC_MASTER_DARK_MEDIAN);

cleanup:
  return returnvalue;
}

/**
  @brief    Write the QC.MDARKRMS value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_mdarkrms (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist, XSH_QC_MASTER_DARK_RMS, value),
	     "Error writing keyword '%s'", XSH_QC_MASTER_DARK_RMS);
  cpl_propertylist_set_comment(plist, XSH_QC_MASTER_DARK_RMS,XSH_QC_MASTER_DARK_RMS_C);

cleanup:
  return;
}

/**
  @brief    Write the QC.MDARKSLOPE value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_mdarkslope (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist, XSH_QC_MDARKSLOPE, value),
	     "Error writing keyword '%s'", XSH_QC_MDARKSLOPE);

cleanup:
  return;
}


/*--------------------------------------------------------------------------- */
/**
  @brief    Write the contamination value
  @param    plist      Property list to write to
  @param    value        The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_bp_map_ntotal(cpl_propertylist * plist, int value)
{
  check_msg (cpl_propertylist_update_int
	     (plist, XSH_QC_BP_MAP_NTOTAL, value),
	     "Error writing keyword '%s'", XSH_QC_BP_MAP_NTOTAL);
  cpl_propertylist_set_comment(plist, XSH_QC_BP_MAP_NTOTAL, XSH_QC_BP_MAP_NTOTAL_C);

cleanup:
  return;
}

/*--------------------------------------------------------------------------- */
/**
  @brief    Write the contamination value
  @param    plist      Property list to write to
  @param    value        The value to write
 */
/*--------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_contamination(cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double
	     (plist, XSH_QC_CONTAM, value),
	     "Error writing keyword '%s'", XSH_QC_CONTAM);
  cpl_propertylist_set_comment(plist, XSH_QC_CONTAM, XSH_QC_CONTAM_C);

cleanup:
  return;
}



/**
  @brief    Write the QC.MDARKAVG value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_mdarkavg (cpl_propertylist * plist, double value)
{
  check_msg(cpl_propertylist_update_double(plist,XSH_QC_MASTER_DARK_MEAN,value),
	     "Error writing keyword '%s'", XSH_QC_MASTER_DARK_MEAN);
  cpl_propertylist_set_comment(plist, XSH_QC_MASTER_DARK_MEAN,XSH_QC_MASTER_DARK_MEAN_C);

cleanup:
  return;
}

/**
  @brief    Write the QC.DARKMED_AVE value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_darkmed_ave (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double (plist, XSH_QC_DARKMED_AVE, value),
	     "Error writing keyword '%s'", XSH_QC_DARKMED_AVE);

cleanup:
  return;
}

/**
  @brief    Write the QC.MDARKAVG value
  @param    plist      Property list to write to
  @param    value      The value to write
 */
/*-------------------------------------------------------------------------- */
void
xsh_pfits_set_qc_darkmed_stdev (cpl_propertylist * plist, double value)
{
  check_msg (cpl_propertylist_update_double
	     (plist, XSH_QC_DARKMED_STDEV, value),
	     "Error writing keyword '%s'", XSH_QC_DARKMED_STDEV);

cleanup:
  return;
}

/**
   @brief    Write the ? value
   @param    plist      Property list to write to
   @param    value      The value to write
*/
/*-------------------------------------------------------------------------- */
void xsh_pfits_set_qc_ord_orderpos_residmin( cpl_propertylist * plist,
					     double value )
{
  check_msg(cpl_propertylist_update_double(plist,QC_ORD_ORDERPOS_RESIDMIN,
					   value),
	    "error writing keyword '%s'", QC_ORD_ORDERPOS_RESIDMIN);
 cleanup:
  return ;
}

void xsh_pfits_set_qc_ord_orderpos_residmax( cpl_propertylist * plist,
					     double value )
{
  check_msg(cpl_propertylist_update_double(plist,QC_ORD_ORDERPOS_RESIDMAX,
					   value),
	    "error writing keyword '%s'", QC_ORD_ORDERPOS_RESIDMAX);
 cleanup:
  return ;
}

void xsh_pfits_set_qc_ord_orderpos_residavg( cpl_propertylist * plist,
					     double value )
{
  check_msg(cpl_propertylist_update_double(plist,QC_ORD_ORDERPOS_RESIDAVG,
					   value),
	    "error writing keyword '%s'", QC_ORD_ORDERPOS_RESIDAVG);
 cleanup:
  return ;
}

void xsh_pfits_set_qc_ord_orderpos_residrms( cpl_propertylist * plist,
					     double value )
{
  check_msg(cpl_propertylist_update_double(plist,QC_ORD_ORDERPOS_RESIDRMS,
					   value),
	    "error writing keyword '%s'", QC_ORD_ORDERPOS_RESIDRMS );
 cleanup:
  return ;
}


void xsh_pfits_set_qc_eff_fclip( cpl_propertylist * plist,
					     double value )
{
  check_msg(cpl_propertylist_update_double(plist,XSH_QC_EFF_FCLIP,value),
	    "error writing keyword '%s'", XSH_QC_EFF_FCLIP);
 cleanup:
  return ;
}

void xsh_pfits_set_qc_eff_nclip( cpl_propertylist * plist,
					     int value )
{
  check_msg(cpl_propertylist_update_int(plist,XSH_QC_EFF_NCLIP,value),
	    "error writing keyword '%s'", XSH_QC_EFF_NCLIP);
 cleanup:
  return ;
}

void xsh_pfits_set_qc_ord_orderpos_max_pred( cpl_propertylist * plist,
					     int value )
{
  check_msg(cpl_propertylist_update_int(plist,QC_ORD_ORDERPOS_MAX_PRED,value),
	    "error writing keyword '%s'", QC_ORD_ORDERPOS_MAX_PRED);
 cleanup:
  return ;
}

void xsh_pfits_set_qc_ord_orderpos_min_pred( cpl_propertylist * plist,
					     int value )
{
  check_msg(cpl_propertylist_update_int(plist,QC_ORD_ORDERPOS_MIN_PRED,value),
	    "error writing keyword '%s'", QC_ORD_ORDERPOS_MIN_PRED);
 cleanup:
  return ;
}

void xsh_pfits_set_qc_ord_orderpos_ndet( cpl_propertylist * plist,
					 int value )
{
  check_msg(cpl_propertylist_update_int(plist,QC_ORD_ORDERPOS_NDET,value),
	    "error writing keyword '%s'", QC_ORD_ORDERPOS_NDET);
 cleanup:
  return ;
}

void xsh_pfits_set_qc_ord_orderpos_nposall( cpl_propertylist * plist,
					    int value )
{
  check_msg(cpl_propertylist_update_int(plist,QC_ORD_ORDERPOS_NPOSALL,value),
	    "error writing keyword '%s'", QC_ORD_ORDERPOS_NPOSALL);
 cleanup:
  return ;
}

void xsh_pfits_set_qc_ord_orderpos_npossel( cpl_propertylist * plist,
					    int value )
{
  check_msg(cpl_propertylist_update_int(plist,QC_ORD_ORDERPOS_NPOSSEL,value),
	    "error writing keyword '%s'", QC_ORD_ORDERPOS_NPOSSEL);
 cleanup:
  return ;
}

void xsh_pfits_set_qc_ord_orderpos_npred( cpl_propertylist * plist,
					  int value )
{
  check_msg(cpl_propertylist_update_int(plist,QC_ORD_ORDERPOS_NPRED,value),
	    "error writing keyword '%s'", QC_ORD_ORDERPOS_NPRED);
 cleanup:
  return ;
}

/** 
 * Set a KW into a propertylist.  The function checks if the KW is
 * defined for this recipe (instrument->recipe_id).
 * The KW name contains a lower case 'i'
 * which is replaced by the index number. For example with th KW
 * "ESO QC ORDER COEFi" and the idx=2, the generated keyword is
 * "ESO QC ORDER COEF2". The type and comment of the KW is taken from
 * the qc_description table (in xsh_qc_definition.h file).
 * 
 * @param plist Propertylist where to write the KW
 * @param value Pointer to value (int, float, double, string, ...)
 * @param kw The QC Keyword (including a lower case 'i' )
 * @param instrument Pointer to the instrument structure
 * @param idx Index of the KW (the 'i' is replaced by this number)
 */
void xsh_pfits_set_qc_multi( cpl_propertylist *plist, void *value,
			     const char * kw, xsh_instrument * instrument,
			     int idx )
{
  qc_description *pqc = NULL ;
  char real_kw[32] ;

  XSH_ASSURE_NOT_NULL( plist ) ;
  XSH_ASSURE_NOT_NULL( value ) ;
  XSH_ASSURE_NOT_NULL( kw ) ;
  XSH_ASSURE_NOT_NULL( instrument ) ;
  XSH_ASSURE_NOT_NULL( instrument->recipe_id ) ;

  pqc = xsh_get_qc_desc_by_kw( kw ) ;
  XSH_ASSURE_NOT_NULL( pqc ) ;
  /* Check that this kw is to be set by the recipe */
  if ( xsh_qc_in_recipe( pqc, instrument ) != 0 ) {
    xsh_msg( "QC Parameter '%s' not in recipe '%s'",
	     kw, instrument->recipe_id ) ;
    return ;
  }
  /* Compute real kw */

  if ( strchr( pqc->kw_name, 'i' ) != NULL ) {
    /* Special multiple kw with 0, 1, 2, .. */
    char kformat[256]; 
    const char *pk;
    char* pm;
    xsh_msg_dbg_high( " ++++ Multiple KW '%s'", pqc->kw_name ) ;

    for( pk = pqc->kw_name, pm = kformat ; *pk != '\0' ; pk++ )
      if ( *pk == 'i' ) {
	strcpy( pm, "%d" ) ;
	pm += 2 ;
      }
      else *pm++ = *pk ;
    *pm = '\0' ;

    sprintf( real_kw, kformat, idx ) ;
  }
  /* Search qc type */
  switch ( pqc->kw_type ) {
  case CPL_TYPE_INT:
    check_msg(cpl_propertylist_update_int( plist, real_kw,
					   *(int *)value),
	      "error writing keyword '%s'", kw ) ;
    break ;
  case CPL_TYPE_FLOAT:
    check_msg(cpl_propertylist_update_float( plist, real_kw,
					     *(float *)value),
	      "error writing keyword '%s'", kw ) ;
    break ;
  case CPL_TYPE_DOUBLE:
    check_msg(cpl_propertylist_update_double( plist, real_kw,
					      *(double *)value),
	      "error writing keyword '%s'", kw ) ;
    break ;
  case CPL_TYPE_STRING:
    check_msg(cpl_propertylist_update_string( plist, real_kw, (char *)value),
	      "error writing keyword '%s'", kw ) ;
    break ;
  default:
    break ;
  }
 cleanup:
  return ;
}

/** 
 * Set a KW into a propertylist. The function checks if the KW is
 * defined for this recipe (instrument->recipe_id).
 * The type and comment of the KW is taken from
 * the qc_description table (in xsh_qc_definition.h file).
 * 
 * @param plist Propertylist where to write the KW
 * @param value Pointer to value (int, float, double, string, ...)
 * @param kw The QC Keyword (including a lower case 'i' )
 * @param instrument Pointer to the instrument structure
 */
void xsh_pfits_set_qc( cpl_propertylist *plist, void *value,
		       const char *kw, xsh_instrument * instrument )
{
  qc_description *pqc = NULL ;

  XSH_ASSURE_NOT_NULL( plist ) ;
  XSH_ASSURE_NOT_NULL( value ) ;
  XSH_ASSURE_NOT_NULL( kw ) ;
  XSH_ASSURE_NOT_NULL( instrument ) ;
  XSH_ASSURE_NOT_NULL( instrument->recipe_id ) ;

  pqc = xsh_get_qc_desc_by_kw( kw);
  XSH_ASSURE_NOT_NULL( pqc ) ;
  /* Check that this kw is to be set by the recipe */
  if ( xsh_qc_in_recipe( pqc, instrument ) != 0 ) {
    xsh_msg( "QC Parameter '%s' not in recipe '%s'",
	     kw, instrument->recipe_id ) ;
    return ;
  }

  /* Search qc type */
  switch ( pqc->kw_type ) {
  case CPL_TYPE_INT:
    check_msg(cpl_propertylist_update_int( plist, pqc->kw_name,
					   *(int *)value),
	      "error writing keyword '%s'", kw ) ;
    break ;
  case CPL_TYPE_FLOAT:
    check_msg(cpl_propertylist_update_float( plist, pqc->kw_name,
					     *(float *)value),
	      "error writing keyword '%s'", kw ) ;
    break ;
  case CPL_TYPE_DOUBLE:
    check_msg(cpl_propertylist_update_double( plist, pqc->kw_name,
					      *(double *)value),
	      "error writing keyword '%s'", kw ) ;
    break ;
  case CPL_TYPE_STRING:
    check_msg(cpl_propertylist_update_string( plist, pqc->kw_name,
					      (char *)value),
	      "error writing keyword '%s'", kw ) ;
    break ;
  default:
    break ;
  }
 cleanup:
  return ;
}

/**@}*/
