/*                                                                            *
 *   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-10-02 15:48:05 $
 * $Revision: 1.44 $
 * $Name: not supported by cvs2svn $
 */

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

/*--------------------------------------------------------------------------*/
/**
 * @defgroup xsh_instrument Instrument Description
 * @ingroup data_handling
 *
 */
/*--------------------------------------------------------------------------*/
/**@{*/

/*---------------------------------------------------------------------------
                                Includes
 ---------------------------------------------------------------------------*/
#include <xsh_data_instrument.h>
#include <xsh_data_order.h>
#include <xsh_pfits.h>
#include <xsh_data_spectralformat.h>
#include <xsh_msg.h>
#include <xsh_dfs.h>
#include <xsh_error.h>
#include <string.h>
/*---------------------------------------------------------------------------
                            Functions prototypes
 ---------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------
                            Implementation
 ---------------------------------------------------------------------------*/
 
/*--------------------------------------------------------------------------*/
/**
  @brief  create new instrument structure
  @return a pointer on the allocated structure (must be deallocated with
    xsh_data_instrument_free

*/
/*--------------------------------------------------------------------------*/
xsh_instrument* xsh_instrument_new (void) 
{  
  xsh_instrument* instrument = NULL;
  instrument = (xsh_instrument*)cpl_malloc(sizeof(xsh_instrument));
  assure (instrument != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
					"Memory allocation failed!");
  /* init */
  instrument->mode = XSH_MODE_UNDEFINED;
  instrument->arm = XSH_ARM_UNDEFINED;
  instrument->lamp = XSH_LAMP_UNDEFINED;
  instrument->config = NULL;
  instrument->pipeline_id = PACKAGE "/" PACKAGE_VERSION;
  instrument->dictionary = "PRO-1.15";
  instrument->recipe_id = NULL;
  instrument->update = 0;
  instrument->uvb_orders_nb = XSH_ORDERS_UVB;
  instrument->uvb_orders_qth_nb = XSH_ORDERS_UVB_QTH;
  instrument->uvb_orders_d2_nb = XSH_ORDERS_UVB_D2;
  instrument->uvb_orders_min = XSH_ORDER_MIN_UVB;
  instrument->uvb_orders_max = XSH_ORDER_MAX_UVB;
  instrument->vis_orders_nb = XSH_ORDERS_VIS;
  instrument->vis_orders_min = XSH_ORDER_MIN_VIS;
  instrument->vis_orders_max = XSH_ORDER_MAX_VIS;
  instrument->nir_orders_nb = XSH_ORDERS_NIR;
  instrument->nir_orders_min = XSH_ORDER_MIN_NIR;
  instrument->nir_orders_max = XSH_ORDER_MAX_NIR;
  instrument->binx = 1;
  instrument->biny = 1;  

  cleanup:
    return instrument;
}

xsh_instrument * xsh_instrument_duplicate( xsh_instrument * old )
{
  xsh_instrument * new = NULL ;

  check( new = xsh_instrument_new() ) ;

  memcpy( new, old, sizeof( xsh_instrument ) ) ;
  new->config = malloc( sizeof( XSH_INSTRCONFIG ) ) ;
  memcpy( new->config, old->config, sizeof( XSH_INSTRCONFIG ) ) ;

 cleanup:
  return new ;
}

/*--------------------------------------------------------------------------*/
/**
  @brief  free an instrument structure
  @param instrument the pointer on the structure to deallocate

*/
/*--------------------------------------------------------------------------*/
void xsh_instrument_free(xsh_instrument** instrument){
  if(instrument && *instrument){
    if((*instrument)->config != NULL){
      cpl_free((*instrument)->config);
      (*instrument)->config = NULL;
    }
    cpl_free(*instrument);
    *instrument = NULL;
  }
}

/*--------------------------------------------------------------------------*/
/**
  @brief get the arm from the frame tag
  @param tag (valid by dfs)
  @return the detected arm
*/
/*--------------------------------------------------------------------------*/
XSH_ARM xsh_arm_get(const char* tag){
  return
  (strstr(tag,"UVB") != NULL)? XSH_ARM_UVB :
  (strstr(tag,"VIS") != NULL)? XSH_ARM_VIS :
  (strstr(tag,"NIR") != NULL)? XSH_ARM_NIR :
  (strstr(tag,"AGC") != NULL)? XSH_ARM_AGC : XSH_ARM_UNDEFINED;
}

