// @(#)root/gpad:$Id$
// Author: Paul Gessinger   25/08/2016

/*************************************************************************
 * Copyright (C) 1995-2016, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TRatioPlot
#define ROOT_TRatioPlot


//////////////////////////////////////////////////////////////////////////
//                                                                      //
// ROOT_TRatioPlot                                                      //
//                                                                      //
// A collection of histograms                                           //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#ifndef ROOT_TObject
#include "TObject.h"
#endif

#ifndef ROOT_TString
#include "TString.h"
#endif

#ifndef ROOT_TGraph
#include "TGraph.h"
#endif

class TH1;
class TPad;
class TVirtualPad;
class TGraphAsymmErrors;
class TGraphErrors;
class TAxis;
class TGaxis;
class TLine;
class TFitResultPtr;
class TFitResult;
class THStack;
class TBrowser;
class TFileMergeInfo;

class TRatioPlot : public TObject {

private:
   TRatioPlot& operator=(const TRatioPlot&) = delete; // Not implemented
   TRatioPlot(const TRatioPlot &hrp) = delete;

   enum CalculationMode {
      kDivideHist = 1, ///< Use `TH1::Divide` to create the ratio.
      kDivideGraph = 2, ///< Use `TGraphAsymmErrors::Divide` to create the ratio.
      kDifference = 3, ///< Calculate the difference between the histograms.
      kFitResidual = 4, ///< Calculate the fit residual between the histogram and a fit stored within it.
      kDifferenceSign = 5 ///< Calculate the difference divided by the error.
   };

   enum ErrorMode {
      kErrorSymmetric = 1, ///< Use the regular `TH1::GetBinError` as the error
      kErrorAsymmetric = 2, ///< Use `TH1::GetBinErrorUp` and `TH1::GetBinErrorLow` for the error, depending on y values.
      kErrorFunc = 3 ///< Use the square root of the function value as the error.
   };

   enum HideLabelMode {
      kHideUp = 1, ///< Hide the first label of the upper y axis when there is low space.
      kHideLow = 2, ///< Hide the last label of the lower y axis when there is low space.
      kNoHide = 3, ///< Do not hide labels when there is low space.
      kForceHideUp = 4, ///< Always hide the first label of the upper y axis
      kForceHideLow = 5 ///< Always hide the last label of the lower y axis
   };


protected:

   TVirtualPad *fParentPad = 0; ///< Stores the pad the ratio plot was created in
   TPad *fUpperPad = 0; ///< The pad which contains the upper plot part
   TPad *fLowerPad = 0; ///< The pad which contains the calculated lower plot part
   TPad *fTopPad = 0; ///< The Pad that drawn on top on the others to have consistent coordinates

   TH1 *fH1 = 0; ///< Stores the primary histogram
   TH1 *fH2 = 0; ///< Stores the secondary histogram, if there is one
   TObject *fHistDrawProxy = 0; ///< The object which is actually drawn, this might be TH1 or THStack

   Int_t fMode = 0; ///< Stores which calculation is supposed to be performed as specified by user option
   Int_t fErrorMode = TRatioPlot::ErrorMode::kErrorSymmetric; ///< Stores the error mode, sym, asym or func
   TString fOption = ""; ///< Stores the option which is given in the constructor as a string
   TString fH1DrawOpt = ""; ///< Stores draw option for h1 given in constructor
   TString fH2DrawOpt = ""; ///< Stores draw option for h2 given in constructor
   TString fGraphDrawOpt = ""; ///< Stores draw option for the lower plot graph given in constructor
   TString fFitDrawOpt = ""; ///< Stores draw option for the fit function in the fit residual case

   Float_t fSplitFraction = 0.3; ///< Stores the fraction at which the upper and lower pads meet

   TGraph *fRatioGraph = 0; ///< Stores the lower plot's graph
   TGraphErrors *fConfidenceInterval1 = 0; ///< Stores the graph for the 1 sigma band
   TGraphErrors *fConfidenceInterval2 = 0; ///< Stores the graph for the 2 sigma band
   Color_t fCi1Color = kGreen; ///< Stores the color for the 1 sigma band
   Color_t fCi2Color = kYellow; ///< Stores the color for the 2 sigma band

   Bool_t fShowConfidenceIntervals = kTRUE; ///< Stores whether to show the confidence interval bands. From Draw option

   Double_t fCl1 = 0.6827; ///< Stores the confidence level for the inner confidence interval band
   Double_t fCl2 = 0.9545; ///< Stores the confidence level for the outer confidence interval band

   Double_t fC1 = 1.; ///< Stores the scale factor for h1 (or THStack sum)
   Double_t fC2 = 1.; ///< Stores the scale factor for h2

   TFitResult *fFitResult = 0; ///< Stores the explicit fit result given in the fit residual case. Can be 0

   TAxis *fSharedXAxis = 0; ///< X axis that stores the range for both plots
   TGaxis *fUpperGXaxis = 0; ///< Upper graphical x axis
   TGaxis *fLowerGXaxis = 0; ///< Lower graphical x axis
   TGaxis *fUpperGYaxis = 0; ///< Upper graphical y axis
   TGaxis *fLowerGYaxis = 0; ///< Lower graphical y axis
   TGaxis *fUpperGXaxisMirror = 0; ///< Upper mirror of the x axis
   TGaxis *fLowerGXaxisMirror = 0; ///< Lower mirror of the x axis
   TGaxis *fUpperGYaxisMirror = 0; ///< Upper mirror of the y axis
   TGaxis *fLowerGYaxisMirror = 0; ///< Lower mirror of the y axis

   TAxis *fUpYaxis = 0; ///< Clone of the upper y axis
   TAxis *fLowYaxis = 0; ///< Clone of the lower y axis

   std::vector<TLine*> fGridlines; ///< Keeps TLine objects for the gridlines
   std::vector<double> fGridlinePositions; ///< Stores the y positions for the gridlines
   Bool_t fShowGridlines = kTRUE; ///< Stores whether to show the gridlines at all
   Int_t fHideLabelMode = TRatioPlot::HideLabelMode::kHideLow; ///< Stores which label to hide if the margin is to narrow, if at all

   // store margins to be able do determine
   // what has changed when user drags
   Float_t fUpTopMargin = 0.1; ///< Stores the top margin of the upper pad
   Float_t fUpBottomMargin = 0.05; ///< Stores the bottom margin of the upper pad
   Float_t fLowTopMargin = 0.05; ///< Stores the top margin of the lower pad
   Float_t fLowBottomMargin = 0.3; ///< Stores the bottom margin of the lower pad

   Float_t fLeftMargin = 0.1; ///< Stores the common left margin of both pads
   Float_t fRightMargin = 0.1; ///< Stores the common right margin of both pads

   Float_t fInsetWidth = 0.0025;

   Bool_t fIsUpdating = kFALSE; ///< Keeps track of whether its currently updating to reject other calls until done
   Bool_t fIsPadUpdating = kFALSE; ///< Keeps track whether pads are updating during resizing

   virtual void SyncAxesRanges();
   virtual void SetupPads();
   virtual void CreateVisualAxes();
   virtual Bool_t SyncPadMargins();
   void SetPadMargins();
   void CreateGridline();
   void BuildLowerPlot();

   void ImportAxisAttributes(TGaxis* gaxis, TAxis* axis);

   Bool_t IsDrawn();

   virtual void Init(TH1* h1, TH1* h2, Option_t *option = "");

public:

   TRatioPlot();
   virtual ~TRatioPlot();
   TRatioPlot(TH1* h1, TH1* h2, Option_t *option = "pois");

   TRatioPlot(THStack* st, TH1* h2, Option_t *option = "pois");

   TRatioPlot(TH1* h1, Option_t *option = "", TFitResult *fitres = 0);

   void SetH1DrawOpt(Option_t *opt);
   void SetH2DrawOpt(Option_t *opt);
   void SetGraphDrawOpt(Option_t *opt);
   void SetFitDrawOpt(Option_t *opt);

   void SetInsetWidth(Double_t width);

   virtual void Draw(Option_t *chopt="");
   virtual void Browse(TBrowser *b);


   virtual void Paint(Option_t *opt = "");

   // Slots for signal receiving
   void UnZoomed();
   void RangeAxisChanged();
   void SubPadResized();

   // Getters
   TAxis *GetXaxis() const { return fSharedXAxis; }
   TAxis *GetUpYaxis() const { return fUpYaxis; }
   TAxis *GetLowYaxis() const { return fLowYaxis; }

   virtual TGraph *GetLowerRefGraph() const;

   ////////////////////////////////////////////////////////////////////////////////
   /// Shortcut for:
   ///
   /// ~~~{.cpp}
   /// rp->GetLowerRefGraph()->GetXaxis();
   /// ~~~

   TAxis *GetLowerRefXaxis() const { return GetLowerRefGraph()->GetXaxis(); }

   ////////////////////////////////////////////////////////////////////////////////
   /// Shortcut for:
   ///
   /// ~~~{.cpp}
   /// rp->GetLowerRefGraph()->GetYaxis();
   /// ~~~

   TAxis *GetLowerRefYaxis() const { return GetLowerRefGraph()->GetYaxis(); }

   virtual TObject *GetUpperRefObject() const;
   TAxis *GetUpperRefXaxis() const;
   TAxis *GetUpperRefYaxis() const;

   ////////////////////////////////////////////////////////////////////////////////
   /// Get the output of the calculation in the form of a graph. The type of
   /// the return value depends on the input option that was given in the constructor.

   TGraph *GetCalculationOutputGraph() const { return fRatioGraph; }

   ////////////////////////////////////////////////////////////////////////////////
   /// Returns the graph for the 1 sigma confidence interval in the fit residual case

   TGraphErrors *GetConfidenceInterval1() const { return fConfidenceInterval1; }

   ////////////////////////////////////////////////////////////////////////////////
   /// Returns the graph for the 2 sigma confidence interval in the fit residual case

   TGraphErrors *GetConfidenceInterval2() const { return fConfidenceInterval2; }

   TPad * GetUpperPad() const { return fUpperPad; }
   TPad * GetLowerPad() const { return fLowerPad; }

   // Setters

   ////////////////////////////////////////////////////////////////////////////////
   /// Explicitly specify the fit result that is to be used for fit residual calculation.
   /// If it is not provided, the last fit registered in the global fitter is used.
   /// The fit result can also be specified in the constructor.
   ///
   /// \param fitres The fit result coming from the fit function call

   void SetFitResult(TFitResultPtr fitres) { fFitResult = fitres.Get(); }

   // Setters for margins
   void SetUpTopMargin(Float_t margin);
   void SetUpBottomMargin(Float_t margin);
   void SetLowTopMargin(Float_t margin);
   void SetLowBottomMargin(Float_t margin);
   void SetLeftMargin(Float_t margin);
   void SetRightMargin(Float_t margin);

   void SetSeparationMargin(Float_t);
   Float_t GetSeparationMargin() const;
   void SetSplitFraction(Float_t sf);
   void SetConfidenceLevels(Double_t cl1, Double_t cl2);

   virtual void SetGridlines(Double_t *gridlines, Int_t numGridlines);
   virtual void SetGridlines(std::vector<double> gridlines);

   void SetConfidenceIntervalColors(Color_t ci1 = kGreen, Color_t ci2 = kYellow);

   void SetC1(Double_t c1) { fC1 = c1; }
   void SetC2(Double_t c2) { fC2 = c2; }

   ClassDef(TRatioPlot, 1)  //A ratio of histograms
};

#endif
 TRatioPlot.h:1
 TRatioPlot.h:2
 TRatioPlot.h:3
 TRatioPlot.h:4
 TRatioPlot.h:5
 TRatioPlot.h:6
 TRatioPlot.h:7
 TRatioPlot.h:8
 TRatioPlot.h:9
 TRatioPlot.h:10
 TRatioPlot.h:11
 TRatioPlot.h:12
 TRatioPlot.h:13
 TRatioPlot.h:14
 TRatioPlot.h:15
 TRatioPlot.h:16
 TRatioPlot.h:17
 TRatioPlot.h:18
 TRatioPlot.h:19
 TRatioPlot.h:20
 TRatioPlot.h:21
 TRatioPlot.h:22
 TRatioPlot.h:23
 TRatioPlot.h:24
 TRatioPlot.h:25
 TRatioPlot.h:26
 TRatioPlot.h:27
 TRatioPlot.h:28
 TRatioPlot.h:29
 TRatioPlot.h:30
 TRatioPlot.h:31
 TRatioPlot.h:32
 TRatioPlot.h:33
 TRatioPlot.h:34
 TRatioPlot.h:35
 TRatioPlot.h:36
 TRatioPlot.h:37
 TRatioPlot.h:38
 TRatioPlot.h:39
 TRatioPlot.h:40
 TRatioPlot.h:41
 TRatioPlot.h:42
 TRatioPlot.h:43
 TRatioPlot.h:44
 TRatioPlot.h:45
 TRatioPlot.h:46
 TRatioPlot.h:47
 TRatioPlot.h:48
 TRatioPlot.h:49
 TRatioPlot.h:50
 TRatioPlot.h:51
 TRatioPlot.h:52
 TRatioPlot.h:53
 TRatioPlot.h:54
 TRatioPlot.h:55
 TRatioPlot.h:56
 TRatioPlot.h:57
 TRatioPlot.h:58
 TRatioPlot.h:59
 TRatioPlot.h:60
 TRatioPlot.h:61
 TRatioPlot.h:62
 TRatioPlot.h:63
 TRatioPlot.h:64
 TRatioPlot.h:65
 TRatioPlot.h:66
 TRatioPlot.h:67
 TRatioPlot.h:68
 TRatioPlot.h:69
 TRatioPlot.h:70
 TRatioPlot.h:71
 TRatioPlot.h:72
 TRatioPlot.h:73
 TRatioPlot.h:74
 TRatioPlot.h:75
 TRatioPlot.h:76
 TRatioPlot.h:77
 TRatioPlot.h:78
 TRatioPlot.h:79
 TRatioPlot.h:80
 TRatioPlot.h:81
 TRatioPlot.h:82
 TRatioPlot.h:83
 TRatioPlot.h:84
 TRatioPlot.h:85
 TRatioPlot.h:86
 TRatioPlot.h:87
 TRatioPlot.h:88
 TRatioPlot.h:89
 TRatioPlot.h:90
 TRatioPlot.h:91
 TRatioPlot.h:92
 TRatioPlot.h:93
 TRatioPlot.h:94
 TRatioPlot.h:95
 TRatioPlot.h:96
 TRatioPlot.h:97
 TRatioPlot.h:98
 TRatioPlot.h:99
 TRatioPlot.h:100
 TRatioPlot.h:101
 TRatioPlot.h:102
 TRatioPlot.h:103
 TRatioPlot.h:104
 TRatioPlot.h:105
 TRatioPlot.h:106
 TRatioPlot.h:107
 TRatioPlot.h:108
 TRatioPlot.h:109
 TRatioPlot.h:110
 TRatioPlot.h:111
 TRatioPlot.h:112
 TRatioPlot.h:113
 TRatioPlot.h:114
 TRatioPlot.h:115
 TRatioPlot.h:116
 TRatioPlot.h:117
 TRatioPlot.h:118
 TRatioPlot.h:119
 TRatioPlot.h:120
 TRatioPlot.h:121
 TRatioPlot.h:122
 TRatioPlot.h:123
 TRatioPlot.h:124
 TRatioPlot.h:125
 TRatioPlot.h:126
 TRatioPlot.h:127
 TRatioPlot.h:128
 TRatioPlot.h:129
 TRatioPlot.h:130
 TRatioPlot.h:131
 TRatioPlot.h:132
 TRatioPlot.h:133
 TRatioPlot.h:134
 TRatioPlot.h:135
 TRatioPlot.h:136
 TRatioPlot.h:137
 TRatioPlot.h:138
 TRatioPlot.h:139
 TRatioPlot.h:140
 TRatioPlot.h:141
 TRatioPlot.h:142
 TRatioPlot.h:143
 TRatioPlot.h:144
 TRatioPlot.h:145
 TRatioPlot.h:146
 TRatioPlot.h:147
 TRatioPlot.h:148
 TRatioPlot.h:149
 TRatioPlot.h:150
 TRatioPlot.h:151
 TRatioPlot.h:152
 TRatioPlot.h:153
 TRatioPlot.h:154
 TRatioPlot.h:155
 TRatioPlot.h:156
 TRatioPlot.h:157
 TRatioPlot.h:158
 TRatioPlot.h:159
 TRatioPlot.h:160
 TRatioPlot.h:161
 TRatioPlot.h:162
 TRatioPlot.h:163
 TRatioPlot.h:164
 TRatioPlot.h:165
 TRatioPlot.h:166
 TRatioPlot.h:167
 TRatioPlot.h:168
 TRatioPlot.h:169
 TRatioPlot.h:170
 TRatioPlot.h:171
 TRatioPlot.h:172
 TRatioPlot.h:173
 TRatioPlot.h:174
 TRatioPlot.h:175
 TRatioPlot.h:176
 TRatioPlot.h:177
 TRatioPlot.h:178
 TRatioPlot.h:179
 TRatioPlot.h:180
 TRatioPlot.h:181
 TRatioPlot.h:182
 TRatioPlot.h:183
 TRatioPlot.h:184
 TRatioPlot.h:185
 TRatioPlot.h:186
 TRatioPlot.h:187
 TRatioPlot.h:188
 TRatioPlot.h:189
 TRatioPlot.h:190
 TRatioPlot.h:191
 TRatioPlot.h:192
 TRatioPlot.h:193
 TRatioPlot.h:194
 TRatioPlot.h:195
 TRatioPlot.h:196
 TRatioPlot.h:197
 TRatioPlot.h:198
 TRatioPlot.h:199
 TRatioPlot.h:200
 TRatioPlot.h:201
 TRatioPlot.h:202
 TRatioPlot.h:203
 TRatioPlot.h:204
 TRatioPlot.h:205
 TRatioPlot.h:206
 TRatioPlot.h:207
 TRatioPlot.h:208
 TRatioPlot.h:209
 TRatioPlot.h:210
 TRatioPlot.h:211
 TRatioPlot.h:212
 TRatioPlot.h:213
 TRatioPlot.h:214
 TRatioPlot.h:215
 TRatioPlot.h:216
 TRatioPlot.h:217
 TRatioPlot.h:218
 TRatioPlot.h:219
 TRatioPlot.h:220
 TRatioPlot.h:221
 TRatioPlot.h:222
 TRatioPlot.h:223
 TRatioPlot.h:224
 TRatioPlot.h:225
 TRatioPlot.h:226
 TRatioPlot.h:227
 TRatioPlot.h:228
 TRatioPlot.h:229
 TRatioPlot.h:230
 TRatioPlot.h:231
 TRatioPlot.h:232
 TRatioPlot.h:233
 TRatioPlot.h:234
 TRatioPlot.h:235
 TRatioPlot.h:236
 TRatioPlot.h:237
 TRatioPlot.h:238
 TRatioPlot.h:239
 TRatioPlot.h:240
 TRatioPlot.h:241
 TRatioPlot.h:242
 TRatioPlot.h:243
 TRatioPlot.h:244
 TRatioPlot.h:245
 TRatioPlot.h:246
 TRatioPlot.h:247
 TRatioPlot.h:248
 TRatioPlot.h:249
 TRatioPlot.h:250
 TRatioPlot.h:251
 TRatioPlot.h:252
 TRatioPlot.h:253
 TRatioPlot.h:254
 TRatioPlot.h:255
 TRatioPlot.h:256
 TRatioPlot.h:257
 TRatioPlot.h:258
 TRatioPlot.h:259
 TRatioPlot.h:260
 TRatioPlot.h:261
 TRatioPlot.h:262
 TRatioPlot.h:263
 TRatioPlot.h:264
 TRatioPlot.h:265
 TRatioPlot.h:266
 TRatioPlot.h:267
 TRatioPlot.h:268
 TRatioPlot.h:269
 TRatioPlot.h:270
 TRatioPlot.h:271
 TRatioPlot.h:272
 TRatioPlot.h:273
 TRatioPlot.h:274