/*****************************************************************************
 * Project: RooFit                                                           *
 * author: Max Baak (mbaak@cern.ch)                                          *
 *****************************************************************************/

// Written by Max Baak (mbaak@cern.ch)
// 2-dimensional morph function between a list of input functions (varlist) as a function of one input parameter (m).
// The vector mrefpoints assigns an m-number to each function in the function list.
// For example: varlist can contain MC histograms (or single numbers) of a reconstructed mass, for certain 
// true Higgs masses indicated in mrefpoints. the input parameter m is the true (continous) Higgs mass.
// Morphing can be set to be linear or non-linear, or mixture of the two.

#ifndef ROO2DMOMENTMORPHFUNCTION
#define ROO2DMOMENTMORPHFUNCTION

#include "RooAbsReal.h"
#include "RooRealProxy.h"
#include "RooCategoryProxy.h"
#include "RooAbsReal.h"
#include "RooAbsCategory.h"

#include "TMatrix.h"
#include "TVectorD.h"

#include <vector>
#include <string>

class Roo2DMomentMorphFunction : public RooAbsReal {

 public:

  enum Setting { Linear, LinearPosFractions } ;

  Roo2DMomentMorphFunction() {} ; 

  Roo2DMomentMorphFunction( const char *name, const char *title,
	                  RooAbsReal& _m1, RooAbsReal& _m2, 
                          const TMatrixD& mrefpoints, const Setting& setting = Linear, const Bool_t& verbose=false ) ;

  Roo2DMomentMorphFunction( const char *name, const char *title,
                          RooAbsReal& _m1, RooAbsReal& _m2,
                          const Int_t& nrows, const Double_t* dm1arr, const Double_t* dm2arr, const Double_t* dvalarr, 
			  const Setting& setting = Linear, const Bool_t& verbose=false ) ;

  Roo2DMomentMorphFunction( const Roo2DMomentMorphFunction& other, const char* name=0 );

  virtual TObject* clone( const char* newname ) const { return new Roo2DMomentMorphFunction(*this,newname); }
  virtual ~Roo2DMomentMorphFunction() ;

  void setMode( const Setting& setting ) { _setting=setting; }

  void Summary() const;

 protected:

  Double_t evaluate() const ;

  void     initialize();
  void     calculateFractions(Bool_t verbose=kTRUE) const;

  RooRealProxy m1 ;
  RooRealProxy m2 ;

  Setting _setting;
  Bool_t _verbose;
  Int_t _ixmin, _ixmax, _iymin, _iymax;
  Int_t	_npoints;

  mutable TMatrixD _mref;
  mutable TMatrixD _MSqr;
  mutable TVectorD _frac;

  mutable TMatrixD _squareVec;
  mutable int _squareIdx[4];

 private:

  Bool_t   findSquare(const double& x, const double& y) const;
  Bool_t   onSameSide(const double& p1x, const double& p1y, const double& p2x, const double& p2y, const double& ax, const double& ay, const double& bx, const double& by) const ;
  Bool_t   pointInSquare(const double& px, const double& py, const double& ax, const double& ay, const double& bx, const double& by, const double& cx, const double& cy, const double& dx, const double& dy) const;
  Bool_t   pointInTriangle(const double& px, const double& py, const double& ax, const double& ay, const double& bx, const double& by, const double& cx, const double& cy) const ;
  Double_t myCrossProduct(const double& ax, const double& ay, const double& bx, const double& by) const ;
  Bool_t   isAcceptableSquare(const double& ax, const double& ay, const double& bx, const double& by, const double& cx, const double& cy, const double& dx, const double& dy) const;

  struct SorterL2H {
    bool operator() (const std::pair<int,double>& p1, const std::pair<int,double>& p2) {
      return (p1.second<p2.second);
    }
  };

 private:
  ClassDef(Roo2DMomentMorphFunction,1) 

};
 