/*--------------------------------------------------------------------------*/
/**
  @brief get the mode from the frame tag
  @param tag (valid by dfs)
  @return the detected mode
*/
/*--------------------------------------------------------------------------*/
XSH_MODE xsh_mode_get(const char* tag){
  return
  (strstr(tag,"IFU") != NULL)? XSH_MODE_IFU :
  (strstr(tag,"SLIT") != NULL)? XSH_MODE_SLIT : XSH_MODE_UNDEFINED;
}

/*--------------------------------------------------------------------------*/
/**
  @brief set the instrument mode as user specifies 
  @param instrument instrument structure
  @param mode       instrument mode
  @return void
*/
/*--------------------------------------------------------------------------*/
void 
xsh_mode_set(xsh_instrument* instrument, XSH_MODE mode){
  instrument->mode = mode;
  return;
}


/*--------------------------------------------------------------------------*/
/**
  @brief set the instrument mode as user specifies
  @param instrument instrument structure
  @param mode       instrument mode
  @return void
*/
/*--------------------------------------------------------------------------*/
void
xsh_decode_bp_set(xsh_instrument* instrument, const int decode_bp){
  instrument->decode_bp = decode_bp;
  return;
}

/*--------------------------------------------------------------------------*/
/**
  @brief get the lamp from the frame tag
  @param tag (valid by dfs)
  @return the detected lamp
*/
/*--------------------------------------------------------------------------*/
XSH_LAMP xsh_lamp_get(const char* tag){
  return
  (strstr(tag,"QTH") != NULL)? XSH_LAMP_QTH :
  (strstr(tag,"D2") != NULL)? XSH_LAMP_D2 : 
  (strstr(tag,"THAR") != NULL)? XSH_LAMP_THAR : XSH_LAMP_UNDEFINED;
}


/*--------------------------------------------------------------------------*/
/**
  @brief analyse a frame tag to set data in instrument structure
  @param inst the instrument sructure to complete or update
  @param tag a valid xshooter tag (validate by dfs)
*/
/*--------------------------------------------------------------------------*/
void xsh_instrument_parse_tag(xsh_instrument* inst,const char* tag){
  XSH_ARM arm = xsh_arm_get(tag);
  XSH_MODE mode = xsh_mode_get(tag);
  XSH_LAMP lamp = xsh_lamp_get(tag);

  xsh_instrument_set_arm(inst,arm);
  xsh_instrument_set_mode(inst,mode);
  xsh_instrument_set_lamp(inst,lamp);  

}

/*--------------------------------------------------------------------------*/
/**
  @brief  Set bad pixel code 
  @param i the instrument structure

*/
/*--------------------------------------------------------------------------*/
void xsh_instrument_set_decode_bp(xsh_instrument* i,const int decode_bp){

   i->decode_bp = decode_bp;
    return;
}


/*--------------------------------------------------------------------------*/
/**
  @brief  Set a mode on instrument structure
  @param i the instrument structure
  @param mode instrument mode of use, if a mode is already defined for the
    instrument the new mode (if valid) must be equal to the older!!
*/
/*--------------------------------------------------------------------------*/
void xsh_instrument_set_mode(xsh_instrument* i,XSH_MODE mode){
  if (mode != XSH_MODE_UNDEFINED){
    if ( (i->mode == XSH_MODE_UNDEFINED)|| (mode == i->mode) ){
      i->mode = mode;
    }
    else {
  	  /* report the error */
/*
      assure(0,CPL_ERROR_ILLEGAL_INPUT,
        "Mode %s already set for the instrument; could'nt update with %s",
        xsh_instrument_mode_tostring(i),xsh_mode_tostring(mode));
*/
    }
  }

    return;
}

/*--------------------------------------------------------------------------*/
/**
  @brief  Set an arm on instrument structure
  @param i the instrument structure
  @param arm instrument arm in use, if an arm is already defined for the
    instrument the new arm must be equal to the older!!
*/
/*--------------------------------------------------------------------------*/
void xsh_instrument_set_arm(xsh_instrument* i,XSH_ARM arm){
  if (arm == XSH_ARM_UNDEFINED) {
    /* report the error */
    assure(0,CPL_ERROR_ILLEGAL_INPUT,"arm must be UVB, VIS or NIR");
  }
  else {
    if( (i->arm == XSH_ARM_UNDEFINED) || (arm == i->arm) ){
      i->update = 1;
      i->arm = arm;
    }
    else {
  	  /* report the error */
      assure(0,CPL_ERROR_ILLEGAL_INPUT,
      "Arm %s already set for the instrument; could'nt update with %s",
      xsh_instrument_arm_tostring(i),xsh_arm_tostring(arm));
    }
  }
  cleanup:
    return;
}

