/* $Id: xsh_model_kernel.h,v 1.47 2011-12-02 14:15:28 amodigli Exp $
 *
 * This file is part of the X-shooter Pipeline
 * Copyright (C) 2006 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: amodigli $
 * $Date: 2011-12-02 14:15:28 $
 * $Revision: 1.47 $
 * $Name: not supported by cvs2svn $
 */

#ifndef XSH_MODEL_KERNEL_H
#define XSH_MODEL_KERNEL_H

//#define FCCDD_FLAG
//#define CCCDD_FLAG
//#define XCCCDD_FLAG
//#define DEBUG

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

#include <math.h>
#include <string.h>
#include <cpl.h>
#include <xsh_data_instrument.h>
#include <xsh_data_order.h>

/*-----------------------------------------------------------------------------
   								Define
 -----------------------------------------------------------------------------*/
/*This is the number of extra rows to be added to the top due to the wrong
default for the NIR array size in xsh_data_instrument.c */
#define NIR_FIX 36

/*-----------------------------------------------------------------------------
   								New types
 -----------------------------------------------------------------------------*/

typedef double DOUBLE;

/* the following three lines are the only one you have to change to modify the vector/matrix default size  */
typedef DOUBLE vec[4];
typedef DOUBLE cvec[4];
typedef DOUBLE mat[4][4];

typedef int detloc[3];
typedef int XY[3];

typedef struct {
  DOUBLE best,min,max;
  int flag;
  char  name[20];
} ann_all_par;

typedef struct
  {
    int counter; 
    double x; 
    double y; 
    int arm; 
    double wave; 
    double flux;
    int slit_pos;
    int order;
  } coord ;

struct xs_3
{
  /* parameterlist */
  int arm;
  double chipxpix,chipypix;
  double xsize_corr, ysize_corr;
  int ASIZE, BSIZE, SIZE;
  int morder, morder_min, morder_max;
  DOUBLE blaze_pad;
  DOUBLE temper, t_ir_p2, t_ir_p3; /* T in K */
  DOUBLE mues, nues, taues, slit_scale, es_s, es_w, es_x, es_xf, es_y, es_y_tot; /* for entrance slit */
  DOUBLE fcol;
  DOUBLE mup1, cmup1, nup1, taup1; /* for prism crossdiperser entrance/final exit surface */
  DOUBLE rind, rind2, rind3, rind_a1, rind_a2, rind_a3, rind_b1, rind_b2, rind_lm1, rind_lm2, rind_lm3, rind_wta0, rind_wta1, rind_wta2, rind_wtb0, rind_wtb1, rind_wtb2; /* for prism simple refrative index fit */
  DOUBLE rind_delta;/*extra param to allow ref_ind change in annealing*/
  DOUBLE mup2, nup2, taup2; /* for prism crossdiperser first exit/re-entrance surface */
  DOUBLE mup3, nup3, taup3; /* for 2nd prism crossdiperser entrance/final exit surface */
  DOUBLE mup4, nup4, taup4; /* for 2nd prism crossdiperser first exit/re-entrance surface */
  DOUBLE mup5, nup5, taup5; /* for 3rd prism crossdiperser entrance/final exit surface */
  DOUBLE mup6, nup6, taup6; /* for 3rd prism crossdiperser first exit/re-entrance surface */

  DOUBLE mug, nug, taug, sg, grat_alpha, grat_beta; /* for grating */
  DOUBLE mud, nud, taud, pix, pix_X, pix_Y, offx, offy, flipx, flipy, xpospix, ypospix, fdet; /* for detector */

  detloc chippix;
  double xdet,ydet;

  double chipx, chipy, chipxup, chipyup, chipxdown, chipydown, chiprot;

  /* pin cushion distortion coeffs*/
  double pc_x_xx, pc_x_x1, pc_x_yy, pc_x_y1, pc_x_xy, pc_x_x3, pc_x_x2y, pc_x_y2x, pc_x_y3;
  double pc_y_xx, pc_y_x1, pc_y_yy, pc_y_y1, pc_y_xy, pc_y_x3, pc_y_x2y, pc_y_y2x, pc_y_y3;
  /*4th order for NIR only*/
  double pc4_x_xy3,pc4_x_x3y,pc4_x_x2y2,pc4_x_x4,pc4_x_y4;
  double pc4_y_xy3,pc4_y_x3y,pc4_y_x2y2,pc4_y_x4,pc4_y_y4;

  /*UVB/VIS extra distortion*/
  double d2_x3, d2_x2, d2_x1;
  double d2_y3x3, d2_y3x2, d2_y3x1,d2_y3x0,d2_y2x3, d2_y2x2, d2_y2x1,d2_y2x0,d2_y1x3, d2_y1x2, d2_y1x1,d2_y1x0;
  /*NIR Chromatic distortion*/
  double ca_x0,ca_x1,ca_y0,ca_y1;

/* matrices which can be computed without order, wavelength and slitposition */
  mat e_slit;
  mat mup_ir_cor, mup_ir_cor_out, toprism1, toprism2, toprism3, toprism4, toprism5, toprism6, prism_out, ret_prism2, ret_prism1, ret_prism_out1,ret_prism4, ret_prism3, ret_prism_out2,ret_prism6, ret_prism5, ret_prism_out3,todetector;
  mat tograt, grat_out;
  DOUBLE slit[10];

  /* Pedigree of config file */
  double config_mjd;
};
typedef struct xs_3 xsh_xs_3;

/*-----------------------------------------------------------------------------
   							        Prototypes
 -----------------------------------------------------------------------------*/


