Visualizer.cpp 10.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** @file Visualizer.cpp
 *  @brief Implementation of Visualizer class.
 *
 *
 *  @author Riccardo Longo
 *  @bug No known bugs.
 */

#include <TH1.h>
#include <TH2.h>
#include <TROOT.h>
#include <TAxis.h>
#include <TGaxis.h>
#include <TPad.h>
Riccardo Longo's avatar
Riccardo Longo committed
15
#include <TCanvas.h>
16
17
18
19
20

#include <iostream>

#include "Visualizer.h"

Chad Lantz's avatar
Chad Lantz committed
21
22
23
24
25
26
/** @brief Visualizer Constructor for Visualizer.
 */
Visualizer::Visualizer( ){

}

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
Visualizer::Visualizer( std::string _style ){
    m_style = _style;
    if(m_style == "ATLAS" || m_style == "atlas") Visualizer::SetAtlasStyle();
}

/**
 * @brief Function inherited from rcdaq. Creates the ATLAS TStyle object
 * @return
 */
TStyle* Visualizer::AtlasStyle(){
    TStyle *atlasStyle = new TStyle("ATLAS","Atlas style");

      // use plain black on white colors
      Int_t icol=0; // WHITE
      atlasStyle->SetFrameBorderMode(icol);
      atlasStyle->SetFrameFillColor(icol);
      atlasStyle->SetCanvasBorderMode(icol);
      atlasStyle->SetCanvasColor(icol);
      atlasStyle->SetPadBorderMode(icol);
      atlasStyle->SetPadColor(icol);
      atlasStyle->SetStatColor(icol);
      //atlasStyle->SetFillColor(icol); // don't use: white fill color for *all* objects

      // set the paper & margin sizes
      atlasStyle->SetPaperSize(20,26);

      // set margin sizes
      atlasStyle->SetPadTopMargin(0.05);
      atlasStyle->SetPadRightMargin(0.05);
      atlasStyle->SetPadBottomMargin(0.16);
      atlasStyle->SetPadLeftMargin(0.16);

      // set title offsets (for axis label)
      atlasStyle->SetTitleXOffset(1.4);
      atlasStyle->SetTitleYOffset(1.4);

      // use large fonts
      //Int_t font=72; // Helvetica italics
      Int_t font=42; // Helvetica
      Double_t tsize=0.05;
      atlasStyle->SetTextFont(font);

      atlasStyle->SetTextSize(tsize);
      atlasStyle->SetLabelFont(font,"x");
      atlasStyle->SetTitleFont(font,"x");
      atlasStyle->SetLabelFont(font,"y");
      atlasStyle->SetTitleFont(font,"y");
      atlasStyle->SetLabelFont(font,"z");
      atlasStyle->SetTitleFont(font,"z");

      atlasStyle->SetLabelSize(tsize,"x");
      atlasStyle->SetTitleSize(tsize,"x");
      atlasStyle->SetLabelSize(tsize,"y");
      atlasStyle->SetTitleSize(tsize,"y");
      atlasStyle->SetLabelSize(tsize,"z");
      atlasStyle->SetTitleSize(tsize,"z");

      // use bold lines and markers
      atlasStyle->SetMarkerStyle(20);
      atlasStyle->SetMarkerSize(1.2);
      atlasStyle->SetHistLineWidth(2.);
      atlasStyle->SetLineStyleString(2,"[12 12]"); // postscript dashes

      // get rid of X error bars
      //atlasStyle->SetErrorX(0.001);
      // get rid of error bar caps
      atlasStyle->SetEndErrorSize(0.);

      // do not display any of the standard histogram decorations
      atlasStyle->SetOptTitle(0);
      //atlasStyle->SetOptStat(1111);
      atlasStyle->SetOptStat(0);
      //atlasStyle->SetOptFit(1111);
      atlasStyle->SetOptFit(0);

      // put tick marks on top and RHS of plots
      atlasStyle->SetPadTickX(1);
      atlasStyle->SetPadTickY(1);

      return atlasStyle;

}

/**
 * @brief Function inherited from rcdaq. Set the ATLAS style.
 */
void Visualizer::SetAtlasStyle(){

    static TStyle* atlasStyle = 0;
    std::cout << "\nApplying ATLAS style settings...\n" << std::endl ;
    if ( atlasStyle==0 ) atlasStyle = AtlasStyle();
    gROOT->SetStyle("ATLAS");
    gROOT->ForceStyle();

}


