// Author: Stefan Schmitt
// DESY, 11/08/11

//  Version 17.1, add scan type RhoSquare
//
//  History:
//     Version 17.0, support for density regularisation and complex binning schemes

#ifndef ROOT_TUnfoldDensity
#define ROOT_TUnfoldDensity

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//                                                                      //
//  TUnfoldDensity, an extension of the class TUnfoldSys to correct for //
//  migration effects. TUnfoldDensity provides methods to deal with     //
//  multidimensional complex binning schemes and variable bin widths    //
//                                                                      //
//  Citation: S.Schmitt, JINST 7 (2012) T10003 [arXiv:1205.6201]        //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

/*
  This file is part of TUnfold.

  TUnfold 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 3 of the License, or
  (at your option) any later version.

  TUnfold 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 TUnfold.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "TUnfoldSys.h"
#include "TUnfoldBinning.h"


class TUnfoldDensity : public TUnfoldSys {
 protected:
   const TUnfoldBinning * fConstOutputBins; // binning scheme for the output
   const TUnfoldBinning * fConstInputBins; // binning scheme for the input
   TUnfoldBinning *fOwnedOutputBins; // output binning scheme if owner
   TUnfoldBinning *fOwnedInputBins; // input binning scheme if owner
   TUnfoldBinning *fRegularisationConditions; // binning scheme for the regularisation conditions

 public:
   enum EDensityMode {
     kDensityModeeNone=0,
     kDensityModeBinWidth=1,
     kDensityModeUser=2,
     kDensityModeBinWidthAndUser=3
   };
 protected:

   virtual TString GetOutputBinName(Int_t iBinX) const; // name a bin

   TUnfoldDensity(void); // constructor for derived classes, do nothing

   Double_t GetDensityFactor(EDensityMode densityMode,Int_t iBin) const; // density correction factor for this bin
   void RegularizeDistributionRecursive
     (const TUnfoldBinning *binning,ERegMode regmode,
      EDensityMode densityMode,const char *distribution,
      const char *axisSteering); // regularize the given binning recursively
   void RegularizeOneDistribution
     (const TUnfoldBinning *binning,ERegMode regmode,
      EDensityMode densityMode,const char *axisSteering); // regularize the distribution of one binning node

 public:
   TUnfoldDensity(const TH2 *hist_A, EHistMap histmap,
		     ERegMode regmode = kRegModeCurvature,
		     EConstraint constraint=kEConstraintArea,
		     EDensityMode densityMode=kDensityModeBinWidthAndUser,
		     const TUnfoldBinning *outputBins=0,
		     const TUnfoldBinning *inputBins=0,
		     const char *regularisationDistribution=0,
		     const char *regularisationAxisSteering="*[UOB]"); // constructor for using the histogram classes. Default regularisation is on the curvature of the bin-width normalized density, excluding underflow and overflow bins

   virtual ~ TUnfoldDensity(void); // delete data members

   void RegularizeDistribution(ERegMode regmode,EDensityMode densityMode,
			       const char *distribution,
			       const char *axisSteering); // regularize distribution(s) of the output binning scheme


   enum EScanTauMode { // scan mode of correlation scan
      kEScanTauRhoAvg =0, // average global correlation coefficient (from TUnfold::GetRhoI())
      kEScanTauRhoMax =1, // maximum global correlation coefficient (from TUnfold::GetRhoI())
      kEScanTauRhoAvgSys =2, // average global correlation coefficient (from TUnfoldSys::GetRhoItotal())
      kEScanTauRhoMaxSys =3,  // maximum global correlation coefficient (from TUnfoldSys::GetRhoItotal())
      kEScanTauRhoSquareAvg =4, // average global correlation coefficient squared (from TUnfold::GetRhoI())
      kEScanTauRhoSquareAvgSys =5 // average global correlation coefficient squared (from TUnfoldSys::GetRhoItotal())
   };

   virtual Int_t ScanTau(Int_t nPoint,Double_t tauMin,Double_t tauMax,
                         TSpline **scanResult,Int_t mode=kEScanTauRhoAvg,
                         const char *distribution=0,const char *projectionMode=0,TGraph **lCurvePlot=0,TSpline **logTauXPlot=0,TSpline **logTauYPlot=0); // scan some variable (e.g. global correlation) and find a minimum using successive calls to DoUnfold(Double_t) at various tau
   virtual Double_t GetScanVariable(Int_t mode,const char *distribution,const char *projectionMode); // calculate variable for ScanTau()

   TH1 *GetOutput(const char *histogramName,
                  const char *histogramTitle=0,const char *distributionName=0,
		  const char *projectionMode=0,Bool_t useAxisBinning=kTRUE) const;  // get unfolding result
   TH1 *GetBias(const char *histogramName,
                const char *histogramTitle=0,const char *distributionName=0,
		const char *projectionMode=0,Bool_t useAxisBinning=kTRUE) const;      // get bias
   TH1 *GetFoldedOutput(const char *histogramName,
                        const char *histogramTitle=0,
                        const char *distributionName=0,
                        const char *projectionMode=0,Bool_t useAxisBinning=kTRUE,
                        Bool_t addBgr=kFALSE) const; // get unfolding result folded back
   TH1 *GetBackground(const char *histogramName,const char *bgrSource=0,
                      const char *histogramTitle=0,
                      const char *distributionName=0,
                      const char *projectionMode=0,Bool_t useAxisBinning=kTRUE,Int_t includeError=3,
                      Bool_t clearHist=kTRUE) const; // get background source
   TH1 *GetInput(const char *histogramName,const char *histogramTitle=0,
                 const char *distributionName=0,
                 const char *projectionMode=0,Bool_t useAxisBinning=kTRUE) const;     // get unfolding input
   TH1 *GetDeltaSysSource(const char *source,
                          const char *histogramName,
                          const char *histogramTitle=0,
                          const char *distributionName=0,
			  const char *projectionMode=0,Bool_t useAxisBinning=kTRUE); // get systematic shifts from one systematic source
   TH1 *GetDeltaSysBackgroundScale(const char *bgrSource,
                                   const char *histogramName,
                                   const char *histogramTitle=0,
                                   const char *distributionName=0,
				   const char *projectionMode=0,Bool_t useAxisBinning=kTRUE); // get correlated uncertainty induced by the scale uncertainty of a background source
   TH1 *GetDeltaSysTau(const char *histogramName,
                       const char *histogramTitle=0,
                       const char *distributionName=0,
		       const char *projectionMode=0,Bool_t useAxisBinning=kTRUE); // get correlated uncertainty from varying tau
   TH2 *GetEmatrixSysUncorr(const char *histogramName,
			    const char *histogramTitle=0,
			    const char *distributionName=0,
			    const char *projectionMode=0,Bool_t useAxisBinning=kTRUE); // get error matrix contribution from uncorrelated errors on the matrix A
   TH2 *GetEmatrixSysBackgroundUncorr(const char *bgrSource,
				      const char *histogramName,
				      const char *histogramTitle=0,
				      const char *distributionName=0,
				      const char *projectionMode=0,Bool_t useAxisBinning=kTRUE); // get error matrix from uncorrelated error of one background source
   TH2 *GetEmatrixInput(const char *histogramName,
                        const char *histogramTitle=0,
			const char *distributionName=0,
			const char *projectionMode=0,Bool_t useAxisBinning=kTRUE); // get error contribution from input vector
   TH2 *GetEmatrixTotal(const char *histogramName,
			const char *histogramTitle=0,
			const char *distributionName=0,
			const char *projectionMode=0,Bool_t useAxisBinning=kTRUE); // get total error including systematic,statistical,background,tau errors
   TH1 *GetRhoIstatbgr(const char *histogramName,const char *histogramTitle=0,
                     const char *distributionName=0,
		     const char *projectionMode=0,Bool_t useAxisBinning=kTRUE,
                     TH2 **ematInv=0);      // get global correlation coefficients, stat+bgr errors only (from TUnfold)
   TH1 *GetRhoItotal(const char *histogramName,const char *histogramTitle=0,
                     const char *distributionName=0,
		     const char *projectionMode=0,Bool_t useAxisBinning=kTRUE,
                     TH2 **ematInv=0);      // get global correlation coefficients, including systematic errors (from TUnfoldSys)
   TH2 *GetRhoIJtotal(const char *histogramName,
		      const char *histogramTitle=0,
		      const char *distributionName=0,
		      const char *projectionMode=0,Bool_t useAxisBinning=kTRUE);     // get correlation coefficients
   TH2 *GetL(const char *histogramName,
             const char *histogramTitle=0,
             Bool_t useAxisBinning=kTRUE); // get regularisation matrix
   TH1 *GetLxMinusBias(const char *histogramName,const char *histogramTitle=0); // get vector L(x-bias) of regularisation conditions 

   TH2 *GetProbabilityMatrix(const char *histogramName,
                           const char *histogramTitle=0,Bool_t useAxisBinning=kTRUE) const; // get matrix of probabilities

   const TUnfoldBinning *GetInputBinning(const char *distributionName=0) const; // find binning scheme for input bins
   const TUnfoldBinning *GetOutputBinning(const char *distributionName=0) const; // find binning scheme for output bins
TUnfoldBinning *GetLBinning(void) const { return fRegularisationConditions; } // binning scheme for regularisation conditions (matrix L)
   ClassDef(TUnfoldDensity, TUnfold_CLASS_VERSION) //Unfolding with densisty regularisation
};

#endif
 TUnfoldDensity.h:1
 TUnfoldDensity.h:2
 TUnfoldDensity.h:3
 TUnfoldDensity.h:4
 TUnfoldDensity.h:5
 TUnfoldDensity.h:6
 TUnfoldDensity.h:7
 TUnfoldDensity.h:8
 TUnfoldDensity.h:9
 TUnfoldDensity.h:10
 TUnfoldDensity.h:11
 TUnfoldDensity.h:12
 TUnfoldDensity.h:13
 TUnfoldDensity.h:14
 TUnfoldDensity.h:15
 TUnfoldDensity.h:16
 TUnfoldDensity.h:17
 TUnfoldDensity.h:18
 TUnfoldDensity.h:19
 TUnfoldDensity.h:20
 TUnfoldDensity.h:21
 TUnfoldDensity.h:22
 TUnfoldDensity.h:23
 TUnfoldDensity.h:24
 TUnfoldDensity.h:25
 TUnfoldDensity.h:26
 TUnfoldDensity.h:27
 TUnfoldDensity.h:28
 TUnfoldDensity.h:29
 TUnfoldDensity.h:30
 TUnfoldDensity.h:31
 TUnfoldDensity.h:32
 TUnfoldDensity.h:33
 TUnfoldDensity.h:34
 TUnfoldDensity.h:35
 TUnfoldDensity.h:36
 TUnfoldDensity.h:37
 TUnfoldDensity.h:38
 TUnfoldDensity.h:39
 TUnfoldDensity.h:40
 TUnfoldDensity.h:41
 TUnfoldDensity.h:42
 TUnfoldDensity.h:43
 TUnfoldDensity.h:44
 TUnfoldDensity.h:45
 TUnfoldDensity.h:46
 TUnfoldDensity.h:47
 TUnfoldDensity.h:48
 TUnfoldDensity.h:49
 TUnfoldDensity.h:50
 TUnfoldDensity.h:51
 TUnfoldDensity.h:52
 TUnfoldDensity.h:53
 TUnfoldDensity.h:54
 TUnfoldDensity.h:55
 TUnfoldDensity.h:56
 TUnfoldDensity.h:57
 TUnfoldDensity.h:58
 TUnfoldDensity.h:59
 TUnfoldDensity.h:60
 TUnfoldDensity.h:61
 TUnfoldDensity.h:62
 TUnfoldDensity.h:63
 TUnfoldDensity.h:64
 TUnfoldDensity.h:65
 TUnfoldDensity.h:66
 TUnfoldDensity.h:67
 TUnfoldDensity.h:68
 TUnfoldDensity.h:69
 TUnfoldDensity.h:70
 TUnfoldDensity.h:71
 TUnfoldDensity.h:72
 TUnfoldDensity.h:73
 TUnfoldDensity.h:74
 TUnfoldDensity.h:75
 TUnfoldDensity.h:76
 TUnfoldDensity.h:77
 TUnfoldDensity.h:78
 TUnfoldDensity.h:79
 TUnfoldDensity.h:80
 TUnfoldDensity.h:81
 TUnfoldDensity.h:82
 TUnfoldDensity.h:83
 TUnfoldDensity.h:84
 TUnfoldDensity.h:85
 TUnfoldDensity.h:86
 TUnfoldDensity.h:87
 TUnfoldDensity.h:88
 TUnfoldDensity.h:89
 TUnfoldDensity.h:90
 TUnfoldDensity.h:91
 TUnfoldDensity.h:92
 TUnfoldDensity.h:93
 TUnfoldDensity.h:94
 TUnfoldDensity.h:95
 TUnfoldDensity.h:96
 TUnfoldDensity.h:97
 TUnfoldDensity.h:98
 TUnfoldDensity.h:99
 TUnfoldDensity.h:100
 TUnfoldDensity.h:101
 TUnfoldDensity.h:102
 TUnfoldDensity.h:103
 TUnfoldDensity.h:104
 TUnfoldDensity.h:105
 TUnfoldDensity.h:106
 TUnfoldDensity.h:107
 TUnfoldDensity.h:108
 TUnfoldDensity.h:109
 TUnfoldDensity.h:110
 TUnfoldDensity.h:111
 TUnfoldDensity.h:112
 TUnfoldDensity.h:113
 TUnfoldDensity.h:114
 TUnfoldDensity.h:115
 TUnfoldDensity.h:116
 TUnfoldDensity.h:117
 TUnfoldDensity.h:118
 TUnfoldDensity.h:119
 TUnfoldDensity.h:120
 TUnfoldDensity.h:121
 TUnfoldDensity.h:122
 TUnfoldDensity.h:123
 TUnfoldDensity.h:124
 TUnfoldDensity.h:125
 TUnfoldDensity.h:126
 TUnfoldDensity.h:127
 TUnfoldDensity.h:128
 TUnfoldDensity.h:129
 TUnfoldDensity.h:130
 TUnfoldDensity.h:131
 TUnfoldDensity.h:132
 TUnfoldDensity.h:133
 TUnfoldDensity.h:134
 TUnfoldDensity.h:135
 TUnfoldDensity.h:136
 TUnfoldDensity.h:137
 TUnfoldDensity.h:138
 TUnfoldDensity.h:139
 TUnfoldDensity.h:140
 TUnfoldDensity.h:141
 TUnfoldDensity.h:142
 TUnfoldDensity.h:143
 TUnfoldDensity.h:144
 TUnfoldDensity.h:145
 TUnfoldDensity.h:146
 TUnfoldDensity.h:147
 TUnfoldDensity.h:148
 TUnfoldDensity.h:149
 TUnfoldDensity.h:150
 TUnfoldDensity.h:151
 TUnfoldDensity.h:152
 TUnfoldDensity.h:153
 TUnfoldDensity.h:154
 TUnfoldDensity.h:155
 TUnfoldDensity.h:156
 TUnfoldDensity.h:157
 TUnfoldDensity.h:158
 TUnfoldDensity.h:159
 TUnfoldDensity.h:160
 TUnfoldDensity.h:161
 TUnfoldDensity.h:162
 TUnfoldDensity.h:163
 TUnfoldDensity.h:164
 TUnfoldDensity.h:165
 TUnfoldDensity.h:166
 TUnfoldDensity.h:167
 TUnfoldDensity.h:168
 TUnfoldDensity.h:169
 TUnfoldDensity.h:170
 TUnfoldDensity.h:171
 TUnfoldDensity.h:172
 TUnfoldDensity.h:173
 TUnfoldDensity.h:174
 TUnfoldDensity.h:175
 TUnfoldDensity.h:176
 TUnfoldDensity.h:177
 TUnfoldDensity.h:178
 TUnfoldDensity.h:179
 TUnfoldDensity.h:180
 TUnfoldDensity.h:181