/*--------------------------------------------------------------------------*/
/**
  @brief  Set a lamp on instrument structure
  @param i the instrument structure
  @param lamp instrument lamp in use, if a lamp is already defined for the
    instrument the new lamp must be equal to the older or UNDEFINED!!
*/
/*--------------------------------------------------------------------------*/
void xsh_instrument_set_lamp(xsh_instrument* i,XSH_LAMP lamp){
  if (lamp != XSH_LAMP_UNDEFINED) {
    if( (i->lamp == XSH_LAMP_UNDEFINED) || (i->lamp == lamp) ){
      i->lamp = lamp;
    }
    else {
      if ( (i->arm == XSH_ARM_UVB) && ( ( lamp == XSH_LAMP_QTH)|| 
           ( lamp == XSH_LAMP_D2))){
        i->lamp = XSH_LAMP_QTH_D2;
      }
      else{
        /* report the error */
        assure(0,CPL_ERROR_ILLEGAL_INPUT,
          "Lamp %s already set for the instrument; could not update with %s",
        xsh_instrument_lamp_tostring(i),xsh_lamp_tostring(lamp));
      }
    }
  }
  cleanup:
    return;
} 

void xsh_instrument_update_lamp(xsh_instrument* i, XSH_LAMP lamp)
{
  XSH_ASSURE_NOT_NULL( i);
  i->lamp = lamp;
  i->update = 1;

  cleanup:
    return;
}

void xsh_instrument_update_from_spectralformat( xsh_instrument* i,
  cpl_frame* spectralformat_frame)
{
  xsh_spectralformat_list *spec_list = NULL;
  int max_order, min_order;
  int nb_qth, nb_d2, nb_total;
  int j;
  
  /* Check parameters */
  XSH_ASSURE_NOT_NULL( i);

  if (spectralformat_frame != NULL){
    check( spec_list = xsh_spectralformat_list_load( spectralformat_frame,
    i));

    nb_total = spec_list->size;
    nb_qth = 0;
    nb_d2 = 0;
    XSH_ASSURE_NOT_ILLEGAL( nb_total > 0);

    max_order = spec_list->list[0].absorder;
    min_order = spec_list->list[0].absorder;

    for(j=0; j< spec_list->size; j++){
      int absorder;
      const char* lamp = NULL;    

      absorder= spec_list->list[j].absorder;
      lamp = spec_list->list[j].lamp;

      if ( absorder >  max_order){
        max_order = absorder;
      }
      if ( absorder < min_order ){
        min_order = absorder;
      }
      if (lamp != NULL){
        if ( strcmp(lamp,"QTH")== 0){
          nb_qth++;
        }
        else if ( strcmp(lamp,"D2") == 0){
          nb_d2++;
        }
      }
    }
    assure(i->arm != XSH_ARM_UNDEFINED,CPL_ERROR_ILLEGAL_INPUT,
      "config is defined only for valid arm");
    switch (i->arm){
      case XSH_ARM_UVB:
        i->uvb_orders_nb = nb_total ;
        i->uvb_orders_qth_nb = nb_qth;
        i->uvb_orders_d2_nb = nb_d2;
        i->uvb_orders_min = min_order;
        i->uvb_orders_max = max_order;
      break;
      case XSH_ARM_VIS:
        i->vis_orders_nb = nb_total;
        i->vis_orders_min = min_order;
        i->vis_orders_max = max_order;
      break;
      case  XSH_ARM_NIR:
        i->nir_orders_nb = nb_total;
        i->nir_orders_min = min_order;
        i->nir_orders_max = max_order;
      break;
      default:
      break;
    }
    i->update = 1;
    xsh_msg_dbg_low("Orders config updated for arm %s", xsh_arm_tostring( i->arm));
    xsh_msg_dbg_low(" Nb orders %d (qth %d, d2 %d) : from %d to %d", 
      nb_total, nb_qth, nb_d2, min_order, max_order);
  }
  else{
    xsh_msg(" No spectralformat : Get default config");
  }

  cleanup:
    xsh_spectralformat_list_free( &spec_list); 
    return;
}