/** @brief OverlayHistos method for Visualizer
 *
 *  Plots two input histograms on the same, specified pad with
127
128
 *  separate axis. Draws two horizontal lines at +_line and -_line 
 *  if f _line is non-zero.
129
 *
130
131
132
133
 *  @param h1 - Base histogram (left y-axis)
 *  @param h2 - Overlayed histogram (right y-axis)
 *  @param pad - Address of a pad to be drawn on
 *  @param _line - y value for which a horizontal line will be drawn
134
 */
135
void Visualizer::OverlayHistos( TH1 *h1, TH1 *h2 , TVirtualPad* pad, float _line){
136
137
138
139
140
141
142

    // If there is no pad or no data in the histograms, return
    if( pad == nullptr ) {std::cerr<< "WARNING: No pad to overlay histos onto" << std::endl; return;}
    if( !h1->GetMinimum() && !h1->GetMaximum()) {std::cerr << "WARNING: "<< h1->GetTitle() << " is empty. Can't overlay" << std::endl; return;}

    //Remove Stat box and double the y-axis range to include negative values
    gStyle->SetOptStat( kFALSE );
143
    h1->DrawCopy();
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
    h1->SetAxisRange( -h1->GetMaximum()*1.1, h1->GetMaximum()*1.1, "Y");
    pad->Update();

   //scale h2 to the pad coordinates
   float rightmax = 1.1*h2->GetMaximum();
   float scale = gPad->GetUymax()/rightmax;
   h2->SetLineColor( kRed );
   h2->Scale( scale );
   h2->DrawCopy( "same" );

   //draw an axis on the right side
   TGaxis axis( gPad->GetUxmax(), gPad->GetUymin(), gPad->GetUxmax(), gPad->GetUymax(), -rightmax, rightmax, 510, "+L");
   axis.SetLineColor( kRed );
   axis.SetLabelColor( kRed );
   axis.DrawClone();
159
160
161
162
163
164
165
166
167
168
   
   //Draw two horizontal lines
   if(_line != 0){
     TLine lineLow (0, -sRMS*scale, h1->GetNbinsX(), -sRMS*scale );
     TLine lineHigh(0,  sRMS*scale, h1->GetNbinsX(),  sRMS*scale );
     lineLow.SetLineColor ( kGreen );
     lineHigh.SetLineColor( kGreen );
     lineLow.DrawClone( );
     lineHigh.DrawClone( );
   }    
169
170
171
172
173
174

   //Rescale h2 back to the original size
   h2->Scale( 1/scale );
   if( m_debug ) pad->Print( Form( "%s_Overlay.pdf", h1->GetTitle() ) ) ;
}

Riccardo Longo's avatar
Riccardo Longo committed
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/**
 * @brief Implementation of Visualizer::ManyPadsPlot. This method takes two vector of histograms that needs to be treated in a peculiar way and
 * takes care of plot those together in a canvas with a given number of columns and rows.
 * @param _first_form - vector of the first type of histograms to be plotted
 * @param _second_form - vector of the second type of histograms to be plotted s
 * @param _ncol - number of columns of the canvas
 * @param _nrow - number of rows of the canvas
 * @param _out_name - name of the plot (w/o extension, that's defined by a data member [ .pdf by default ]
 * @param _treatment - treatment of the plots (at the moment only one available, overlay)
 */
void Visualizer::ManyPadsPlot( std::vector< TH1* > _first_form, std::vector< TH1* > _second_form, int _ncol, int _nrow, std::string _out_name, std::string _treatment){

    if(_treatment != "overlay" && _treatment != "OVERLAY" && _treatment != "Overlay"){
        std::cerr << "WARNING!!! You're looking for a treatment that has not been implemented yet! Please check it carefully" << std::endl;
        std::cerr << "Exiting w/o doing anything .." << std::endl;
        return;
    }

    if(_first_form.size() != _second_form.size())
        std::cerr << "WARNING!!! The two vectors of histograms "
                     "have different size. May result in a crash..." << std::endl;

    if( _first_form.size() < _ncol*_nrow ||  _second_form.size() < _ncol*_nrow )
        std::cerr << "WARNING!!! You have selected a vector of histrograms that will not fill all your pads"
                     "This may result in a crash..." << std::endl;

    if( _first_form.size() > _ncol*_nrow ||  _second_form.size() > _ncol*_nrow )
        std::cerr << "WARNING!!! You have selected a vector of histrograms that is bigger than the number of requested pads"
                     "This may result in histograms lost w/o plotting..." << std::endl;

    //This for the moment is hardcoded. Maybe can be moved to data member to have more general usage also for single plots.
    int squared_pad_size = 300;
    TCanvas* canv = new TCanvas( _out_name.c_str(),_out_name.c_str(),
                                 squared_pad_size*_ncol, squared_pad_size*_nrow);
    canv->Divide(_ncol,_nrow);
    for( int idraw = 0; idraw < _first_form.size(); idraw++){
        canv->cd(idraw+1);
        if( _treatment == "overlay" || _treatment != "OVERLAY" || _treatment != "Overlay" ){
            OverlayHistos( _first_form.at(idraw), _second_form.at(idraw), gPad);
        }
    }
    canv->Print(( _out_name + m_extension ).c_str());

}

