// This may look like C code, but it is really -*- C++ -*-
//
// Methode d'ajustement non-lineaire sur des objets 
//                                   R. Ansari    02/2000

#ifndef OBJFITTER_SEEN
#define OBJFITTER_SEEN

#include "machdefs.h"

#include "tmatrix.h"
#include "cimage.h"
#include "tvector.h"
#include "histos.h"
#include "histos2.h"
#include "hisprof.h"
#include "generalfit.h"


namespace SOPHYA {

class  ObjectFitter {
public:
  // Residus et fonction fittees sur matrix
  static TMatrix<uint_2> FitResidus(TMatrix<uint_2> const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix<int_2> FitResidus(TMatrix<int_2> const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix<int_4> FitResidus(TMatrix<int_4> const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);  
  static TMatrix<int_8> FitResidus(TMatrix<int_8> const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix<r_4> FitResidus(TMatrix<r_4> const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix<r_8> FitResidus(TMatrix<r_8> const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix< complex<r_4> > FitResidus(TMatrix< complex<r_4> > const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix< complex<r_8> > FitResidus(TMatrix< complex<r_8> > const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);

  static TMatrix<uint_2> FitFunction(TMatrix<uint_2> const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix<int_2> FitFunction(TMatrix<int_2> const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix<int_4> FitFunction(TMatrix<int_4> const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix<int_8> FitFunction(TMatrix<int_8> const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix<r_4> FitFunction(TMatrix<r_4> const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix<r_8> FitFunction(TMatrix<r_8> const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix< complex<r_4> > FitFunction(TMatrix< complex<r_4> > const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix< complex<r_8> > FitFunction(TMatrix< complex<r_8> > const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);

  // Residus et fonction fittees sur vecteurs
  static TVector<uint_2> FitResidus(TVector<uint_2> const & vec, GeneralFit& gfit,
			       double xorg=0.,double dx=1.);
  static TVector<int_2> FitResidus(TVector<int_2> const & vec, GeneralFit& gfit,
			       double xorg=0.,double dx=1.);
  static TVector<int_4> FitResidus(TVector<int_4> const & vec, GeneralFit& gfit,
			       double xorg=0.,double dx=1.);
  static TVector<int_8> FitResidus(TVector<int_8> const & vec, GeneralFit& gfit,
			       double xorg=0.,double dx=1.);
  static TVector<r_4> FitResidus(TVector<r_4> const & vec, GeneralFit& gfit,
			       double xorg=0.,double dx=1.);
  static TVector<r_8> FitResidus(TVector<r_8> const & vec, GeneralFit& gfit,
			       double xorg=0.,double dx=1.);
  static TVector< complex<r_4> > FitResidus(TVector< complex<r_4> > const & vec, GeneralFit& gfit,
			       double xorg=0.,double dx=1.);
  static TVector< complex<r_8> > FitResidus(TVector< complex<r_8> > const & vec, GeneralFit& gfit,
			       double xorg=0.,double dx=1.);

  static TVector<uint_2> FitFunction(TVector<uint_2> const & vec, GeneralFit& gfit,
				double xorg=0.,double dx=1.);
  static TVector<int_2> FitFunction(TVector<int_2> const & vec, GeneralFit& gfit,
				double xorg=0.,double dx=1.);
  static TVector<int_4> FitFunction(TVector<int_4> const & vec, GeneralFit& gfit,
				double xorg=0.,double dx=1.);
  static TVector<int_8> FitFunction(TVector<int_8> const & vec, GeneralFit& gfit,
				double xorg=0.,double dx=1.);
  static TVector<r_4> FitFunction(TVector<r_4> const & vec, GeneralFit& gfit,
				double xorg=0.,double dx=1.);
  static TVector<r_8> FitFunction(TVector<r_8> const & vec, GeneralFit& gfit,
				double xorg=0.,double dx=1.);
  static TVector< complex<r_4> > FitFunction(TVector< complex<r_4> > const & vec, GeneralFit& gfit,
				double xorg=0.,double dx=1.);
  static TVector< complex<r_8> > FitFunction(TVector< complex<r_8> > const & vec, GeneralFit& gfit,
				double xorg=0.,double dx=1.);

  // Residus et fonction fittees sur Image
  static Image<uint_2> FitResidus(Image<uint_2> const & im, GeneralFit& gfit);
  static Image<int_4> FitResidus(Image<int_4> const & im, GeneralFit& gfit);
  static Image<int_8> FitResidus(Image<int_8> const & im, GeneralFit& gfit);
  static Image<r_4> FitResidus(Image<r_4> const & im, GeneralFit& gfit);
  static Image<r_8> FitResidus(Image<r_8> const & im, GeneralFit& gfit);

  static Image<uint_2> FitFunction(Image<uint_2> const & im, GeneralFit& gfit);
  static Image<int_4> FitFunction(Image<int_4> const & im, GeneralFit& gfit);
  static Image<int_8> FitFunction(Image<int_8> const & im, GeneralFit& gfit);
  static Image<r_4> FitFunction(Image<r_4> const & im, GeneralFit& gfit);
  static Image<r_8> FitFunction(Image<r_8> const & im, GeneralFit& gfit);

  // Residus et fonction fittees sur Histo
  static Histo FitResidus(Histo const& h, GeneralFit& gfit);
  static Histo FitFunction(Histo const& h, GeneralFit& gfit);
  static int_4 Fit(Histo const & h, GeneralFit& gfit
          ,GeneralFitData::FitErrType errtype=GeneralFitData::DefaultError
          ,double errscale=1.,double errmin=1.);

  // Residus et fonction fittees sur Histo2D
  static Histo2D FitResidus(Histo2D const& h, GeneralFit& gfit);
  static Histo2D FitFunction(Histo2D const& h, GeneralFit& gfit);
  static int_4 Fit(Histo2D const & h, GeneralFit& gfit
          ,GeneralFitData::FitErrType errtype=GeneralFitData::DefaultError
          ,double errscale=1.,double errmin=0.);

  // Residus et fonction fittees sur HProf
  static inline Histo FitResidus(HProf const& h, GeneralFit& gfit)
         {h.UpdateHisto(); return FitResidus((Histo const&) h,gfit);}
  static inline Histo FitFunction(HProf const& h, GeneralFit& gfit)
         {h.UpdateHisto(); return FitFunction((Histo const&) h,gfit);}
  static int_4 Fit(HProf const & h, GeneralFit& gfit
          ,GeneralFitData::FitErrType errtype=GeneralFitData::DefaultError
          ,double errscale=1.,double errmin=0.)
          {h.UpdateHisto();
           return Fit((Histo const&) h,gfit,errtype,errscale,errmin);}

  // Residus et fonction fittees sur GeneralFitData
  static inline GeneralFitData FitResidus(GeneralFitData const& g, GeneralFit& gfit)
                            {return g.FitResidus(gfit);}
  static inline GeneralFitData FitFunction(GeneralFitData const& g, GeneralFit& gfit)
                            {return g.FitFunction(gfit);}
};

//  Classe template pour ajustement sur tableaux (Vecteurs, Matrices)
template <class T>
class  ArrayFitter {
public:
  // Residus et fonction fittees sur matrix
  static TMatrix<T> FitResidus(TMatrix<T> const & mtx, GeneralFit& gfit,
			       double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  static TMatrix<T> FitFunction(TMatrix<T> const & mtx, GeneralFit& gfit,
				double xorg=0.,double yorg=0.,double dx=1.,double dy=1.);
  // Residus et fonction fittees sur vecteurs
  static TVector<T> FitResidus(TVector<T> const & vec, GeneralFit& gfit,
			       double xorg=0.,double dx=1.);
  static TVector<T> FitFunction(TVector<T> const & vec, GeneralFit& gfit,
				double xorg=0.,double dx=1.);
};

//  Classe template pour ajustement sur images
template <class T>
class  ImageFitter {
public:
  static Image<T> FitResidus(Image<T> const & mtx, GeneralFit& gfit);
  static Image<T> FitFunction(Image<T> const & mtx, GeneralFit& gfit);
};

}  // Fin du namespace


#endif   // OBJFITTER_SEEN
