From a74c1f11e8b01b81ce9aab4bd3659c141132c114 Mon Sep 17 00:00:00 2001
From: zleba <radek.zlebcik@gmail.com>
Date: Tue, 4 Jul 2017 20:26:22 +0200
Subject: [PATCH] Splitting to header and source

---
 plottingHelper.C | 1639 ++++++++++++++++++++++++++++++++++++++++++++
 plottingHelper.h | 1714 +++-------------------------------------------
 2 files changed, 1724 insertions(+), 1629 deletions(-)
 create mode 100644 plottingHelper.C

diff --git a/plottingHelper.C b/plottingHelper.C
new file mode 100644
index 0000000..c55e2c0
--- /dev/null
+++ b/plottingHelper.C
@@ -0,0 +1,1639 @@
+#include "plottingHelper.h"
+
+
+/// The namespace of whole Plotting Helper utility
+/// 
+///
+namespace PlottingHelper {
+
+using namespace std;
+
+
+/// @name Getters
+/// Functions returning elements of the active frame
+///@{ 
+
+/// The method returns current frame on the active pad.
+///
+/// Useful for example to set maximum of the y-axis, GetFrame()->SetMaximum(5)
+TH1 *GetFrame()
+{
+   // get first histogram in the list of primitives
+
+   TH1 *hobj = nullptr;
+
+   TIter next(gPad->GetListOfPrimitives());
+   TObject *obj;
+   while ((obj = next())) {
+      if(obj->InheritsFrom(TH1::Class())) {
+         hobj = (TH1*)obj;
+         //hobj->DrawCopy("sameaxis");
+			break;
+      }
+      if(obj->InheritsFrom(TMultiGraph::Class())) {
+         TMultiGraph *mg = (TMultiGraph*)obj;
+			hobj = mg ? mg->GetHistogram() : nullptr;
+			//if (hobj) hobj->DrawCopy("sameaxis");
+			break;
+      }
+      if(obj->InheritsFrom(TGraph::Class())) {
+         TGraph *g = (TGraph*)obj;
+			hobj = g ? g->GetHistogram() : nullptr;
+         //hobj->DrawCopy("sameaxis");
+			break;
+      }
+      if(obj->InheritsFrom(THStack::Class())) {
+         THStack *hs = (THStack*)obj;
+			hobj = hs ? hs->GetHistogram() : nullptr;
+			//hobj->DrawCopy("sameaxis");
+			break;
+      }
+   }
+    if(!hobj) {cout << "No frame created in active pad" << endl;}
+
+   return hobj;
+}
+
+/// Return x-axis of the active frame
+TAxis *GetXaxis() {
+    TH1 *frame = GetFrame();
+    return frame ? frame->GetXaxis() : nullptr;
+}
+
+/// Return y-axis of the active frame
+TAxis *GetYaxis() {
+    TH1 *frame = GetFrame();
+    return frame ? frame->GetYaxis() : nullptr;
+}
+
+/// Return z-axis of the active frame
+TAxis *GetZaxis() {
+    TH1 *frame = GetFrame();
+    return frame ? frame->GetZaxis() : nullptr;
+}  
+
+///@} 
+
+
+
+/// @name Units helpers
+/// Functions to convert units and obtain axis fractions
+///@{ 
+
+/// Transform font size from px to the relative units
+///
+/// The returned size is dependent on the currently active pad - the gPad pointer
+/// @param px The font size in px
+/// @return The font size in relative units
+double PxFontToRel(double px)
+{
+	double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
+	double pxW = gPad->GetWw()*gPad->GetAbsWNDC();
+
+	if(pxW < pxH) return px/pxW;
+	         else return px/pxH;
+
+    //double pad_width  = gPad->XtoPixel(gPad->GetX2());
+    //double pad_height = gPad->YtoPixel(gPad->GetY1()); 
+	//if(pxW < pxH) return px/pad_width / corX;
+	         //else return px/pad_height / corY;
+}
+
+
+/// Transform font size from relative units to pixels
+///
+/// The returned size is dependent on the currently active pad - the gPad pointer
+/// @param rel The font size in relative units
+/// @return The font size in pixels
+double RelFontToPx(double rel)
+{
+	double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
+	double pxW = gPad->GetWw()*gPad->GetAbsWNDC();
+	if(pxW < pxH) return rel*pxW;
+	         else return rel*pxH;
+}
+
+
+/// Fraction of the pad width covered by x-axis
+double GetAxisFractionX()
+{
+    //return (gPad->GetUxmax() - gPad->GetUxmin())/(gPad->GetX2() - gPad->GetX1());
+    return (1. - gPad->GetLeftMargin() - gPad->GetRightMargin());
+}
+
+/// Fraction of the pad height covered by y-axis
+double GetAxisFractionY()
+{
+    //return (gPad->GetUymax() - gPad->GetUymin())/(gPad->GetY2() - gPad->GetY1());
+    return (1. - gPad->GetBottomMargin() - gPad->GetTopMargin());
+}
+
+/// Convert tick length in px of x-axis to the relative units
+double TickAbsToRelX(double tick)
+{
+    double nom = GetAxisFractionX() * gPad->GetAbsHNDC() * gPad->GetWh();
+	return tick/nom;
+}
+
+
+/// Convert tick length in px of y-axis to the relative units
+double TickAbsToRelY(double tick)
+{
+    double nom =  GetAxisFractionY() * gPad->GetAbsWNDC() * gPad->GetWw();
+	return tick/nom;
+}
+
+///@}
+
+/// @name Decorators
+/// Functions to simply define text sizes, offsets and axis ticks
+///@{ 
+
+/// Set text size of x- and y-axis titles and labels to the frame title
+///
+/// Note that the Canvas width and height is specified in TCanvas constructor.
+/// The font size is defined as the height of envelope between "gh" characters
+/// The height of numbers is for example 3/4 of the font size.
+void SetFonts(double pxX, double pxY, double pxT)
+{
+    TH1 *frame = GetFrame();
+    if(!frame) return;
+
+    if(pxY < 0) pxY = pxX;
+    if(pxT < 0) pxT = pxX;
+
+    double relSizeX = PxFontToRel(pxX);
+    double relSizeY = PxFontToRel(pxY);
+    double relSizeT = PxFontToRel(pxT);
+
+	frame->GetXaxis()->SetTitleSize(relSizeX);
+	frame->GetXaxis()->SetLabelSize(relSizeX);
+
+	frame->GetYaxis()->SetTitleSize(relSizeY);
+	frame->GetYaxis()->SetLabelSize(relSizeY);
+
+    frame->SetTitleSize(relSizeT);
+}
+
+///
+/// Set ticks sizes of x and y-axis in px
+///
+void SetTicks(double tickX, double tickY)
+{
+    TH1 *frame = GetFrame();
+    if(!frame) return;
+
+    //gPad->Update();
+    if(tickY < 0) tickY = tickX;
+	frame->GetXaxis()->SetTickSize(TickAbsToRelX(tickX) );
+	frame->GetYaxis()->SetTickSize(TickAbsToRelY(tickY) );
+}
+
+/// Set offset of the x-axis labels.
+///
+/// The zero offset correspond to labels "standing" on top of the x-axis.
+/// The offset is measured in units corresponds to height of numbers like "012..."
+/// Therefore offset 1 correspond to labels touching x-axis by from the bottom.
+void SetLabelOffsetX(double off)
+{
+    TH1 *frame = GetFrame();
+    if(!frame) return;
+
+    double labSize = frame->GetXaxis()->GetLabelSize();
+    double off0 = 0;
+    if(gPad->GetLogx()) {
+        off0 = -1.15;
+        if(frame->GetXaxis()->GetNoExponent()) off0 += 0.33;
+    }
+    else {
+        off0 = -0.8;
+    }
+
+    double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
+    double fact = RelFontToPx(labSize)/pxH;
+    off *= fact *3/4.; //conversion to "1354" height
+
+
+    off += off0 * labSize;
+    frame->GetXaxis()->SetLabelOffset(off);
+}
+
+
+
+
+/// Set offset of the x-axis title.
+///
+/// The zero offset corresponds to title which is intersect by the x-axi in its middle.
+/// The offset is measured in units corresponds to height of numbers like "012..."
+/// Therefore offset 0.5 corresponds to numeric title touching x-axis by from the bottom.
+/// Note that the height of numbers is 3/4 of the font size (height) which is defined by the
+/// gh vertical envelope. It means that if title contains h, offset 4/3 * 0.5 would result of "h" touching axis
+/// The title text size must be set before offset!
+///
+void SetTitleOffsetX(double off)
+{
+    TH1 *frame = GetFrame();
+    if(!frame) return;
+
+    TAxis *ax = frame->GetXaxis();
+    off *= 3/4.;
+    ax->SetTitleOffset(off* RelFontToPx(ax->GetTitleSize())/1.6 / ( gPad->GetWh()* ax->GetTitleSize()*gPad->GetAbsHNDC() ) );
+}
+
+/// Set offset of the y-axis labels.
+///
+/// The zero offset corresponds to labels touching the y-axis from the left
+/// The offset is measured in units corresponds to height of numbers like "012..."
+/// I.e. the width of 0 if lying.
+/// The label text size must be set before offset!
+///
+void SetLabelOffsetY(double off)
+{
+    TH1 *frame = GetFrame();
+    if(!frame) return;
+    TAxis *ax = frame->GetYaxis();
+    double labSize = ax->GetLabelSize();
+    double pxW =  gPad->GetWw() * gPad->GetAbsWNDC() ;
+    double fact = RelFontToPx(labSize)/pxW;
+
+    double off0 = 0;
+    if(gPad->GetLogy())
+        off0 = -0.08;
+
+
+    off *= 3/4.;
+    ax->SetLabelOffset(off *  fact + off0*labSize );
+}
+
+/// Set offset of the y-axis title.
+///
+/// The zero offset corresponds to title which is intersect by the y-axis in its middle.
+/// The offset is measured in units corresponds to height of numbers like "012..."
+/// Note that the height of numbers is 3/4 of the font size (height) which is defined by the
+/// gh vertical envelope.
+/// The title text size must be set before offset!
+///
+void SetTitleOffsetY(double off)
+{
+    TH1 *frame = GetFrame();
+    if(!frame) return;
+    TAxis *ax = frame->GetYaxis();
+    off *= 3/4.;//to vertical size of "0"
+    ax->SetTitleOffset( off*  RelFontToPx(ax->GetTitleSize())/1.6 / ( gPad->GetWw()*ax->GetTitleSize()* gPad->GetAbsWNDC() ) );
+}
+
+/// Set of the fonts and ticks sizes 
+///
+/// Set size of x-,y-axis labels and titles to px (in pixels).
+/// In addition the x and y tick lengths can be specified
+void SetFontsTicks(double px, double tickX, double tickY)
+{
+    SetFonts(px);
+    SetTicks(tickX, tickY);
+}
+
+/// Set offsets of x,y labels and titles
+///
+/// Note that root is using different alignment of labels and titles
+/// We don't try to correct for that as we assume that in general
+/// the actual form of the title can be specified later
+/// The title's and label's text sizes must be set before offsets!
+void SetOffsets(double lX, double tX, double lY, double tY)
+{
+    SetLabelOffsetX(lX);
+    SetTitleOffsetX(tX);
+    SetLabelOffsetY(lY);
+    SetTitleOffsetY(tY);
+}
+
+/// Set Fonts, Ticks and Offsets
+///
+/// Set up fonts sizes, ticks length and titles/labels offsets
+/// All parameters are given as vectors, call as SetFTO({14}, {5}, {1.3, 2.3, 0.3, 2.3});
+void SetFTO(vector<double> fonts, vector<double> ticks, vector<double> offsets)
+{
+    fonts.resize(3, -1);
+    ticks.resize(2, -1);
+    offsets.resize(4, 0);
+
+    SetFonts(fonts[0], fonts[1], fonts[2]);
+    SetTicks(ticks[0], ticks[1]);
+    SetOffsets(offsets[0], offsets[1], offsets[2], offsets[3]);
+}
+
+///@}
+
+
+
+/// @name Generalized titles
+/// Functions to simplify drawing of latex captions related to the particular frame(s)
+/// Especially useful in case of describing complex grid of frames.
+/// For captions inside of frame consider also using of automatic legend.
+/// Conventional axis titles can be easily "reproduced" with these methods
+///@{ 
+
+/// Draw latex in coordinates x,y give a hull of two frames in given TPads
+///
+/// The rectangular hull of two frames corresponding to pad1 and pad2 is used as an NDC-like coordinate system
+/// For example the x-value starts from the most left side of frame1 and/or frame2 and ends in the most right side of these frames
+/// Note that in current implementation given pads cannot contain any sub-pad = there must be only one frame in pad1 and one frame
+/// in pad2.
+/// @param pad1 The pad where the first frame is located
+/// @param pad2 The pad where the second frame is located (can be the same as pad1)
+/// @param x,y  Normalised coordinates between 0 and 1 defined by the hull of frame1 and frame2, 0,0 is on bottom left
+/// @param text Latex which will be plotted, consider using #splitline #bf, #it, #font[], #color[].
+/// @param fSize Font size in pixels, by default the font size is taken from the title of the first frame.
+/// @param style The text alignment and orientation. The text-orientation is defined by rotating
+/// of letter "v", that means "v,<,>,^". The default text alignment to the center horizontally and vertically.
+/// The text can be also aligned to the left "l" or right "r", vertically to the bottom "b" or top "t"
+void DrawLatex(TVirtualPad *pad1, TVirtualPad *pad2, double x, double y, TString text, double fSize, TString style)
+{
+    TVirtualPad *padOrg = gPad;
+    assert(pad1->GetCanvas() == pad2->GetCanvas());
+    TCanvas *can = pad1->GetCanvas();
+
+    //Setting of style
+    TLatex *tex = new TLatex();
+
+    int hAlign = 2;
+    int vAlign = 2;
+
+    double angle;
+    if(style.Contains('>')) {
+        if(style.Contains('l')) vAlign = 1;
+        if(style.Contains('r')) vAlign = 3;
+        if(style.Contains('b')) hAlign = 1;
+        if(style.Contains('t')) hAlign = 3;
+        angle = 90;
+    }
+    else if(style.Contains('<')) {
+        if(style.Contains('l')) vAlign = 3;
+        if(style.Contains('r')) vAlign = 1;
+        if(style.Contains('b')) hAlign = 3;
+        if(style.Contains('t')) hAlign = 1;
+        angle = 270;
+    }
+    else if(style.Contains('^')) {
+        if(style.Contains('l')) hAlign = 3;
+        if(style.Contains('r')) hAlign = 1;
+        if(style.Contains('b')) vAlign = 3;
+        if(style.Contains('t')) vAlign = 1;
+        angle = 180;
+    }
+    else {
+        if(style.Contains('l')) hAlign = 1;
+        if(style.Contains('r')) hAlign = 3;
+        if(style.Contains('b')) vAlign = 1;
+        if(style.Contains('t')) vAlign = 3;
+        angle = 0;
+    }
+
+    tex->SetTextAlign(10*hAlign + vAlign);
+    tex->SetTextAngle(angle);
+    tex->SetTextFont(42);
+
+    double l[2], r[2], b[2], t[2];
+
+    TVirtualPad *pads[] = {pad1, pad2};
+
+    for(int i = 0; i < 2; ++i) {
+        l[i] = pads[i]->GetAbsXlowNDC() + pads[i]->GetAbsWNDC()*pads[i]->GetLeftMargin();
+        r[i] = pads[i]->GetAbsXlowNDC() + pads[i]->GetAbsWNDC()*(1-pads[i]->GetRightMargin());
+        b[i] = pads[i]->GetAbsYlowNDC() + pads[i]->GetAbsHNDC()*pads[i]->GetBottomMargin();
+        t[i] = pads[i]->GetAbsYlowNDC() + pads[i]->GetAbsHNDC()*(1-pads[i]->GetTopMargin());
+    }
+
+    double left  = min(l[0], l[1]);
+    double right = max(r[0], r[1]);
+    double bottom= min(b[0], b[1]);
+    double top   = max(t[0], t[1]);
+
+    double xGlob = left   + (right-left) *x;
+    double yGlob = bottom + (top-bottom) *y;
+
+
+    auto isBtw = [](double low, double x, double high) {return low < x && x < high;};
+    bool isInside = false;
+    for(int i = 0; (i < 2 && pads[0] != pads[1]) || (i<1); ++i) {
+        if(isBtw(l[i],xGlob,r[i]) && isBtw(b[i],yGlob,t[i]) ) {
+            pads[i]->cd();
+            if(fSize < 0) {
+                TH1 *frame = GetFrame();
+                fSize = frame ? RelFontToPx(frame->GetTitleSize()) : 12;
+            }
+            tex->SetTextSize(PxFontToRel(fSize));
+
+            double xFactor = (r[i] - l[i]) / (right - left);
+            double yFactor = (t[i] - b[i]) / (top - bottom);
+            assert(x / xFactor < 1);
+            assert(y / yFactor < 1);
+
+
+            double xLoc = pads[i]->GetLeftMargin() + x/xFactor *
+                           (1 - pads[i]->GetLeftMargin() - pads[i]->GetRightMargin());
+            double yLoc = pads[i]->GetBottomMargin() + y/yFactor *
+                           (1 - pads[i]->GetBottomMargin() - pads[i]->GetTopMargin());
+
+            //TLine *l = new TLine();
+            //l->SetLineColor(kRed);
+            //l->DrawLineNDC(xLoc, yLoc, xLoc + 0.1, yLoc);
+            tex->DrawLatexNDC(xLoc, yLoc, text);
+            isInside = true;
+        }
+    }
+
+    if(!isInside) {
+        if(fSize < 0) {
+            pads[0]->cd();
+            TH1 *frame = GetFrame();
+            fSize = frame ? RelFontToPx(frame->GetTitleSize()) : 12;
+        }
+        can->cd();
+        tex->SetTextSize(PxFontToRel(fSize));
+        tex->DrawLatexNDC(xGlob, yGlob, text);
+    }
+
+    gPad->Update();
+    padOrg->cd();
+}
+
+
+/// Draw latex at coordinates of the frame inside the corresponding TPad
+///
+/// For description see the DrawLatex method, here only the one pad is provided
+void DrawLatex(TVirtualPad *pad, double x, double y, TString text, double fSize, TString style)
+{
+    DrawLatex(pad, pad, x, y, text, fSize, style);
+}
+
+
+/// Draw latex at coordinates of the frame corresponding to active TPad
+///
+/// The same as DrawLatex but used for active pad
+void DrawLatex(double x, double y, TString text, double fSize, TString style)
+{
+    DrawLatex(gPad, x, y, text, fSize, style);
+}
+
+
+/// Draw latex with distant Offset to the border of the frame1 and frame2 hull
+///
+/// The offset coding is used to cover left, right, bottom and top scenarios
+void DrawLatexLRTB(TVirtualPad *pad1, TVirtualPad *pad2, double Offset, TString text, double fSize, TString style)
+{
+    TVirtualPad *padOrg = gPad;
+    if(fSize < 0) {
+        pad1->cd();
+        TH1 *frame = GetFrame();
+        fSize = frame ? RelFontToPx(frame->GetTitleSize()) : 12;
+        padOrg->cd();
+    }
+    auto Close = [](double x, double val) {return abs(x-1000*val) <1000;};
+
+    double x = 0.5, y = 0.5;
+
+
+    double b[2], t[2], l[2], r[2];
+
+    TVirtualPad *pads[] = {pad1, pad2};
+    for(int i = 0; i < 2; ++i) {
+        l[i] = pads[i]->GetAbsXlowNDC() + pads[i]->GetAbsWNDC()*pads[i]->GetLeftMargin();
+        r[i] = pads[i]->GetAbsXlowNDC() + pads[i]->GetAbsWNDC()*(1-pads[i]->GetRightMargin());
+        b[i] = pads[i]->GetAbsYlowNDC() + pads[i]->GetAbsHNDC()*pads[i]->GetBottomMargin();
+        t[i] = pads[i]->GetAbsYlowNDC() + pads[i]->GetAbsHNDC()*(1-pads[i]->GetTopMargin());
+    }
+
+    double left  = min(l[0], l[1]);
+    double right = max(r[0], r[1]);
+    double bottom= min(b[0], b[1]);
+    double top   = max(t[0], t[1]);
+
+    if(Close(Offset,2) || Close(Offset, 8)) {
+        if(style.Contains('l')) x = 0.0;
+        if(style.Contains('r')) x = 1.0;
+        double unit = (fSize * 3./4) / ( pad1->GetWh() * (top - bottom) );
+
+        if(Close(Offset,2)) y = 1 + unit*(Offset - 2000);
+        else                y = 0 - unit*(Offset - 8000);
+
+    }
+    else if(Close(Offset,4) || Close(Offset, 6)) {
+        if(style.Contains('b')) y = 0.0;
+        if(style.Contains('t')) y = 1.0;
+        double unit = (fSize * 3./4) / ( pad1->GetWw() * (right - left) );
+
+        if(Close(Offset,6)) x = 1 + unit*(Offset - 6000);
+        else                x = 0 - unit*(Offset - 4000);
+    }
+    else
+        assert(0);
+
+    DrawLatex(pad1, pad2, x, y, text, fSize, style);
+}
+
+/// Draw latex up of frame1 and frame2
+///
+/// Draw the latex above the frames 1 and 2. The Offset is in units of text height of text. It is exactly the same unit
+/// as used for the title offsets
+void DrawLatexUp(TVirtualPad *pad1, TVirtualPad *pad2, double Offset, TString text, double fSize, TString style) {
+    DrawLatexLRTB(pad1, pad2, 2000 + Offset, text, fSize, style);
+}
+
+///Draw latex down of frame1 and frame2
+void DrawLatexDown(TVirtualPad *pad1,TVirtualPad *pad2, double Offset, TString text, double fSize, TString style) {
+    DrawLatexLRTB(pad1, pad2, 8000 + Offset, text, fSize, style);
+}
+
+///Draw latex right of frame1 and frame2
+void DrawLatexRight(TVirtualPad *pad1, TVirtualPad *pad2, double Offset, TString text, double fSize, TString style) {
+    DrawLatexLRTB(pad1, pad2, 6000 + Offset, text, fSize, style);
+}
+
+///Draw latex left of frame1 and frame2
+void DrawLatexLeft(TVirtualPad *pad1, TVirtualPad *pad2, double Offset, TString text, double fSize, TString style) {
+    DrawLatexLRTB(pad1, pad2, 4000 + Offset, text, fSize, style);
+}
+
+
+///Draw latex up of frame corresponding to given pad
+void DrawLatexUp(TVirtualPad *pad, double Offset, TString text, double fSize, TString style) {
+    DrawLatexUp(pad, pad, Offset, text, fSize, style);
+}
+
+///Draw latex down of frame corresponding to given pad
+void DrawLatexDown(TVirtualPad *pad, double Offset, TString text, double fSize, TString style) {
+    DrawLatexDown(pad, pad, Offset, text, fSize, style);
+}
+
+///Draw latex right of frame corresponding to given pad
+void DrawLatexRight(TVirtualPad *pad, double Offset, TString text, double fSize, TString style) {
+    DrawLatexRight(pad, pad, Offset, text, fSize, style);
+}
+
+///Draw latex left of frame corresponding to given pad
+void DrawLatexLeft(TVirtualPad *pad, double Offset, TString text, double fSize, TString style) {
+    DrawLatexLeft(pad, pad, Offset, text, fSize, style);
+}
+
+
+///Draw latex up of frame corresponding to active pad
+void DrawLatexUp(double Offset, TString text, double fSize, TString style) {
+    DrawLatexUp(gPad, Offset, text, fSize, style);
+}
+///Draw latex down of frame corresponding to active pad
+void DrawLatexDown(double Offset, TString text, double fSize, TString style) {
+    DrawLatexDown(gPad, Offset, text, fSize, style);
+}
+///Draw latex right of frame corresponding to active pad
+void DrawLatexRight(double Offset, TString text, double fSize, TString style) {
+    DrawLatexRight(gPad, Offset, text, fSize, style);
+}
+///Draw latex left of frame corresponding to active pad
+void DrawLatexLeft(double Offset, TString text, double fSize, TString style) {
+    DrawLatexLeft(gPad, Offset, text, fSize, style);
+}
+
+
+
+
+///@}
+
+
+/// @name Auto-legend
+/// Functions to place lagend automaticaly and prevent overlaps
+///@{ 
+
+/// Convert layout bit to string
+///
+/// Used to setup the position of particular TLegend by SetName
+/// For example leg->SetName(SetLayout(kPos1)) for legend in to top left
+/// Used internally by newLegend
+/// @see newLegend()
+/// @param pos the position bit, for instance kPos2 | kPos8
+/// @return the number printed in decadic base to the string
+const char *SetLayout(unsigned pos)
+{
+    return to_string(pos).c_str();
+}
+
+
+unsigned SimplifyPos(unsigned pos)
+{
+    if(pos & kPos5) return kPos5;
+    if(pos & kPos2) pos &= !kPos1 & !kPos3;
+    if(pos & kPos4) pos &= !kPos1 & !kPos7;
+    if(pos & kPos6) pos &= !kPos3 & !kPos9;
+    if(pos & kPos8) pos &= !kPos7 & !kPos9;
+    return pos;
+}
+
+
+/// Calculates positions and height and width of rectangle which encapsulates TLatex.
+///
+/// Works well for 4 basic orientation, 0,90,180,270 degree.
+/// Does not work for properly for vertical alignment to the bottom of the line
+///
+RectangleNDC GetNDC(TLatex *lat)
+{
+
+	int hAlign = lat->GetTextAlign() / 10 - 1;
+	int vAlign = lat->GetTextAlign() % 10 - 1;
+	if(vAlign == -1) vAlign = 0;
+
+	RectangleNDC rTitle;
+
+	rTitle.fHeight = lat->GetYsize() / (gPad->GetY2()-gPad->GetY1());
+	rTitle.fWidth = lat->GetXsize()  / (gPad->GetX2()-gPad->GetX1());
+	rTitle.fX = lat->GetX();
+	rTitle.fY = lat->GetY();
+
+
+	if(lat->GetTextAngle() == 0) {
+		rTitle.fX -= hAlign*rTitle.fWidth/2.;
+		rTitle.fY -= vAlign*rTitle.fHeight/2.;
+	}
+	else {
+		swap(rTitle.fWidth, rTitle.fHeight);
+		double rat = gPad->GetWh() / double(gPad->GetWw());
+		rat /= gPad->GetAbsWNDC() / double(gPad->GetAbsHNDC());
+		rTitle.fWidth *= rat;
+		rTitle.fHeight *= 1./rat;
+
+		if(lat->GetTextAngle() == 90) {
+			rTitle.fY -= (hAlign)*rTitle.fHeight/2.;
+			vAlign = 2-vAlign;
+			rTitle.fX -=1.*vAlign*rTitle.fWidth/2.;
+		}
+		else if(lat->GetTextAngle() == 270) {
+			hAlign = 2-hAlign;
+			rTitle.fY -= (hAlign)*rTitle.fHeight/2.;
+			rTitle.fX -=1.*vAlign*rTitle.fWidth/2.;
+		}
+	}
+	rTitle.lat = lat;
+	return rTitle;
+}
+
+/// Define new legend at position pos with nCols columns.
+///
+/// The text size is set to be the same as the size of y-axis title
+/// All this values can be changed later on manually, like
+/// leg->SetTextSize(1.3*leg->GetTextSize())
+///
+TLegend *newLegend(unsigned pos, int nCols)
+{
+        TLegend *leg = new TLegend(0., 0., 0., 0.);
+        leg->SetName(SetLayout(pos));
+        leg->SetTextSize(GetYaxis()->GetTitleSize());
+        leg->SetNColumns(nCols);
+        return leg;
+}
+
+/// Calculates sizes of the legend in NDC
+///
+/// Note that due to the bug in root the y-size to be set to TLegend object
+/// is sometimes diffrent than the real size
+void GetLegendSizes(TLegend *leg, double &SizeX, double &SizeY, double &SizeYroot)
+{
+
+    double lineSeparation = 1.0;
+    double markerSize = 1.5;
+    double columnSeparation = 0;
+
+    //double fontSize = RelFontToPx(GetYaxis()->GetTitleSize());
+    double fontSize = RelFontToPx(leg->GetTextSize());
+
+    gPad->Update();
+    //cout <<"There is just start " <<  gPad->GetUymax() << " "<< gPad->GetUymin() << endl;
+
+    leg->SetBorderSize(0);
+    //leg->SetLineStyle(2);
+    leg->SetFillStyle(0);
+    leg->SetTextSize(PxFontToRel(fontSize));
+
+    double fSizeNDCy = fontSize / (gPad->GetWh() * gPad->GetAbsHNDC());
+    double fSizeNDCx = fontSize / (gPad->GetWw() * gPad->GetAbsWNDC());
+
+    int nHeaders = 0;
+    int nLegItems = 0;
+
+    int nCols = leg->GetNColumns();
+    vector<double> maxC(nCols, 0);
+    double headerW = 0;
+    int colId = 0;
+    for(const auto &&entry : *leg->GetListOfPrimitives()) {
+        TString lab = dynamic_cast<TLegendEntry *>(entry)->GetLabel();
+        TString opt = dynamic_cast<TLegendEntry *>(entry)->GetOption();
+        cout << "Label "<< leg->GetNRows()<<" " << lab << endl;
+        TLatex *lat = new TLatex(0.5, 0.5, lab);
+        lat->SetTextSize(leg->GetTextSize());
+        lat->SetTextFont(leg->GetTextFont());
+
+        double textW = GetNDC(lat).fWidth;
+        if(opt == "h") {
+            headerW = max(headerW, textW);
+            ++nHeaders;
+            colId = -1;
+        }
+        else {
+            maxC[colId] = max(maxC[colId], textW);
+            ++nLegItems;
+        }
+        colId = (colId != nCols-1) ? colId + 1 : 0;
+        delete lat;
+    }
+    double maxW = accumulate(maxC.begin(),maxC.end(),0.);
+
+    int nRows = nHeaders + (nLegItems+nCols-1)/nCols;
+    //cout << "RADEK nRows " << nRows << endl;
+    SizeY = lineSeparation*fSizeNDCy*nRows;
+
+    headerW += 0.1*fSizeNDCx*markerSize;
+
+    SizeX = max(nCols*fSizeNDCx*markerSize +
+               (nCols-1)*fSizeNDCx*columnSeparation + maxW, headerW);
+    leg->SetMargin( nCols*fSizeNDCx*markerSize / SizeX);
+
+    leg->SetColumnSeparation((nCols-1)*fSizeNDCx*columnSeparation / SizeX);
+
+
+    SizeYroot = lineSeparation*fSizeNDCy*leg->GetNRows();
+
+}
+
+
+
+
+/// Setup the position of legends provided in legs array
+///
+/// Note that the legends must be drawn manually
+/// To draw legends directly, use DrawLegends
+///
+void PlaceLegends(vector<TLegend*> legs, bool keepRange)
+{
+    int nScaleSteps = keepRange ? 1 : 20;
+
+    vector<double> sizesX, sizesY, sizesYroot;
+
+    for(unsigned i = 0; i < legs.size(); ++i) {
+        double SizeX, SizeY, SizeYroot;
+        GetLegendSizes(legs[i], SizeX, SizeY, SizeYroot);
+        sizesX.push_back(SizeX);
+        sizesY.push_back(SizeY);
+        sizesYroot.push_back(SizeYroot);
+    }
+
+    PLACER placer;
+    gPad->Update();
+
+    placer.init(legs, sizesX, sizesY);
+
+    vector<double> xx, yy;
+    double scaleUp, scaleDn;
+    tie(scaleUp, scaleDn) = placer.GetSolution(xx, yy, nScaleSteps);
+    //return;
+    
+    for(unsigned i = 0; i < legs.size(); ++i) {
+        legs[i]->SetX1(xx[i]);
+        legs[i]->SetY1(yy[i] + sizesY[i] - sizesYroot[i]);
+        legs[i]->SetX2(xx[i] + sizesX[i]);
+        legs[i]->SetY2(yy[i] + sizesY[i]);
+    }
+
+    
+    TH1 *frameNow = GetFrame();
+    if(gPad->GetLogy()) {
+        //double Max = frameNow->GetMaximum();
+        //double Min = frameNow->GetMinimum();
+        double Max = pow(10,gPad->GetUymax());
+        double Min = pow(10,gPad->GetUymin());
+
+        frameNow->SetMaximum(Min * pow(Max/Min, scaleUp));
+        frameNow->SetMinimum(Max / pow(Max/Min, scaleDn));
+    }
+    else {
+        double Max = gPad->GetUymax();
+        double Min = gPad->GetUymin();
+
+        frameNow->SetMaximum(Min + (Max-Min)*scaleUp);
+        frameNow->SetMinimum(Max - (Max-Min)*scaleDn);
+    }
+
+    /*
+    for(int i = 0; i < legs.size(); ++i) {
+        TLine *l = new TLine;
+        l->SetNDC();
+        l->DrawLineNDC(xx[i], yy[i], xx[i]+sizesX[i], yy[i]);
+        l->DrawLineNDC(xx[i], yy[i]+sizesY[i], xx[i]+sizesX[i], yy[i]+sizesY[i]);
+        l->DrawLineNDC(xx[i], yy[i], xx[i], yy[i]+sizesY[i]);
+        l->DrawLineNDC(xx[i]+sizesX[i], yy[i], xx[i]+sizesX[i], yy[i]+sizesY[i]);
+    }
+    */
+
+}
+
+/// Draw legends provided in vector legs in such a way that there is no overlap.
+///
+/// in case that keepRange=true the y-axis range is not touch even if the amount of space is not sufficiend.
+/// The keepRange=true is very useful when a grid of histograms is plotted
+///
+void DrawLegends(vector<TLegend*> legs, bool keepRange)
+{
+    PlaceLegends(legs, keepRange);
+    for(auto & leg : legs)
+        leg->Draw();
+}
+
+
+    //Initalize layOuts, dims, legBorders, borders
+    void PLACER::init(vector<TLegend *> legs, vector<double> &sizesX, vector<double> &sizesY) {
+        nLeg = legs.size();
+        for(auto & leg : legs) {
+            unsigned layOut = atoi(leg->GetName());
+
+            vector<pair<int,int>> pos;
+
+            PosIterator iter(nSteps, layOut);
+            while(iter.Iterate()) {
+               pos.push_back(make_pair(iter.iSave, iter.jSave));
+            }
+            layOuts.push_back(pos);
+        }
+
+        dims.resize(layOuts.size());
+        for(unsigned i = 0; i < dims.size(); ++i)
+            dims[i] = layOuts[i].size();
+        SizesX = sizesX;
+        SizesY = sizesY;
+        GetLegendsPositions();
+
+    }
+
+    double PLACER::iterate(vector<int> &bestLayout) {
+        vector<int> idxs(dims.size());
+        vector<double> distsNow(dims.size());
+        vector<double> distsBest(dims.size());
+
+        double maxDist = 0;
+
+        while (1) {
+            // Print
+            double dist = analyze(idxs, distsNow);
+
+            if(dist >= maxDist) {
+                bool state = true;
+                for(int i = 0; i < nLeg; ++i) {
+                    state = state && distsNow[i] >= distsBest[i];
+                }
+                if(dist > maxDist || (dist == maxDist && state)) {
+                    bestLayout = idxs;
+                    distsBest = distsNow;
+                }
+                maxDist = dist;
+            }
+
+            // Update
+            unsigned j;
+            for(j = 0; j < dims.size(); ++j) {
+                idxs[j]++;
+                if (idxs[j] < static_cast<int>(dims[j])) break;
+                idxs[j] = 0;
+            }
+            if (j == dims.size()) break;
+        }
+        return maxDist;
+    }
+
+
+    void PLACER::GetLegendsPositions() {
+
+        LoadHistoBorders(borders);
+
+        legBorders.resize(nLeg);
+
+        double fontSize = RelFontToPx(GetYaxis()->GetTitleSize());
+        minSepar = 0.5*fontSize; //inPixels
+
+        TH1 *frameNow = GetFrame();
+        double ytickLowNDC = frameNow->GetYaxis()->GetTickLength() * GetAxisFractionY();
+        double ytickHighNDC = ytickLowNDC * gPad->GetTicky();
+        double xtickLowNDC = frameNow->GetXaxis()->GetTickLength() * GetAxisFractionX();
+        double xtickHighNDC = xtickLowNDC * gPad->GetTickx();
+
+        double fSizeNDCy = minSepar / (gPad->GetWh() * gPad->GetAbsHNDC());
+        double fSizeNDCx = minSepar / (gPad->GetWw() * gPad->GetAbsWNDC());
+
+
+        for(int k = 0; k < nLeg; ++k) {
+
+            double SizeX = SizesX[k];
+            double SizeY = SizesY[k];
+
+            double xMin =  gPad->GetLeftMargin() + ytickLowNDC + fSizeNDCx;
+            double xMax =  1 - gPad->GetRightMargin() - ytickHighNDC - SizeX - fSizeNDCx;
+            double yMax =  1 - gPad->GetTopMargin() - xtickHighNDC - SizeY - fSizeNDCy;
+            double yMin =  gPad->GetBottomMargin() + xtickLowNDC  + fSizeNDCy;
+
+
+            legBorders[k].resize(dims[k]);
+
+            for(unsigned l = 0; l < dims[k]; ++l) {
+                int i = layOuts[k][l].first;
+                int j = layOuts[k][l].second;
+                
+                double xx = xMin + (xMax-xMin)/(nSteps-1) * j;
+                double yy = yMax - (yMax-yMin)/(nSteps-1) * i;
+
+
+                //Legend borders
+                legBorders[k][l].recs.push_back({xx, yy, SizeX, SizeY});
+                legBorders[k][l].FromNDC2px();
+
+            }
+        }
+    }
+
+
+    void PLACER::GetDistancesPx(double scaleUp, double scaleDn) {
+        auto bordersPx = borders;
+        for(auto &b : bordersPx)
+            b.FromAbs2px(scaleUp, scaleDn);
+
+        distToHists.resize(nLeg);
+
+        for(int i = 0; i < nLeg; ++i) {
+            distToHists[i].resize(dims[i]);
+            for(unsigned l = 0; l < dims[i]; ++l) 
+                distToHists[i][l] = MinDistanceSingle(bordersPx, legBorders[i][l], 0.99*minSepar);
+        }
+    }
+
+
+    pair<double,double> PLACER::GetSolution(vector<double> &xx, vector<double> &yy,
+                                                         int nScaleSteps) {
+        
+        double scaleUp=1., scaleDn=1.;
+
+        vector<int> bestLayout;
+
+        for(int sum = 0; sum < nScaleSteps; ++sum)
+        for(int iUp = sum; iUp >= 0; --iUp) {
+                int iDn = sum - iUp;
+                if(!gPad->GetLogy() && iDn != 0) continue;
+                scaleUp = pow(4, iUp/10.);
+                scaleDn = pow(4, iDn/10.);
+
+                GetDistancesPx(scaleUp, scaleDn);
+
+                double dist = iterate(bestLayout);
+
+                if(dist > minSepar)
+                    goto gotoAfterScaleLoop;
+        }
+        cout << "No solution found for legend" << endl;
+        
+        gotoAfterScaleLoop:
+
+        xx.resize(nLeg);
+        yy.resize(nLeg);
+        for(int i = 0; i < nLeg; ++i) {
+            Point p;
+            p.x = legBorders[i][bestLayout[i]].recs[0].fX;
+            p.y = legBorders[i][bestLayout[i]].recs[0].fY;
+            p = Px2NDC(p);
+            xx[i] = p.x;
+            yy[i] = p.y;
+        }
+
+        return {scaleUp, scaleDn};
+        //cout << "done " << maxDist << endl;
+    }
+
+
+
+
+    void PLACER::LoadHistoBorders(vector<Borders> &borders)
+    {
+        //Load histograms
+        vector<TObject *> hists;
+        for(const auto &&prim : *gPad->GetListOfPrimitives()) {
+            cout << prim->GetName() <<" "<< prim->ClassName() <<  endl;
+            if(strcmp(prim->GetName(),"hframe") && strcmp(prim->ClassName(),"TH1F"))
+                if(dynamic_cast<TH1*>(prim)) 
+                    hists.push_back(prim);
+        }
+
+
+        /////////////////////
+        //GetDistance
+        /////////////////////
+        if(hists.size() == 0) {
+            gPad->Modified();
+            return;
+        }
+
+        for(unsigned i = 0; i < hists.size(); ++i) {
+            Borders br;
+            br.GetHistBorders(dynamic_cast<TH1*>(hists[i]));
+            borders.push_back(br);
+        }
+
+    }
+
+
+    double PLACER::analyze(vector<int> &indx, vector<double> &dists) {
+        double minDist = 1e40;
+        //Distances to histograms
+        for(unsigned k = 0; k < indx.size(); ++k) {
+            minDist = min(minDist, distToHists[k][indx[k]]);
+            dists[k] = distToHists[k][indx[k]];
+            if(minDist < minSepar)
+                return minDist;
+        }
+
+        for(unsigned k = 0;   k < indx.size(); ++k) 
+        for(unsigned l = k+1; l < indx.size(); ++l) {
+            double dist = MinDistance2(0.99*minSepar,
+                           legBorders[k][indx[k]], legBorders[l][indx[l]]);
+            minDist = min(minDist, dist);
+            dists[k] = min(dists[k], dist);
+            if(minDist < minSepar)
+                return minDist;
+        }
+
+
+        return minDist;
+
+    }
+
+
+
+Point Abs2Px(Point p, double scaleUp, double scaleDn)
+{
+   	double valXmin = gPad->GetX1();
+    double valXmax = gPad->GetX2();
+
+    double valYmin = gPad->GetY2() - scaleDn*(gPad->GetY2()-gPad->GetY1());
+    double valYmax = gPad->GetY1() + scaleUp*(gPad->GetY2()-gPad->GetY1());
+
+
+	double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
+	double pxW = gPad->GetWw()*gPad->GetAbsWNDC();
+
+
+    if(gPad->GetLogx()) p.x = log10(p.x);
+    if(gPad->GetLogy()) p.y = log10(p.y);
+
+    p.x =  (p.x - valXmin)/(valXmax-valXmin) * pxW;
+    p.y =  (p.y - valYmin)/(valYmax-valYmin) * pxH;
+
+    //cout << p.x <<" "<<  p.y << endl;
+    return p;
+}
+
+Point Px2NDC(Point p)
+{
+	double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
+	double pxW = gPad->GetWw()*gPad->GetAbsWNDC();
+    p.x = p.x/pxW;
+    p.y = p.y/pxH;
+    return p;
+}
+
+
+
+double MinDistanceSingle(vector<Borders> &bor, double minSkip, double x, double y, double w, double h)
+{
+    Borders bS;
+    bS.recs.push_back( {x, y, w, h} );
+    bS.FromNDC2px();
+
+    double minDist = 1e40;
+    for(Borders &b : bor) {
+        double d = MinDistance2(0.99*minSkip, b, bS);
+        minDist = min(minDist, d);
+        if(minDist <= minSkip) return minDist;
+    }
+    return sqrt(minDist);
+}
+
+
+double MinDistanceSingle(vector<Borders> &bor, Borders bSingle, double minSkip)
+{
+    double minDist = 1e40;
+    for(Borders &b : bor) {
+        double d = MinDistance2(0.99*minSkip, b, bSingle);
+        minDist = min(minDist, d);
+        if(minDist <= minSkip) return minDist;
+    }
+    return sqrt(minDist);
+}
+
+
+
+double MinDistance2(double minSkip, const Borders &br1, const Borders &br2)
+{
+    double minDist = 1e40;
+    for(const auto &r1 : br1.recs)
+        for(const auto &r2 : br2.recs) {
+            double d = Borders::Distance2(r1, r2);
+            minDist = min(minDist, d);
+            if(minDist <= minSkip) return minDist;
+        }
+    return minDist;
+
+}
+
+void Borders::FromNDC2px()
+{
+	double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
+	double pxW = gPad->GetWw()*gPad->GetAbsWNDC();
+
+    for(Rectangle &r : recs) { 
+        r.fX *= pxW;
+        r.fY *= pxH;
+        r.fWidth  *= pxW;
+        r.fHeight *= pxH;
+    }
+}
+
+/*
+void Borders::FromPx2NDC()
+{
+	double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
+	double pxW = gPad->GetWw()*gPad->GetAbsWNDC();
+
+    for(Rectangle &r : recs) { 
+        r.fX /= pxW;
+        r.fY /= pxH;
+        r.fWidth  /= pxW;
+        r.fHeight /= pxH;
+    }
+}
+*/
+
+
+
+void Borders::FromAbs2px(double scaleUp, double scaleDn)
+{
+    for(Rectangle &r : recs) { 
+        Point p1(r.fX, r.fY);
+        Point p2(r.fX+r.fWidth, r.fY+r.fHeight);
+
+        p1 = Abs2Px(p1, scaleUp, scaleDn);
+        p2 = Abs2Px(p2, scaleUp, scaleDn);
+        r.fX = p1.x;
+        r.fY = p1.y;
+        r.fWidth  = p2.x-p1.x;
+        r.fHeight = p2.y-p1.y;
+    }
+}
+
+///
+/// Return the borders of the provided histogram
+///
+void Borders::GetHistBorders(TH1 *h)
+{
+    for(int i = 1; i <= h->GetNbinsX(); ++i) {
+        double xMin = h->GetBinLowEdge(i);
+        double xMax = h->GetBinLowEdge(i) + h->GetBinWidth(i);
+        double yMin = h->GetBinContent(i)-h->GetBinError(i);
+        double yMax = h->GetBinContent(i)+h->GetBinError(i);
+
+        const double lim  = 1e-30;
+
+        if(gPad->GetLogx()) {
+            xMin = max(lim, xMin);
+            xMax = max(lim, xMax);
+        }
+        if(gPad->GetLogy()) {
+            yMin = max(lim, yMin);
+            yMax = max(lim, yMax);
+        }
+        recs.push_back({xMax, yMin, xMax-xMin, yMax-yMin});
+
+        TString drawOpt = h->GetDrawOption();
+        if(drawOpt.Contains("hist") && i > 1) {
+            double yMinLeft = h->GetBinContent(i-1)-h->GetBinError(i-1);
+            double yMaxLeft = h->GetBinContent(i-1)+h->GetBinError(i-1);
+            if(gPad->GetLogy()) {
+                yMinLeft = max(lim, yMinLeft);
+                yMaxLeft = max(lim, yMaxLeft);
+            }
+            double yMinNow = min(yMin, yMinLeft);
+            double yMaxNow = max(yMax, yMaxLeft);
+            recs.push_back({xMin, yMinNow, 0., yMaxNow-yMinNow});
+        }
+
+    }
+}
+
+
+/// Distance between two rectangles, 0 if overlap
+double Borders::Distance2(const Rectangle &r1, const Rectangle &r2)
+{
+    double x1  = r1.fX;
+    double x1b = r1.fX + r1.fWidth;
+    double x2  = r2.fX;
+    double x2b = r2.fX + r2.fWidth;
+
+    double y1  = r1.fY;
+    double y1b = r1.fY + r1.fHeight;
+    double y2  = r2.fY;
+    double y2b = r2.fY + r2.fHeight;
+
+    bool left = x2b < x1;
+    bool right = x1b < x2;
+    bool bottom = y2b < y1;
+    bool top = y1b < y2;
+    if(top && left)
+        return hypot2(x2b-x1, y2-y1b);
+    else if(left && bottom)
+        return hypot2(x2b-x1, y2b-y1);
+    else if(bottom && right)
+        return hypot2(x2-x1b, y2b-y1);
+    else if(right && top)
+        return hypot2(x2-x1b, y2-y1b);
+    else if(left)
+        return hypot2(x1 - x2b,0.);
+    else if(right)
+        return hypot2(x2 - x1b,0.);
+    else if(bottom)
+        return hypot2(y1 - y2b,0.);
+    else if(top)
+        return hypot2(y2 - y1b,0.);
+    else
+        return 0.;
+}
+
+///@}
+
+
+/// @name Miscellaneous
+/// Utilities for redraw axes, divde pad and auto y-range calculation
+///@{ 
+
+/// Redraw the current frame and axis ticks.
+///
+/// Useful if the original ticks were covered during plotting
+///
+void UpdateFrame()
+{
+    gPad->Update();
+    gPad->RedrawAxis();
+    TFrame *fr = gPad->GetFrame();
+    if(fr) {
+        fr->SetFillStyle(0);
+        fr->Draw();
+    }
+    else
+        cout << "No frame at active pad" << endl;
+    gPad->Update();
+}
+
+
+/// Calculate the automatic range of the vertical axis and apply it.
+///
+/// Useful when several histograms are plotted to the same frame. 
+/// In such case the y-range is normally chosen according to the one which is plotted first (without "same")
+/// This method select such a range which corresponds to union of all y-ranges  
+/// When applying this method y-range is no more plotting order dependent
+void CalcYaxisRange()
+{
+	TH1 *hFrame = GetFrame();
+    if(!hFrame) return;
+	TAxis *ax = hFrame->GetXaxis();
+
+	int iFirst = ax->GetFirst();
+	int iLast  = ax->GetLast();
+
+	double xMin = ax->GetBinLowEdge(iFirst);
+	double xMax = ax->GetBinLowEdge(iLast) + ax->GetBinWidth(iLast);
+
+
+	double widthMin=0,  widthMax=0;
+	double centerMin=0, centerMax=0;
+	//return ;
+	double yMin = 1e100, yMax = -1e100;
+	for(auto && obj : *gPad->GetListOfPrimitives()) {
+
+		if(obj->InheritsFrom(TH1::Class()))
+			((TH1*)obj)->GetXaxis()->SetRangeUser(xMin, xMax);
+		else if(obj->InheritsFrom(TMultiGraph::Class()))
+			((TMultiGraph*)obj)->GetXaxis()->SetRangeUser(xMin, xMax);
+		else if(obj->InheritsFrom(TGraph::Class()))
+			((TGraph*)obj)->GetXaxis()->SetRangeUser(xMin, xMax);
+		else if(obj->InheritsFrom(THStack::Class()))
+			((THStack*)obj)->GetXaxis()->SetRangeUser(xMin, xMax);
+
+
+		if(obj->InheritsFrom(TH1::Class()) ||
+			obj->InheritsFrom(TMultiGraph::Class()) ||
+			obj->InheritsFrom(TGraph::Class())  ||
+			obj->InheritsFrom(THStack::Class()) ) {
+
+			obj->Paint();
+			//double zoom = gPad->GetUymax() - gPad->GetUymin();
+			double yMinNow = gPad->GetUymin();
+			double yMaxNow = gPad->GetUymax();
+
+			if(yMinNow < yMin) {
+				yMin = yMinNow;
+				widthMin = yMaxNow - yMinNow;
+				centerMin = (yMaxNow + yMinNow)/2.;
+			}
+			if(yMaxNow > yMax) {
+				yMax = yMaxNow;
+				widthMax = yMaxNow - yMinNow;
+				centerMax = (yMaxNow + yMinNow)/2.;
+			}
+		}
+	}
+
+
+	double width = yMax - yMin;
+
+
+	double zoomMin = width / widthMin;
+	double zoomMax = width / widthMax;
+	
+	if(yMin >= 0. && !gPad->GetLogy())
+		yMin = max(0., centerMin - zoomMin * widthMin/2.);
+	else
+		yMin =  centerMin - zoomMin * widthMin/2.;
+	yMax = centerMax + zoomMax * widthMax/2.;
+	
+
+	if(gPad->GetLogy()) {
+		hFrame->SetMinimum(pow(10,yMin));
+		hFrame->SetMaximum(pow(10,yMax));
+	}
+	else {
+		hFrame->SetMinimum(yMin);
+		hFrame->SetMaximum(yMax);
+	}
+}
+
+/// Set simultaneously left and right margin of active pad
+///
+/// Implemented to avoid the bug in ROOT which causes that
+/// gPad->SetLeftMargin(0.5); gPad->SetRightMargin(0.1);
+/// is not always the same as
+/// gPad->SetRightMargin(0.1); gPad->SetLeftMargin(0.5);
+void SetLeftRight(double lMargin, double rMargin)
+{
+    gPad->SetLeftMargin(0);
+    gPad->SetRightMargin(0);
+    gPad->SetLeftMargin(lMargin);
+    gPad->SetRightMargin(rMargin);
+}
+
+/// Set simultaneously top and bottom margin of active pad
+///
+/// Implemented to avoid the bug in ROOT which causes that
+/// gPad->SetTopMargin(0.5); gPad->SetBottomMargin(0.1);
+/// is not always the same as
+/// gPad->SetBottomMargin(0.1); gPad->SetTopMargin(0.5);
+void SetTopBottom(double tMargin, double bMargin)
+{
+    gPad->SetTopMargin(0);
+    gPad->SetBottomMargin(0);
+    gPad->SetTopMargin(tMargin);
+    gPad->SetBottomMargin(bMargin);
+}
+
+
+
+////////////////////////////////////////////////////////////////////
+/// Construct the lattice of pads according to the provided x and y sizes
+///
+/// Comparing to classical Divide method this function left no empty space
+/// between frames but left spaces for axes.
+/// Note that without setting the offsets, font sizes and tics manually
+/// the ticks differs between pads.
+/// From this reason, we recommend calling SetFTO() in each pad
+/// The margins of the original pad are kept
+/// This method can be nested is some of the created pads needs additional subdivision.
+/// The resulting pads can be accessed by the standard cd() command as in ROOT Divide().
+/// @param xDivs vector defining horizontal sizes of frames, the absolute normalisation does not matter
+/// @param yDivs vector defining vertical sizes of frames, the absolute normalisation does not matter
+///
+void DividePad(vector<double> xDivs, vector<double> yDivs)
+{
+    TVirtualPad *orgPad = gPad;
+
+    double lMag = orgPad->GetLeftMargin();
+    double rMag = orgPad->GetRightMargin();
+    double tMag = orgPad->GetTopMargin();
+    double bMag = orgPad->GetBottomMargin();
+
+    int nx = xDivs.size();
+    int ny = yDivs.size();
+
+    double Nx = accumulate(xDivs.begin(), xDivs.end(), 0.);
+    double Ny = accumulate(yDivs.begin(), yDivs.end(), 0.);
+    vector<double> xPos(nx+1), yPos(ny+1);
+    xPos[0] = yPos[0] = 0;
+    for(int i = 1; i <= nx; ++i)
+        xPos[i] = xPos[i-1] + xDivs[i-1]/Nx * (1-lMag-rMag);
+    for(int i = 1; i <= ny; ++i)
+        yPos[i] = yPos[i-1] + yDivs[i-1]/Ny * (1-tMag-bMag);
+
+    
+    for(int ix = 0; ix < nx; ++ix)
+    for(int iy = 0; iy < ny; ++iy) {
+        double xl = (ix == 0)    ? 0 : lMag+xPos[ix];
+        double xr = (ix == nx-1) ? 1 : lMag+xPos[ix+1];
+
+        double yt = (iy == 0)    ? 1 : 1-tMag-yPos[iy];
+        double yb = (iy == ny-1) ? 0 : 1-tMag-yPos[iy+1];
+
+        int id = iy*nx+ix+1;
+        TPad *pad = new TPad(SF("%s_%d", orgPad->GetName(), id), "", xl, yb, xr, yt);
+
+        double lNew =  (ix == 0) ? lMag/(xPos[1]+lMag) : 0;
+        double rNew =  (ix == nx-1) ? rMag/( 1-lMag - xPos[nx-1]) : 0;
+
+        double tNew =  (iy == 0) ? tMag/(yPos[1]+tMag) : 0;
+        double bNew =   (iy == ny-1) ? bMag/(1-tMag - yPos[ny-1]) : 0;
+
+        pad->cd();
+        SetLeftRight(lNew, rNew);
+        SetTopBottom(tNew, bNew);
+        orgPad->cd();
+        
+//        if(ix == nx-1) {
+//            cout << "Hela : " <<  lMag + xPos[nx-1] << endl;
+//            cout << "lMag rMag : " <<lMag <<" "<<  rMag << endl;
+//            cout  << "Ratio " << rMag / (1-lMag-xPos[nx-1]) << endl;
+//        }
+
+        pad->SetNumber(id);
+        pad->Draw();
+    }
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////
+/// Construct the lattice of frames according to the provided x and y sizes using transparency trick.
+///
+/// This function creates set of transparent overlapping pads, each of them covering whole canvas.
+/// The margins of of of these pads are chosen in such a way that the lattice of frames is constructed.
+/// Comparing to the DividePad method this method allows to include spaces between plotted frames.
+/// In case that "zero" spaces are selected the frame structure would look the same only the axis
+/// would not be cut off by the frame edge.
+/// On the other hand one needs to ensure that nuisance exes are not plotted
+/// (i.e. setting their font size to 0).
+/// Note that argument vectors divX and divY must always contain odd number of elements (sizes).
+/// Comparing to DividePad method this method can be run several time for the same pad.
+/// In such a way more complex frame structure can be created than the regular lattice.
+/// The resulting pads can be accessed by the standard cd() command as in ROOT Divide().
+/// In case of more calls on the same pad the indexes continues where there previous ended.
+///
+/// @param xDivs vector defining horizontal sizes of frames and spaces between them,
+///    the absolute normalisation does not matter. The structure is the following {space, frame, space, frame, space}
+///    In case of useMargins=true the very left and right space is taken from pad margins.
+/// @param yDivs the same as xDivs but in vertical coordinate
+/// @param useMargins specify wherever the current pad margins should be used.
+///
+void DivideTransparent(vector<double> divX, vector<double> divY, bool useMargins)
+{
+
+    TVirtualPad *orgPad = gPad;
+
+    if(divX.size() % 2 != 1 || int(divX.size()) < (3-2*useMargins) ) {
+        cout << "Wrong divX= " << divX.size() << endl;
+        return;
+    }
+    if(divY.size() % 2 != 1 || int(divY.size()) < (3-2*useMargins) ) {
+        cout << "Wrong divY= " << divY.size() << endl;
+        return;
+    }
+
+
+
+    double sumX = accumulate(divX.begin(), divX.end(), 0.0);
+    double sumY = accumulate(divY.begin(), divY.end(), 0.0);
+
+    if(useMargins == true) {
+        double l = orgPad->GetLeftMargin();
+        double r = orgPad->GetRightMargin();
+        double t = orgPad->GetTopMargin();
+        double b = orgPad->GetBottomMargin();
+        
+
+        vector<double> newX, newY;
+        newX.push_back(l * sumX/(1-l-r));
+        newX.insert(newX.end(), divX.begin(), divX.end());
+        newX.push_back(r * sumX/(1-l-r));
+
+        newY.push_back(t * sumY/(1-t-b));
+        newY.insert(newY.end(), divY.begin(), divY.end());
+        newY.push_back(b * sumY/(1-t-b));
+
+        DivideTransparent(newX, newY, false);
+        return;
+    }
+
+
+
+    vector<double> edgesX(divX.size()+1);
+    vector<double> edgesY(divY.size()+1);
+
+    edgesX[0] = edgesY[0] = 0;
+    for(unsigned i = 1; i < edgesX.size(); ++i)
+        edgesX[i] = edgesX[i-1] + divX[i-1]/sumX;
+    for(unsigned i = 1; i < edgesY.size(); ++i)
+        edgesY[i] = edgesY[i-1] + divY[i-1]/sumY;
+
+    int nPadsX = (divX.size()-1)/2;
+    //int nPadsY = (divY.size()-1)/2;
+
+    int kStart = 1;
+    while(orgPad->GetPad(kStart))
+        ++kStart;
+    --kStart;
+
+
+    int i = 1;
+    //for(int x = 1; x < edgesX.size()-1; x+=2)
+    for(int y = 1; y < int(edgesY.size())-1; y+=2) 
+    for(int x = edgesX.size()-3; x >= 1; x-=2) {
+        //i = (nPadsY-1-(y-1)/2) * nPadsX + (nPadsX-1-(x-1)/2) + 1; 
+        i = ((y-1)/2) * nPadsX + ((x-1)/2) + 1; 
+        
+        TPad *pad = new TPad(TString::Format("%s_%d", orgPad->GetName(), kStart+i), "", 0.0, 0.0, 1, 1);
+        pad->SetFillStyle(0);
+
+        
+        double l = max(0.,edgesX[x]);
+        double r = max(0.,1-edgesX[x+1]);
+        double t = max(0.,edgesY[y]);
+        double b = max(0.,1-edgesY[y+1]);
+
+        //cout <<"LeftRight " << l <<" "<<  r <<" "<< (1-l-r) <<" "<< i<< endl;
+
+        pad->cd();
+        SetLeftRight(l, r);
+        SetTopBottom(t, b);
+        orgPad->cd();
+
+
+        pad->SetNumber(kStart+i);
+        pad->Draw();
+        ++i;
+    }
+}
+
+/// Merge vectors into one
+///
+/// In current version up to 7 vectors can be merged
+vector<double> merge(vector<double> v1, vector<double> v2, vector<double> v3, vector<double> v4, vector<double> v5, vector<double> v6, vector<double> v7)
+{
+    vector<vector<double>> v = {v1, v2, v3, v4, v5, v6, v7};
+    vector<double> res;
+    for(unsigned i = 0; i < v.size(); ++i)
+        res.insert(res.end(), v[i].begin(), v[i].end());
+    return res;
+}
+
+/// Repeat the provided pattern
+///
+/// Returns the vector which includes n times the vector x
+vector<double> repeat(vector<double> x, int n)
+{
+    vector<double> res = x;
+    for(int i = 1; i < n; ++i)
+        res.insert(res.end(), x.begin(), x.end());
+    return res;
+}
+
+/// Construct group of frames
+///
+/// Returns vector describing layout of n identical frames which are separated by the same space size
+/// The spaces before first space and after last frame are not included
+vector<double> group(double frame, double space, int n)
+{
+    vector<double> res;
+    for(int i = 0; i < n-1; ++i) {
+        res.push_back(frame);
+        res.push_back(space);
+    }
+    res.push_back(frame);
+    return res;
+}
+
+
+
+
+///@}
+
+
+
+}
+
+void plottingHelper()
+{
+}
diff --git a/plottingHelper.h b/plottingHelper.h
index d8606f1..ce1e8e1 100644
--- a/plottingHelper.h
+++ b/plottingHelper.h
@@ -1,21 +1,19 @@
 #ifndef __plottingHelper__
 #define __plottingHelper__
 
-#include "TPad.h"
 #include "TCanvas.h"
-#include "TH1.h"
 #include "TROOT.h"
-#include "TLegend.h"
 #include "TLatex.h"
-#include <iostream>
 #include "TString.h"
 #include "TFrame.h"
+#include "TLegend.h"
 #include "TLegendEntry.h"
 #include "TGraph.h"
 #include "TMarker.h"
 #include "THStack.h"
 #include "TMultiGraph.h"
 
+#include <iostream>
 #include <vector>
 #include <algorithm>
 #include <utility>
@@ -26,7 +24,7 @@
 /// The namespace of whole Plotting Helper utility
 /// 
 ///
-namespace plottingHelper {
+namespace PlottingHelper {
 
 using namespace std;
 
@@ -66,7 +64,11 @@ enum {
     kPos6 = BIT(6), ///< Right side
     kPos7 = BIT(7), ///< Left bottom corner
     kPos8 = BIT(8), ///< Bottom side
-    kPos9 = BIT(9)  ///< Right bottom corner
+    kPos9 = BIT(9), ///< Right bottom corner
+    kPos2c= BIT(10),///< Center of top side
+    kPos4c= BIT(11),///< Center of left side
+    kPos6c= BIT(12),///< Center of right side
+    kPos8c= BIT(13) ///< Center of bottom side
 };
 
 
@@ -100,6 +102,16 @@ struct PosIterator {
                 goto after;
             if((pos & kPos9)  && i==last && j==last)
                 goto after;
+
+            if((pos & kPos2c)  && i==0 && j==last/2)
+                goto after;
+            if((pos & kPos4c)  && i==last/2 && j==0)
+                goto after;
+            if((pos & kPos6c)  && i==last/2 && j==last)
+                goto after;
+            if((pos & kPos8c)  && i==last && j==last/2)
+                goto after;
+
             if((pos & kPos2)  && i==0)
                 goto after;
             if((pos & kPos8)  && i==last)
@@ -125,598 +137,48 @@ struct PosIterator {
     unsigned pos;
 };
 
-/// @name Getters
-/// Functions returning elements of the active frame
-///@{ 
-
-/// The method returns current frame on the active pad.
-///
-/// Useful for example to set maximum of the y-axis, GetFrame()->SetMaximum(5)
-inline TH1 *GetFrame()
-{
-   // get first histogram in the list of primitives
-
-	TH1 *hobj = nullptr;
-
-   TIter next(gPad->GetListOfPrimitives());
-   TObject *obj;
-   while ((obj = next())) {
-      if(obj->InheritsFrom(TH1::Class())) {
-         hobj = (TH1*)obj;
-         //hobj->DrawCopy("sameaxis");
-			break;
-      }
-      if(obj->InheritsFrom(TMultiGraph::Class())) {
-         TMultiGraph *mg = (TMultiGraph*)obj;
-			hobj = mg ? mg->GetHistogram() : nullptr;
-			//if (hobj) hobj->DrawCopy("sameaxis");
-			break;
-      }
-      if(obj->InheritsFrom(TGraph::Class())) {
-         TGraph *g = (TGraph*)obj;
-			hobj = g ? g->GetHistogram() : nullptr;
-         //hobj->DrawCopy("sameaxis");
-			break;
-      }
-      if(obj->InheritsFrom(THStack::Class())) {
-         THStack *hs = (THStack*)obj;
-			hobj = hs ? hs->GetHistogram() : nullptr;
-			//hobj->DrawCopy("sameaxis");
-			break;
-      }
-   }
-    if(!hobj) {cout << "No frame created in active pad" << endl;}
-
-   return hobj;
-}
-
-/// Return x-axis of the active frame
-inline TAxis *GetXaxis() {
-    TH1 *frame = GetFrame();
-    return frame ? frame->GetXaxis() : nullptr;
-}
-
-/// Return y-axis of the active frame
-inline TAxis *GetYaxis() {
-    TH1 *frame = GetFrame();
-    return frame ? frame->GetYaxis() : nullptr;
-}
-
-/// Return z-axis of the active frame
-inline TAxis *GetZaxis() {
-    TH1 *frame = GetFrame();
-    return frame ? frame->GetZaxis() : nullptr;
-}  
-
-///@} 
-
-
-
-/// @name Units helpers
-/// Functions to convert units and obtain axis fractions
-///@{ 
-
-/// Transform font size from px to the relative units
-///
-/// The returned size is dependent on the currently active pad - the gPad pointer
-/// @param px The font size in px
-/// @return The font size in relative units
-inline double PxFontToRel(double px)
-{
-	double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
-	double pxW = gPad->GetWw()*gPad->GetAbsWNDC();
-
-	if(pxW < pxH) return px/pxW;
-	         else return px/pxH;
-
-    //double pad_width  = gPad->XtoPixel(gPad->GetX2());
-    //double pad_height = gPad->YtoPixel(gPad->GetY1()); 
-	//if(pxW < pxH) return px/pad_width / corX;
-	         //else return px/pad_height / corY;
-}
-
-
-/// Transform font size from relative units to pixels
-///
-/// The returned size is dependent on the currently active pad - the gPad pointer
-/// @param rel The font size in relative units
-/// @return The font size in pixels
-inline double RelFontToPx(double rel)
-{
-	double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
-	double pxW = gPad->GetWw()*gPad->GetAbsWNDC();
-	if(pxW < pxH) return rel*pxW;
-	         else return rel*pxH;
-}
-
-
-/// Fraction of the pad width covered by x-axis
-inline double GetAxisFractionX()
-{
-    //return (gPad->GetUxmax() - gPad->GetUxmin())/(gPad->GetX2() - gPad->GetX1());
-    return (1. - gPad->GetLeftMargin() - gPad->GetRightMargin());
-}
-
-/// Fraction of the pad height covered by y-axis
-inline double GetAxisFractionY()
-{
-    //return (gPad->GetUymax() - gPad->GetUymin())/(gPad->GetY2() - gPad->GetY1());
-    return (1. - gPad->GetBottomMargin() - gPad->GetTopMargin());
-}
-
-/// Convert tick length in px of x-axis to the relative units
-inline double TickAbsToRelX(double tick)
-{
-    double nom = GetAxisFractionX() * gPad->GetAbsHNDC() * gPad->GetWh();
-	return tick/nom;
-}
-
-
-/// Convert tick length in px of y-axis to the relative units
-inline double TickAbsToRelY(double tick)
-{
-    double nom =  GetAxisFractionY() * gPad->GetAbsWNDC() * gPad->GetWw();
-	return tick/nom;
-}
-
-///@}
-
-/// @name Decorators
-/// Functions to simply define text sizes, offsets and axis ticks
-///@{ 
-
-/// Set text size of x- and y-axis titles and labels to the frame title
-///
-/// Note that the Canvas width and height is specified in TCanvas constructor.
-/// The font size is defined as the height of envelope between "gh" characters
-/// The height of numbers is for example 3/4 of the font size.
-inline void SetFonts(double pxX, double pxY = -1, double pxT = -1)
-{
-    TH1 *frame = GetFrame();
-    if(!frame) return;
-
-    if(pxY < 0) pxY = pxX;
-    if(pxT < 0) pxT = pxX;
-
-    double relSizeX = PxFontToRel(pxX);
-    double relSizeY = PxFontToRel(pxY);
-    double relSizeT = PxFontToRel(pxT);
-
-	frame->GetXaxis()->SetTitleSize(relSizeX);
-	frame->GetXaxis()->SetLabelSize(relSizeX);
-
-	frame->GetYaxis()->SetTitleSize(relSizeY);
-	frame->GetYaxis()->SetLabelSize(relSizeY);
-
-    frame->SetTitleSize(relSizeT);
-}
-
-///
-/// Set ticks sizes of x and y-axis in px
-///
-inline void SetTicks(double tickX, double tickY = -1)
-{
-    TH1 *frame = GetFrame();
-    if(!frame) return;
-
-    //gPad->Update();
-    if(tickY < 0) tickY = tickX;
-	frame->GetXaxis()->SetTickSize(TickAbsToRelX(tickX) );
-	frame->GetYaxis()->SetTickSize(TickAbsToRelY(tickY) );
-}
-
-/// Set offset of the x-axis labels.
-///
-/// The zero offset correspond to labels "standing" on top of the x-axis.
-/// The offset is measured in units corresponds to height of numbers like "012..."
-/// Therefore offset 1 correspond to labels touching x-axis by from the bottom.
-inline void SetLabelOffsetX(double off)
-{
-    TH1 *frame = GetFrame();
-    if(!frame) return;
-
-    double labSize = frame->GetXaxis()->GetLabelSize();
-    double off0 = 0;
-    if(gPad->GetLogx()) {
-        off0 = -1.15;
-        if(frame->GetXaxis()->GetNoExponent()) off0 += 0.33;
-    }
-    else {
-        off0 = -0.8;
-    }
-
-    double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
-    double fact = RelFontToPx(labSize)/pxH;
-    off *= fact *3/4.; //conversion to "1354" height
-
-
-    off += off0 * labSize;
-    frame->GetXaxis()->SetLabelOffset(off);
-}
-
-
-
-
-/// Set offset of the x-axis title.
-///
-/// The zero offset corresponds to title which is intersect by the x-axi in its middle.
-/// The offset is measured in units corresponds to height of numbers like "012..."
-/// Therefore offset 0.5 corresponds to numeric title touching x-axis by from the bottom.
-/// Note that the height of numbers is 3/4 of the font size (height) which is defined by the
-/// gh vertical envelope. It means that if title contains h, offset 4/3 * 0.5 would result of "h" touching axis
-/// The title text size must be set before offset!
-///
-inline void SetTitleOffsetX(double off)
-{
-    TH1 *frame = GetFrame();
-    if(!frame) return;
-
-    TAxis *ax = frame->GetXaxis();
-    off *= 3/4.;
-    ax->SetTitleOffset(off* RelFontToPx(ax->GetTitleSize())/1.6 / ( gPad->GetWh()* ax->GetTitleSize()*gPad->GetAbsHNDC() ) );
-}
-
-/// Set offset of the y-axis labels.
-///
-/// The zero offset corresponds to labels touching the y-axis from the left
-/// The offset is measured in units corresponds to height of numbers like "012..."
-/// I.e. the width of 0 if lying.
-/// The label text size must be set before offset!
-///
-inline void SetLabelOffsetY(double off)
-{
-    TH1 *frame = GetFrame();
-    if(!frame) return;
-    TAxis *ax = frame->GetYaxis();
-    double labSize = ax->GetLabelSize();
-    double pxW =  gPad->GetWw() * gPad->GetAbsWNDC() ;
-    double fact = RelFontToPx(labSize)/pxW;
-
-    double off0 = 0;
-    if(gPad->GetLogy())
-        off0 = -0.08;
-
-
-    off *= 3/4.;
-    ax->SetLabelOffset(off *  fact + off0*labSize );
-}
-
-/// Set offset of the y-axis title.
-///
-/// The zero offset corresponds to title which is intersect by the y-axis in its middle.
-/// The offset is measured in units corresponds to height of numbers like "012..."
-/// Note that the height of numbers is 3/4 of the font size (height) which is defined by the
-/// gh vertical envelope.
-/// The title text size must be set before offset!
-///
-inline void SetTitleOffsetY(double off)
-{
-    TH1 *frame = GetFrame();
-    if(!frame) return;
-    TAxis *ax = frame->GetYaxis();
-    off *= 3/4.;//to vertical size of "0"
-    ax->SetTitleOffset( off*  RelFontToPx(ax->GetTitleSize())/1.6 / ( gPad->GetWw()*ax->GetTitleSize()* gPad->GetAbsWNDC() ) );
-}
-
-/// Set of the fonts and ticks sizes 
-///
-/// Set size of x-,y-axis labels and titles to px (in pixels).
-/// In addition the x and y tick lengths can be specified
-inline void SetFontsTicks(double px, double tickX, double tickY = -1.)
-{
-    SetFonts(px);
-    SetTicks(tickX, tickY);
-}
-
-/// Set offsets of x,y labels and titles
-///
-/// Note that root is using different alignment of labels and titles
-/// We don't try to correct for that as we assume that in general
-/// the actual form of the title can be specified later
-/// The title's and label's text sizes must be set before offsets!
-inline void SetOffsets(double lX, double tX, double lY, double tY)
-{
-    SetLabelOffsetX(lX);
-    SetTitleOffsetX(tX);
-    SetLabelOffsetY(lY);
-    SetTitleOffsetY(tY);
-}
-
-/// Set Fonts, Ticks and Offsets
-///
-/// Set up fonts sizes, ticks length and titles/labels offsets
-/// All parameters are given as vectors, call as SetFTO({14}, {5}, {1.3, 2.3, 0.3, 2.3});
-inline void SetFTO(vector<double> fonts, vector<double> ticks, vector<double> offsets)
-{
-    fonts.resize(3, -1);
-    ticks.resize(2, -1);
-    offsets.resize(4, 0);
-
-    SetFonts(fonts[0], fonts[1], fonts[2]);
-    SetTicks(ticks[0], ticks[1]);
-    SetOffsets(offsets[0], offsets[1], offsets[2], offsets[3]);
-}
-
-///@}
-
-
-
-/// @name Generalized titles
-/// Functions to simplify drawing of latex captions related to the particular frame(s)
-/// Especially useful in case of describing complex grid of frames.
-/// For captions inside of frame consider also using of automatic legend.
-/// Conventional axis titles can be easily "reproduced" with these methods
-///@{ 
-
-/// Draw latex in coordinates x,y give a hull of two frames in given TPads
-///
-/// The rectangular hull of two frames corresponding to pad1 and pad2 is used as an NDC-like coordinate system
-/// For example the x-value starts from the most left side of frame1 and/or frame2 and ends in the most right side of these frames
-/// Note that in current implementation given pads cannot contain any sub-pad = there must be only one frame in pad1 and one frame
-/// in pad2.
-/// @param pad1 The pad where the first frame is located
-/// @param pad2 The pad where the second frame is located (can be the same as pad1)
-/// @param x,y  Normalised coordinates between 0 and 1 defined by the hull of frame1 and frame2, 0,0 is on bottom left
-/// @param text Latex which will be plotted, consider using #splitline #bf, #it, #font[], #color[].
-/// @param fSize Font size in pixels, by default the font size is taken from the title of the first frame.
-/// @param style The text alignment and orientation. The text-orientation is defined by rotating
-/// of letter "v", that means "v,<,>,^". The default text alignment to the center horizontally and vertically.
-/// The text can be also aligned to the left "l" or right "r", vertically to the bottom "b" or top "t"
-inline void DrawLatex(TVirtualPad *pad1, TVirtualPad *pad2, double x, double y, TString text, double fSize=-1.0, TString style="")
-{
-    TVirtualPad *padOrg = gPad;
-    assert(pad1->GetCanvas() == pad2->GetCanvas());
-    TCanvas *can = pad1->GetCanvas();
-
-    //Setting of style
-    TLatex *tex = new TLatex();
-
-    int hAlign = 2;
-    int vAlign = 2;
-
-    double angle;
-    if(style.Contains('>')) {
-        if(style.Contains('l')) vAlign = 1;
-        if(style.Contains('r')) vAlign = 3;
-        if(style.Contains('b')) hAlign = 1;
-        if(style.Contains('t')) hAlign = 3;
-        angle = 90;
-    }
-    else if(style.Contains('<')) {
-        if(style.Contains('l')) vAlign = 3;
-        if(style.Contains('r')) vAlign = 1;
-        if(style.Contains('b')) hAlign = 3;
-        if(style.Contains('t')) hAlign = 1;
-        angle = 270;
-    }
-    else if(style.Contains('^')) {
-        if(style.Contains('l')) hAlign = 3;
-        if(style.Contains('r')) hAlign = 1;
-        if(style.Contains('b')) vAlign = 3;
-        if(style.Contains('t')) vAlign = 1;
-        angle = 180;
-    }
-    else {
-        if(style.Contains('l')) hAlign = 1;
-        if(style.Contains('r')) hAlign = 3;
-        if(style.Contains('b')) vAlign = 1;
-        if(style.Contains('t')) vAlign = 3;
-        angle = 0;
-    }
-
-    tex->SetTextAlign(10*hAlign + vAlign);
-    tex->SetTextAngle(angle);
-    tex->SetTextFont(42);
-
-    double l[2], r[2], b[2], t[2];
-
-    TVirtualPad *pads[] = {pad1, pad2};
-
-    for(int i = 0; i < 2; ++i) {
-        l[i] = pads[i]->GetAbsXlowNDC() + pads[i]->GetAbsWNDC()*pads[i]->GetLeftMargin();
-        r[i] = pads[i]->GetAbsXlowNDC() + pads[i]->GetAbsWNDC()*(1-pads[i]->GetRightMargin());
-        b[i] = pads[i]->GetAbsYlowNDC() + pads[i]->GetAbsHNDC()*pads[i]->GetBottomMargin();
-        t[i] = pads[i]->GetAbsYlowNDC() + pads[i]->GetAbsHNDC()*(1-pads[i]->GetTopMargin());
-    }
-
-    double left  = min(l[0], l[1]);
-    double right = max(r[0], r[1]);
-    double bottom= min(b[0], b[1]);
-    double top   = max(t[0], t[1]);
-
-    double xGlob = left   + (right-left) *x;
-    double yGlob = bottom + (top-bottom) *y;
-
-
-    auto isBtw = [](double low, double x, double high) {return low < x && x < high;};
-    bool isInside = false;
-    for(int i = 0; (i < 2 && pads[0] != pads[1]) || (i<1); ++i) {
-        if(isBtw(l[i],xGlob,r[i]) && isBtw(b[i],yGlob,t[i]) ) {
-            pads[i]->cd();
-            if(fSize < 0) {
-                TH1 *frame = GetFrame();
-                fSize = frame ? RelFontToPx(frame->GetTitleSize()) : 12;
-            }
-            tex->SetTextSize(PxFontToRel(fSize));
-
-            double xFactor = (r[i] - l[i]) / (right - left);
-            double yFactor = (t[i] - b[i]) / (top - bottom);
-            assert(x / xFactor < 1);
-            assert(y / yFactor < 1);
-
+TH1   *GetFrame();
+TAxis *GetXaxis();
+TAxis *GetYaxis();
+TAxis *GetZaxis();
 
-            double xLoc = pads[i]->GetLeftMargin() + x/xFactor *
-                           (1 - pads[i]->GetLeftMargin() - pads[i]->GetRightMargin());
-            double yLoc = pads[i]->GetBottomMargin() + y/yFactor *
-                           (1 - pads[i]->GetBottomMargin() - pads[i]->GetTopMargin());
+double PxFontToRel(double px);
+double RelFontToPx(double rel);
+double GetAxisFractionX();
+double GetAxisFractionY();
+double TickAbsToRelX(double tick);
+double TickAbsToRelY(double tick);
 
-            //TLine *l = new TLine();
-            //l->SetLineColor(kRed);
-            //l->DrawLineNDC(xLoc, yLoc, xLoc + 0.1, yLoc);
-            tex->DrawLatexNDC(xLoc, yLoc, text);
-            isInside = true;
-        }
-    }
+void SetFonts(double pxX, double pxY = -1, double pxT = -1);
+void SetTicks(double tickX, double tickY = -1);
+void SetLabelOffsetX(double off);
+void SetTitleOffsetX(double off);
+void SetLabelOffsetY(double off);
+void SetTitleOffsetY(double off);
+void SetFontsTicks(double px, double tickX, double tickY = -1.);
+void SetOffsets(double lX, double tX, double lY, double tY);
+void SetFTO(vector<double> fonts, vector<double> ticks, vector<double> offsets);
 
-    if(!isInside) {
-        if(fSize < 0) {
-            pads[0]->cd();
-            TH1 *frame = GetFrame();
-            fSize = frame ? RelFontToPx(frame->GetTitleSize()) : 12;
-        }
-        can->cd();
-        tex->SetTextSize(PxFontToRel(fSize));
-        tex->DrawLatexNDC(xGlob, yGlob, text);
-    }
-
-    gPad->Update();
-    padOrg->cd();
-}
-
-
-/// Draw latex at coordinates of the frame inside the corresponding TPad
-///
-/// For description see the DrawLatex method, here only the one pad is provided
-inline void DrawLatex(TVirtualPad *pad, double x, double y, TString text, double fSize=-1.0, TString style="")
-{
-    DrawLatex(pad, pad, x, y, text, fSize, style);
-}
-
-
-/// Draw latex at coordinates of the frame corresponding to active TPad
-///
-/// The same as DrawLatex but used for active pad
-inline void DrawLatex(double x, double y, TString text, double fSize=-1.0, TString style="")
-{
-    DrawLatex(gPad, x, y, text, fSize, style);
-}
-
-
-/// Draw latex with distant Offset to the border of the frame1 and frame2 hull
-///
-/// The offset coding is used to cover left, right, bottom and top scenarios
-inline void DrawLatexLRTB(TVirtualPad *pad1, TVirtualPad *pad2, double Offset, TString text, double fSize=-1.0, TString style="")
-{
-    TVirtualPad *padOrg = gPad;
-    if(fSize < 0) {
-        pad1->cd();
-        TH1 *frame = GetFrame();
-        fSize = frame ? RelFontToPx(frame->GetTitleSize()) : 12;
-        padOrg->cd();
-    }
-    auto Close = [](double x, double val) {return abs(x-1000*val) <1000;};
-
-    double x = 0.5, y = 0.5;
-
-
-    double b[2], t[2], l[2], r[2];
-
-    TVirtualPad *pads[] = {pad1, pad2};
-    for(int i = 0; i < 2; ++i) {
-        l[i] = pads[i]->GetAbsXlowNDC() + pads[i]->GetAbsWNDC()*pads[i]->GetLeftMargin();
-        r[i] = pads[i]->GetAbsXlowNDC() + pads[i]->GetAbsWNDC()*(1-pads[i]->GetRightMargin());
-        b[i] = pads[i]->GetAbsYlowNDC() + pads[i]->GetAbsHNDC()*pads[i]->GetBottomMargin();
-        t[i] = pads[i]->GetAbsYlowNDC() + pads[i]->GetAbsHNDC()*(1-pads[i]->GetTopMargin());
-    }
-
-    double left  = min(l[0], l[1]);
-    double right = max(r[0], r[1]);
-    double bottom= min(b[0], b[1]);
-    double top   = max(t[0], t[1]);
-
-    if(Close(Offset,2) || Close(Offset, 8)) {
-        if(style.Contains('l')) x = 0.0;
-        if(style.Contains('r')) x = 1.0;
-        double unit = (fSize * 3./4) / ( pad1->GetWh() * (top - bottom) );
-
-        if(Close(Offset,2)) y = 1 + unit*(Offset - 2000);
-        else                y = 0 - unit*(Offset - 8000);
-
-    }
-    else if(Close(Offset,4) || Close(Offset, 6)) {
-        if(style.Contains('b')) y = 0.0;
-        if(style.Contains('t')) y = 1.0;
-        double unit = (fSize * 3./4) / ( pad1->GetWw() * (right - left) );
-
-        if(Close(Offset,6)) x = 1 + unit*(Offset - 6000);
-        else                x = 0 - unit*(Offset - 4000);
-    }
-    else
-        assert(0);
-
-    DrawLatex(pad1, pad2, x, y, text, fSize, style);
-}
-
-/// Draw latex up of frame1 and frame2
-///
-/// Draw the latex above the frames 1 and 2. The Offset is in units of text height of text. It is exactly the same unit
-/// as used for the title offsets
-inline void DrawLatexUp(TVirtualPad *pad1, TVirtualPad *pad2, double Offset, TString text, double fSize=-1.0, TString style="") {
-    DrawLatexLRTB(pad1, pad2, 2000 + Offset, text, fSize, style);
-}
-
-///Draw latex down of frame1 and frame2
-inline void DrawLatexDown(TVirtualPad *pad1,TVirtualPad *pad2, double Offset, TString text, double fSize=-1.0, TString style="") {
-    DrawLatexLRTB(pad1, pad2, 8000 + Offset, text, fSize, style);
-}
-
-///Draw latex right of frame1 and frame2
-inline void DrawLatexRight(TVirtualPad *pad1, TVirtualPad *pad2, double Offset, TString text, double fSize=-1.0, TString style="") {
-    DrawLatexLRTB(pad1, pad2, 6000 + Offset, text, fSize, style);
-}
-
-///Draw latex left of frame1 and frame2
-inline void DrawLatexLeft(TVirtualPad *pad1, TVirtualPad *pad2, double Offset, TString text, double fSize=-1.0, TString style="") {
-    DrawLatexLRTB(pad1, pad2, 4000 + Offset, text, fSize, style);
-}
-
-
-///Draw latex up of frame corresponding to given pad
-inline void DrawLatexUp(TVirtualPad *pad, double Offset, TString text, double fSize=-1.0, TString style="") {
-    DrawLatexUp(pad, pad, Offset, text, fSize, style);
-}
-
-///Draw latex down of frame corresponding to given pad
-inline void DrawLatexDown(TVirtualPad *pad, double Offset, TString text, double fSize=-1.0, TString style="") {
-    DrawLatexDown(pad, pad, Offset, text, fSize, style);
-}
-
-///Draw latex right of frame corresponding to given pad
-inline void DrawLatexRight(TVirtualPad *pad, double Offset, TString text, double fSize=-1.0, TString style="") {
-    DrawLatexRight(pad, pad, Offset, text, fSize, style);
-}
-
-///Draw latex left of frame corresponding to given pad
-inline void DrawLatexLeft(TVirtualPad *pad, double Offset, TString text, double fSize=-1.0, TString style="") {
-    DrawLatexLeft(pad, pad, Offset, text, fSize, style);
-}
-
-
-///Draw latex up of frame corresponding to active pad
-inline void DrawLatexUp(double Offset, TString text, double fSize=-1.0, TString style="") {
-    DrawLatexUp(gPad, Offset, text, fSize, style);
-}
-///Draw latex down of frame corresponding to active pad
-inline void DrawLatexDown(double Offset, TString text, double fSize=-1.0, TString style="") {
-    DrawLatexDown(gPad, Offset, text, fSize, style);
-}
-///Draw latex right of frame corresponding to active pad
-inline void DrawLatexRight(double Offset, TString text, double fSize=-1.0, TString style="") {
-    DrawLatexRight(gPad, Offset, text, fSize, style);
-}
-///Draw latex left of frame corresponding to active pad
-inline void DrawLatexLeft(double Offset, TString text, double fSize=-1.0, TString style="") {
-    DrawLatexLeft(gPad, Offset, text, fSize, style);
-}
-
-
-
-
-///@}
 
+void DrawLatex(TVirtualPad *pad1, TVirtualPad *pad2, double x, double y, TString text, double fSize=-1.0, TString style="");
+void DrawLatex(TVirtualPad *pad, double x, double y, TString text, double fSize=-1.0, TString style="");
+void DrawLatex(double x, double y, TString text, double fSize=-1.0, TString style="");
+void DrawLatexLRTB(TVirtualPad *pad1, TVirtualPad *pad2, double Offset, TString text, double fSize=-1.0, TString style="");
 
+void DrawLatexUp(TVirtualPad *pad1, TVirtualPad *pad2, double Offset, TString text, double fSize=-1.0, TString style="");
+void DrawLatexDown(TVirtualPad *pad1,TVirtualPad *pad2, double Offset, TString text, double fSize=-1.0, TString style="");
+void DrawLatexRight(TVirtualPad *pad1, TVirtualPad *pad2, double Offset, TString text, double fSize=-1.0, TString style="");
+void DrawLatexLeft(TVirtualPad *pad1, TVirtualPad *pad2, double Offset, TString text, double fSize=-1.0, TString style="");
 
+void DrawLatexUp(TVirtualPad *pad, double Offset, TString text, double fSize=-1.0, TString style="");
+void DrawLatexDown(TVirtualPad *pad, double Offset, TString text, double fSize=-1.0, TString style="");
+void DrawLatexRight(TVirtualPad *pad, double Offset, TString text, double fSize=-1.0, TString style="");
+void DrawLatexLeft(TVirtualPad *pad, double Offset, TString text, double fSize=-1.0, TString style="");
 
+void DrawLatexUp(double Offset, TString text, double fSize=-1.0, TString style="");
+void DrawLatexDown(double Offset, TString text, double fSize=-1.0, TString style="");
+void DrawLatexRight(double Offset, TString text, double fSize=-1.0, TString style="");
+void DrawLatexLeft(double Offset, TString text, double fSize=-1.0, TString style="");
 
 
 
@@ -733,20 +195,16 @@ struct Borders{
 };
 
 //Don't search for lower distance if minSkip reach
-static double MinDistance2(double minSkip, const Borders &br1, const Borders &br2);
+double MinDistance2(double minSkip, const Borders &br1, const Borders &br2);
 
 //Don't search for lower distance if minSkip reach
-static double MinDistanceSingle(vector<Borders> &bor, double minSkip, double x, double y, double w, double h);
-static double MinDistanceSingle(vector<Borders> &bor, Borders bSingle, double minSkip);
-
+double MinDistanceSingle(vector<Borders> &bor, double minSkip, double x, double y, double w, double h);
+double MinDistanceSingle(vector<Borders> &bor, Borders bSingle, double minSkip);
 
 
-
-
-static Point Px2NDC(Point p);
+Point Px2NDC(Point p);
 
 struct PLACER {
-
     int nLeg;
     vector<unsigned> dims;
     vector<vector<pair<int,int>>> layOuts;
@@ -760,257 +218,18 @@ struct PLACER {
     int nSteps = 10;
     double minSepar;
 
-    //Initalize layOuts, dims, legBorders, borders
-    void init(vector<TLegend *> legs, vector<double> &sizesX, vector<double> &sizesY) {
-        nLeg = legs.size();
-        for(auto & leg : legs) {
-            unsigned layOut = atoi(leg->GetName());
-
-            vector<pair<int,int>> pos;
-
-            PosIterator iter(nSteps, layOut);
-            while(iter.Iterate()) {
-               pos.push_back(make_pair(iter.iSave, iter.jSave));
-            }
-            layOuts.push_back(pos);
-        }
-
-        dims.resize(layOuts.size());
-        for(unsigned i = 0; i < dims.size(); ++i)
-            dims[i] = layOuts[i].size();
-        SizesX = sizesX;
-        SizesY = sizesY;
-        GetLegendsPositions();
-
-    }
-
-    double iterate(vector<int> &bestLayout) {
-        vector<int> idxs(dims.size());
-        vector<double> distsNow(dims.size());
-        vector<double> distsBest(dims.size());
-
-        double maxDist = 0;
-
-        while (1) {
-            // Print
-            double dist = analyze(idxs, distsNow);
-
-            if(dist >= maxDist) {
-                bool state = true;
-                for(int i = 0; i < nLeg; ++i) {
-                    state = state && distsNow[i] >= distsBest[i];
-                }
-                if(dist > maxDist || (dist == maxDist && state)) {
-                    bestLayout = idxs;
-                    distsBest = distsNow;
-                }
-                maxDist = dist;
-            }
-
-            // Update
-            unsigned j;
-            for(j = 0; j < dims.size(); ++j) {
-                idxs[j]++;
-                if (idxs[j] < static_cast<int>(dims[j])) break;
-                idxs[j] = 0;
-            }
-            if (j == dims.size()) break;
-        }
-        return maxDist;
-    }
-
-
-    void GetLegendsPositions() {
-
-        LoadHistoBorders(borders);
-
-        legBorders.resize(nLeg);
-
-        double fontSize = RelFontToPx(GetYaxis()->GetTitleSize());
-        minSepar = 0.5*fontSize; //inPixels
-
-        TH1 *frameNow = GetFrame();
-        double ytickLowNDC = frameNow->GetYaxis()->GetTickLength() * GetAxisFractionY();
-        double ytickHighNDC = ytickLowNDC * gPad->GetTicky();
-        double xtickLowNDC = frameNow->GetXaxis()->GetTickLength() * GetAxisFractionX();
-        double xtickHighNDC = xtickLowNDC * gPad->GetTickx();
-
-        double fSizeNDCy = minSepar / (gPad->GetWh() * gPad->GetAbsHNDC());
-        double fSizeNDCx = minSepar / (gPad->GetWw() * gPad->GetAbsWNDC());
-
-
-        for(int k = 0; k < nLeg; ++k) {
-
-            double SizeX = SizesX[k];
-            double SizeY = SizesY[k];
-
-            double xMin =  gPad->GetLeftMargin() + ytickLowNDC + fSizeNDCx;
-            double xMax =  1 - gPad->GetRightMargin() - ytickHighNDC - SizeX - fSizeNDCx;
-            double yMax =  1 - gPad->GetTopMargin() - xtickHighNDC - SizeY - fSizeNDCy;
-            double yMin =  gPad->GetBottomMargin() + xtickLowNDC  + fSizeNDCy;
-
-
-            legBorders[k].resize(dims[k]);
-
-            for(unsigned l = 0; l < dims[k]; ++l) {
-                int i = layOuts[k][l].first;
-                int j = layOuts[k][l].second;
-                
-                double xx = xMin + (xMax-xMin)/(nSteps-1) * j;
-                double yy = yMax - (yMax-yMin)/(nSteps-1) * i;
-
-
-                //Legend borders
-                legBorders[k][l].recs.push_back({xx, yy, SizeX, SizeY});
-                legBorders[k][l].FromNDC2px();
-
-            }
-        }
-    }
-
-
-    void GetDistancesPx(double scaleUp, double scaleDn) {
-        auto bordersPx = borders;
-        for(auto &b : bordersPx)
-            b.FromAbs2px(scaleUp, scaleDn);
-
-        distToHists.resize(nLeg);
-
-        for(int i = 0; i < nLeg; ++i) {
-            distToHists[i].resize(dims[i]);
-            for(unsigned l = 0; l < dims[i]; ++l) 
-                distToHists[i][l] = MinDistanceSingle(bordersPx, legBorders[i][l], 0.99*minSepar);
-        }
-    }
-
-
+    void init(vector<TLegend *> legs, vector<double> &sizesX, vector<double> &sizesY);
+    double iterate(vector<int> &bestLayout);
+    void GetLegendsPositions();
+    void GetDistancesPx(double scaleUp, double scaleDn);
     pair<double,double> GetSolution(vector<double> &xx, vector<double> &yy,
-                                                         int nScaleSteps=10) {
-        
-        double scaleUp=1., scaleDn=1.;
-
-        vector<int> bestLayout;
-
-        for(int sum = 0; sum < nScaleSteps; ++sum)
-        for(int iUp = sum; iUp >= 0; --iUp) {
-                int iDn = sum - iUp;
-                if(!gPad->GetLogy() && iDn != 0) continue;
-                scaleUp = pow(4, iUp/10.);
-                scaleDn = pow(4, iDn/10.);
-                //cout << "Scales " << scaleUp << " "<< scaleDn << endl;
-
-                GetDistancesPx(scaleUp, scaleDn);
-
-                double dist = iterate(bestLayout);
-
-                if(dist > minSepar)
-                    goto gotoAfterScaleLoop;
-        }
-        
-        gotoAfterScaleLoop:
-
-        xx.resize(nLeg);
-        yy.resize(nLeg);
-        for(int i = 0; i < nLeg; ++i) {
-            Point p;
-            p.x = legBorders[i][bestLayout[i]].recs[0].fX;
-            p.y = legBorders[i][bestLayout[i]].recs[0].fY;
-            p = Px2NDC(p);
-            xx[i] = p.x;
-            yy[i] = p.y;
-        }
-
-        return {scaleUp, scaleDn};
-        //cout << "done " << maxDist << endl;
-    }
-
-
-
-
-    void LoadHistoBorders(vector<Borders> &borders)
-    {
-        //Load histograms
-        vector<TObject *> hists;
-        for(const auto &&prim : *gPad->GetListOfPrimitives()) {
-            cout << prim->GetName() <<" "<< prim->ClassName() <<  endl;
-            if(strcmp(prim->GetName(),"hframe") && strcmp(prim->ClassName(),"TH1F"))
-                if(dynamic_cast<TH1*>(prim)) 
-                    hists.push_back(prim);
-        }
-
-
-        /////////////////////
-        //GetDistance
-        /////////////////////
-        if(hists.size() == 0) {
-            gPad->Modified();
-            return;
-        }
-
-        for(unsigned i = 0; i < hists.size(); ++i) {
-            Borders br;
-            br.GetHistBorders(dynamic_cast<TH1*>(hists[i]));
-            borders.push_back(br);
-        }
-
-    }
-
-
-    double analyze(vector<int> &indx, vector<double> &dists) {
-        double minDist = 1e40;
-        //Distances to histograms
-        for(unsigned k = 0; k < indx.size(); ++k) {
-            minDist = min(minDist, distToHists[k][indx[k]]);
-            dists[k] = distToHists[k][indx[k]];
-            if(minDist < minSepar)
-                return minDist;
-        }
-
-        for(unsigned k = 0;   k < indx.size(); ++k) 
-        for(unsigned l = k+1; l < indx.size(); ++l) {
-            double dist = MinDistance2(0.99*minSepar,
-                           legBorders[k][indx[k]], legBorders[l][indx[l]]);
-            minDist = min(minDist, dist);
-            dists[k] = min(dists[k], dist);
-            if(minDist < minSepar)
-                return minDist;
-        }
-
-
-        return minDist;
-
-    }
-
-
+                                                         int nScaleSteps=10);
+    void LoadHistoBorders(vector<Borders> &borders);
+    double analyze(vector<int> &indx, vector<double> &dists);
 };
 
-/// @name Auto-legend
-/// Functions to place lagend automaticaly and prevent overlaps
-///@{ 
-
-/// Convert layout bit to string
-///
-/// Used to setup the position of particular TLegend by SetName
-/// For example leg->SetName(SetLayout(kPos1)) for legend in to top left
-/// Used internally by newLegend
-/// @see newLegend()
-/// @param pos the position bit, for instance kPos2 | kPos8
-/// @return the number printed in decadic base to the string
-inline const char *SetLayout(unsigned pos)
-{
-    return to_string(pos).c_str();
-}
-
-
-inline unsigned SimplifyPos(unsigned pos)
-{
-    if(pos & kPos5) return kPos5;
-    if(pos & kPos2) pos &= !kPos1 & !kPos3;
-    if(pos & kPos4) pos &= !kPos1 & !kPos7;
-    if(pos & kPos6) pos &= !kPos3 & !kPos9;
-    if(pos & kPos8) pos &= !kPos7 & !kPos9;
-    return pos;
-}
+const char *SetLayout(unsigned pos);
+unsigned SimplifyPos(unsigned pos);
 
 ///
 /// Struct containing NDC sizes and positions of the corresponding TLatex
@@ -1023,795 +242,32 @@ struct RectangleNDC {
 };
 
 
-/// Calculates positions and height and width of rectangle which encapsulates TLatex.
-///
-/// Works well for 4 basic orientation, 0,90,180,270 degree.
-/// Does not work for properly for vertical alignment to the bottom of the line
-///
-inline RectangleNDC GetNDC(TLatex *lat)
-{
-
-	int hAlign = lat->GetTextAlign() / 10 - 1;
-	int vAlign = lat->GetTextAlign() % 10 - 1;
-	if(vAlign == -1) vAlign = 0;
-
-	RectangleNDC rTitle;
-
-	rTitle.fHeight = lat->GetYsize() / (gPad->GetY2()-gPad->GetY1());
-	rTitle.fWidth = lat->GetXsize()  / (gPad->GetX2()-gPad->GetX1());
-	rTitle.fX = lat->GetX();
-	rTitle.fY = lat->GetY();
-
-
-	if(lat->GetTextAngle() == 0) {
-		rTitle.fX -= hAlign*rTitle.fWidth/2.;
-		rTitle.fY -= vAlign*rTitle.fHeight/2.;
-	}
-	else {
-		swap(rTitle.fWidth, rTitle.fHeight);
-		double rat = gPad->GetWh() / double(gPad->GetWw());
-		rat /= gPad->GetAbsWNDC() / double(gPad->GetAbsHNDC());
-		rTitle.fWidth *= rat;
-		rTitle.fHeight *= 1./rat;
-
-		if(lat->GetTextAngle() == 90) {
-			rTitle.fY -= (hAlign)*rTitle.fHeight/2.;
-			vAlign = 2-vAlign;
-			rTitle.fX -=1.*vAlign*rTitle.fWidth/2.;
-		}
-		else if(lat->GetTextAngle() == 270) {
-			hAlign = 2-hAlign;
-			rTitle.fY -= (hAlign)*rTitle.fHeight/2.;
-			rTitle.fX -=1.*vAlign*rTitle.fWidth/2.;
-		}
-	}
-	rTitle.lat = lat;
-	return rTitle;
-}
+RectangleNDC GetNDC(TLatex *lat);
+TLegend *newLegend(unsigned pos, int nCols = 1);
+void GetLegendSizes(TLegend *leg, double &SizeX, double &SizeY, double &SizeYroot);
+void PlaceLegends(vector<TLegend*> legs, bool keepRange = false);
+void DrawLegends(vector<TLegend*> legs, bool keepRange=false);
 
-/// Define new legend at position pos with nCols columns.
-///
-/// The text size is set to be the same as the size of y-axis title
-/// All this values can be changed later on manually, like
-/// leg->SetTextSize(1.3*leg->GetTextSize())
-///
-TLegend *newLegend(unsigned pos, int nCols = 1)
-{
-        TLegend *leg = new TLegend(0., 0., 0., 0.);
-        leg->SetName(SetLayout(pos));
-        leg->SetTextSize(GetYaxis()->GetTitleSize());
-        leg->SetNColumns(nCols);
-        return leg;
-}
-
-/// Calculates sizes of the legend in NDC
-///
-/// Note that due to the bug in root the y-size to be set to TLegend object
-/// is sometimes diffrent than the real size
-void GetLegendSizes(TLegend *leg, double &SizeX, double &SizeY, double &SizeYroot)
-{
-
-    double lineSeparation = 1.2;
-    double markerSize = 1.5;
-    double columnSeparation = 0;
-
-    //double fontSize = RelFontToPx(GetYaxis()->GetTitleSize());
-    double fontSize = RelFontToPx(leg->GetTextSize());
-
-    gPad->Update();
-    //cout <<"There is just start " <<  gPad->GetUymax() << " "<< gPad->GetUymin() << endl;
-
-    leg->SetBorderSize(0);
-    //leg->SetLineStyle(2);
-    leg->SetFillStyle(0);
-    leg->SetTextSize(PxFontToRel(fontSize));
-
-    double fSizeNDCy = fontSize / (gPad->GetWh() * gPad->GetAbsHNDC());
-    double fSizeNDCx = fontSize / (gPad->GetWw() * gPad->GetAbsWNDC());
-
-    int nHeaders = 0;
-    int nLegItems = 0;
-
-    int nCols = leg->GetNColumns();
-    vector<double> maxC(nCols, 0);
-    double headerW = 0;
-    int colId = 0;
-    for(const auto &&entry : *leg->GetListOfPrimitives()) {
-        TString lab = dynamic_cast<TLegendEntry *>(entry)->GetLabel();
-        TString opt = dynamic_cast<TLegendEntry *>(entry)->GetOption();
-        cout << "Label "<< leg->GetNRows()<<" " << lab << endl;
-        TLatex *lat = new TLatex(0.5, 0.5, lab);
-        lat->SetTextSize(leg->GetTextSize());
-        lat->SetTextFont(leg->GetTextFont());
-
-        double textW = GetNDC(lat).fWidth;
-        if(opt == "h") {
-            headerW = max(headerW, textW);
-            ++nHeaders;
-            colId = -1;
-        }
-        else {
-            maxC[colId] = max(maxC[colId], textW);
-            ++nLegItems;
-        }
-        colId = (colId != nCols-1) ? colId + 1 : 0;
-        delete lat;
-    }
-    double maxW = accumulate(maxC.begin(),maxC.end(),0.);
-
-    int nRows = nHeaders + (nLegItems+nCols-1)/nCols;
-    //cout << "RADEK nRows " << nRows << endl;
-    SizeY = lineSeparation*fSizeNDCy*nRows;
-
-    headerW += 0.1*fSizeNDCx*markerSize;
-
-    SizeX = max(nCols*fSizeNDCx*markerSize +
-               (nCols-1)*fSizeNDCx*columnSeparation + maxW, headerW);
-    leg->SetMargin( nCols*fSizeNDCx*markerSize / SizeX);
-
-    leg->SetColumnSeparation((nCols-1)*fSizeNDCx*columnSeparation / SizeX);
-
-
-    SizeYroot = lineSeparation*fSizeNDCy*leg->GetNRows();
-
-}
-
-
-
-
-/// Setup the position of legends provided in legs array
-///
-/// Note that the legends must be drawn manually
-/// To draw legends directly, use DrawLegends
-///
-void PlaceLegends(vector<TLegend*> legs, bool keepRange = false)
-{
-    int nScaleSteps = keepRange ? 1 : 10;
+Point Abs2Px(Point p, double scaleUp, double scaleDn);
+Point Px2NDC(Point p);
 
-    vector<double> sizesX, sizesY, sizesYroot;
 
-    for(unsigned i = 0; i < legs.size(); ++i) {
-        double SizeX, SizeY, SizeYroot;
-        GetLegendSizes(legs[i], SizeX, SizeY, SizeYroot);
-        sizesX.push_back(SizeX);
-        sizesY.push_back(SizeY);
-        sizesYroot.push_back(SizeYroot);
-    }
-
-    PLACER placer;
-
-    placer.init(legs, sizesX, sizesY);
-
-    vector<double> xx, yy;
-    double scaleUp, scaleDn;
-    tie(scaleUp, scaleDn) = placer.GetSolution(xx, yy, nScaleSteps);
-    //return;
-    
-    for(unsigned i = 0; i < legs.size(); ++i) {
-        legs[i]->SetX1(xx[i]);
-        legs[i]->SetY1(yy[i] + sizesY[i] - sizesYroot[i]);
-        legs[i]->SetX2(xx[i] + sizesX[i]);
-        legs[i]->SetY2(yy[i] + sizesY[i]);
-    }
-
-    
-    TH1 *frameNow = GetFrame();
-    if(gPad->GetLogy()) {
-        double Max = frameNow->GetMaximum();
-        double Min = frameNow->GetMinimum();
-        frameNow->SetMaximum(Min * pow(Max/Min, scaleUp));
-        frameNow->SetMinimum(Max / pow(Max/Min, scaleDn));
-    }
-    else {
-        double Max = frameNow->GetMaximum();
-        double Min = frameNow->GetMinimum();
-        frameNow->SetMaximum(Min + (Max-Min)*scaleUp);
-        frameNow->SetMinimum(Max - (Max-Min)*scaleDn);
-    }
-
-    /*
-    for(int i = 0; i < legs.size(); ++i) {
-        TLine *l = new TLine;
-        l->SetNDC();
-        l->DrawLineNDC(xx[i], yy[i], xx[i]+sizesX[i], yy[i]);
-        l->DrawLineNDC(xx[i], yy[i]+sizesY[i], xx[i]+sizesX[i], yy[i]+sizesY[i]);
-        l->DrawLineNDC(xx[i], yy[i], xx[i], yy[i]+sizesY[i]);
-        l->DrawLineNDC(xx[i]+sizesX[i], yy[i], xx[i]+sizesX[i], yy[i]+sizesY[i]);
-
-    }
-    */
-}
-
-/// Draw legends provided in vector legs in such a way that there is no overlap.
-///
-/// in case that keepRange=true the y-axis range is not touch even if the amount of space is not sufficiend.
-/// The keepRange=true is very useful when a grid of histograms is plotted
-///
-void DrawLegends(vector<TLegend*> legs, bool keepRange=false)
-{
-    PlaceLegends(legs, keepRange);
-    for(auto & leg : legs)
-        leg->Draw();
-}
-
-
-
-
-
-
-
-
-
-
-static Point Abs2Px(Point p, double scaleUp, double scaleDn)
-{
-   	double valXmin = gPad->GetX1();
-    double valXmax = gPad->GetX2();
-
-    double valYmin = gPad->GetY2() - scaleDn*(gPad->GetY2()-gPad->GetY1());
-    double valYmax = gPad->GetY1() + scaleUp*(gPad->GetY2()-gPad->GetY1());
-
-
-	double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
-	double pxW = gPad->GetWw()*gPad->GetAbsWNDC();
-
-
-    if(gPad->GetLogx()) p.x = log10(p.x);
-    if(gPad->GetLogy()) p.y = log10(p.y);
-
-    p.x =  (p.x - valXmin)/(valXmax-valXmin) * pxW;
-    p.y =  (p.y - valYmin)/(valYmax-valYmin) * pxH;
-
-    //cout << p.x <<" "<<  p.y << endl;
-    return p;
-}
-
-static Point Px2NDC(Point p)
-{
-	double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
-	double pxW = gPad->GetWw()*gPad->GetAbsWNDC();
-    p.x = p.x/pxW;
-    p.y = p.y/pxH;
-    return p;
-}
-
-
-
-inline double MinDistanceSingle(vector<Borders> &bor, double minSkip, double x, double y, double w, double h)
-{
-    Borders bS;
-    bS.recs.push_back( {x, y, w, h} );
-    bS.FromNDC2px();
-
-    double minDist = 1e40;
-    for(Borders &b : bor) {
-        double d = MinDistance2(0.99*minSkip, b, bS);
-        minDist = min(minDist, d);
-        if(minDist <= minSkip) return minDist;
-    }
-    return sqrt(minDist);
-}
-
-
-static double MinDistanceSingle(vector<Borders> &bor, Borders bSingle, double minSkip)
-{
-    double minDist = 1e40;
-    for(Borders &b : bor) {
-        double d = MinDistance2(0.99*minSkip, b, bSingle);
-        minDist = min(minDist, d);
-        if(minDist <= minSkip) return minDist;
-    }
-    return sqrt(minDist);
-}
-
-
-
-static double MinDistance2(double minSkip, const Borders &br1, const Borders &br2)
-{
-    double minDist = 1e40;
-    for(const auto &r1 : br1.recs)
-        for(const auto &r2 : br2.recs) {
-            double d = Borders::Distance2(r1, r2);
-            minDist = min(minDist, d);
-            if(minDist <= minSkip) return minDist;
-        }
-    return minDist;
-
-}
-
-void Borders::FromNDC2px()
-{
-	double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
-	double pxW = gPad->GetWw()*gPad->GetAbsWNDC();
-
-    for(Rectangle &r : recs) { 
-        r.fX *= pxW;
-        r.fY *= pxH;
-        r.fWidth  *= pxW;
-        r.fHeight *= pxH;
-    }
-}
-
-/*
-void Borders::FromPx2NDC()
-{
-	double pxH = gPad->GetWh()*gPad->GetAbsHNDC();
-	double pxW = gPad->GetWw()*gPad->GetAbsWNDC();
-
-    for(Rectangle &r : recs) { 
-        r.fX /= pxW;
-        r.fY /= pxH;
-        r.fWidth  /= pxW;
-        r.fHeight /= pxH;
-    }
-}
-*/
-
-
-
-void Borders::FromAbs2px(double scaleUp, double scaleDn)
-{
-    for(Rectangle &r : recs) { 
-        Point p1(r.fX, r.fY);
-        Point p2(r.fX+r.fWidth, r.fY+r.fHeight);
-
-        p1 = Abs2Px(p1, scaleUp, scaleDn);
-        p2 = Abs2Px(p2, scaleUp, scaleDn);
-        r.fX = p1.x;
-        r.fY = p1.y;
-        r.fWidth  = p2.x-p1.x;
-        r.fHeight = p2.y-p1.y;
-    }
-}
-
-///
-/// Return the borders of the provided histogram
-///
-void Borders::GetHistBorders(TH1 *h)
-{
-    for(int i = 1; i <= h->GetNbinsX(); ++i) {
-        double xMin = h->GetBinLowEdge(i);
-        double xMax = h->GetBinLowEdge(i) + h->GetBinWidth(i);
-        double yMin = h->GetBinContent(i)-h->GetBinError(i);
-        double yMax = h->GetBinContent(i)+h->GetBinError(i);
-
-        const double lim  = 1e-30;
-
-        if(gPad->GetLogx()) {
-            xMin = max(lim, xMin);
-            xMax = max(lim, xMax);
-        }
-        if(gPad->GetLogy()) {
-            yMin = max(lim, yMin);
-            yMax = max(lim, yMax);
-        }
-        recs.push_back({xMax, yMin, xMax-xMin, yMax-yMin});
-
-        TString drawOpt = h->GetDrawOption();
-        if(drawOpt.Contains("hist") && i > 1) {
-            double yMinLeft = h->GetBinContent(i-1)-h->GetBinError(i-1);
-            double yMaxLeft = h->GetBinContent(i-1)+h->GetBinError(i-1);
-            if(gPad->GetLogy()) {
-                yMinLeft = max(lim, yMinLeft);
-                yMaxLeft = max(lim, yMaxLeft);
-            }
-            double yMinNow = min(yMin, yMinLeft);
-            double yMaxNow = max(yMax, yMaxLeft);
-            recs.push_back({xMin, yMinNow, 0., yMaxNow-yMinNow});
-        }
-
-    }
-}
+double MinDistanceSingle(vector<Borders> &bor, double minSkip, double x, double y, double w, double h);
+double MinDistanceSingle(vector<Borders> &bor, Borders bSingle, double minSkip);
+double MinDistance2(double minSkip, const Borders &br1, const Borders &br2);
 
 inline double hypot2(double x, double y) {return x*x+y*y;}
 
-/// Distance between two rectangles, 0 if overlap
-double Borders::Distance2(const Rectangle &r1, const Rectangle &r2)
-{
-    double x1  = r1.fX;
-    double x1b = r1.fX + r1.fWidth;
-    double x2  = r2.fX;
-    double x2b = r2.fX + r2.fWidth;
-
-    double y1  = r1.fY;
-    double y1b = r1.fY + r1.fHeight;
-    double y2  = r2.fY;
-    double y2b = r2.fY + r2.fHeight;
-
-    bool left = x2b < x1;
-    bool right = x1b < x2;
-    bool bottom = y2b < y1;
-    bool top = y1b < y2;
-    if(top && left)
-        return hypot2(x2b-x1, y2-y1b);
-    else if(left && bottom)
-        return hypot2(x2b-x1, y2b-y1);
-    else if(bottom && right)
-        return hypot2(x2-x1b, y2b-y1);
-    else if(right && top)
-        return hypot2(x2-x1b, y2-y1b);
-    else if(left)
-        return hypot2(x1 - x2b,0.);
-    else if(right)
-        return hypot2(x2 - x1b,0.);
-    else if(bottom)
-        return hypot2(y1 - y2b,0.);
-    else if(top)
-        return hypot2(y2 - y1b,0.);
-    else
-        return 0.;
-}
-
-///@}
-
-
-/// @name Miscellaneous
-/// Utilities for redraw axes, divde pad and auto y-range calculation
-///@{ 
-
-/// Redraw the current frame and axis ticks.
-///
-/// Useful if the original ticks were covered during plotting
-///
-inline void UpdateFrame()
-{
-    gPad->Update();
-    gPad->RedrawAxis();
-    TFrame *fr = gPad->GetFrame();
-    if(fr) {
-        fr->SetFillStyle(0);
-        fr->Draw();
-    }
-    else
-        cout << "No frame at active pad" << endl;
-    gPad->Update();
-}
-
-
-/// Calculate the automatic range of the vertical axis and apply it.
-///
-/// Useful when several histograms are plotted to the same frame. 
-/// In such case the y-range is normally chosen according to the one which is plotted first (without "same")
-/// This method select such a range which corresponds to union of all y-ranges  
-/// When applying this method y-range is no more plotting order dependent
-inline void CalcYaxisRange()
-{
-	TH1 *hFrame = GetFrame();
-    if(!hFrame) return;
-	TAxis *ax = hFrame->GetXaxis();
-
-	int iFirst = ax->GetFirst();
-	int iLast  = ax->GetLast();
-
-	double xMin = ax->GetBinLowEdge(iFirst);
-	double xMax = ax->GetBinLowEdge(iLast) + ax->GetBinWidth(iLast);
-
-
-	//cout << "First " << hFrame->GetXaxis()->GetFirst() << endl;
-	//cout << "Last  " << hFrame->GetXaxis()->GetLast() << endl;
-	cout << xMin << " "<< xMax << endl;
-
-	double widthMin,  widthMax;
-	double centerMin, centerMax;
-	//return ;
-	double yMin = 1e40, yMax = -1e40;
-	for(auto && obj : *gPad->GetListOfPrimitives()) {
-
-		if(obj->InheritsFrom(TH1::Class()))
-			((TH1*)obj)->GetXaxis()->SetRangeUser(xMin, xMax);
-		else if(obj->InheritsFrom(TMultiGraph::Class()))
-			((TMultiGraph*)obj)->GetXaxis()->SetRangeUser(xMin, xMax);
-		else if(obj->InheritsFrom(TGraph::Class()))
-			((TGraph*)obj)->GetXaxis()->SetRangeUser(xMin, xMax);
-		else if(obj->InheritsFrom(THStack::Class()))
-			((THStack*)obj)->GetXaxis()->SetRangeUser(xMin, xMax);
-
-
-		if(obj->InheritsFrom(TH1::Class()) ||
-			obj->InheritsFrom(TMultiGraph::Class()) ||
-			obj->InheritsFrom(TGraph::Class())  ||
-			obj->InheritsFrom(THStack::Class()) ) {
-
-			obj->Paint();
-			//double zoom = gPad->GetUymax() - gPad->GetUymin();
-			double yMinNow = gPad->GetUymin();
-			double yMaxNow = gPad->GetUymax();
-
-			if(yMinNow < yMin) {
-				yMin = yMinNow;
-				widthMin = yMaxNow - yMinNow;
-				centerMin = (yMaxNow + yMinNow)/2.;
-			}
-			if(yMaxNow > yMax) {
-				yMax = yMaxNow;
-				widthMax = yMaxNow - yMinNow;
-				centerMax = (yMaxNow + yMinNow)/2.;
-			}
-		}
-	}
-
-
-	double width = yMax - yMin;
-
-
-	double zoomMin = width / widthMin;
-	double zoomMax = width / widthMax;
-	
-	if(yMin >= 0. && !gPad->GetLogy())
-		yMin = max(0., centerMin - zoomMin * widthMin/2.);
-	else
-		yMin =  centerMin - zoomMin * widthMin/2.;
-	yMax = centerMax + zoomMax * widthMax/2.;
-	
-
-	//cout <<"Minima "<< yMin <<" "<< yMax << endl;
-	if(gPad->GetLogy()) {
-		hFrame->SetMinimum(pow(10,yMin));
-		hFrame->SetMaximum(pow(10,yMax));
-	}
-	else {
-		hFrame->SetMinimum(yMin);
-		hFrame->SetMaximum(yMax);
-	}
-}
-
-/// Set simultaneously left and right margin of active pad
-///
-/// Implemented to avoid the bug in ROOT which causes that
-/// gPad->SetLeftMargin(0.5); gPad->SetRightMargin(0.1);
-/// is not always the same as
-/// gPad->SetRightMargin(0.1); gPad->SetLeftMargin(0.5);
-inline void SetLeftRight(double lMargin, double rMargin)
-{
-    gPad->SetLeftMargin(0);
-    gPad->SetRightMargin(0);
-    gPad->SetLeftMargin(lMargin);
-    gPad->SetRightMargin(rMargin);
-}
-
-/// Set simultaneously top and bottom margin of active pad
-///
-/// Implemented to avoid the bug in ROOT which causes that
-/// gPad->SetTopMargin(0.5); gPad->SetBottomMargin(0.1);
-/// is not always the same as
-/// gPad->SetBottomMargin(0.1); gPad->SetTopMargin(0.5);
-inline void SetTopBottom(double tMargin, double bMargin)
-{
-    gPad->SetTopMargin(0);
-    gPad->SetBottomMargin(0);
-    gPad->SetTopMargin(tMargin);
-    gPad->SetBottomMargin(bMargin);
-}
-
-
-
-////////////////////////////////////////////////////////////////////
-/// Construct the lattice of pads according to the provided x and y sizes
-///
-/// Comparing to classical Divide method this function left no empty space
-/// between frames but left spaces for axes.
-/// Note that without setting the offsets, font sizes and tics manually
-/// the ticks differs between pads.
-/// From this reason, we recommend calling SetFTO() in each pad
-/// The margins of the original pad are kept
-/// This method can be nested is some of the created pads needs additional subdivision.
-/// The resulting pads can be accessed by the standard cd() command as in ROOT Divide().
-/// @param xDivs vector defining horizontal sizes of frames, the absolute normalisation does not matter
-/// @param yDivs vector defining vertical sizes of frames, the absolute normalisation does not matter
-///
-inline void DividePad(vector<double> xDivs, vector<double> yDivs)
-{
-    TVirtualPad *orgPad = gPad;
-
-    double lMag = orgPad->GetLeftMargin();
-    double rMag = orgPad->GetRightMargin();
-    double tMag = orgPad->GetTopMargin();
-    double bMag = orgPad->GetBottomMargin();
-
-    int nx = xDivs.size();
-    int ny = yDivs.size();
-
-    double Nx = accumulate(xDivs.begin(), xDivs.end(), 0.);
-    double Ny = accumulate(yDivs.begin(), yDivs.end(), 0.);
-    vector<double> xPos(nx+1), yPos(ny+1);
-    xPos[0] = yPos[0] = 0;
-    for(int i = 1; i <= nx; ++i)
-        xPos[i] = xPos[i-1] + xDivs[i-1]/Nx * (1-lMag-rMag);
-    for(int i = 1; i <= ny; ++i)
-        yPos[i] = yPos[i-1] + yDivs[i-1]/Ny * (1-tMag-bMag);
-
-    
-    for(int ix = 0; ix < nx; ++ix)
-    for(int iy = 0; iy < ny; ++iy) {
-        double xl = (ix == 0)    ? 0 : lMag+xPos[ix];
-        double xr = (ix == nx-1) ? 1 : lMag+xPos[ix+1];
-
-        double yt = (iy == 0)    ? 1 : 1-tMag-yPos[iy];
-        double yb = (iy == ny-1) ? 0 : 1-tMag-yPos[iy+1];
-
-        int id = iy*nx+ix+1;
-        TPad *pad = new TPad(SF("%s_%d", orgPad->GetName(), id), "", xl, yb, xr, yt);
-
-        double lNew =  (ix == 0) ? lMag/(xPos[1]+lMag) : 0;
-        double rNew =  (ix == nx-1) ? rMag/( 1-lMag - xPos[nx-1]) : 0;
-
-        double tNew =  (iy == 0) ? tMag/(yPos[1]+tMag) : 0;
-        double bNew =   (iy == ny-1) ? bMag/(1-tMag - yPos[ny-1]) : 0;
-
-        pad->cd();
-        SetLeftRight(lNew, rNew);
-        SetTopBottom(tNew, bNew);
-        orgPad->cd();
-        
-//        if(ix == nx-1) {
-//            cout << "Hela : " <<  lMag + xPos[nx-1] << endl;
-//            cout << "lMag rMag : " <<lMag <<" "<<  rMag << endl;
-//            cout  << "Ratio " << rMag / (1-lMag-xPos[nx-1]) << endl;
-//        }
-
-        pad->SetNumber(id);
-        pad->Draw();
-    }
-}
-
-
-
-
-////////////////////////////////////////////////////////////////////
-/// Construct the lattice of frames according to the provided x and y sizes using transparency trick.
-///
-/// This function creates set of transparent overlapping pads, each of them covering whole canvas.
-/// The margins of of of these pads are chosen in such a way that the lattice of frames is constructed.
-/// Comparing to the DividePad method this method allows to include spaces between plotted frames.
-/// In case that "zero" spaces are selected the frame structure would look the same only the axis
-/// would not be cut off by the frame edge.
-/// On the other hand one needs to ensure that nuisance exes are not plotted
-/// (i.e. setting their font size to 0).
-/// Note that argument vectors divX and divY must always contain odd number of elements (sizes).
-/// Comparing to DividePad method this method can be run several time for the same pad.
-/// In such a way more complex frame structure can be created than the regular lattice.
-/// The resulting pads can be accessed by the standard cd() command as in ROOT Divide().
-/// In case of more calls on the same pad the indexes continues where there previous ended.
-///
-/// @param xDivs vector defining horizontal sizes of frames and spaces between them,
-///    the absolute normalisation does not matter. The structure is the following {space, frame, space, frame, space}
-///    In case of useMargins=true the very left and right space is taken from pad margins.
-/// @param yDivs the same as xDivs but in vertical coordinate
-/// @param useMargins specify wherever the current pad margins should be used.
-///
-inline void DivideTransparent(vector<double> divX, vector<double> divY, bool useMargins = true)
-{
-
-    TVirtualPad *orgPad = gPad;
-
-    if(divX.size() % 2 != 1 || int(divX.size()) < (3-2*useMargins) ) {
-        cout << "Wrong divX= " << divX.size() << endl;
-        return;
-    }
-    if(divY.size() % 2 != 1 || int(divY.size()) < (3-2*useMargins) ) {
-        cout << "Wrong divY= " << divY.size() << endl;
-        return;
-    }
-
-
-
-    double sumX = accumulate(divX.begin(), divX.end(), 0.0);
-    double sumY = accumulate(divY.begin(), divY.end(), 0.0);
-
-    if(useMargins == true) {
-        double l = orgPad->GetLeftMargin();
-        double r = orgPad->GetRightMargin();
-        double t = orgPad->GetTopMargin();
-        double b = orgPad->GetBottomMargin();
-        
-
-        vector<double> newX, newY;
-        newX.push_back(l * sumX/(1-l-r));
-        newX.insert(newX.end(), divX.begin(), divX.end());
-        newX.push_back(r * sumX/(1-l-r));
-
-        newY.push_back(t * sumY/(1-t-b));
-        newY.insert(newY.end(), divY.begin(), divY.end());
-        newY.push_back(b * sumY/(1-t-b));
-
-        DivideTransparent(newX, newY, false);
-        return;
-    }
-
-
-
-    vector<double> edgesX(divX.size()+1);
-    vector<double> edgesY(divY.size()+1);
-
-    edgesX[0] = edgesY[0] = 0;
-    for(unsigned i = 1; i < edgesX.size(); ++i)
-        edgesX[i] = edgesX[i-1] + divX[i-1]/sumX;
-    for(unsigned i = 1; i < edgesY.size(); ++i)
-        edgesY[i] = edgesY[i-1] + divY[i-1]/sumY;
-
-    int nPadsX = (divX.size()-1)/2;
-    //int nPadsY = (divY.size()-1)/2;
-
-    int kStart = 1;
-    while(orgPad->GetPad(kStart))
-        ++kStart;
-    --kStart;
-
-
-    int i = 1;
-    //for(int x = 1; x < edgesX.size()-1; x+=2)
-    for(int y = 1; y < int(edgesY.size())-1; y+=2) 
-    for(int x = edgesX.size()-3; x >= 1; x-=2) {
-        //i = (nPadsY-1-(y-1)/2) * nPadsX + (nPadsX-1-(x-1)/2) + 1; 
-        i = ((y-1)/2) * nPadsX + ((x-1)/2) + 1; 
-        
-        TPad *pad = new TPad(TString::Format("%s_%d", orgPad->GetName(), kStart+i), "", 0.0, 0.0, 1, 1);
-        pad->SetFillStyle(0);
-
-        
-        double l = max(0.,edgesX[x]);
-        double r = max(0.,1-edgesX[x+1]);
-        double t = max(0.,edgesY[y]);
-        double b = max(0.,1-edgesY[y+1]);
-
-        //cout <<"LeftRight " << l <<" "<<  r <<" "<< (1-l-r) <<" "<< i<< endl;
-
-        pad->cd();
-        SetLeftRight(l, r);
-        SetTopBottom(t, b);
-        orgPad->cd();
-
-
-        pad->SetNumber(kStart+i);
-        pad->Draw();
-        ++i;
-    }
-}
-
-/// Merge vectors into one
-///
-/// In current version up to 7 vectors can be merged
-inline vector<double> merge(vector<double> v1, vector<double> v2={}, vector<double> v3={}, vector<double> v4={}, vector<double> v5={}, vector<double> v6={}, vector<double> v7={} )
-{
-    vector<vector<double>> v = {v1, v2, v3, v4, v5, v6, v7};
-    vector<double> res;
-    for(unsigned i = 0; i < v.size(); ++i)
-        res.insert(res.end(), v[i].begin(), v[i].end());
-    return res;
-}
-
-/// Repeat the provided pattern
-///
-/// Returns the vector which includes n times the vector x
-inline vector<double> repeat(vector<double> x, int n)
-{
-    vector<double> res = x;
-    for(int i = 1; i < n; ++i)
-        res.insert(res.end(), x.begin(), x.end());
-    return res;
-}
-
-/// Construct group of frames
-///
-/// Returns vector describing layout of n identical frames which are separated by the same space size
-/// The spaces before first space and after last frame are not included
-inline vector<double> group(double frame, double space, int n)
-{
-    vector<double> res;
-    for(int i = 0; i < n-1; ++i) {
-        res.push_back(frame);
-        res.push_back(space);
-    }
-    res.push_back(frame);
-    return res;
-}
-
-
-
-
-///@}
-
 
+void UpdateFrame();
+void CalcYaxisRange();
+void SetLeftRight(double lMargin, double rMargin);
+void SetTopBottom(double tMargin, double bMargin);
+void DividePad(vector<double> xDivs, vector<double> yDivs);
+void DivideTransparent(vector<double> divX, vector<double> divY, bool useMargins = true);
+vector<double> merge(vector<double> v1, vector<double> v2={}, vector<double> v3={}, vector<double> v4={}, vector<double> v5={}, vector<double> v6={}, vector<double> v7={} );
+vector<double> repeat(vector<double> x, int n);
+vector<double> group(double frame, double space, int n);
 
 }
 
-- 
GitLab