/*                                                                           *
 *   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-15 12:37:13 $
 * $Revision: 1.19 $
 */


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

HIGH_ABS_REGION NirTellComputeResidRegions[] = {
  {1105.0, 1266.0},
  {1300.0, 1343.0},
  {1468.0, 1780.0},
  {1940.0, 1994.0},
  {2030.0, 2046.0},
  {2080.0, 2100.0},
  {0., 0.}
} ;


HIGH_ABS_REGION VisTellComputeResidRegions[] = {
  {691., 695.},
  {715., 734.},
  {766., 770.},
  {893., 904.},
  {943., 983.},
  {0., 0.}
  } ;


HIGH_ABS_REGION UvbTellComputeResidRegions[] = {
  {0., 0.}
  } ;

HIGH_ABS_REGION NirTellFitRegions[] = {
  {1039.0, 1041.0}, // 1040.0 nm
  {1059.0, 1061.0}, // 1060.0 nm
  {1190.0, 1192.0}, // 1191.0 nm
  {1228.0, 1230.0}, // 1229.0 nm
  {1243.0, 1245.0}, // 1244.0 nm
  {1552.0, 1554.0}, // 1553.0 nm
  {1589.0, 1591.0}, // 1590.0 nm
  {1619.0, 1621.0}, // 1620.0 nm
  {1658.0, 1660.0}, // 1659.0 nm
  {1691.0, 1693.0}, // 1692.0 nm
  {1702.0, 1704.0}, // 1703.0 nm
  {1709.0, 1711.0}, // 1710.0 nm
  {1717.0, 1719.0}, // 1718.0 nm
  {1990.0, 1992.0}, // 1991.0 nm
  {2036.0, 2038.0}, // 2037.0 nm
  {2102.0, 2103.0}, // 2102.0 nm
  {2112.0, 2114.0}, // 2113.0 nm
  {2125.0, 2127.0}, // 2126.0 nm
  {2132.0, 2134.0}, // 2133.0 nm
  {2137.0, 2139.0}, // 2138.0 nm
  {2141.0, 2143.0}, // 2142.0 nm
  {2144.0, 2146.0}, // 2145.0 nm
  {2156.0, 2158.0}, // 2157.0 nm
  {2163.0, 2165.0}, // 2164.0 nm
  {2186.0, 2188.0}, // 2187.0 nm
  {2209.0, 2211.0}, // 2210.0 nm
  {2239.0, 2241.0}, // 2240.0 nm
  {2259.0, 2261.0}, // 2260.0 nm
  {2279.0, 2281.0}, // 2280.0 nm
  {2306.0, 2308.0}, // 2307.0 nm
  {2324.0, 2326.0}, // 2325.0 nm
  {2342.0, 2344.0}, // 2343.0 nm
  {2379.0, 2381.0}, // 2380.0 nm
  {2429.0, 2431.0}, // 2430.0 nm
  {2475.0, 2477.0}, // 2476.0 nm
  {0., 0.}
} ;


HIGH_ABS_REGION NirJhTellFitRegions[] = {
  {1039.0, 1041.0}, // 1040.0 nm
  {1059.0, 1061.0}, // 1060.0 nm
  {1190.0, 1192.0}, // 1191.0 nm
  {1228.0, 1230.0}, // 1229.0 nm
  {1243.0, 1245.0}, // 1244.0 nm
  {1552.0, 1554.0}, // 1553.0 nm
  {1589.0, 1591.0}, // 1590.0 nm
  {1619.0, 1621.0}, // 1620.0 nm
  {1658.0, 1660.0}, // 1659.0 nm
  {1691.0, 1693.0}, // 1692.0 nm
  {1702.0, 1704.0}, // 1703.0 nm
  {1709.0, 1711.0}, // 1710.0 nm
  {1717.0, 1719.0}, // 1718.0 nm
  {1990.0, 1992.0}, // 1991.0 nm
  {2036.0, 2038.0}, // 2037.0 nm
  {0., 0.}
} ;

