Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-08-28 03:58:38

0001 #include "GeometryComparisonPlotter.h"
0002 
0003 /***********************************************************************************/
0004 /*                            GEOMETRY COMPARISON PLOTTER                          */
0005 /* See the talk of 15 January 2015 for short documentation and the example script. */
0006 /* This code is highly commented if need be to upgrade it.                         */
0007 /* Any further question is to be asked to Patrick Connor (patrick.connor@desy.de). */
0008 /*                                             Thanks a million <3                 */
0009 /***********************************************************************************/
0010 
0011 // NOTE: look for "TO DO" as a keyword to now what should be upgraded in later versions....
0012 
0013 // modes
0014 #define TALKATIVE  // get some comments while processing
0015 //#define DEBUG     // get a lot of comments while processing + canvases -> resource-consuming!
0016 
0017 // MACROS
0018 #define INSIDE_VECTOR(vector)                          \
0019   cout << #vector << "={";                             \
0020   for (unsigned int i = 0; i < vector.size() - 1; i++) \
0021     cout << vector[i] << ",";                          \
0022   cout << vector.back() << "}";
0023 #define CHECK_MAP_CONTENT(m, type)                                       \
0024   for (map<TString, type>::iterator it = m.begin(); it != m.end(); it++) \
0025     cout << __FILE__ << ":" << __LINE__ << ":Info: " << #m << "[" << it->first << "]=" << it->second << endl;
0026 
0027 // CONSTRUCTOR AND DESTRUCTOR
0028 GeometryComparisonPlotter::GeometryComparisonPlotter(TString tree_file_name,
0029                                                      TString output_directory,
0030                                                      TString modulesToPlot,
0031                                                      TString alignmentName,
0032                                                      TString referenceName,
0033                                                      bool printOnlyGlobal,
0034                                                      bool makeProfilePlots)
0035     : _output_directory(output_directory + TString(output_directory.EndsWith("/") ? "" : "/")),
0036       _output_filename("comparison.root"),
0037       _print_option("pdf"),
0038       _module_plot_option(modulesToPlot),
0039       _alignment_name(alignmentName),
0040       _reference_name(referenceName),
0041       _print_only_global(printOnlyGlobal),
0042       _make_profile_plots(makeProfilePlots),
0043       _print(true),   // print the graphs in a file (e.g. pdf)
0044       _legend(true),  // print the graphs in a file (e.g. pdf)
0045       _write(true),   // write the graphs in a root file
0046       _batchMode(
0047 #ifdef DEBUG
0048           false  // false = display canvases (very time- and resource-consuming)
0049 #else
0050           true  // true = no canvases
0051 #endif
0052           ),
0053       _1dModule(true),           // cut on 1d modules
0054       _2dModule(true),           // cut on 2d modules
0055       _levelCut(DEFAULT_LEVEL),  // module level (see branch of same name)
0056       _grid_x(0),                // by default no display the grid in the canvases
0057       _grid_y(0),                // by default no display the grid in the canvases
0058       _window_width(DEFAULT_WINDOW_WIDTH),
0059       _window_height(DEFAULT_WINDOW_HEIGHT) {
0060 #ifdef TALKATIVE
0061   cout << ">>> TALKATIVE MODE ACTIVATED <<<" << endl;
0062 #endif
0063 #ifdef DEBUG
0064   cout << ">>> DEBUG MODE ACTIVATED <<<" << endl;
0065   cout << __FILE__ << ":" << __LINE__ << ":Info: inside constructor of GeometryComparisonPlotter utility" << endl;
0066 #endif
0067 
0068   //_sublevel_names = {"PXB", "PXF", "TIB", "TID", "TOB", "TEC"}; // C++11
0069   _sublevel_names[0] = TString("PXB");
0070   _sublevel_names[1] = TString("PXF");
0071   _sublevel_names[2] = TString("TIB");
0072   _sublevel_names[3] = TString("TID");
0073   _sublevel_names[4] = TString("TOB");
0074   _sublevel_names[5] = TString("TEC");
0075   // TO DO: handle other structures
0076 
0077   // read tree
0078   tree_file = new TFile(tree_file_name, "UPDATE");
0079   data = (TTree *)tree_file->Get("alignTree");
0080   // int branches
0081   data->SetBranchAddress("id", &branch_i["id"]);
0082   data->SetBranchAddress("inModuleList", &branch_i["inModuleList"]);
0083   data->SetBranchAddress("badModuleQuality", &branch_i["badModuleQuality"]);
0084   data->SetBranchAddress("mid", &branch_i["mid"]);
0085   data->SetBranchAddress("level", &branch_i["level"]);
0086   data->SetBranchAddress("mlevel", &branch_i["mlevel"]);
0087   data->SetBranchAddress("sublevel", &branch_i["sublevel"]);
0088   data->SetBranchAddress("useDetId", &branch_i["useDetId"]);
0089   data->SetBranchAddress("detDim", &branch_i["detDim"]);
0090   // float branches
0091   data->SetBranchAddress("x", &branch_f["x"]);
0092   data->SetBranchAddress("y", &branch_f["y"]);
0093   data->SetBranchAddress("z", &branch_f["z"]);
0094   data->SetBranchAddress("alpha", &branch_f["alpha"]);
0095   data->SetBranchAddress("beta", &branch_f["beta"]);
0096   data->SetBranchAddress("gamma", &branch_f["gamma"]);
0097   data->SetBranchAddress("phi", &branch_f["phi"]);
0098   data->SetBranchAddress("eta", &branch_f["eta"]);
0099   data->SetBranchAddress("r", &branch_f["r"]);
0100   data->SetBranchAddress("dx", &branch_f["dx"]);
0101   data->SetBranchAddress("dy", &branch_f["dy"]);
0102   data->SetBranchAddress("dz", &branch_f["dz"]);
0103   data->SetBranchAddress("dphi", &branch_f["dphi"]);
0104   data->SetBranchAddress("dr", &branch_f["dr"]);
0105   data->SetBranchAddress("dalpha", &branch_f["dalpha"]);
0106   data->SetBranchAddress("dbeta", &branch_f["dbeta"]);
0107   data->SetBranchAddress("dgamma", &branch_f["dgamma"]);
0108   if (data->GetBranch("rdphi") ==
0109       0x0)  // in the case of rdphi branch not existing, it is created from r and dphi branches
0110   {
0111 #ifdef TALKATIVE
0112     cout << __FILE__ << ":" << __LINE__
0113          << ":Info: computing the rdphi branch from r and dphi branches (assuming they exist...)" << endl;
0114 #endif
0115     TBranch *br_rdphi = data->Branch("rdphi", &branch_f["rdphi"], "rdphi/F");
0116     for (unsigned int ientry = 0; ientry < data->GetEntries(); ientry++) {
0117       data->GetEntry(ientry);
0118       branch_f["rdphi"] = branch_f["r"] * branch_f["dphi"];
0119       br_rdphi->Fill();
0120     }
0121   } else
0122     data->SetBranchAddress("rdphi", &branch_f["rdphi"]);
0123 
0124 #ifdef DEBUG
0125   cout << __FILE__ << ":" << __LINE__ << ":Info: branch addresses set" << endl;
0126 #endif
0127 
0128   // style
0129   gROOT->Reset();
0130 
0131   data->SetMarkerSize(0.5);
0132   data->SetMarkerStyle(6);
0133 
0134   gStyle->SetOptStat("emr");
0135   gStyle->SetTitleAlign(22);
0136   gStyle->SetTitleX(0.5);
0137   gStyle->SetTitleY(0.97);
0138   gStyle->SetTitleFont(62);
0139   //gStyle->SetOptTitle(0);
0140 
0141   gStyle->SetTextFont(132);
0142   gStyle->SetTextSize(0.08);
0143   gStyle->SetLabelFont(132, "x");
0144   gStyle->SetLabelFont(132, "y");
0145   gStyle->SetLabelFont(132, "z");
0146   gStyle->SetTitleSize(0.08, "x");
0147   gStyle->SetTitleSize(0.08, "y");
0148   gStyle->SetTitleSize(0.08, "z");
0149   gStyle->SetLabelSize(0.08, "x");
0150   gStyle->SetLabelSize(0.08, "y");
0151   gStyle->SetLabelSize(0.08, "z");
0152 
0153   gStyle->SetMarkerStyle(8);
0154   gStyle->SetHistLineWidth(2);
0155   gStyle->SetLineStyleString(2, "[12 12]");  // postscript dashes
0156 
0157   gStyle->SetFrameBorderMode(0);
0158   gStyle->SetCanvasBorderMode(0);
0159   gStyle->SetPadBorderMode(0);
0160   gStyle->SetPadColor(0);
0161   gStyle->SetCanvasColor(0);
0162   gStyle->SetTitleColor(1);
0163   gStyle->SetStatColor(0);
0164   gStyle->SetStatBorderSize(1);
0165   gStyle->SetFrameFillColor(0);
0166 
0167   gStyle->SetPadTickX(1);
0168   gStyle->SetPadTickY(1);
0169 
0170   gStyle->SetPadTopMargin(0.1);
0171   gStyle->SetPadRightMargin(0.05);
0172   gStyle->SetPadBottomMargin(0.16);
0173   gStyle->SetPadLeftMargin(0.18);
0174 
0175 #ifdef DEBUG
0176   cout << __FILE__ << ":" << __LINE__ << ":Info: end of constructor" << endl;
0177 #endif
0178 }
0179 
0180 GeometryComparisonPlotter::~GeometryComparisonPlotter() {
0181 #ifdef DEBUG
0182   cout << __FILE__ << ":" << __LINE__ << ":Info: in destructor of the GeometryComparisonPlotter utility" << endl;
0183 #endif
0184   tree_file->Close();
0185 #ifdef DEBUG
0186   cout << __FILE__ << ":" << __LINE__ << ":Info: ending." << endl;
0187 #endif
0188 }
0189 
0190 // MAIN METHOD
0191 void GeometryComparisonPlotter::MakePlots(
0192     vector<TString> x,    // axes to combine to plot
0193     vector<TString> y,    // every combination (except the ones such that x=y) will be perfomed
0194     vector<float> dyMin,  // Minimum of y-variable to enable fixed ranges of the histogram
0195     vector<float> dyMax)  // Minimum of y-variable
0196 {
0197   /// -1) check that only existing branches are called
0198   // (we use a macro to avoid copy/paste)
0199 #define CHECK_BRANCHES(branchname_vector)                                                                           \
0200   for (unsigned int i = 0; i < branchname_vector.size(); i++) {                                                     \
0201     if (branch_f.find(branchname_vector[i]) == branch_f.end()) {                                                    \
0202       cout << __FILE__ << ":" << __LINE__ << ":Error: The branch " << branchname_vector[i] << " is not recognised." \
0203            << endl;                                                                                                 \
0204       return;                                                                                                       \
0205     }                                                                                                               \
0206   }
0207   CHECK_BRANCHES(x);
0208   CHECK_BRANCHES(y);
0209 
0210   const unsigned int nentries = data->GetEntries();
0211 
0212 #ifdef TALKATIVE
0213   cout << __FILE__ << ":" << __LINE__ << ":Info: ";
0214   INSIDE_VECTOR(x);
0215   cout << endl << __FILE__ << ":" << __LINE__ << ":Info: ";
0216   INSIDE_VECTOR(y);
0217   cout << endl;
0218 #endif
0219 
0220   /// 0) min and max values
0221   // the max and min of the graphs are computed from the tree if they have not been manually input yet
0222   // (we use a macro to avoid copy/paste)
0223 #define LIMITS(axes_vector)                                                          \
0224   for (unsigned int i = 0; i < axes_vector.size(); i++) {                            \
0225     if (_SF.find(axes_vector[i]) == _SF.end())                                       \
0226       _SF[axes_vector[i]] = 1.;                                                      \
0227     if (_min.find(axes_vector[i]) == _min.end())                                     \
0228       _min[axes_vector[i]] = _SF[axes_vector[i]] * data->GetMinimum(axes_vector[i]); \
0229     if (_max.find(axes_vector[i]) == _max.end())                                     \
0230       _max[axes_vector[i]] = _SF[axes_vector[i]] * data->GetMaximum(axes_vector[i]); \
0231   }
0232   LIMITS(x);
0233   LIMITS(y);
0234 
0235 #ifdef TALKATIVE
0236   CHECK_MAP_CONTENT(_min, float);
0237   CHECK_MAP_CONTENT(_max, float);
0238   CHECK_MAP_CONTENT(_SF, float);
0239 #endif
0240 
0241   /// 1) declare TGraphs and Histograms for profile plots if these are to be plotted
0242   // the idea is to produce at the end a table of 8 TMultiGraphs and histograms:
0243   // - 0=Tracker, with color code for the different sublevels
0244   // - 1..6=different sublevels, with color code for z < or > 0
0245   // - 7=only pixel with color code for BPIX and FPIX
0246 
0247   // (convention: the six first (resp. last) correspond to z>0 (resp. z<0))
0248   // Modules with bad quality and in a list of modules that is given
0249   // by the user (e.g. list of bad/untouched modules, default: empty list)
0250   // are stored in seperate graphs and might be plotted (depends on the module
0251   // plot option, default: all modules plotted)
0252   // This means that 3*2*6 TGraphs will be filled during the loop on the TTree,
0253   // and will be arranged differently with different color codes in the TMultiGraphs
0254 
0255   // For the profile plots
0256   // Either all modules, only good modules or good modules + those in a given list will be plotted
0257   // This means that 2*6 TH2F will be filled during the loop on the TTree,
0258   // and will be arranged differently with different color codes in the Histograms
0259 #ifndef NB_SUBLEVELS
0260 #define NB_SUBLEVELS 6
0261 #endif
0262 #define NB_Z_SLICES 2
0263 #define NB_MODULE_QUALITY 3
0264 #define COLOR_CODE(icolor) int(icolor / 4) + icolor + 1
0265 
0266   TGraph *graphs[x.size()][y.size()][NB_SUBLEVELS * NB_Z_SLICES * NB_MODULE_QUALITY];
0267   long int ipoint[x.size()][y.size()][NB_SUBLEVELS * NB_Z_SLICES * NB_MODULE_QUALITY];
0268 
0269   TMultiGraph
0270       *mgraphs[x.size()][y.size()]
0271               [2 + NB_SUBLEVELS];  // the 0th is for global plots, the 1..6th for sublevel plots, 7th for pixel only
0272   TCanvas *c[x.size()][y.size()][2 + NB_SUBLEVELS], *c_global[2 + NB_SUBLEVELS];
0273   canvas_index++;  // this static index is a safety used in case the MakePlots method is used several times to avoid overloading
0274 
0275   // histograms for profile plots,
0276   // 2D-hists to store the data
0277   // 1D-hists to calculate mean and sigma of y-values for each x-bin of the 2D-hists and for the final profile hist
0278   TH2F *histos2D[x.size()][y.size()][NB_SUBLEVELS * NB_Z_SLICES];
0279   TH1F *histos[x.size()][y.size()][NB_SUBLEVELS * NB_Z_SLICES];
0280   TH1F *histosYValues[x.size()][y.size()]
0281                      [NB_SUBLEVELS * NB_Z_SLICES];  // Used to calculate the mean and RMS for each x-bin of the 2D-hist
0282   TH1F *histosTracker
0283       [x.size()][y.size()]
0284       [NB_SUBLEVELS *
0285        NB_Z_SLICES];  // for the tracker plots all histos are copied to avoid using the same hists in different canvas
0286 
0287   TCanvas *c_hist[x.size()][y.size()][2 + NB_SUBLEVELS], *c_global_hist[2 + NB_SUBLEVELS];
0288 
0289   unsigned int nXBins;  // Sensible number of x-bins differs depending on the variable
0290 
0291   for (unsigned int ic = 0; ic <= NB_SUBLEVELS + 1; ic++) {
0292     c_global[ic] = new TCanvas(
0293         TString::Format(
0294             "global_%s_%d", ic == 0 ? "tracker" : (ic == 7 ? "pixel" : _sublevel_names[ic - 1].Data()), canvas_index),
0295         TString::Format("Global overview of the %s variables",
0296                         ic == 0 ? "tracker" : (ic == 7 ? "pixel" : _sublevel_names[ic - 1].Data())),
0297         _window_width,
0298         _window_height);
0299     c_global[ic]->Divide(x.size(), y.size());
0300 
0301     if (_make_profile_plots) {
0302       c_global_hist[ic] =
0303           new TCanvas(TString::Format("global_profile_plots_%s_%d",
0304                                       ic == 0 ? "tracker" : (ic == 7 ? "pixel" : _sublevel_names[ic - 1].Data()),
0305                                       canvas_index),
0306                       TString::Format("Global overview profile plots of the %s variables",
0307                                       ic == 0 ? "tracker" : (ic == 7 ? "pixel" : _sublevel_names[ic - 1].Data())),
0308                       _window_width,
0309                       _window_height);
0310       c_global_hist[ic]->Divide(x.size(), y.size());
0311     }
0312   }
0313 
0314   for (unsigned int ix = 0; ix < x.size(); ix++) {
0315     for (unsigned int iy = 0; iy < y.size(); iy++) {
0316       //if (x[ix] == y[iy]) continue;       // do not plot graphs like (r,r) or (phi,phi)
0317       for (unsigned int igraph = 0; igraph < NB_SUBLEVELS * NB_Z_SLICES * NB_MODULE_QUALITY; igraph++) {
0318         // declaring
0319         ipoint[ix][iy][igraph] =
0320             0;  // the purpose of an index for every graph is to avoid thousands of points at the origin of each
0321         graphs[ix][iy][igraph] = new TGraph();
0322 
0323         graphs[ix][iy][igraph]->SetMarkerColor(COLOR_CODE(igraph));
0324         graphs[ix][iy][igraph]->SetMarkerStyle(6);
0325         // pimping
0326         graphs[ix][iy][igraph]->SetName(
0327             x[ix] + y[iy] + _sublevel_names[igraph % NB_SUBLEVELS] +
0328             TString(igraph % (NB_SUBLEVELS * NB_Z_SLICES) >= NB_SUBLEVELS ? "n"
0329                                                                           : "p")  // graphs for negative/positive  z
0330             + TString(igraph >= NB_SUBLEVELS * NB_Z_SLICES ? (igraph >= 2 * NB_SUBLEVELS * NB_Z_SLICES ? "bad" : "list")
0331                                                            : "good"));  // graphs for good, bad modules and from a list
0332         graphs[ix][iy][igraph]->SetTitle(
0333             _sublevel_names[igraph % NB_SUBLEVELS] +
0334             TString(igraph % (NB_SUBLEVELS * NB_Z_SLICES) >= NB_SUBLEVELS ? " at z<0" : " at z>=0") +
0335             TString(igraph >= NB_SUBLEVELS * NB_Z_SLICES
0336                         ? (igraph >= 2 * NB_SUBLEVELS * NB_Z_SLICES ? " bad modules" : " in list")
0337                         : " good modules") +
0338             TString(";") + LateXstyle(x[ix]) + " /" + _units[x[ix]] + TString(";") + LateXstyle(y[iy]) + " /" +
0339             _units[y[iy]]);
0340         graphs[ix][iy][igraph]->SetMarkerStyle(
0341             igraph >= NB_SUBLEVELS * NB_Z_SLICES
0342                 ? (igraph >= 2 * NB_SUBLEVELS * NB_Z_SLICES ? 4 : 5)
0343                 : 6);  // empty circle for bad modules, X for those in list, dot for good ones
0344       }
0345     }
0346   }
0347 
0348   // Use seperate loop for the profile histograms since we do not produce histograms for the different module qualities
0349   if (_make_profile_plots) {
0350     for (unsigned int ix = 0; ix < x.size(); ix++) {
0351       if (x[ix] == "phi")
0352         nXBins = 10;
0353       else
0354         nXBins = 40;
0355 
0356       for (unsigned int iy = 0; iy < y.size(); iy++) {
0357         for (unsigned int igraph = 0; igraph < NB_SUBLEVELS * NB_Z_SLICES; igraph++) {
0358           // declaring
0359           histos2D[ix][iy][igraph] =
0360               new TH2F("2Dhist" + x[ix] + y[iy] + _sublevel_names[igraph % NB_SUBLEVELS] +
0361                            TString(igraph % (NB_SUBLEVELS * NB_Z_SLICES) >= NB_SUBLEVELS ? "n" : "p") +
0362                            TString(std::to_string(canvas_index)),
0363                        "",
0364                        nXBins,
0365                        _min[x[ix]],
0366                        _max[x[ix]],
0367                        1000,
0368                        _min[y[iy]],
0369                        _max[y[iy]] + 1.);
0370         }
0371       }
0372     }
0373   }
0374 
0375 #ifdef DEBUG
0376   cout << __FILE__ << ":" << __LINE__ << ":Info: Creation of the TGraph[" << x.size() << "][" << y.size() << "]["
0377        << NB_SUBLEVELS * NB_Z_SLICES * NB_MODULE_QUALITY << "] ended." << endl;
0378 #endif
0379 
0380   /// 2) loop on the TTree data
0381 #ifdef DEBUG
0382   cout << __FILE__ << ":" << __LINE__ << ":Info: Looping on the TTree" << endl;
0383 #endif
0384 #ifdef TALKATIVE
0385   unsigned int progress = 0;
0386   cout << __FILE__ << ":" << __LINE__ << ":Info: 0%" << endl;
0387 #endif
0388   for (unsigned int ientry = 0; ientry < nentries; ientry++) {
0389 #ifdef TALKATIVE
0390     if (10 * ientry / nentries != progress) {
0391       progress = 10 * ientry / nentries;
0392       cout << __FILE__ << ":" << __LINE__ << ":Info: " << 10 * progress << "%" << endl;
0393     }
0394 #endif
0395     // load current tree entry
0396     data->GetEntry(ientry);
0397 
0398     // CUTS on entry
0399     if (branch_i["level"] != _levelCut)
0400       continue;
0401     if (!_1dModule && branch_i["detDim"] == 1)
0402       continue;
0403     if (!_2dModule && branch_i["detDim"] == 2)
0404       continue;
0405 
0406     // loop on the different couples of variables to plot in a graph
0407     for (unsigned int ix = 0; ix < x.size(); ix++) {
0408       // CUTS on x[ix]
0409       if (_SF[x[ix]] * branch_f[x[ix]] > _max[x[ix]] || _SF[x[ix]] * branch_f[x[ix]] < _min[x[ix]]) {
0410         //#ifdef DEBUG
0411         //                cout << "branch_f[x[ix]]=" << branch_f[x[ix]] << endl;
0412         //#endif
0413         continue;
0414       }
0415 
0416       for (unsigned int iy = 0; iy < y.size(); iy++) {
0417         // CUTS on y[iy]
0418         //if (x[ix] == y[iy])                                                   continue; // TO DO: handle display when such a case occurs
0419         if (branch_i["sublevel"] < 1 || branch_i["sublevel"] > NB_SUBLEVELS)
0420           continue;
0421 
0422         // FILLING histograms take even those outside the plotted range into account
0423         if (_make_profile_plots) {
0424           if (_module_plot_option == "all") {
0425             const short int igraph = (branch_i["sublevel"] - 1) + (branch_f["z"] >= 0 ? 0 : NB_SUBLEVELS);
0426             histos2D[ix][iy][igraph]->Fill(_SF[x[ix]] * branch_f[x[ix]], _SF[y[iy]] * branch_f[y[iy]]);
0427           } else if (_module_plot_option == "good" && branch_i["badModuleQuality"] == 0) {
0428             const short int igraph = (branch_i["sublevel"] - 1) + (branch_f["z"] >= 0 ? 0 : NB_SUBLEVELS);
0429             histos2D[ix][iy][igraph]->Fill(_SF[x[ix]] * branch_f[x[ix]], _SF[y[iy]] * branch_f[y[iy]]);
0430           } else if (_module_plot_option == "list" &&
0431                      (branch_i["inModuleList"] == 1 || branch_i["badModuleQuality"] == 0)) {
0432             const short int igraph = (branch_i["sublevel"] - 1) + (branch_f["z"] >= 0 ? 0 : NB_SUBLEVELS);
0433             histos2D[ix][iy][igraph]->Fill(_SF[x[ix]] * branch_f[x[ix]], _SF[y[iy]] * branch_f[y[iy]]);
0434           }
0435         }
0436 
0437         // restrict scatter plots to chosen range
0438         if (_SF[y[iy]] * branch_f[y[iy]] > _max[y[iy]] || _SF[y[iy]] * branch_f[y[iy]] < _min[y[iy]]) {
0439           //#ifdef DEBUG
0440           //                    cout << "branch_f[y[iy]]=" << branch_f[y[iy]] << endl;
0441           //#endif
0442           continue;
0443         }
0444 
0445         // FILLING GRAPH
0446         if (y.size() >= x.size()) {
0447           if (branch_i["inModuleList"] == 0 && branch_i["badModuleQuality"] == 0) {
0448             const short int igraph = (branch_i["sublevel"] - 1) + (branch_f["z"] >= 0 ? 0 : NB_SUBLEVELS);
0449             graphs[ix][iy][igraph]->SetPoint(
0450                 ipoint[ix][iy][igraph], _SF[x[ix]] * branch_f[x[ix]], _SF[y[iy]] * branch_f[y[iy]]);
0451             ipoint[ix][iy][igraph]++;
0452           }
0453           if (branch_i["inModuleList"] > 0) {
0454             const short int igraph =
0455                 (branch_i["sublevel"] - 1) + (branch_f["z"] >= 0 ? 0 : NB_SUBLEVELS) + NB_SUBLEVELS * NB_Z_SLICES;
0456             graphs[ix][iy][igraph]->SetPoint(
0457                 ipoint[ix][iy][igraph], _SF[x[ix]] * branch_f[x[ix]], _SF[y[iy]] * branch_f[y[iy]]);
0458             ipoint[ix][iy][igraph]++;
0459           }
0460           if (branch_i["badModuleQuality"] > 0) {
0461             const short int igraph =
0462                 (branch_i["sublevel"] - 1) + (branch_f["z"] >= 0 ? 0 : NB_SUBLEVELS) + 2 * NB_SUBLEVELS * NB_Z_SLICES;
0463             graphs[ix][iy][igraph]->SetPoint(
0464                 ipoint[ix][iy][igraph], _SF[x[ix]] * branch_f[x[ix]], _SF[y[iy]] * branch_f[y[iy]]);
0465             ipoint[ix][iy][igraph]++;
0466           }
0467         } else {
0468           if (branch_i["inModuleList"] == 0 && branch_i["badModuleQuality"] == 0) {
0469             const short int igraph = (branch_i["sublevel"] - 1) + (branch_f["z"] >= 0 ? 0 : NB_SUBLEVELS);
0470             graphs[iy][ix][igraph]->SetPoint(
0471                 ipoint[iy][ix][igraph], _SF[x[ix]] * branch_f[x[ix]], _SF[y[iy]] * branch_f[y[iy]]);
0472             ipoint[iy][ix][igraph]++;
0473           }
0474           if (branch_i["inModuleList"] > 0) {
0475             const short int igraph =
0476                 (branch_i["sublevel"] - 1) + (branch_f["z"] >= 0 ? 0 : NB_SUBLEVELS) + NB_SUBLEVELS * NB_Z_SLICES;
0477             graphs[iy][ix][igraph]->SetPoint(
0478                 ipoint[iy][ix][igraph], _SF[x[ix]] * branch_f[x[ix]], _SF[y[iy]] * branch_f[y[iy]]);
0479             ipoint[iy][ix][igraph]++;
0480           }
0481           if (branch_i["badModuleQuality"] > 0) {
0482             const short int igraph =
0483                 (branch_i["sublevel"] - 1) + (branch_f["z"] >= 0 ? 0 : NB_SUBLEVELS) + 2 * NB_SUBLEVELS * NB_Z_SLICES;
0484             graphs[iy][ix][igraph]->SetPoint(
0485                 ipoint[ix][iy][igraph], _SF[x[ix]] * branch_f[x[ix]], _SF[y[iy]] * branch_f[y[iy]]);
0486             ipoint[iy][ix][igraph]++;
0487           }
0488         }
0489       }
0490     }
0491   }
0492 #ifdef TALKATIVE
0493   cout << __FILE__ << ":" << __LINE__ << ":Info: 100%\tLoop ended" << endl;
0494 #endif
0495 
0496   /// 3) merge TGraph objects into TMultiGraph objects, then draw, print and write (according to the options _batchMode, _print and _write respectively)
0497   gROOT->SetBatch(_batchMode);  // if true, then equivalent to "root -b", i.e. no canvas
0498   if (_write) {                 // opening the file to write the graphs
0499     output = new TFile(_output_directory + TString(_output_filename),
0500                        "UPDATE");  // possibly existing file will be updated, otherwise created
0501     if (output->IsZombie()) {
0502       cout << __FILE__ << ":" << __LINE__ << ":Error: Opening of " << _output_directory + TString(_output_filename)
0503            << " failed" << endl;
0504       exit(-1);
0505     }
0506 #ifdef TALKATIVE
0507     cout << __FILE__ << ":" << __LINE__ << ":Info: output file is " << _output_directory + TString(_output_filename)
0508          << endl;
0509 #endif
0510   }
0511   // declaring TMultiGraphs and TCanvas
0512   // Usually more y variables than x variables
0513   // creating TLegend
0514   TLegend *legend = MakeLegend(.1, .92, .9, 1., NB_SUBLEVELS);
0515   if (_write)
0516     legend->Write();
0517 
0518   // check which modules are supposed to be plotted
0519   unsigned int n_module_types = 1;
0520   if (_module_plot_option == "all") {
0521     n_module_types = 3;  //plot all modules (good, list and bad )
0522   } else if (_module_plot_option == "list") {
0523     n_module_types = 2;  // plot good modules and those in the list
0524   } else if (_module_plot_option == "good") {
0525     n_module_types = 1;  // only plot the modules that are neither bad or in the list
0526   }
0527 
0528 #define INDEX_IN_GLOBAL_CANVAS(i1, i2) 1 + i1 + i2 *x.size()
0529   // running on the TGraphs to produce the TMultiGraph and draw/print them
0530   for (unsigned int ix = 0; ix < x.size(); ix++) {
0531 #ifdef DEBUG
0532     cout << __FILE__ << ":" << __LINE__ << ":Info: x[" << ix << "]=" << x[ix] << endl;
0533 #endif
0534 
0535     // looping on Y axes
0536     for (unsigned int iy = 0; iy < y.size(); iy++) {
0537 #ifdef DEBUG
0538       cout << __FILE__ << ":" << __LINE__ << ":Info: x[" << ix << "]=" << x[ix] << " and y[" << iy << "]=" << y[iy]
0539            << "\t-> creating TMultiGraph" << endl;
0540 #endif
0541       mgraphs[ix][iy][0] = new TMultiGraph(
0542           TString::Format("mgr_%s_vs_%s_tracker_%d",
0543                           x[ix].Data(),
0544                           y[iy].Data(),
0545                           canvas_index),  // name
0546           //LateXstyle(x[ix]) + TString(" vs. ") + LateXstyle(y[iy]) + TString(" for Tracker") // graph title
0547           TString(";") + LateXstyle(x[ix]) + " /" + _units[x[ix]]          // x axis title
0548               + TString(";") + LateXstyle(y[iy]) + " /" + _units[y[iy]]);  // y axis title
0549 
0550       mgraphs[ix][iy][7] = new TMultiGraph(
0551           TString::Format("mgr_%s_vs_%s_pixel_%d",
0552                           x[ix].Data(),
0553                           y[iy].Data(),
0554                           canvas_index),  // name
0555           //LateXstyle(x[ix]) + TString(" vs. ") + LateXstyle(y[iy]) + TString(" for Tracker") // graph title
0556           TString(";") + LateXstyle(x[ix]) + " /" + _units[x[ix]]          // x axis title
0557               + TString(";") + LateXstyle(y[iy]) + " /" + _units[y[iy]]);  // y axis title
0558 
0559       /// TRACKER and PIXEL
0560       // fixing ranges and filling TMultiGraph
0561       // for (unsigned short int jgraph = NB_SUBLEVELS*NB_Z_SLICES-1 ; jgraph >= 0 ; --jgraph)
0562       for (unsigned short int jgraph = 0; jgraph < NB_SUBLEVELS * NB_Z_SLICES * n_module_types; jgraph++) {
0563         unsigned short int igraph =
0564             NB_SUBLEVELS * NB_Z_SLICES * n_module_types - jgraph -
0565             1;  // reverse counting for humane readability (one of the sublevel takes much more place than the others)
0566 
0567 #ifdef DEBUG
0568         cout << __FILE__ << ":" << __LINE__ << ":Info: writing TGraph to file" << endl;
0569 #endif
0570         // write into root file
0571         if (_write)
0572           graphs[ix][iy][igraph]->Write();
0573         if (graphs[ix][iy][igraph]->GetN() == 0) {
0574 #ifdef TALKATIVE
0575           cout << __FILE__ << ":" << __LINE__ << ":Info: " << graphs[ix][iy][igraph]->GetName() << " is empty." << endl;
0576 #endif
0577           continue;
0578         }
0579 #ifdef DEBUG
0580         cout << __FILE__ << ":" << __LINE__ << ":Info: cloning, coloring and adding TGraph "
0581              << _sublevel_names[igraph % NB_SUBLEVELS] << (igraph >= NB_SUBLEVELS ? "(z<0)" : "(z>0)")
0582              << " to global TMultiGraph" << endl;
0583 #endif
0584         // clone to prevent any injure on the graph
0585         TGraph *gr = (TGraph *)graphs[ix][iy][igraph]->Clone();
0586         // color
0587         gr->SetMarkerColor(COLOR_CODE(igraph % NB_SUBLEVELS));
0588         mgraphs[ix][iy][0]->Add(gr, "P");  //, (mgraphs[ix][iy][0]->GetListOfGraphs()==0?"AP":"P"));
0589 
0590         if (igraph % NB_SUBLEVELS == 0 || igraph % NB_SUBLEVELS == 1)
0591           mgraphs[ix][iy][7]->Add(gr, "P");  // Add BPIX (0) and FPIX (1) to pixel plot
0592       }
0593 
0594       /// SUBLEVELS (1..6)
0595       for (unsigned int isublevel = 1; isublevel <= NB_SUBLEVELS; isublevel++) {
0596 #ifdef DEBUG
0597         cout << __FILE__ << ":" << __LINE__ << ":Info: cloning, coloring and adding TGraph "
0598              << _sublevel_names[isublevel - 1] << " to sublevel TMultiGraph" << endl;
0599 #endif
0600         mgraphs[ix][iy][isublevel] =
0601             new TMultiGraph(TString::Format("%s_vs_%s_%s_%d",
0602                                             x[ix].Data(),
0603                                             y[iy].Data(),
0604                                             _sublevel_names[isublevel - 1].Data(),
0605                                             canvas_index),  // name
0606                             //LateXstyle(x[ix]) + TString(" vs. ") + LateXstyle(y[iy]) + TString(" for ") +
0607                             _sublevel_names[isublevel - 1]                                   // graph title
0608                                 + TString(";") + LateXstyle(x[ix]) + " /" + _units[x[ix]]    // x axis title
0609                                 + TString(";") + LateXstyle(y[iy]) + " /" + _units[y[iy]]);  // y axis title
0610 
0611         graphs[ix][iy][isublevel - 1]->SetMarkerColor(kBlack);
0612         graphs[ix][iy][NB_SUBLEVELS + isublevel - 1]->SetMarkerColor(kRed);
0613         graphs[ix][iy][2 * NB_SUBLEVELS + isublevel - 1]->SetMarkerColor(kGray + 1);
0614         graphs[ix][iy][3 * NB_SUBLEVELS + isublevel - 1]->SetMarkerColor(kRed - 7);
0615         graphs[ix][iy][4 * NB_SUBLEVELS + isublevel - 1]->SetMarkerColor(kGray + 1);
0616         graphs[ix][iy][5 * NB_SUBLEVELS + isublevel - 1]->SetMarkerColor(kRed - 7);
0617         if (graphs[ix][iy][isublevel - 1]->GetN() > 0)
0618           mgraphs[ix][iy][isublevel]->Add(
0619               graphs[ix][iy][isublevel - 1],
0620               "P");  //(mgraphs[ix][iy][isublevel-1]->GetListOfGraphs()==0?"AP":"P")); // z>0
0621 #ifdef TALKATIVE
0622         else
0623           cout << __FILE__ << ":" << __LINE__
0624                << ":Info: graphs[ix][iy][isublevel-1]=" << graphs[ix][iy][isublevel - 1]->GetName()
0625                << " is empty -> not added into " << mgraphs[ix][iy][isublevel]->GetName() << endl;
0626 #endif
0627         if (graphs[ix][iy][NB_SUBLEVELS + isublevel - 1]->GetN() > 0)
0628           mgraphs[ix][iy][isublevel]->Add(
0629               graphs[ix][iy][NB_SUBLEVELS + isublevel - 1],
0630               "P");  //(mgraphs[ix][iy][isublevel-1]->GetListOfGraphs()==0?"AP":"P")); // z<0
0631 #ifdef TALKATIVE
0632         else
0633           cout << __FILE__ << ":" << __LINE__ << ":Info: graphs[ix][iy][NB_SUBLEVEL+isublevel-1]="
0634                << graphs[ix][iy][NB_Z_SLICES + isublevel - 1]->GetName() << " is empty -> not added into "
0635                << mgraphs[ix][iy][isublevel]->GetName() << endl;
0636 #endif
0637 #if NB_Z_SLICES != 2
0638         cout << __FILE__ << ":" << __LINE__ << ":Error: color code incomplete for Z slices..." << endl;
0639 #endif
0640         if (_module_plot_option == "all") {
0641           if (graphs[ix][iy][2 * NB_SUBLEVELS + isublevel - 1]->GetN() > 0)
0642             mgraphs[ix][iy][isublevel]->Add(graphs[ix][iy][2 * NB_SUBLEVELS + isublevel - 1], "P");
0643           if (graphs[ix][iy][3 * NB_SUBLEVELS + isublevel - 1]->GetN() > 0)
0644             mgraphs[ix][iy][isublevel]->Add(graphs[ix][iy][3 * NB_SUBLEVELS + isublevel - 1], "P");
0645           if (graphs[ix][iy][4 * NB_SUBLEVELS + isublevel - 1]->GetN() > 0)
0646             mgraphs[ix][iy][isublevel]->Add(graphs[ix][iy][4 * NB_SUBLEVELS + isublevel - 1], "P");
0647           if (graphs[ix][iy][5 * NB_SUBLEVELS + isublevel - 1]->GetN() > 0)
0648             mgraphs[ix][iy][isublevel]->Add(graphs[ix][iy][5 * NB_SUBLEVELS + isublevel - 1], "P");
0649         }
0650         if (_module_plot_option == "list") {
0651           if (graphs[ix][iy][2 * NB_SUBLEVELS + isublevel - 1]->GetN() > 0)
0652             mgraphs[ix][iy][isublevel]->Add(graphs[ix][iy][2 * NB_SUBLEVELS + isublevel - 1], "P");
0653           if (graphs[ix][iy][3 * NB_SUBLEVELS + isublevel - 1]->GetN() > 0)
0654             mgraphs[ix][iy][isublevel]->Add(graphs[ix][iy][3 * NB_SUBLEVELS + isublevel - 1], "P");
0655         }
0656       }
0657 
0658       // fixing ranges, saving, and drawing of TMultiGraph (tracker AND sublevels AND pixel, i.e. 2+NB_SUBLEVELS objects)
0659       // the individual canvases are saved, but the global are just drawn and will be saved later
0660       for (unsigned short int imgr = 0; imgr <= NB_SUBLEVELS + 1; imgr++) {
0661 #ifdef DEBUG
0662         cout << __FILE__ << ":" << __LINE__ << ":Info: treating individual canvases." << endl;
0663 #endif
0664         // drawing into individual canvas and printing it (including a legend for the tracker canvas)
0665         c[ix][iy][imgr] = new TCanvas(
0666             TString::Format("c_%s_vs_%s_%s_%d",
0667                             x[ix].Data(),
0668                             y[iy].Data(),
0669                             imgr == 0 ? "tracker" : (imgr == 7 ? "pixel" : _sublevel_names[imgr - 1].Data()),
0670                             canvas_index),
0671             TString::Format("%s vs. %s at %s level",
0672                             x[ix].Data(),
0673                             y[iy].Data(),
0674                             imgr == 0 ? "tracker" : (imgr == 7 ? "pixel" : _sublevel_names[imgr - 1].Data())),
0675             _window_width,
0676             _window_height);
0677         c[ix][iy][imgr]->SetGrid(_grid_x, _grid_y);  // grid
0678 
0679         if (mgraphs[ix][iy][imgr]->GetListOfGraphs() != 0) {
0680           if (dyMin[iy] != -99999) {
0681             mgraphs[ix][iy][imgr]->SetMinimum(dyMin[iy]);
0682           }
0683           if (dyMax[iy] != -99999) {
0684             mgraphs[ix][iy][imgr]->SetMaximum(dyMax[iy]);
0685           }
0686           mgraphs[ix][iy][imgr]->Draw("A");
0687         }
0688         if (imgr == 0 && _legend)
0689           legend->Draw();  // only for the tracker
0690         if (_print && !_print_only_global)
0691           c[ix][iy][imgr]->Print(
0692               _output_directory + mgraphs[ix][iy][imgr]->GetName() + ExtensionFromPrintOption(_print_option),
0693               _print_option);
0694 
0695         // writing into root file
0696         if (_write)
0697           mgraphs[ix][iy][imgr]->Write();
0698 
0699         // drawing into global canvas
0700         c_global[imgr]->cd(INDEX_IN_GLOBAL_CANVAS(ix, iy));
0701         c_global[imgr]->GetPad(INDEX_IN_GLOBAL_CANVAS(ix, iy))->SetFillStyle(4000);         //  make the pad transparent
0702         c_global[imgr]->GetPad(INDEX_IN_GLOBAL_CANVAS(ix, iy))->SetGrid(_grid_x, _grid_y);  // grid
0703         if (mgraphs[ix][iy][imgr]->GetListOfGraphs() != 0) {
0704           if (dyMin[iy] != -99999) {
0705             mgraphs[ix][iy][imgr]->SetMinimum(dyMin[iy]);
0706           }
0707           if (dyMax[iy] != -99999) {
0708             mgraphs[ix][iy][imgr]->SetMaximum(dyMax[iy]);
0709           }
0710           mgraphs[ix][iy][imgr]->Draw("A");
0711         }
0712         // printing will be performed after customisation (e.g. legend or title) just after the loops on ix and iy
0713       }
0714     }  // end of loop on y
0715   }    // end of loop on x
0716 
0717   // CUSTOMISATION
0718   gStyle->SetOptTitle(0);  // otherwise, the title is repeated in every pad of the global canvases
0719                            // -> instead, we will write it in the upper part in a TPaveText or in a TLegend
0720   for (unsigned int ic = 0; ic <= NB_SUBLEVELS + 1; ic++) {
0721     c_global[ic]->Draw();
0722 
0723     // setting legend to tracker canvases
0724     if (!_legend)
0725       break;
0726     TCanvas *c_temp = (TCanvas *)c_global[ic]->Clone(c_global[ic]->GetTitle() + TString("_sub"));
0727     c_temp->Draw();
0728     c_global[ic] = new TCanvas(
0729         c_temp->GetName() + TString("_final"), c_temp->GetTitle(), c_temp->GetWindowWidth(), c_temp->GetWindowHeight());
0730     c_global[ic]->Draw();
0731     TPad *p_up = new TPad(TString("legend_") + c_temp->GetName(),
0732                           "",
0733                           0.,
0734                           0.9,
0735                           1.,
0736                           1.,  // relative position
0737                           -1,
0738                           0,
0739                           0),  // display options
0740         *p_down = new TPad(TString("main_") + c_temp->GetName(), "", 0., 0., 1., 0.9, -1, 0, 0);
0741     // in the lower part, draw the plots
0742     p_down->Draw();
0743     p_down->cd();
0744     c_temp->DrawClonePad();
0745     c_global[ic]->cd();
0746     // in the upper part, pimp the canvas :p
0747     p_up->Draw();
0748     p_up->cd();
0749     if (ic == 0)  // tracker
0750     {
0751       TLegend *global_legend = MakeLegend(.05, .1, .7, .8, NB_SUBLEVELS);  //, "brNDC");
0752       global_legend->Draw();
0753       TPaveText *pt_geom = new TPaveText(.75, .1, .95, .8, "NB");
0754       pt_geom->SetFillColor(0);
0755       pt_geom->SetTextSize(0.25);
0756       pt_geom->AddText(TString("x: ") + _reference_name);
0757       pt_geom->AddText(TString("y: ") + _alignment_name + TString(" - ") + _reference_name);
0758       pt_geom->Draw();
0759     } else if (ic == 7)  // pixel
0760     {
0761       TLegend *global_legend = MakeLegend(.05, .1, .7, .8, 2);  //, "brNDC");
0762       global_legend->Draw();
0763       TPaveText *pt_geom = new TPaveText(.75, .1, .95, .8, "NB");
0764       pt_geom->SetFillColor(0);
0765       pt_geom->SetTextSize(0.25);
0766       pt_geom->AddText(TString("x: ") + _reference_name);
0767       pt_geom->AddText(TString("y: ") + _alignment_name + TString(" - ") + _reference_name);
0768       pt_geom->Draw();
0769     } else  // sublevels
0770     {
0771       TPaveText *pt = new TPaveText(.05, .1, .7, .8, "NB");
0772       pt->SetFillColor(0);
0773       pt->AddText(_sublevel_names[ic - 1]);
0774       pt->Draw();
0775       TPaveText *pt_geom = new TPaveText(.6, .1, .95, .8, "NB");
0776       pt_geom->SetFillColor(0);
0777       pt_geom->SetTextSize(0.3);
0778       pt_geom->AddText(TString("x: ") + _reference_name);
0779       pt_geom->AddText(TString("y: ") + _alignment_name + TString(" - ") + _reference_name);
0780       pt_geom->Draw();
0781     }
0782     // printing
0783     if (_print)
0784       c_global[ic]->Print(_output_directory + c_global[ic]->GetName() + ExtensionFromPrintOption(_print_option),
0785                           _print_option);
0786     if (_write)
0787       c_global[ic]->Write();
0788   }
0789 
0790   // printing global canvases
0791   if (_write)
0792     output->Close();
0793 
0794   // Now produce the profile plots if the option is chosen
0795   // Use seperate loops since no seperate plots are produced for different module qualities
0796   if (_make_profile_plots) {
0797     // Fill Content of 2D-hists into 1D-hists for the profile plots
0798     // Loop over all y-bins for a certain x-bin, calculate mean and RMS as entries of the 1D-hists
0799     bool entries = false;
0800     for (unsigned int ix = 0; ix < x.size(); ix++) {
0801       for (unsigned int iy = 0; iy < y.size(); iy++) {
0802         for (unsigned int igraph = 0; igraph < NB_SUBLEVELS * NB_Z_SLICES; igraph++) {
0803           // Declare hists which will be plotted for the profile plots
0804           histos[ix][iy][igraph] =
0805               new TH1F("1Dhist" + x[ix] + y[iy] + _sublevel_names[igraph % NB_SUBLEVELS] +
0806                            TString(igraph % (NB_SUBLEVELS * NB_Z_SLICES) >= NB_SUBLEVELS ? "n" : "p") +
0807                            TString(std::to_string(canvas_index)),
0808                        "",
0809                        histos2D[ix][iy][igraph]->GetXaxis()->GetNbins(),
0810                        _min[x[ix]],
0811                        _max[x[ix]]);
0812           histos[ix][iy][igraph]->SetMarkerColor(COLOR_CODE(igraph));
0813           histos[ix][iy][igraph]->SetLineColor(COLOR_CODE(igraph));
0814           histos[ix][iy][igraph]->StatOverflows(kTRUE);
0815 
0816           // Loop over x bins
0817           for (int binx = 0; binx <= histos2D[ix][iy][igraph]->GetXaxis()->GetNbins(); binx++) {
0818             entries = false;
0819             // Declare y-histogram for each x bin
0820             histosYValues[ix][iy][igraph] =
0821                 new TH1F("1Dhist_Y-Values" + x[ix] + y[iy] + _sublevel_names[igraph % NB_SUBLEVELS] +
0822                              TString(igraph % (NB_SUBLEVELS * NB_Z_SLICES) >= NB_SUBLEVELS ? "n" : "p") +
0823                              TString(std::to_string(canvas_index)) + TString(std::to_string(binx)),
0824                          "",
0825                          histos2D[ix][iy][igraph]->GetYaxis()->GetNbins(),
0826                          _min[y[iy]],
0827                          _max[y[iy]] + 1.);
0828             histosYValues[ix][iy][igraph]->StatOverflows(kTRUE);
0829             // Loop over y-bins for each x-bin of the 2D histogram and put it into the 1-d y histograms
0830             // Take overflow bin into account
0831             for (int biny = 0; biny <= histos2D[ix][iy][igraph]->GetYaxis()->GetNbins() + 1; biny++) {
0832               if (histos2D[ix][iy][igraph]->GetBinContent(binx, biny) > 1.) {
0833                 histosYValues[ix][iy][igraph]->SetBinContent(biny, histos2D[ix][iy][igraph]->GetBinContent(binx, biny));
0834                 entries = true;
0835               }
0836             }
0837             if (entries) {
0838               histos[ix][iy][igraph]->SetBinContent(binx, histosYValues[ix][iy][igraph]->GetMean());
0839               histos[ix][iy][igraph]->SetBinError(binx, histosYValues[ix][iy][igraph]->GetRMS());
0840             } else
0841               histos[ix][iy][igraph]->SetBinContent(binx, -999999.);
0842           }
0843         }
0844 
0845         // Customize and print the histograms
0846 
0847         /// TRACKER
0848         // fixing ranges and draw profile plot histos
0849 
0850         c_hist[ix][iy][0] =
0851             new TCanvas(TString::Format("c_hist_%s_vs_%s_tracker_%d", x[ix].Data(), y[iy].Data(), canvas_index),
0852                         TString::Format("Profile plot %s vs. %s at tracker level", x[ix].Data(), y[iy].Data()),
0853                         _window_width,
0854                         _window_height);
0855         c_hist[ix][iy][0]->SetGrid(_grid_x, _grid_y);  // grid
0856         // Draw the frame that will contain the histograms
0857         // One needs to specify the binning and title
0858         c_hist[ix][iy][0]->GetPad(0)->DrawFrame(_min[x[ix]],
0859                                                 dyMin[iy] != -99999 ? dyMin[iy] : _min[y[iy]],
0860                                                 _max[x[ix]],
0861                                                 dyMax[iy] != -99999 ? dyMax[iy] : _max[y[iy]],
0862                                                 TString(";") + LateXstyle(x[ix]) + " /" + _units[x[ix]] + TString(";") +
0863                                                     LateXstyle(y[iy]) + " /" + _units[y[iy]]);
0864         if (_legend)
0865           legend->Draw("same");
0866 
0867         for (unsigned short int jgraph = 0; jgraph < NB_SUBLEVELS * NB_Z_SLICES; jgraph++) {
0868           unsigned short int igraph =
0869               NB_SUBLEVELS * NB_Z_SLICES - jgraph -
0870               1;  // reverse counting for humane readability (one of the sublevel takes much more place than the others)
0871 
0872           // clone to prevent any injure on the graph
0873           histosTracker[ix][iy][igraph] = (TH1F *)histos[ix][iy][igraph]->Clone();
0874           // color
0875           histosTracker[ix][iy][igraph]->SetMarkerColor(COLOR_CODE(igraph % NB_SUBLEVELS));
0876           histosTracker[ix][iy][igraph]->SetLineColor(COLOR_CODE(igraph % NB_SUBLEVELS));
0877           histosTracker[ix][iy][igraph]->SetMarkerStyle(6);
0878           histosTracker[ix][iy][igraph]->Draw("same pe0");
0879         }
0880 
0881         if (_print && !_print_only_global)
0882           c_hist[ix][iy][0]->Print(
0883               _output_directory +
0884                   TString::Format("Profile_plot_%s_vs_%s_tracker_%d", x[ix].Data(), y[iy].Data(), canvas_index) +
0885                   ExtensionFromPrintOption(_print_option),
0886               _print_option);
0887 
0888         //Draw into profile hists global tracker canvas
0889         c_global_hist[0]->cd(INDEX_IN_GLOBAL_CANVAS(ix, iy));
0890         c_global_hist[0]->GetPad(INDEX_IN_GLOBAL_CANVAS(ix, iy))->SetFillStyle(4000);  //  make the pad transparent
0891         c_global_hist[0]->GetPad(INDEX_IN_GLOBAL_CANVAS(ix, iy))->SetGrid(_grid_x, _grid_y);  // grid
0892         c_global_hist[0]
0893             ->GetPad(INDEX_IN_GLOBAL_CANVAS(ix, iy))
0894             ->DrawFrame(_min[x[ix]],
0895                         dyMin[iy] != -99999 ? dyMin[iy] : _min[y[iy]],
0896                         _max[x[ix]],
0897                         dyMax[iy] != -99999 ? dyMax[iy] : _max[y[iy]],
0898                         TString(";") + LateXstyle(x[ix]) + " /" + _units[x[ix]] + TString(";") + LateXstyle(y[iy]) +
0899                             " /" + _units[y[iy]]);
0900 
0901         for (unsigned short int jgraph = 0; jgraph < NB_SUBLEVELS * NB_Z_SLICES; jgraph++) {
0902           unsigned short int igraph =
0903               NB_SUBLEVELS * NB_Z_SLICES - jgraph -
0904               1;  // reverse counting for humane readability (one of the sublevel takes much more place than the others)
0905           histosTracker[ix][iy][igraph]->Draw("same pe0");
0906         }
0907 
0908         /// PIXEL
0909         // fixing ranges and draw profile plot histos
0910 
0911         c_hist[ix][iy][7] =
0912             new TCanvas(TString::Format("c_hist_%s_vs_%s_pixel_%d", x[ix].Data(), y[iy].Data(), canvas_index),
0913                         TString::Format("Profile plot %s vs. %s at pixel level", x[ix].Data(), y[iy].Data()),
0914                         _window_width,
0915                         _window_height);
0916         c_hist[ix][iy][7]->SetGrid(_grid_x, _grid_y);  // grid
0917         // Draw the frame that will contain the histograms
0918         // One needs to specify the binning and title
0919         c_hist[ix][iy][7]->GetPad(0)->DrawFrame(_min[x[ix]],
0920                                                 dyMin[iy] != -99999 ? dyMin[iy] : _min[y[iy]],
0921                                                 _max[x[ix]],
0922                                                 dyMax[iy] != -99999 ? dyMax[iy] : _max[y[iy]],
0923                                                 TString(";") + LateXstyle(x[ix]) + " /" + _units[x[ix]] + TString(";") +
0924                                                     LateXstyle(y[iy]) + " /" + _units[y[iy]]);
0925         if (_legend)
0926           legend->Draw("same");
0927 
0928         for (unsigned short int jgraph = 0; jgraph < NB_SUBLEVELS * NB_Z_SLICES; jgraph++) {
0929           unsigned short int igraph =
0930               NB_SUBLEVELS * NB_Z_SLICES - jgraph -
0931               1;  // reverse counting for humane readability (one of the sublevel takes much more place than the others)
0932 
0933           if (igraph % NB_SUBLEVELS == 0 || igraph % NB_SUBLEVELS == 1)  //Only BPIX and FPIX
0934           {
0935             // clone to prevent any injure on the graph
0936             histosTracker[ix][iy][igraph] = (TH1F *)histos[ix][iy][igraph]->Clone();
0937             // color
0938             histosTracker[ix][iy][igraph]->SetMarkerColor(COLOR_CODE(igraph % NB_SUBLEVELS));
0939             histosTracker[ix][iy][igraph]->SetLineColor(COLOR_CODE(igraph % NB_SUBLEVELS));
0940             histosTracker[ix][iy][igraph]->SetMarkerStyle(6);
0941             histosTracker[ix][iy][igraph]->Draw("same pe0");
0942           }
0943         }
0944 
0945         if (_print && !_print_only_global)
0946           c_hist[ix][iy][7]->Print(
0947               _output_directory +
0948                   TString::Format("Profile_plot_%s_vs_%s_pixel_%d", x[ix].Data(), y[iy].Data(), canvas_index) +
0949                   ExtensionFromPrintOption(_print_option),
0950               _print_option);
0951 
0952         //Draw into profile hists global tracker canvas
0953         c_global_hist[7]->cd(INDEX_IN_GLOBAL_CANVAS(ix, iy));
0954         c_global_hist[7]->GetPad(INDEX_IN_GLOBAL_CANVAS(ix, iy))->SetFillStyle(4000);  //  make the pad transparent
0955         c_global_hist[7]->GetPad(INDEX_IN_GLOBAL_CANVAS(ix, iy))->SetGrid(_grid_x, _grid_y);  // grid
0956         c_global_hist[7]
0957             ->GetPad(INDEX_IN_GLOBAL_CANVAS(ix, iy))
0958             ->DrawFrame(_min[x[ix]],
0959                         dyMin[iy] != -99999 ? dyMin[iy] : _min[y[iy]],
0960                         _max[x[ix]],
0961                         dyMax[iy] != -99999 ? dyMax[iy] : _max[y[iy]],
0962                         TString(";") + LateXstyle(x[ix]) + " /" + _units[x[ix]] + TString(";") + LateXstyle(y[iy]) +
0963                             " /" + _units[y[iy]]);
0964 
0965         for (unsigned short int jgraph = 0; jgraph < NB_SUBLEVELS * NB_Z_SLICES; jgraph++) {
0966           unsigned short int igraph =
0967               NB_SUBLEVELS * NB_Z_SLICES - jgraph -
0968               1;  // reverse counting for humane readability (one of the sublevel takes much more place than the others)
0969           histosTracker[ix][iy][igraph]->Draw("same pe0");
0970         }
0971         // printing will be performed after customisation (e.g. legend or title) just after the loops on ix and iy
0972         /// SUBLEVELS (1..6)
0973         for (unsigned int isublevel = 1; isublevel <= NB_SUBLEVELS; isublevel++) {
0974           // Draw and print profile histograms
0975           c_hist[ix][iy][isublevel] =
0976               new TCanvas(TString::Format("c_hist_%s_vs_%s_%s_%d",
0977                                           x[ix].Data(),
0978                                           y[iy].Data(),
0979                                           isublevel == 0 ? "tracker" : _sublevel_names[isublevel - 1].Data(),
0980                                           canvas_index),
0981                           TString::Format("Profile plot %s vs. %s at %s level",
0982                                           x[ix].Data(),
0983                                           y[iy].Data(),
0984                                           isublevel == 0 ? "tracker" : _sublevel_names[isublevel - 1].Data()),
0985                           _window_width,
0986                           _window_height);
0987           c_hist[ix][iy][isublevel]->SetGrid(_grid_x, _grid_y);  // grid
0988           c_hist[ix][iy][isublevel]->GetPad(0)->DrawFrame(_min[x[ix]],
0989                                                           dyMin[iy] != -99999 ? dyMin[iy] : _min[y[iy]],
0990                                                           _max[x[ix]],
0991                                                           dyMax[iy] != -99999 ? dyMax[iy] : _max[y[iy]],
0992                                                           TString(";") + LateXstyle(x[ix]) + " /" + _units[x[ix]] +
0993                                                               TString(";") + LateXstyle(y[iy]) + " /" + _units[y[iy]]);
0994 
0995           histos[ix][iy][isublevel - 1]->SetMarkerColor(kBlack);
0996           histos[ix][iy][isublevel - 1]->SetLineColor(kBlack);
0997           histos[ix][iy][NB_SUBLEVELS + isublevel - 1]->SetMarkerColor(kRed);
0998           histos[ix][iy][NB_SUBLEVELS + isublevel - 1]->SetLineColor(kRed);
0999 
1000           histos[ix][iy][isublevel - 1]->Draw("same pe0");
1001           histos[ix][iy][NB_SUBLEVELS + isublevel - 1]->Draw("same pe0");
1002 
1003           if (_print && !_print_only_global)
1004             c_hist[ix][iy][isublevel]->Print(_output_directory +
1005                                                  TString::Format("Profile_plot_%s_vs_%s_%s_%d",
1006                                                                  x[ix].Data(),
1007                                                                  y[iy].Data(),
1008                                                                  _sublevel_names[isublevel - 1].Data(),
1009                                                                  canvas_index) +
1010                                                  ExtensionFromPrintOption(_print_option),
1011                                              _print_option);
1012 
1013           // draw into global canvas
1014           // printing will be performed after customisation (e.g. legend or title) just after the loops on ix and iy
1015           c_global_hist[isublevel]->cd(INDEX_IN_GLOBAL_CANVAS(ix, iy));
1016           c_global_hist[isublevel]
1017               ->GetPad(INDEX_IN_GLOBAL_CANVAS(ix, iy))
1018               ->SetFillStyle(4000);  //  make the pad transparent
1019           c_global_hist[isublevel]->GetPad(INDEX_IN_GLOBAL_CANVAS(ix, iy))->SetGrid(_grid_x, _grid_y);  // grid
1020           c_global_hist[isublevel]
1021               ->GetPad(INDEX_IN_GLOBAL_CANVAS(ix, iy))
1022               ->DrawFrame(_min[x[ix]],
1023                           dyMin[iy] != -99999 ? dyMin[iy] : _min[y[iy]],
1024                           _max[x[ix]],
1025                           dyMax[iy] != -99999 ? dyMax[iy] : _max[y[iy]],
1026                           TString(";") + LateXstyle(x[ix]) + " /" + _units[x[ix]] + TString(";") + LateXstyle(y[iy]) +
1027                               " /" + _units[y[iy]]);
1028 
1029           histos[ix][iy][isublevel - 1]->Draw("same pe0");
1030           histos[ix][iy][NB_SUBLEVELS + isublevel - 1]->Draw("same pe0");
1031         }
1032 
1033       }  // end of loop on y
1034     }    // end of loop on x
1035 
1036     // CUSTOMISATION
1037     gStyle->SetOptTitle(0);  // otherwise, the title is repeated in every pad of the global canvases
1038                              // -> instead, we will write it in the upper part in a TPaveText or in a TLegend
1039     for (unsigned int ic = 0; ic <= NB_SUBLEVELS; ic++) {
1040       // setting legend to tracker canvases
1041       if (!_legend)
1042         break;
1043 
1044       // setting legend to tracker canvases
1045       if (!_legend)
1046         break;
1047       TCanvas *c_temp_hist = (TCanvas *)c_global_hist[ic]->Clone(c_global_hist[ic]->GetTitle() + TString("_sub"));
1048       c_temp_hist->Draw();
1049       c_global_hist[ic] = new TCanvas(c_temp_hist->GetName() + TString("_final"),
1050                                       c_temp_hist->GetTitle(),
1051                                       c_temp_hist->GetWindowWidth(),
1052                                       c_temp_hist->GetWindowHeight());
1053       c_global_hist[ic]->Draw();
1054       TPad *p_up = new TPad(TString("legend_") + c_temp_hist->GetName(),
1055                             "",
1056                             0.,
1057                             0.9,
1058                             1.,
1059                             1.,  // relative position
1060                             -1,
1061                             0,
1062                             0),  // display options
1063           *p_down = new TPad(TString("main_") + c_temp_hist->GetName(), "", 0., 0., 1., 0.9, -1, 0, 0);
1064       // in the lower part, draw the plots
1065       p_down->Draw();
1066       p_down->cd();
1067       c_temp_hist->DrawClonePad();
1068       c_global_hist[ic]->cd();
1069       // in the upper part, pimp the canvas :p
1070       p_up->Draw();
1071       p_up->cd();
1072       if (ic == 0)  // tracker
1073       {
1074         TLegend *global_legend = MakeLegend(.05, .1, .7, .8, NB_SUBLEVELS);  //, "brNDC");
1075         global_legend->Draw();
1076         TPaveText *pt_geom = new TPaveText(.75, .1, .95, .8, "NB");
1077         pt_geom->SetFillColor(0);
1078         pt_geom->SetTextSize(0.25);
1079         pt_geom->AddText(TString("x: ") + _reference_name);
1080         pt_geom->AddText(TString("y: ") + _alignment_name + TString(" - ") + _reference_name);
1081         pt_geom->Draw();
1082       } else if (ic == 7)  // pixel
1083       {
1084         TLegend *global_legend = MakeLegend(.05, .1, .7, .8, 2);  //, "brNDC");
1085         global_legend->Draw();
1086         TPaveText *pt_geom = new TPaveText(.75, .1, .95, .8, "NB");
1087         pt_geom->SetFillColor(0);
1088         pt_geom->SetTextSize(0.25);
1089         pt_geom->AddText(TString("x: ") + _reference_name);
1090         pt_geom->AddText(TString("y: ") + _alignment_name + TString(" - ") + _reference_name);
1091         pt_geom->Draw();
1092       } else  // sublevels
1093       {
1094         TPaveText *pt = new TPaveText(.05, .1, .7, .8, "NB");
1095         pt->SetFillColor(0);
1096         pt->AddText(_sublevel_names[ic - 1]);
1097         pt->Draw();
1098         TPaveText *pt_geom = new TPaveText(.6, .1, .95, .8, "NB");
1099         pt_geom->SetFillColor(0);
1100         pt_geom->SetTextSize(0.3);
1101         pt_geom->AddText(TString("x: ") + _reference_name);
1102         pt_geom->AddText(TString("y: ") + _alignment_name + TString(" - ") + _reference_name);
1103         pt_geom->Draw();
1104       }
1105       // printing
1106       if (_print)
1107         c_global_hist[ic]->Print(
1108             _output_directory + c_global_hist[ic]->GetName() + ExtensionFromPrintOption(_print_option), _print_option);
1109     }
1110   }
1111 
1112 #ifdef TALKATIVE
1113   cout << __FILE__ << ":" << __LINE__ << ":Info: End of MakePlots method" << endl;
1114 #endif
1115 }
1116 
1117 // Make additional table for the mean/RMS values of differences
1118 void GeometryComparisonPlotter::MakeTables(
1119     vector<TString> x,    // axes to combine to plot
1120     vector<TString> y,    // only requires the differences (y values in the plots) and ranges
1121     vector<float> dyMin,  // Minimum of y-variable to enable fixed ranges of the histogram
1122     vector<float> dyMax)  // Maximum of y-variable to enable fixed ranges of the histogram
1123 {
1124   /// -1) check that only existing branches are called
1125   // (we use a macro to avoid copy/paste)
1126 #define CHECK_BRANCHES(branchname_vector)                                                                           \
1127   for (unsigned int i = 0; i < branchname_vector.size(); i++) {                                                     \
1128     if (branch_f.find(branchname_vector[i]) == branch_f.end()) {                                                    \
1129       cout << __FILE__ << ":" << __LINE__ << ":Error: The branch " << branchname_vector[i] << " is not recognised." \
1130            << endl;                                                                                                 \
1131       return;                                                                                                       \
1132     }                                                                                                               \
1133   }
1134   CHECK_BRANCHES(x);
1135   CHECK_BRANCHES(y);
1136 
1137   const unsigned int nentries = data->GetEntries();
1138 
1139 #ifdef TALKATIVE
1140   cout << __FILE__ << ":" << __LINE__ << ":Info: ";
1141   INSIDE_VECTOR(x);
1142   cout << endl;
1143   cout << __FILE__ << ":" << __LINE__ << ":Info: ";
1144   INSIDE_VECTOR(y);
1145   cout << endl;
1146 #endif
1147 
1148   /// 0) min and max values
1149   // the max and min of the graphs are computed from the tree if they have not been manually input yet
1150   // (we use a macro to avoid copy/paste)
1151 #define LIMITS(axes_vector)                                                          \
1152   for (unsigned int i = 0; i < axes_vector.size(); i++) {                            \
1153     if (_SF.find(axes_vector[i]) == _SF.end())                                       \
1154       _SF[axes_vector[i]] = 1.;                                                      \
1155     if (_min.find(axes_vector[i]) == _min.end())                                     \
1156       _min[axes_vector[i]] = _SF[axes_vector[i]] * data->GetMinimum(axes_vector[i]); \
1157     if (_max.find(axes_vector[i]) == _max.end())                                     \
1158       _max[axes_vector[i]] = _SF[axes_vector[i]] * data->GetMaximum(axes_vector[i]); \
1159   }
1160   LIMITS(x);
1161   LIMITS(y);
1162 
1163 #ifdef TALKATIVE
1164   CHECK_MAP_CONTENT(_min, float);
1165   CHECK_MAP_CONTENT(_max, float);
1166   CHECK_MAP_CONTENT(_SF, float);
1167 #endif
1168 
1169   /// 1) declare histograms
1170   // the idea is to produce tables of the differences and the absolute positions containing mean and RMS values
1171   // for the different subdetectors - 0..5=different sublevels.
1172   // Values for each endcap detector are to be split in +/-z, for the barrel detectors in +/- x (half barrels)
1173   // Since it is easier to handle in the loops, all subdetectors will be split in
1174   // 4 parts at first: (+/-x)X(+/-z)
1175   // This means that 2*2*6 histograms will be filled during the loop on the TTree
1176   // Pairs of histograms need to be combined afterwards again
1177   // Histograms 0-5 are at +x and +z, 6-11 at +x and -z, 12-17 at -x and +z, and 18-23 at -x and -z
1178   //
1179   // Two version of the table containing the differences are produced. Once using Gaussian fits (more stable
1180   // vs single outliers but perform poorly if the distributions are non-Gaussian) and once using
1181   // the mean and RMS of the histograms (more stable but outliers have a strong impact on the RMS).
1182   // For the absolute positions, only mean+RMS are used since the detector layout is not Gaussian
1183   // (structures due to layers/rings etc)
1184 #ifndef NB_SUBLEVELS
1185 #define NB_SUBLEVELS 6
1186 #endif
1187 #define NB_Z_SLICES 2
1188 #define NB_X_SLICES 2
1189 
1190   TH1F *histosx[x.size()][NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES];
1191   float meanValuex[x.size()][NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES];
1192   float RMSx[x.size()][NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES];
1193 
1194   TH1F *histos[y.size()][NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES];
1195   TF1 *gausFit[y.size()][NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES];
1196   float meanValue[y.size()][NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES];
1197   float meanValueGaussian[y.size()][NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES];
1198   float RMS[y.size()][NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES];
1199   float RMSGaussian[y.size()][NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES];
1200 
1201   for (unsigned int iy = 0; iy < y.size(); iy++) {
1202     for (unsigned int ihist = 0; ihist < NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES; ihist++) {
1203       // Create and correctly name a histogram for each subdetector*Z_Slice*X_Slice
1204       histos[iy][ihist] = new TH1F("hist" + y[iy] + _sublevel_names[ihist % NB_SUBLEVELS] +
1205                                        TString(ihist % (NB_SUBLEVELS * NB_Z_SLICES) >= NB_SUBLEVELS ? "zn" : "zp") +
1206                                        TString(ihist >= NB_SUBLEVELS * NB_Z_SLICES ? "xn" : "xp"),
1207                                    "",
1208                                    1000,
1209                                    _min[y[iy]],
1210                                    _max[y[iy]] + 1.);
1211       histos[iy][ihist]->StatOverflows(kTRUE);
1212     }
1213   }
1214 
1215   for (unsigned int ix = 0; ix < x.size(); ix++) {
1216     for (unsigned int ihist = 0; ihist < NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES; ihist++) {
1217       // Create and correctly name a histogram for each subdetector*Z_Slice*ModuleType
1218       histosx[ix][ihist] = new TH1F("histx" + x[ix] + _sublevel_names[ihist % NB_SUBLEVELS] +
1219                                         TString(ihist % (NB_SUBLEVELS * NB_Z_SLICES) >= NB_SUBLEVELS ? "zn" : "zp") +
1220                                         TString(ihist >= NB_SUBLEVELS * NB_Z_SLICES ? "xn" : "xp"),
1221                                     "",
1222                                     1000,
1223                                     _min[x[ix]],
1224                                     _max[x[ix]] + 1.);
1225       histosx[ix][ihist]->StatOverflows(kTRUE);
1226     }
1227   }
1228 
1229 #ifdef DEBUG
1230   cout << __FILE__ << ":" << __LINE__ << ":Info: Creation of the TH1F[" << y.size() << "]["
1231        << NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES << "] ended." << endl;
1232 #endif
1233 
1234   /// 2) loop on the TTree data
1235 #ifdef DEBUG
1236   cout << __FILE__ << ":" << __LINE__ << ":Info: Looping on the TTree" << endl;
1237 #endif
1238 #ifdef TALKATIVE
1239   unsigned int progress = 0;
1240   cout << __FILE__ << ":" << __LINE__ << ":Info: 0%" << endl;
1241 #endif
1242   for (unsigned int ientry = 0; ientry < nentries; ientry++) {
1243 #ifdef TALKATIVE
1244     if (10 * ientry / nentries != progress) {
1245       progress = 10 * ientry / nentries;
1246       cout << __FILE__ << ":" << __LINE__ << ":Info: " << 10 * progress << "%" << endl;
1247     }
1248 #endif
1249     // load current tree entry
1250     data->GetEntry(ientry);
1251 
1252     // CUTS on entry
1253     if (branch_i["level"] != _levelCut)
1254       continue;
1255     if (!_1dModule && branch_i["detDim"] == 1)
1256       continue;
1257     if (!_2dModule && branch_i["detDim"] == 2)
1258       continue;
1259 
1260     for (unsigned int iy = 0; iy < y.size(); iy++) {
1261       if (branch_i["sublevel"] < 1 || branch_i["sublevel"] > NB_SUBLEVELS)
1262         continue;
1263       if (_SF[y[iy]] * branch_f[y[iy]] > _max[y[iy]] || _SF[y[iy]] * branch_f[y[iy]] < _min[y[iy]]) {
1264         //#ifdef DEBUG
1265         //                    cout << "branch_f[y[iy]]=" << branch_f[y[iy]] << endl;
1266         //#endif
1267         continue;
1268       }
1269 
1270       // FILLING HISTOGRAMS
1271 
1272       // histogram for all modules
1273       const short int ihisto = (branch_i["sublevel"] - 1) + (branch_f["z"] >= 0 ? 0 : NB_SUBLEVELS) +
1274                                (branch_f["x"] >= 0 ? 0 : NB_SUBLEVELS * NB_Z_SLICES);
1275 
1276       if (_module_plot_option == "all")
1277         histos[iy][ihisto]->Fill(_SF[y[iy]] * branch_f[y[iy]]);
1278 
1279       // Only good modules
1280       else if (_module_plot_option == "good" && branch_i["badModuleQuality"] == 0)
1281         histos[iy][ihisto]->Fill(_SF[y[iy]] * branch_f[y[iy]]);
1282 
1283       // Only good modules and those in the list
1284       else if (_module_plot_option == "list" && (branch_i["inModuleList"] == 1 || branch_i["badModuleQuality"] == 0))
1285         histos[iy][ihisto]->Fill(_SF[y[iy]] * branch_f[y[iy]]);
1286     }
1287 
1288     for (unsigned int ix = 0; ix < x.size(); ix++) {
1289       if (branch_i["sublevel"] < 1 || branch_i["sublevel"] > NB_SUBLEVELS)
1290         continue;
1291       if (_SF[x[ix]] * branch_f[x[ix]] > _max[x[ix]] || _SF[x[ix]] * branch_f[x[ix]] < _min[x[ix]]) {
1292         //#ifdef DEBUG
1293         //                    cout << "branch_f[y[iy]]=" << branch_f[y[iy]] << endl;
1294         //#endif
1295         continue;
1296       }
1297 
1298       // FILLING HISTOGRAMS
1299 
1300       // histogram for all modules
1301       const short int ihistosx = (branch_i["sublevel"] - 1) + (branch_f["z"] >= 0 ? 0 : NB_SUBLEVELS) +
1302                                  (branch_f["x"] >= 0 ? 0 : NB_SUBLEVELS * NB_Z_SLICES);
1303 
1304       if (_module_plot_option == "all")
1305         histosx[ix][ihistosx]->Fill(_SF[x[ix]] * branch_f[x[ix]]);
1306 
1307       // Only good modules
1308       else if (_module_plot_option == "good" && branch_i["badModuleQuality"] == 0)
1309         histosx[ix][ihistosx]->Fill(_SF[x[ix]] * branch_f[x[ix]]);
1310 
1311       // Only good modules and those in the list
1312       else if (_module_plot_option == "list" && (branch_i["inModuleList"] == 1 || branch_i["badModuleQuality"] == 0))
1313         histosx[ix][ihistosx]->Fill(_SF[x[ix]] * branch_f[x[ix]]);
1314     }
1315   }
1316 #ifdef TALKATIVE
1317   cout << __FILE__ << ":" << __LINE__ << ":Info: 100%\tLoop ended" << endl;
1318 #endif
1319 
1320   //~ TString rangeLabel = "";
1321   // Calculate mean and standard deviation for each histogram
1322   for (unsigned int iy = 0; iy < y.size(); iy++) {
1323     for (unsigned int ihist = 0; ihist < NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES; ihist++) {
1324       // combine +/-z histograms for barrel detectors
1325       if (ihist % (NB_SUBLEVELS * NB_Z_SLICES) == 0 || ihist % (NB_SUBLEVELS * NB_Z_SLICES) == 2 ||
1326           ihist % (NB_SUBLEVELS * NB_Z_SLICES) == 4) {
1327         histos[iy][ihist]->Add(histos[iy][ihist + NB_SUBLEVELS]);
1328       }
1329       // combine +/-x histograms for endcap detectors (only used for half shells in barrel)
1330       if (ihist < NB_SUBLEVELS * NB_Z_SLICES &&
1331           (ihist % NB_SUBLEVELS == 1 || ihist % NB_SUBLEVELS == 3 || ihist % NB_SUBLEVELS == 5)) {
1332         histos[iy][ihist]->Add(histos[iy][ihist + NB_SUBLEVELS * NB_Z_SLICES]);
1333       }
1334       meanValue[iy][ihist] = histos[iy][ihist]->GetMean();
1335       RMS[iy][ihist] = histos[iy][ihist]->GetRMS();
1336 
1337       histos[iy][ihist]->Fit("gaus");
1338       gausFit[iy][ihist] = histos[iy][ihist]->GetFunction("gaus");
1339       meanValueGaussian[iy][ihist] = gausFit[iy][ihist]->GetParameter(1);
1340       RMSGaussian[iy][ihist] = gausFit[iy][ihist]->GetParameter(2);
1341     }
1342   }
1343 
1344   for (unsigned int ix = 0; ix < x.size(); ix++) {
1345     for (unsigned int ihist = 0; ihist < NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES; ihist++) {
1346       // combine +/-z histograms for barrel detectors
1347       if (ihist % (NB_SUBLEVELS * NB_Z_SLICES) == 0 || ihist % (NB_SUBLEVELS * NB_Z_SLICES) == 2 ||
1348           ihist % (NB_SUBLEVELS * NB_Z_SLICES) == 4) {
1349         histosx[ix][ihist]->Add(histosx[ix][ihist + NB_SUBLEVELS]);
1350       }
1351       // combine +/-x histograms for endcap detectors (only used for half shells in barrel)
1352       if (ihist < NB_SUBLEVELS * NB_Z_SLICES &&
1353           (ihist % NB_SUBLEVELS == 1 || ihist % NB_SUBLEVELS == 3 || ihist % NB_SUBLEVELS == 5)) {
1354         histosx[ix][ihist]->Add(histosx[ix][ihist + NB_SUBLEVELS * NB_Z_SLICES]);
1355       }
1356       meanValuex[ix][ihist] = histosx[ix][ihist]->GetMean();
1357       RMSx[ix][ihist] = histosx[ix][ihist]->GetRMS();
1358     }
1359   }
1360 
1361   TString tableFileName, tableCaption, tableAlign, tableHeadline;
1362   TString PXBpLine, PXBmLine, PXFpLine, PXFmLine, TIBpLine, TIBmLine, TOBpLine, TOBmLine, TIDpLine, TIDmLine, TECpLine,
1363       TECmLine;
1364 
1365   // table using mean and RMS, round to integers in µm etc.
1366   tableFileName = "table_differences.tex";
1367   if (_module_plot_option == "all")
1368     tableCaption = "Means and standard deviations of " + _alignment_name + " - " + _reference_name +
1369                    " for each subdetector, all modules used.";
1370   else if (_module_plot_option == "good")
1371     tableCaption = "Means and standard deviations of " + _alignment_name + " - " + _reference_name +
1372                    " for each subdetector, only good modules used.";
1373   else if (_module_plot_option == "list")
1374     tableCaption = "Means and standard deviations of " + _alignment_name + " - " + _reference_name +
1375                    " for each subdetector, good modules and those in given list used.";
1376 
1377   WriteTable(y, NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES, meanValue, RMS, "0", tableCaption, tableFileName);
1378 
1379   //~ // table using  Gaussian fit, round to integers in µm etc.
1380   tableFileName = "table_differences_Gaussian.tex";
1381   if (_module_plot_option == "all")
1382     tableCaption = "Means and standard deviations for Gaussian fit of " + _alignment_name + " - " + _reference_name +
1383                    " for each subdetector, all modules used.";
1384   else if (_module_plot_option == "good")
1385     tableCaption = "Means and standard deviations for Gaussian fit of " + _alignment_name + " - " + _reference_name +
1386                    " for each subdetector, only good modules used.";
1387   else if (_module_plot_option == "list")
1388     tableCaption = "Means and standard deviations for Gaussian fit of " + _alignment_name + " - " + _reference_name +
1389                    " for each subdetector, good modules and those in given list used.";
1390 
1391   WriteTable(
1392       y, NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES, meanValueGaussian, RMSGaussian, "0", tableCaption, tableFileName);
1393 
1394   // Table for the mean positions on the x-axis, round to 3 digits in cm etc.
1395   tableFileName = "table_meanPos.tex";
1396 
1397   if (_module_plot_option == "all")
1398     tableCaption = "Mean positions and standard deviations in " + _reference_name +
1399                    " geometry for each subdetector, all modules used.";
1400   else if (_module_plot_option == "good")
1401     tableCaption = "Mean positions and standard deviations in " + _reference_name +
1402                    " geometry for each subdetector, only good modules used.";
1403   else if (_module_plot_option == "list")
1404     tableCaption = "Mean positions and standard deviations in " + _reference_name +
1405                    " geometry for each subdetector, good modules and those in given list used.";
1406 
1407   WriteTable(x, NB_SUBLEVELS * NB_Z_SLICES * NB_X_SLICES, meanValuex, RMSx, "3", tableCaption, tableFileName);
1408 
1409 #ifdef TALKATIVE
1410   cout << __FILE__ << ":" << __LINE__ << ":Info: End of MakeLegends method" << endl;
1411 #endif
1412 }
1413 
1414 // OPTION METHODS
1415 void GeometryComparisonPlotter::SetPrint(const bool kPrint) { _print = kPrint; }
1416 void GeometryComparisonPlotter::SetLegend(const bool kLegend) { _legend = kLegend; }
1417 void GeometryComparisonPlotter::SetWrite(const bool kWrite) { _write = kWrite; }
1418 void GeometryComparisonPlotter::Set1dModule(const bool k1dModule) { _1dModule = k1dModule; }
1419 void GeometryComparisonPlotter::Set2dModule(const bool k2dModule) { _2dModule = k2dModule; }
1420 void GeometryComparisonPlotter::SetLevelCut(const int kLevelCut) { _levelCut = kLevelCut; }
1421 void GeometryComparisonPlotter::SetBatchMode(const bool kBatchMode) { _batchMode = kBatchMode; }
1422 void GeometryComparisonPlotter::SetGrid(const int kGridX, const int kGridY) {
1423   _grid_x = kGridX;
1424   _grid_y = kGridY;
1425 }
1426 void GeometryComparisonPlotter::SetBranchMax(const TString branchname, const float max) { _max[branchname] = max; }
1427 void GeometryComparisonPlotter::SetBranchMin(const TString branchname, const float min) { _min[branchname] = min; }
1428 void GeometryComparisonPlotter::SetBranchSF(const TString branchname, const float SF) { _SF[branchname] = SF; }
1429 void GeometryComparisonPlotter::SetBranchUnits(const TString branchname, const TString units) {
1430   _units[branchname] = units;
1431 }
1432 void GeometryComparisonPlotter::SetPrintOption(const Option_t *print_option) { _print_option = print_option; }
1433 void GeometryComparisonPlotter::SetCanvasSize(const int window_width, const int window_height) {
1434   _window_width = window_width;
1435   _window_height = window_height;
1436 }
1437 void GeometryComparisonPlotter::SetOutputFileName(const TString name) { _output_filename = name; }
1438 void GeometryComparisonPlotter::SetOutputDirectoryName(const TString name) {
1439   _output_directory = name + TString(name.EndsWith("/") ? "" : "/");
1440 }
1441 
1442 // PRIVATE METHODS
1443 TString GeometryComparisonPlotter::LateXstyle(TString word) {
1444   word.ToLower();
1445   if (word.BeginsWith("d"))
1446     word.ReplaceAll("d", "#Delta");
1447   if (word == TString("rdphi"))
1448     word = "r#Delta#phi";  // TO DO: find something less ad hoc...
1449   else if (word.EndsWith("phi"))
1450     word.ReplaceAll("phi", "#phi");
1451   else if (word.EndsWith("alpha"))
1452     word.ReplaceAll("alpha", "#alpha");
1453   else if (word.EndsWith("beta"))
1454     word.ReplaceAll("beta", "#beta");
1455   else if (word.EndsWith("gamma"))
1456     word.ReplaceAll("gamma", "#gamma");
1457   else if (word.EndsWith("eta"))
1458     word.ReplaceAll("eta", "#eta");
1459   return word;
1460 }
1461 
1462 TString GeometryComparisonPlotter::LateXstyleTable(TString word) {
1463   word.ToLower();
1464   if (word.BeginsWith("d"))
1465     word.ReplaceAll("d", "$\\Delta$");
1466   if (word == TString("rdphi"))
1467     word = "r$\\Delta\\phi$";  // TO DO: find something less ad hoc...
1468   else if (word.EndsWith("phi"))
1469     word.ReplaceAll("phi", "$\\phi$");
1470   else if (word.EndsWith("alpha"))
1471     word.ReplaceAll("alpha", "$\\alpha$");
1472   else if (word.EndsWith("beta"))
1473     word.ReplaceAll("beta", "$\\beta$");
1474   else if (word.EndsWith("gamma"))
1475     word.ReplaceAll("gamma", "#$\\gamma$");
1476   else if (word.EndsWith("eta"))
1477     word.ReplaceAll("eta", "$\\eta$");
1478   return word;
1479 }
1480 
1481 TString GeometryComparisonPlotter::ExtensionFromPrintOption(TString print_option) {
1482   if (print_option.Contains("pdf"))
1483     return TString(".pdf");
1484   else if (print_option.Contains("eps"))
1485     return TString(".eps");
1486   else if (print_option.Contains("ps"))
1487     return TString(".ps");
1488   else if (print_option.Contains("svg"))
1489     return TString(".svg");
1490   else if (print_option.Contains("tex"))
1491     return TString(".tex");
1492   else if (print_option.Contains("gif"))
1493     return TString(".gif");
1494   else if (print_option.Contains("xpm"))
1495     return TString(".xpm");
1496   else if (print_option.Contains("png"))
1497     return TString(".png");
1498   else if (print_option.Contains("jpg"))
1499     return TString(".jpg");
1500   else if (print_option.Contains("tiff"))
1501     return TString(".tiff");
1502   else if (print_option.Contains("cxx"))
1503     return TString(".cxx");
1504   else if (print_option.Contains("xml"))
1505     return TString(".xml");
1506   else if (print_option.Contains("root"))
1507     return TString(".root");
1508   else {
1509     cout << __FILE__ << ":" << __LINE__ << ":Warning: unknown format. Returning .pdf, but possibly wrong..." << endl;
1510     return TString(".pdf");
1511   }
1512 }
1513 
1514 TLegend *GeometryComparisonPlotter::MakeLegend(
1515     double x1, double y1, double x2, double y2, int nPlottedSublevels, const TString title) {
1516   TLegend *legend = new TLegend(x1, y1, x2, y2, title.Data(), "NBNDC");
1517   legend->SetNColumns(nPlottedSublevels);
1518   legend->SetFillColor(0);
1519   legend->SetLineColor(0);  // redundant with option
1520   legend->SetLineWidth(0);  // redundant with option
1521   for (int isublevel = 0; isublevel < nPlottedSublevels;
1522        isublevel++)  // nPlottedSublevels is either NB_SUBLEVELS for the tracker or 2 for the pixel
1523   {
1524     TGraph *g = new TGraph(0);
1525     g->SetMarkerColor(COLOR_CODE(isublevel));
1526     g->SetFillColor(COLOR_CODE(isublevel));
1527     g->SetMarkerStyle(kFullSquare);
1528     g->SetMarkerSize(10);
1529     legend->AddEntry(g, _sublevel_names[isublevel], "p");
1530   }
1531   return legend;
1532 }
1533 
1534 void GeometryComparisonPlotter::WriteTable(vector<TString> x,
1535                                            unsigned int nLevelsTimesSlices,
1536                                            float meanValue[10][24],
1537                                            float RMS[10][24],
1538                                            const TString nDigits,
1539                                            const TString tableCaption,
1540                                            const TString tableFileName) {
1541   std::ofstream output(_output_directory + tableFileName);
1542 
1543   TString tableAlign, tableHeadline;
1544   TString PXBpLine, PXBmLine, PXFpLine, PXFmLine, TIBpLine, TIBmLine, TOBpLine, TOBmLine, TIDpLine, TIDmLine, TECpLine,
1545       TECmLine;
1546   char meanChar[x.size()][nLevelsTimesSlices][10];
1547   char RMSChar[x.size()][nLevelsTimesSlices][10];
1548 
1549   tableAlign = "l";
1550   tableHeadline = "";
1551   PXBpLine = "PXB x$+$";
1552   PXBmLine = "PXB x$-$";
1553   PXFpLine = "PXF z$+$";
1554   PXFmLine = "PXF z$-$";
1555   TIBpLine = "TIB x$+$";
1556   TIBmLine = "TIB x$-$";
1557   TIDpLine = "TID z$+$";
1558   TIDmLine = "TID z$-$";
1559   TOBpLine = "TOB x$+$";
1560   TOBmLine = "TOB x$-$";
1561   TECpLine = "TEC z$+$";
1562   TECmLine = "TEC z$-$";
1563 
1564   for (unsigned int ix = 0; ix < x.size(); ix++) {
1565     for (unsigned int isubDet = 0; isubDet < nLevelsTimesSlices; isubDet++) {
1566       sprintf(meanChar[ix][isubDet], "%." + nDigits + "f", meanValue[ix][isubDet]);
1567       sprintf(RMSChar[ix][isubDet], "%." + nDigits + "f", RMS[ix][isubDet]);
1568     }
1569     tableAlign += "|c";
1570     tableHeadline += " & " + LateXstyleTable(x[ix]) + " / " + _units[x[ix]].ReplaceAll("#mum", "$\\mu$m");
1571 
1572     PXBpLine += " & $";
1573     PXBpLine += meanChar[ix][0];
1574     PXBpLine += "\\pm";
1575     PXBpLine += RMSChar[ix][0];
1576     PXBpLine += " $";
1577     PXBmLine += " & $";
1578     PXBmLine += meanChar[ix][12];
1579     PXBmLine += "\\pm";
1580     PXBmLine += RMSChar[ix][12];
1581     PXBmLine += " $";
1582     PXFpLine += " & $";
1583     PXFpLine += meanChar[ix][1];
1584     PXFpLine += "\\pm";
1585     PXFpLine += RMSChar[ix][1];
1586     PXFpLine += " $";
1587     PXFmLine += " & $";
1588     PXFmLine += meanChar[ix][7];
1589     PXFmLine += "\\pm";
1590     PXFmLine += RMSChar[ix][7];
1591     PXFmLine += " $";
1592     TIBpLine += " & $";
1593     TIBpLine += meanChar[ix][2];
1594     TIBpLine += "\\pm";
1595     TIBpLine += RMSChar[ix][2];
1596     TIBpLine += " $";
1597     TIBmLine += " & $";
1598     TIBmLine += meanChar[ix][14];
1599     TIBmLine += "\\pm";
1600     TIBmLine += RMSChar[ix][14];
1601     TIBmLine += " $";
1602     TIDpLine += " & $";
1603     TIDpLine += meanChar[ix][3];
1604     TIDpLine += "\\pm";
1605     TIDpLine += RMSChar[ix][3];
1606     TIDpLine += " $";
1607     TIDmLine += " & $";
1608     TIDmLine += meanChar[ix][9];
1609     TIDmLine += "\\pm";
1610     TIDmLine += RMSChar[ix][9];
1611     TIDmLine += " $";
1612     TOBpLine += " & $";
1613     TOBpLine += meanChar[ix][4];
1614     TOBpLine += "\\pm";
1615     TOBpLine += RMSChar[ix][4];
1616     TOBpLine += " $";
1617     TOBmLine += " & $";
1618     TOBmLine += meanChar[ix][16];
1619     TOBmLine += "\\pm";
1620     TOBmLine += RMSChar[ix][16];
1621     TOBmLine += " $";
1622     TECpLine += " & $";
1623     TECpLine += meanChar[ix][5];
1624     TECpLine += "\\pm";
1625     TECpLine += RMSChar[ix][5];
1626     TECpLine += " $";
1627     TECmLine += " & $";
1628     TECmLine += meanChar[ix][11];
1629     TECmLine += "\\pm";
1630     TECmLine += RMSChar[ix][11];
1631     TECmLine += " $";
1632   }
1633 
1634   // Write the table to the tex file
1635   output << "\\begin{table}" << std::endl;
1636   output << "\\caption{" << tableCaption << "}" << std::endl;
1637   output << "\\begin{tabular}{" << tableAlign << "}" << std::endl;
1638   output << "\\hline" << std::endl;
1639   output << tableHeadline << " \\\\" << std::endl;
1640   output << "\\hline" << std::endl;
1641   output << PXBpLine << " \\\\" << std::endl;
1642   output << PXBmLine << " \\\\" << std::endl;
1643   output << PXFpLine << " \\\\" << std::endl;
1644   output << PXFmLine << " \\\\" << std::endl;
1645   output << TIBpLine << " \\\\" << std::endl;
1646   output << TIBmLine << " \\\\" << std::endl;
1647   output << TIDpLine << " \\\\" << std::endl;
1648   output << TIDmLine << " \\\\" << std::endl;
1649   output << TOBpLine << " \\\\" << std::endl;
1650   output << TOBmLine << " \\\\" << std::endl;
1651   output << TECpLine << " \\\\" << std::endl;
1652   output << TECmLine << " \\\\" << std::endl;
1653   output << "\\hline" << std::endl;
1654   output << "\\end{tabular}" << std::endl;
1655   output << "\\end{table}" << std::endl;
1656 }