/*--------------------------------------------------------------------------*/
/**
  @brief  Set the recipe_id into the instrument structure
  @param instrument the instrument structure
  @param recipe_id The recipe_id (a string)
*/
/*--------------------------------------------------------------------------*/
void xsh_instrument_set_recipe_id(xsh_instrument* instrument, 
  const char *recipe_id)
{
  if (recipe_id != NULL) {
    instrument->recipe_id = recipe_id;
  }
  else {
    /* report the error */
    instrument->recipe_id = "unknown";
  }

  return;
} 

/*--------------------------------------------------------------------------*/
/**
  @brief  Get a mode on instrument structure
  @return mode instrument mode of use
*/
/*--------------------------------------------------------------------------*/
XSH_MODE xsh_instrument_get_mode(xsh_instrument* i){
  return i->mode;
}

/*--------------------------------------------------------------------------*/
/**
  @brief  Get an arm on instrument structure
  @return arm instrument arm in use
*/
/*--------------------------------------------------------------------------*/
XSH_ARM xsh_instrument_get_arm(xsh_instrument* i){
  return i->arm;
}

/*--------------------------------------------------------------------------*/
/**
  @brief  Get a lamp on instrument structure
  @param i the instrument we use
  @return lamp instrument lamp in use
*/
/*--------------------------------------------------------------------------*/
XSH_LAMP xsh_instrument_get_lamp(xsh_instrument* i){
  return i->lamp;
}

/*--------------------------------------------------------------------------*/
/**
  @brief  Get the Arc seconds per pixel for this Arm
  @param instrument Instrument description structure
  @return The arcsec value (double)
*/
/*--------------------------------------------------------------------------*/
double xsh_arcsec_get(xsh_instrument * instrument )
{
  return 
    ( instrument->arm == XSH_ARM_NIR) ? XSH_ARCSEC_NIR :
    ( instrument->arm == XSH_ARM_UVB) ? XSH_ARCSEC_UVB : 
    ( instrument->arm == XSH_ARM_VIS) ? XSH_ARCSEC_VIS : 0. ;
}


/*--------------------------------------------------------------------------*/
/**
  @brief  Get the resoltion
  @param instrument Instrument description structure
  @param slit 
    the slit size
  @return The resolution value (double)
*/
/*--------------------------------------------------------------------------*/
double xsh_resolution_get( xsh_instrument *instrument, double slit)
{
  double resolution = 0.0;
  
  if ( (instrument->arm == XSH_ARM_UVB) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 0.5)){
    resolution = 9100;
  }
  else if ((instrument->arm == XSH_ARM_UVB) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 0.8)){
    resolution = 6200;
  }
  else if ((instrument->arm == XSH_ARM_UVB) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 1.0)){
    resolution = 5100;
  }
  else if ((instrument->arm == XSH_ARM_UVB) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 1.3)){
    resolution = 4000;
  }
  else if ((instrument->arm == XSH_ARM_UVB) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 1.6)){
    resolution = 3300;
  }
  else if ((instrument->arm == XSH_ARM_UVB) && (instrument->mode == XSH_MODE_IFU)){
    resolution = 7900;
  }
  else if ( (instrument->arm == XSH_ARM_VIS) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 0.4)){
    resolution = 17400;
  }
  else if ((instrument->arm == XSH_ARM_VIS) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 0.7)){
    resolution = 11000;
  }
  else if ((instrument->arm == XSH_ARM_VIS) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 0.9)){
    resolution = 8800;
  }
  else if ((instrument->arm == XSH_ARM_VIS) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 1.2)){
    resolution = 6700;
  }
  else if ((instrument->arm == XSH_ARM_VIS) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 1.5)){
    resolution = 5400;
  }
  else if ((instrument->arm == XSH_ARM_VIS) && (instrument->mode == XSH_MODE_IFU)){
    resolution = 12600;
  }
  else if ( (instrument->arm == XSH_ARM_NIR) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 0.4)){
    resolution = 11300;
  }
  else if ((instrument->arm == XSH_ARM_NIR) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 0.6)){
    resolution = 8100;
  }
  else if ((instrument->arm == XSH_ARM_NIR) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 0.9)){
    resolution = 5600;
  }
  else if ((instrument->arm == XSH_ARM_NIR) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 1.2)){
    resolution = 4300;
  }
  else if ((instrument->arm == XSH_ARM_NIR) && (instrument->mode == XSH_MODE_SLIT) && ( slit == 1.5)){
    resolution = 3500;
  }
  else if ((instrument->arm == XSH_ARM_NIR) && (instrument->mode == XSH_MODE_IFU)){
    resolution = 8100;
  }
  else{
    resolution = 0.0;
  }
  return resolution;
}