HIGH_ABS_REGION VisTellFitRegions[] = {
  {535.4, 536.2}, // 535.8 +/- 0.4
  {551.9, 552.7}, // 552.3
  {555.8, 556.6}, // 556.2
  {563.6, 564.4}, // 564.0
  {603.6, 604.4}, // 604.0 
  {616.6, 617.4}, // 617.0
  {638.6, 639.4}, // 639.0
  {682.9, 683.7}, // 683.3
  {707.3, 708.1}, // 707.7 
  {747.1, 747.9}, // 747.5
  {753.9, 754.7}, // 754.3
  {777.7, 778.3}, // 777.9
  {781.1, 781.9}, // 781.5
  {789.2, 790.0}, // 789.6
  {799.3, 800.1}, // 799.7
  {809.6, 810.4}, // 810.0
  {841.0, 841.8}, // 841.4
  {850.1, 850.9}, // 850.5
  {864.6, 865.4}, // 865.0
  {874.6, 875.4}, // 875.0
  {887.9, 888.7}, // 888.3
  {923.4, 924.2}, // 923.8
  {971.2, 972.0}, // 971.6
  {979.4, 980.2}, // 979.8
  {995.2, 996.0}, // 995.6
  {1006.1, 1006.9}, // 1006.5
  {1017.6, 1018.4}, // 1018.0
  {0., 0.}
  } ;


HIGH_ABS_REGION UvbTellFitRegions[] = {
  {0., 0.}
  } ;

/*
HIGH_ABS_REGION NirHighAbsRegions[] = {
  {1060.0, 1232.9}, // nm
  {1247.4, 1500.0}, // nm
  {1549.0, 1588.5}, // nm
  {1595.0, 1625.0}, // nm
  {1630.0, 1983.5}, // nm
  {1984.2, 1988.1}, // nm
  {1988.9, 1991.1}, // nm
  {1991.7, 2138.0}, // nm
  {2145.0, 2191.0}, // nm
  {2218.0, 2271.0}, // nm
  {2351.0, 2431.0}, // nm
  {0., 0.} 
} ;

*/
/* 1.5.31-2.0.8
HIGH_ABS_REGION NirHighAbsRegions[] = {
  //{1080.0, 1180.0}, // nm
  {1247.4, 1450.0}, // nm
  {1500.0, 2138.0}, // nm
  //{1247.4, 1500.0}, // nm
  //{1770.0, 1983.5}, // nm
  //{1991.7, 2138.0}, // nm
  {2145.0, 2191.0}, // nm
  {2218.0, 2271.0}, // nm
  {0., 0.}
} ;
*/

/* 2.0.9 */


HIGH_ABS_REGION NirHighAbsRegions[] = {
  {1076.0, 1176.0}, // nm (water vapour)
  {1236.0, 1296.0}, // nm (water vapour)
  {1316.0, 1506.0}, // nm (region between J and H)
  {1736.0, 1986.0}, // nm (region between H and K)
  {1996.0, 2036.0}, // nm (region between H and K)
  {2046.0, 2086.0}, // nm (region between H and K)
  {0., 0.}
} ;


HIGH_ABS_REGION NirJhHighAbsRegions[] = {
  {1076.0, 1176.0}, // nm (water vapour)
  {1236.0, 1296.0}, // nm (water vapour)
  {1316.0, 1506.0}, // nm (region between J and H)
  {1736.0, 1986.0}, // nm (region between H and K)
  {1996.0, 2036.0}, // nm (region between H and K)
  {2046.0, 2086.0}, // nm (region between H and K)
  {0., 0.}
} ;


/* Sabine's list 
HIGH_ABS_REGION NirHighAbsRegions[] = {
  {1113.0, 1164.0}, // nm
  {1337.0, 1507.0}, // nm
  {1754.0, 1974.0}, // nm
  {1988.0, 2026.0}, // nm
  {2045.0, 2088.0}, // nm
  {0., 0.} 
} ;
*/