220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/**
 * @brief Implementation of Visualizer::SinglePadPlot. This method takes two vectors of floats and plots them on a single pad with the requested "treatment".
 * Currently supports scatter plot and overlay
 * @param _v1 - vector of floats. Can represent x values for a scatter, or y values of a histogram
 * @param _v2 - vector of the second type of histograms to be plotted s
 * @param _out_name - name of the plot (w/o extension, that's defined by a data member [ .pdf by default ]
 * @param _treatment - treatment of the plots (scatter, overlay, overlay with lines)
 * @param _line - y value for which a horizontal line will be drawn
 */
void Visualizer::SinglePlot( std::vector< float > _v1, std::vector< float > _v2, std::string _out_name, std::string _treatment, float _line){
        
    if(_v1.size() != _v2.size())
    std::cerr << "WARNING!!! The two vectors have different size. "
                 "May result in a crash..." << std::endl;
                     
    int sw = -1;
    if( _treatment == "overlay" || _treatment != "OVERLAY" || _treatment != "Overlay" ) sw = 0;
    if( _treatment == "overlay with lines" || _treatment != "OVERLAY WITH LINES" || _treatment != "Overlay with lines" ) sw = 1;
    if( _treatment == "scatter" || _treatment != "SCATTER" || _treatment != "Scatter" ) sw = 2;
    
    if(sw == -1){
        std::cerr << "WARNING!!! You're looking for a treatment that has not been implemented yet! Please check it carefully" << std::endl;
        std::cerr << "Exiting w/o doing anything .." << std::endl;
        return;
    }
    
    int squared_pad_size = 300;
    TCanvas* canv = new TCanvas( _out_name.c_str(),_out_name.c_str(),
                                 squared_pad_size*_ncol, squared_pad_size*_nrow);
    canv->cd();
    
    if(sw == 0 || sw == 1){
        TH1D* h1 = new TH1D( _out_name.c_str(), _out_name.c_str(), _v1.size(), _v1.at(0), _v1.at(_v1.size()-1));
        TH1D* h2 = new TH1D( (_out_name + "(1)").c_str(), (_out_name + "(1)").c_str(), _v1.size(), _v2.at(0), _v2.at(_v1.size()-1));
        
        //Fill each histogram separately in case they are different sizes
        for(int bin = 0; bin < _v1.size(); bin++){
            h1->SetBinContent(bin,_v1.at(bin));
        }
        for(int bin = 0; bin < _v2.size(); bin++){
            h2->SetBinContent(bin,_v2.at(bin));
        }
        
        //Draw the overlayed histos either with or without lines, depending on the selection
        if(sw == 0) OverlayHistos( h1, h2, gpad);
        if(sw == 1) OverlayHistos( h1, h2, gpad, _line);
    }
    if(sw == 2){
        ScatterPlot(_v1, _v2, gpad);
    }
    
    canv->Print(( _out_name + m_extension ).c_str());
}

/** 
 * @brief Draws a scatter plot from two vectors 
 *
 * @param _vx - Vector of x values
 * @param _vy - Vector of y values
 * @param pad - Address of a pad to be drawn on
 */
void Visualizer::ScatterPlot( std::vector< float > _vx, std::vector< float > _vy, TVirtualPad* pad){
    //Declare TVectors using the input std::vectors
    TVector< float > _TVx( _vx.size(), &_vx[0]);
    TVector< float > _TVy( _vy.size(), &_vy[0]);
    
    TGraph g(_TVx, _TVy);
    g.DrawCopy("ap"); 
}