/*--------------------------------------------------------------------------*/
/**
  @brief  Get the instrument default set of keywords
  @param i the instrument we use
  @return the instrument set of keywords
*/
/*--------------------------------------------------------------------------*/
XSH_INSTRCONFIG * xsh_instrument_get_config(xsh_instrument * i)
{
  assure(i->arm != XSH_ARM_UNDEFINED,CPL_ERROR_ILLEGAL_INPUT,
    "config is defined only for valid arm");
  /* allocate the config */
  if ( (i->config != NULL) && (i->update == 1)) {
    XSH_FREE( i->config);
    i->update = 0;
  }
  if (i->config == NULL){
    i->update=0;
    XSH_MALLOC( i->config, XSH_INSTRCONFIG, 1);

    /* init common */
    i->config->naxis = 2;

    switch (i->arm){
      case XSH_ARM_UVB:
	i->config->bitpix = 16;
	i->config->nx = 2048;
	i->config->ny = 3000;
	i->config->prscx = 0;
	i->config->prscy = 0;
	i->config->ovscx = 0;
	i->config->ovscy = 0;
	i->config->ron = 9.0; /* 0.6 */
	i->config->conad = 1.9;
        if (i->lamp == XSH_LAMP_D2){
    	  i->config->orders = i->uvb_orders_d2_nb;
        }
        else if (i->lamp == XSH_LAMP_QTH){
          i->config->orders = i->uvb_orders_qth_nb;
        }
        else{
          i->config->orders = i->uvb_orders_nb;
        }
	i->config->order_min = i->uvb_orders_min;
	i->config->order_max = i->uvb_orders_max ;
        break;
      case XSH_ARM_VIS:
	i->config->bitpix = 16;
	i->config->nx = 2048;
	i->config->ny = 4000;
	i->config->prscx = 0;
	i->config->prscy = 0;
	i->config->ovscx = 0;
	i->config->ovscy = 0;
	i->config->ron = 0.6;
	i->config->conad = 1.9;
	i->config->orders = i->vis_orders_nb;
	i->config->order_min = i->vis_orders_min;
	i->config->order_max = i->vis_orders_max;
	break;
      default:
	i->config->bitpix = 32;
	i->config->nx = 1020;
	i->config->ny = 2040;
	i->config->prscx = 0;
	i->config->prscy = 0;
	i->config->ovscx = 0;
	i->config->ovscy = 0;
	i->config->ron = 0.6;
	i->config->conad = 1.9;
	i->config->pxspace = 1.8E-05 ;
	i->config->orders = i->nir_orders_nb;
	i->config->order_min = i->nir_orders_min;
	i->config->order_max = i->nir_orders_max;
	break;
    }
    i->config->naxis1 = (i->config->nx + i->config->prscx + i->config->ovscx) 
	    / i->binx;
    i->config->naxis2 = (i->config->ny + i->config->prscy + i->config->ovscy) 
	    / i->biny;
  }
 cleanup:
  return i->config;
    
}

int xsh_instrument_get_binx( xsh_instrument * instrument )
{
  int res = 1 ;

  XSH_ASSURE_NOT_NULL( instrument ) ;
  res = instrument->binx ;

 cleanup:
  return res ;
}

int xsh_instrument_get_biny( xsh_instrument * instrument )
{
  int res = 1 ;

  XSH_ASSURE_NOT_NULL( instrument ) ;
  res = instrument->biny ;

 cleanup:
  return res ;
}

void xsh_instrument_set_binx( xsh_instrument * instrument, const int binx )
{

  XSH_ASSURE_NOT_NULL( instrument ) ;
  instrument->binx = binx;

 cleanup:
  return ;
}

void xsh_instrument_set_biny( xsh_instrument * instrument, const int biny )
{

  XSH_ASSURE_NOT_NULL( instrument ) ;
  instrument->biny = biny;

 cleanup:
  return ;
}