/* 1.5.31 
HIGH_ABS_REGION VisHighAbsRegions[] = {
  {500.0, 540.0}, // nm
  {585.0, 604.0}, // nm
  {632.0, 644.0}, // nm
  {684.5, 695.0}, // nm
  {695.5, 714.0}, // nm
  {740.0, 775.5}, // nm
  {783.7, 856.0}, // nm
  {887.5, 993.4}, // nm
  {0., 0.}
} ;
*/
/* Sabine's list: 
HIGH_ABS_REGION VisHighAbsRegions[] = {
  {684.0, 696.0}, // nm
  {756.0, 773.0}, // nm
  {810.0, 835.0}, // nm
  {893.0, 923.0}, // nm
  {927.0, 966.0}, // nm
  {966.0, 980.0}, // nm
  {0., 0.}
} ;
*/

/* 1.5.32 */
HIGH_ABS_REGION VisHighAbsRegions[] = {
  {500.0, 532.0}, // nm
  {634.0, 642.0}, // nm
  {684.5, 696.0}, // nm
  {758.0, 770.0}, // nm
  {812.0, 819.0}, // nm
  {894.0, 924.0}, // nm
  {928.0, 968.0}, // nm
  {974.0, 984.0}, // nm
  {0., 0.}
} ;


HIGH_ABS_REGION UvbHighAbsRegions[] = {
  {556.0, 580.0}, // nm
  {0., 0.}
} ;



HIGH_ABS_REGION * 
xsh_fill_high_abs_regions(
   xsh_instrument* instrument,
   cpl_frame* high_abs_frame)
{
   HIGH_ABS_REGION * phigh=NULL;
   int nrow=0;
   double* pwmin=0;
   double* pwmax=0;
   int i=0;
   cpl_table* high_abs_tab=NULL;
   XSH_ARM the_arm;

  if(high_abs_frame !=NULL) {
     high_abs_tab=cpl_table_load(cpl_frame_get_filename(high_abs_frame),1,0);
  }
  the_arm=xsh_instrument_get_arm(instrument);



   if(high_abs_tab!=NULL) {
      nrow=cpl_table_get_nrow(high_abs_tab);
      check(pwmin=cpl_table_get_data_double(high_abs_tab,"LAMBDA_MIN"));
      check(pwmax=cpl_table_get_data_double(high_abs_tab,"LAMBDA_MAX"));

      phigh = (HIGH_ABS_REGION *) cpl_calloc(nrow + 1, sizeof(HIGH_ABS_REGION));
      for(i=0;i<nrow;i++) {
         phigh[i].lambda_min=pwmin[i];
         phigh[i].lambda_max=pwmax[i];
      }
      phigh[nrow].lambda_min=0;
      phigh[nrow].lambda_max=0;

   } else {

      /* Now specific to high absorption region (linear interpolation)
         NIR and VIS only
      */
      if ( the_arm == XSH_ARM_UVB ) {
         /* Specific UVB */
         phigh = UvbHighAbsRegions ;
      }
      else if ( the_arm == XSH_ARM_VIS ) {
         /* Specific VIS */
         phigh = VisHighAbsRegions ;
      }
      else if (the_arm == XSH_ARM_NIR) {
      /* Specific NIR */
      if (instrument->config->order_min == 13
          && instrument->config->order_max == 26
          && instrument->config->orders == 14) {
        phigh = NirHighAbsRegions;
      } else {
        phigh = NirJhHighAbsRegions;
      }
    }

   }
  cleanup:
   xsh_free_table(&high_abs_tab);
   return phigh;
}