#endif

 Roo2DMomentMorphFunction.h:1
 Roo2DMomentMorphFunction.h:2
 Roo2DMomentMorphFunction.h:3
 Roo2DMomentMorphFunction.h:4
 Roo2DMomentMorphFunction.h:5
 Roo2DMomentMorphFunction.h:6
 Roo2DMomentMorphFunction.h:7
 Roo2DMomentMorphFunction.h:8
 Roo2DMomentMorphFunction.h:9
 Roo2DMomentMorphFunction.h:10
 Roo2DMomentMorphFunction.h:11
 Roo2DMomentMorphFunction.h:12
 Roo2DMomentMorphFunction.h:13
 Roo2DMomentMorphFunction.h:14
 Roo2DMomentMorphFunction.h:15
 Roo2DMomentMorphFunction.h:16
 Roo2DMomentMorphFunction.h:17
 Roo2DMomentMorphFunction.h:18
 Roo2DMomentMorphFunction.h:19
 Roo2DMomentMorphFunction.h:20
 Roo2DMomentMorphFunction.h:21
 Roo2DMomentMorphFunction.h:22
 Roo2DMomentMorphFunction.h:23
 Roo2DMomentMorphFunction.h:24
 Roo2DMomentMorphFunction.h:25
 Roo2DMomentMorphFunction.h:26
 Roo2DMomentMorphFunction.h:27
 Roo2DMomentMorphFunction.h:28
 Roo2DMomentMorphFunction.h:29
 Roo2DMomentMorphFunction.h:30
 Roo2DMomentMorphFunction.h:31
 Roo2DMomentMorphFunction.h:32
 Roo2DMomentMorphFunction.h:33
 Roo2DMomentMorphFunction.h:34
 Roo2DMomentMorphFunction.h:35
 Roo2DMomentMorphFunction.h:36
 Roo2DMomentMorphFunction.h:37
 Roo2DMomentMorphFunction.h:38
 Roo2DMomentMorphFunction.h:39
 Roo2DMomentMorphFunction.h:40
 Roo2DMomentMorphFunction.h:41
 Roo2DMomentMorphFunction.h:42
 Roo2DMomentMorphFunction.h:43
 Roo2DMomentMorphFunction.h:44
 Roo2DMomentMorphFunction.h:45
 Roo2DMomentMorphFunction.h:46
 Roo2DMomentMorphFunction.h:47
 Roo2DMomentMorphFunction.h:48
 Roo2DMomentMorphFunction.h:49
 Roo2DMomentMorphFunction.h:50
 Roo2DMomentMorphFunction.h:51
 Roo2DMomentMorphFunction.h:52
 Roo2DMomentMorphFunction.h:53
 Roo2DMomentMorphFunction.h:54
 Roo2DMomentMorphFunction.h:55
 Roo2DMomentMorphFunction.h:56
 Roo2DMomentMorphFunction.h:57
 Roo2DMomentMorphFunction.h:58
 Roo2DMomentMorphFunction.h:59
 Roo2DMomentMorphFunction.h:60
 Roo2DMomentMorphFunction.h:61
 Roo2DMomentMorphFunction.h:62
 Roo2DMomentMorphFunction.h:63
 Roo2DMomentMorphFunction.h:64
 Roo2DMomentMorphFunction.h:65
 Roo2DMomentMorphFunction.h:66
 Roo2DMomentMorphFunction.h:67
 Roo2DMomentMorphFunction.h:68
 Roo2DMomentMorphFunction.h:69
 Roo2DMomentMorphFunction.h:70
 Roo2DMomentMorphFunction.h:71
 Roo2DMomentMorphFunction.h:72
 Roo2DMomentMorphFunction.h:73
 Roo2DMomentMorphFunction.h:74
 Roo2DMomentMorphFunction.h:75
 Roo2DMomentMorphFunction.h:76
 Roo2DMomentMorphFunction.h:77
 Roo2DMomentMorphFunction.h:78
 Roo2DMomentMorphFunction.h:79
 Roo2DMomentMorphFunction.h:80
 Roo2DMomentMorphFunction.h:81
 Roo2DMomentMorphFunction.h:82
 Roo2DMomentMorphFunction.h:83
 Roo2DMomentMorphFunction.h:84
 Roo2DMomentMorphFunction.h:85
 Roo2DMomentMorphFunction.h:86
 Roo2DMomentMorphFunction.h:87
 Roo2DMomentMorphFunction.h:88
 Roo2DMomentMorphFunction.h:89
 Roo2DMomentMorphFunction.h:90
 Roo2DMomentMorphFunction.h:91
 Roo2DMomentMorphFunction.h:92
 Roo2DMomentMorphFunction.h:93
 Roo2DMomentMorphFunction.h:94
 Roo2DMomentMorphFunction.h:95
 Roo2DMomentMorphFunction.h:96
 Roo2DMomentMorphFunction.h:97