int  xsh_3_readfile(double * abest, double * amin, double * amax, int * aname, const char *, struct xs_3 *, ann_all_par *);
void xsh_3_init(struct xs_3 *);
void xsh_ref_ind_read_old(const char * ref_ind_file, DOUBLE ** ref_ind, DOUBLE temper);
void xsh_ref_ind_read(int arm, DOUBLE ** ref_ind, DOUBLE temper);
void xsh_3_eval(DOUBLE  lambda, int morder, DOUBLE ** ref_ind, struct xs_3 *p_xs_3);
void xsh_3_eval_check(DOUBLE  lambda, int morder, DOUBLE ** ref_ind, struct xs_3 *p_xs_3);
void xsh_3_detpix(struct xs_3 *p_xs_3);
void xsh_3_detpix_check(struct xs_3 *p_xs_3);

DOUBLE *xsh_alloc1Darray(int asize); 
int * xsh_alloc1Darray_INT(int asize); 
double** xsh_alloc2Darray( int asize, int bsize);
double *** xsh_alloc3Darray2(int asize,int bsize,int csize);
double *** xsh_alloc3Darray(int asize,int bsize,int csize);
int ** xsh_alloc2Darray_i(int asize, int bsize);
float ** xsh_alloc2Darray_f(int asize, int bsize);
int xsh_free2Darray(double ** ccdtemp, int asize);
int xsh_free3Darray(double *** ccdtemp, int asize,int bsize);
int xsh_free2Darray_i(int ** ccdtemp, int asize);
int xsh_free2Darray_f(float ** ccdtemp, int asize);
double * xsh_copy2D_to_1D(double ** ccdtemp, int asize, int bsize);
double** xsh_copy1D_to_2D(double * oneDccdtemp, int asize, int bsize);

void xsh_addvectors(vec, vec);  
void xsh_addvectors3D(vec, vec);  
void xsh_subtractvectors(vec,vec);
DOUBLE xsh_scalarproduct(vec,vec);
void xsh_multiply(vec a, DOUBLE k);
void xsh_multiplythreematrix(mat A, mat B, mat C,mat D);
void xsh_showvector(vec a);
//void xsh_nullvector(vec a);
//void xsh_copyvector(vec, vec);
void xsh_normz(vec a);
void xsh_normall(vec a);

void xsh_showmatrix(mat A);
void xsh_initializematrix(mat A);
void xsh_multiplymatrix(mat A,mat B, mat C);
//void xsh_nullmatrix(mat A);
//void xsh_copymatrix(mat A, mat B);
void xsh_matrixforvector(vec a,mat B,vec c);
void xsh_transpose(mat A,mat B);

void xsh_rotationmatrix(mat A, const char axis, const DOUBLE angle);
void xsh_rotin(mat A,const DOUBLE x_angle, const DOUBLE y_angle,
	      const DOUBLE z_angle);
void xsh_refract(vec, DOUBLE, vec);

void xsh_model_get_xy(xsh_xs_3* p_xs_3,
		      xsh_instrument* instr,
		      double lambda_nm,
		      int morder,
		      double slit,
		      double* x,
		      double* y);
cpl_vector** xsh_model_locus(struct xs_3* p_xs_3,
			     xsh_instrument* instr,
			     double ent_slit_pos);
cpl_frame* xsh_model_spectralformat_create(struct xs_3* p_xs_3,
					   const char* tab_filename);
cpl_table* xsh_model_THE(struct xs_3* p_xs_3,
			 const char* line_list,
			 xsh_instrument* instr,
			 int num_ph,
			 double sep_ph);
cpl_frame* xsh_model_THE_create(struct xs_3* p_xs_3,
				xsh_instrument* instr,
				const char* line_list,
				int num_ph,
				double sep_ph,
				const char* THE_filename);

cpl_frame* xsh_model_pipe_anneal(cpl_frame* cfg_frame,
				 cpl_frame* resid_frame,
				 int maxit,
				 double ann_fac,
				 int scenario,int rec_id);

double xsh_model_sellmeier_ext(int arm, double temper, double lam_sqr);
double xsh_model_ref_ind_air(double temper, double lam_sqr);

void xsh_model_binxy(struct xs_3* p_xs_3,
		     int bin_X,
		     int bin_Y);
cpl_vector * xsh_model_refining_detect(const cpl_vector* in,
				       int fwhm,
				       double sigma,
				       int  display);
int xsh_model_first_anneal(
   cpl_parameterlist*   parlist, 
   cpl_frameset*   frameset);

int xsh_model_first_anneal_save(const cpl_table *, xsh_instrument*,
                                cpl_parameterlist *,cpl_frameset *) ;

int xsh_model_map_ifu(double xifu,
		      double yifu,
		      xsh_xs_3* p_xs_3);

int xsh_model_offset(DOUBLE  disp_pix_shift,
		     DOUBLE  slit_pix_shift,
		     struct xs_3* p_xs_3);

void xsh_order_edge_list_fit(xsh_order_list *list, int size, double* order,
			     double* posx, double* posy, 
                             int deg_poly, int edge);

cpl_frame* xsh_model_order_edges_tab_create(xsh_xs_3* p_xs_3, 
					    const char* tab_filename);
cpl_error_code 
xsh_model_maps_create(xsh_xs_3* p_xs_3, 
		      xsh_instrument* instr,
                      const char * wtag,
                      const char * stag,
                      cpl_frame** wmap_frame,
                      cpl_frame** smap_frame,const int save_tmp);

#endif