HIGH_ABS_REGION *
xsh_fill_tell_fit_regions(
   xsh_instrument* instrument,
   cpl_frame* high_abs_frame)
{
   HIGH_ABS_REGION * phigh=NULL;
   int nrow=0;
   double* pwmin=0;
   double* pwmax=0;
   int i=0;
   cpl_table* high_abs_tab=NULL;
   XSH_ARM the_arm;

  if(high_abs_frame !=NULL) {
     high_abs_tab=cpl_table_load(cpl_frame_get_filename(high_abs_frame),1,0);
  }
  the_arm=xsh_instrument_get_arm(instrument);



   if(high_abs_tab!=NULL) {
      nrow=cpl_table_get_nrow(high_abs_tab);
      check(pwmin=cpl_table_get_data_double(high_abs_tab,"LAMBDA_MIN"));
      check(pwmax=cpl_table_get_data_double(high_abs_tab,"LAMBDA_MAX"));

      phigh = (HIGH_ABS_REGION *) cpl_calloc(nrow + 1, sizeof(HIGH_ABS_REGION));
      for(i=0;i<nrow;i++) {
         phigh[i].lambda_min=pwmin[i];
         phigh[i].lambda_max=pwmax[i];
      }
      phigh[nrow].lambda_min=0;
      phigh[nrow].lambda_max=0;

   } else {

      /* Now specific to high absorption region (linear interpolation)
         NIR and VIS only
      */
      if ( the_arm == XSH_ARM_UVB ) {
         /* Specific UVB */
         phigh = UvbTellFitRegions ;
      }
      else if ( the_arm == XSH_ARM_VIS ) {
         /* Specific VIS */
         phigh = VisTellFitRegions ;
      }
      else if ( the_arm == XSH_ARM_NIR ) {
         /* Specific JH-NIR */
        if (instrument->config->order_min == 13
            && instrument->config->order_max == 26
            && instrument->config->orders == 14) {
          phigh = NirJhTellFitRegions;
        } else {
          /* Specific NIR */
         phigh = NirTellFitRegions ;
        }
      }

   }
  cleanup:
   xsh_free_table(&high_abs_tab);
   return phigh;
}



HIGH_ABS_REGION *
xsh_fill_tell_compute_resid_regions(
   xsh_instrument* instrument,
   cpl_frame* high_abs_frame)
{
   HIGH_ABS_REGION * phigh=NULL;
   int nrow=0;
   double* pwmin=0;
   double* pwmax=0;
   int i=0;
   cpl_table* high_abs_tab=NULL;
   XSH_ARM the_arm;

  if(high_abs_frame !=NULL) {
     high_abs_tab=cpl_table_load(cpl_frame_get_filename(high_abs_frame),1,0);
  }
  the_arm=xsh_instrument_get_arm(instrument);



   if(high_abs_tab!=NULL) {
      nrow=cpl_table_get_nrow(high_abs_tab);
      check(pwmin=cpl_table_get_data_double(high_abs_tab,"LAMBDA_MIN"));
      check(pwmax=cpl_table_get_data_double(high_abs_tab,"LAMBDA_MAX"));

      phigh = (HIGH_ABS_REGION *) cpl_calloc(nrow + 1, sizeof(HIGH_ABS_REGION));
      for(i=0;i<nrow;i++) {
         phigh[i].lambda_min=pwmin[i];
         phigh[i].lambda_max=pwmax[i];
      }
      phigh[nrow].lambda_min=0;
      phigh[nrow].lambda_max=0;

   } else {

      /* Now specific to high absorption region (linear interpolation)
         NIR and VIS only
      */
      if ( the_arm == XSH_ARM_UVB ) {
         /* Specific UVB */
         phigh = UvbTellComputeResidRegions ;
      }
      else if ( the_arm == XSH_ARM_VIS ) {
         /* Specific VIS */
         phigh = VisTellComputeResidRegions ;
      }
      else if ( the_arm == XSH_ARM_NIR ) {
         /* Specific NIR */
         phigh = NirTellComputeResidRegions ;
      }

   }
  cleanup:
   xsh_free_table(&high_abs_tab);
   return phigh;
}
