#ifndef FCT2DFIT_SEEN
#define FCT2DFIT_SEEN

#include "generalfit.h"

namespace SOPHYA {

//================================================================
// GeneralFunction 2D pour PSF pixel taille 1x1
//================================================================

//! Classe de definition d'une PSF 2D a nPar parametres
class GeneralPSF2D : public GeneralFunction {
public:
  GeneralPSF2D(unsigned int nPar);
  virtual ~GeneralPSF2D();

  virtual double ValueH(double const xp[], double const* parm);
  virtual double VolPSF(double const* parm);
  virtual void   DefaultParam(double *parm);

  void SetVolEps(double const prec) ;
protected:
  double VolEps;
};

//================================================================
// GeneralFunction 2D pour MULTI-PSF pixel taille 1x1
//================================================================

//! Classe de definition d'un ensemble de PSF2D
class GenMultiPSF2D : public GeneralPSF2D {
public:
  GenMultiPSF2D(GeneralPSF2D* psf2d,unsigned int nstar);
  virtual ~GenMultiPSF2D();

  virtual double Value(double const xp[], double const* Par);
  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);

protected:
  GeneralPSF2D* mPsf2D; // Type de PSF generique a fiter.
  int mNStar;           // Nombre d etoiles a fiter.
  int mNParmTot;        // Nombre total de parametres pour le fit.
  int mNParm;           // Nombre de parametre pour la PSF generique.
  int mNForme;          // Nombre de parametres de forme autres que Sx,Sy,Rho
  double* mParm;        // pour la PSF generique. Buffer pour PSF generique
  double* mDer;         // et pour le stoquage temporaire des derivees.
};

//==============================================================================
// CLASSES DE FONCTIONS 2D type PSF AVEC PARAMETRES POUR LE FIT pixel taille 1x1
//==============================================================================

//////////////////////////////////////////////////////////////////
//! gaussienne + fond 2D
class GauRho2D : public GeneralPSF2D {
public:
  GauRho2D();
  virtual ~GauRho2D();

  virtual double Value(double const xp[], double const* Par);
  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
  virtual double ValueH(double const xp[], double const* Par);
  virtual double VolPSF(double const* Par);
  virtual void   DefaultParam(double *Par);
};

//////////////////////////////////////////////////////////////////
//! gaussienne integree + fond 2D
class GauRhInt2D : public GeneralPSF2D {
public:
  GauRhInt2D();
  virtual ~GauRhInt2D();

  virtual double Value(double const xp[], double const* Par);
  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
  virtual double ValueH(double const xp[], double const* Par);
  virtual double VolPSF(double const* Par);
  virtual void   DefaultParam(double *Par);
};

//////////////////////////////////////////////////////////////////
//! gaussienne 2D de volume 1 approchee par dl au 3ieme ordre
class GdlRho2D : public GeneralPSF2D {
public:
  GdlRho2D();
  virtual ~GdlRho2D();

  virtual double Value(double const xp[], double const* Par);
  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
  virtual double ValueH(double const xp[], double const* Par);
  virtual double VolPSF(double const* Par);
  virtual void   DefaultParam(double *Par);
};

//////////////////////////////////////////////////////////////////
//! gaussienne integree 2D de volume 1 approchee par dl au 3ieme ordre
class GdlRhInt2D : public GeneralPSF2D {
public:
  GdlRhInt2D();
  virtual ~GdlRhInt2D();

  virtual double Value(double const xp[], double const* Par);
  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
  virtual double ValueH(double const xp[], double const* Par);
  virtual double VolPSF(double const* Par);
  virtual void   DefaultParam(double *Par);
};

//////////////////////////////////////////////////////////////////
//! gaussienne 2D de volume 1 approchee par dl au 2sd ordre
class Gdl1Rho2D : public GeneralPSF2D {
public:
  Gdl1Rho2D();
  virtual ~Gdl1Rho2D();

  virtual double Value(double const xp[], double const* Par);
  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
  virtual double ValueH(double const xp[], double const* Par);
  virtual double VolPSF(double const* Par);
  virtual void   DefaultParam(double *Par);
};

//////////////////////////////////////////////////////////////////
//! gaussienne ontegree 2D de volume 1 approchee par dl au 2sd ordre
class Gdl1RhInt2D : public GeneralPSF2D {
public:
  Gdl1RhInt2D();
  virtual ~Gdl1RhInt2D();

  virtual double Value(double const xp[], double const* Par);
  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
  virtual double ValueH(double const xp[], double const* Par);
  virtual double VolPSF(double const* Par);
  virtual void   DefaultParam(double *Par);
};

//////////////////////////////////////////////////////////////////
//! gaussienne 2D de hauteur 1 approchee dl 3ieme
class Gdl2Rho2D : public GeneralPSF2D {
public:
  Gdl2Rho2D();
  virtual ~Gdl2Rho2D();

  virtual double Value(double const xp[], double const* Par);
  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
  virtual double ValueH(double const xp[], double const* Par);
  virtual void   DefaultParam(double *Par);
};

//////////////////////////////////////////////////////////////////
//! gaussienne integree 2D de hauteur 1 approchee dl 3ieme
class Gdl2RhInt2D : public GeneralPSF2D {
public:
  Gdl2RhInt2D();
  virtual ~Gdl2RhInt2D();

  virtual double Value(double const xp[], double const* Par);
  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
  virtual double ValueH(double const xp[], double const* Par);
  virtual void   DefaultParam(double *Par);
};

//////////////////////////////////////////////////////////////////
//! Moffat 2D
class MofRho2D : public GeneralPSF2D {
public:
  MofRho2D();
  virtual ~MofRho2D();

  virtual double Value(double const xp[], double const* Par);
  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
  virtual double ValueH(double const xp[], double const* Par);
  virtual double VolPSF(double const* Par);
  virtual void   DefaultParam(double *Par);
};

//////////////////////////////////////////////////////////////////
//! Moffat integree 2D
class MofRhInt2D : public GeneralPSF2D {
public:
  MofRhInt2D();
  virtual ~MofRhInt2D();

  virtual double Value(double const xp[], double const* Par);
  virtual double Val_Der(double const xp[],double const* Par,double* DgDpar);
  virtual double ValueH(double const xp[], double const* Par);
  virtual double VolPSF(double const* Par);
  virtual void   DefaultParam(double *Par);
};

//==============================================================================
// CLASSES DE FONCTIONS 2D type Xi2 AVEC PARAMETRES POUR LE FIT pixel taille 1x1
//==============================================================================

//////////////////////////////////////////////////////////////////
//! Chi2 pour une Gaussienne+fond 2D
class X2_GauRho2D : public GeneralXi2 {
public:
  X2_GauRho2D();
  virtual ~X2_GauRho2D();

  virtual double Value(GeneralFitData& data, double* parm, int& ndataused);
  virtual double Derivee2(GeneralFitData& data, int i,int j, double* parm);

protected:
  GauRho2D* gaurho2d;
};

} // Fin du namespace

#endif