/*--------------------------------------------------------------------------*/
/**
  @brief  Get the string associated with a mode
  @param i the instrument we use
  @return the string symbolized the mode
*/
/*--------------------------------------------------------------------------*/
const char* xsh_instrument_mode_tostring(xsh_instrument* i){
  return xsh_mode_tostring(i->mode);
}

/*--------------------------------------------------------------------------*/
/**
  @brief  Get the string associated with an arm
  @param i the instrument we use
  @return the string symbolized the mode
*/
/*--------------------------------------------------------------------------*/
const char* xsh_instrument_arm_tostring(xsh_instrument* i){
  return xsh_arm_tostring(i->arm);
}

/*--------------------------------------------------------------------------*/
/**
  @brief  Get the string associated with a lamp
  @param i the instrument we use
  @return the string symbolized the lamp
*/
/*--------------------------------------------------------------------------*/
const char* xsh_instrument_lamp_tostring(xsh_instrument* i){
  return xsh_lamp_tostring(i->lamp);
}


/*--------------------------------------------------------------------------*/
/**
  @brief  Get the string associated with a mode
  @param mode the mode we use
  @return the string symbolized the mode
*/
/*--------------------------------------------------------------------------*/
const char* xsh_mode_tostring(XSH_MODE mode){
  return 
    (mode == XSH_MODE_IFU) ? "IFU" :
    (mode == XSH_MODE_SLIT) ? "SLIT" : "UNDEFINED";
}

/*--------------------------------------------------------------------------*/
/**
  @brief  Get the string associated with an arm
  @param arm the arm we use
  @return the string symbolized the arm
*/
/*--------------------------------------------------------------------------*/
const char* xsh_arm_tostring(XSH_ARM arm){
  return 
    (arm == XSH_ARM_UVB) ? "UVB" :
    (arm == XSH_ARM_VIS) ? "VIS" :
    (arm == XSH_ARM_NIR) ? "NIR" :
    (arm == XSH_ARM_AGC) ? "AGC" : "UNDEFINED";
}

/*--------------------------------------------------------------------------*/
/**
  @brief  Get the string associated with a lamp
  @param lamp the lamp we use
  @return the string symbolized the lamp
*/
/*--------------------------------------------------------------------------*/
const char* xsh_lamp_tostring(XSH_LAMP lamp){
  return 
    (lamp == XSH_LAMP_QTH) ? "QTH" :
    (lamp == XSH_LAMP_D2) ? "D2" : 
    (lamp == XSH_LAMP_THAR) ? "THAR" : "UNDEFINED";
}

int
xsh_instrument_nir_is_JH(cpl_frame* frame, xsh_instrument* instr)
{

  int result=0;  
  cpl_propertylist* plist=NULL;
  const char* name=NULL;
  const char* slit=NULL;
  name=cpl_frame_get_filename(frame);
  plist=cpl_propertylist_load(name,0);
  if(cpl_propertylist_has(plist,XSH_SLIT_NIR)) {
    slit=xsh_pfits_get_slit_value(plist,instr);
    if(strstr(slit,"JH")!=NULL) {
      xsh_msg_warning("JH band, special case");
      result=1;
    }
  }
  xsh_free_propertylist(&plist);
  return result;
}

cpl_error_code
xsh_instrument_nir_corr_if_JH(cpl_frameset* raws, xsh_instrument* instr)
{
  cpl_frame* frame=NULL;

  frame=cpl_frameset_get_frame(raws,0);

  if(instr->arm == XSH_ARM_NIR) {

    if(xsh_instrument_nir_is_JH(frame,instr)) {
       instr->config->order_min=13;
       instr->config->order_max=26;
       instr->config->orders=14;
    }

  }

  return cpl_error_get_code();
}


cpl_error_code
xsh_instrument_nir_corr_if_spectral_format_is_JH(cpl_frameset* calib, xsh_instrument* instr)
{
  cpl_frame* frame=NULL;

  if(instr->arm == XSH_ARM_NIR) {
    frame=xsh_find_spectral_format( calib, instr);
    XSH_ASSURE_NOT_NULL_MSG(frame,"Null input SPECTRAL_FORMAT_TAB");
    if(xsh_instrument_nir_is_JH(frame,instr)) {
       instr->config->order_min=13;
       instr->config->order_max=26;
       instr->config->orders=14;
    }

  }
 cleanup:

  return cpl_error_get_code();
}
/**@}*/
