Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:45:46

0001 // Common style file for TkAl public plots
0002 // --------------------------------------------------------------
0003 // 
0004 // Defines a set of functions to define the plotting style and
0005 // provide commonly used style objects such as histogram title
0006 // and legends. Can be used in compiled code and uncompiled scripts.
0007 //
0008 // Always call TkAlStyle::set(PublicationStatus) in the beginning
0009 // of your plotting script to adjust the gStyle options. Also,
0010 // the behaviour of some other methods of this class depend on
0011 // this, e.g. the histogram title displays "CMS preliminary" etc.
0012 // depending on the PublicationStatus. Call TkAlStyle::set before
0013 // declaring any histograms (or call TH1::UseCurrentStyle()) to
0014 // make sure the style settings are used.
0015 // --------------------------------------------------------------
0016 
0017 #ifndef TKAL_STYLE_CC
0018 #define TKAL_STYLE_CC
0019 
0020 #include "TColor.h"
0021 #include "TError.h"
0022 #include "TLegend.h"
0023 #include "TPaveText.h"
0024 #include "TString.h"
0025 #include "TStyle.h"
0026 #include <iostream>
0027 
0028 
0029 // Publication status: determines what is plotted in title
0030 enum PublicationStatus { NO_STATUS, INTERNAL, INTERNAL_SIMULATION, PRELIMINARY, PUBLIC, SIMULATION, UNPUBLISHED, CUSTOM };
0031 TString toTString(const PublicationStatus status) {
0032   TString str = "";
0033   if(      status == NO_STATUS )           str = "Status not set yet!";
0034   else if( status == INTERNAL )            str = "internal";
0035   else if( status == INTERNAL_SIMULATION ) str = "simulation (internal)";
0036   else if( status == PRELIMINARY )         str = "preliminary";
0037   else if( status == PUBLIC      )         str = "public";
0038   else if( status == SIMULATION  )         str = "simulation (public)";
0039   else if( status == UNPUBLISHED )         str = "unpublished";
0040   else if( status == CUSTOM      )         str = "custom title set";
0041 
0042   return str;
0043 }
0044 
0045 
0046 // Data era: determines labels of data-taking periods, e.g. CRUZET
0047 enum Era { NONE, CRUZET15, CRAFT15, COLL0T15 };
0048 static TString toTString(const Era era) {
0049     TString str = "";
0050     if(      era == CRUZET15 ) str = "0T cosmic ray data 2015";
0051     else if( era == CRAFT15  ) str = "3.8T cosmic ray data 2015";
0052     else if( era == COLL0T15 ) str = "0T collision data 2015";
0053 
0054     return str;
0055 }
0056 
0057 
0058 class TkAlStyle {
0059 public:
0060   // Adjusts the gStyle settings and store the PublicationStatus
0061   static void set(const PublicationStatus status, const Era era = NONE, const TString customTitle = "", const TString customRightTitle = "");
0062   static void set(const TString customTitle);
0063   static PublicationStatus status() { return publicationStatus_; }
0064 
0065   // Draws a title "<CMS label> 2015" on the current pad
0066   // dependending on the PublicationStatus
0067   //  INTERNAL    : no extra label (intended for AN-only plots with data)
0068   //  INTERNAL    : show "Simulation" label (intended for AN-only plots, no "CMS")
0069   //  PRELIMINARY : show "CMS preliminary 2015" label
0070   //  PUBLIC      : show "CMS 2015" label
0071   //  SIMULATION  : show "CMS Simulation" label
0072   //  UNPUBLISHED : show "CMS (unpublished)" label (intended for additional material on TWiki)
0073   // Note that this method does not allow for easy memory
0074   // handling. For that, use standardTitle().
0075   static void drawStandardTitle() { standardTitle()->Draw("same"); standardRightTitle()->Draw("same"); }
0076   static void drawStandardTitle(const Era era) { standardTitle()->Draw("same"); standardRightTitle(era)->Draw("same"); }
0077 
0078   // Returns a TPaveText object that fits as a histogram title
0079   // with the current pad dimensions.
0080   // It has the same text as described in drawStandardTitle().
0081   // The idea of this method is that one has control over the
0082   // TPaveText object and can do proper memory handling.
0083   static TPaveText* standardTitle(PublicationStatus status) {
0084     return title(header(status));
0085   }
0086   static TPaveText* standardTitle() {
0087     return standardTitle(publicationStatus_);
0088   }
0089 
0090   static TPaveText* standardRightTitle(const Era era) {
0091     return righttitle(rightheader(era));
0092   }
0093   static TPaveText* standardRightTitle() {
0094     return standardRightTitle(era_);
0095   }
0096 
0097   // Returns a TPaveText object that fits as a histogram title
0098   // with the current pad dimensions and displays the specified text txt.
0099   static TPaveText* customTitle(const TString& txt) { return title(txt); }
0100   static TPaveText* customRightTitle(const TString& txt) { return righttitle(txt); }
0101 
0102   static TString legendheader;
0103   static TString legendoptions;
0104   static double textSize;
0105   // Returns a TLegend object that fits into the top-right corner
0106   // of the current pad. Its width, relative to the pad size (without
0107   // margins), can be specified. Its height is optimized for nEntries
0108   // entries.
0109   static TLegend* legend(const int nEntries, const double relWidth=0.5) {
0110     return legendTR(nEntries,relWidth);
0111   }
0112   static TLegend* legend(TString position, const int nEntries, const double relWidth=0.5) {
0113     position.ToLower();
0114     if( !( position.Contains("top") || position.Contains("bottom") ) )
0115       position += "top";
0116     if( !( position.Contains("left") || position.Contains("right") ) )
0117       position += "right";
0118     TLegend* leg = nullptr;
0119     if(        position.Contains("top")    && position.Contains("right") ) {
0120       leg = legendTR(nEntries,relWidth);
0121     } else if( position.Contains("top")    && position.Contains("left")  ) {
0122       leg = legendTL(nEntries,relWidth);
0123     } else if( position.Contains("bottom") && position.Contains("right") ) {
0124       leg = legendBR(nEntries,relWidth);
0125     } else if( position.Contains("bottom") && position.Contains("left")  ) {
0126       leg = legendBL(nEntries,relWidth);
0127     } else {
0128       leg = legendTR(nEntries,relWidth);
0129     }
0130 
0131     return leg;
0132   }
0133   // Same but explicitly state position on pad
0134   static TLegend* legendTL(const int nEntries, const double relWidth=0.5) {
0135     return legend(nEntries,relWidth,true,true);
0136   }
0137   static TLegend* legendTR(const int nEntries, const double relWidth=0.5) {
0138     return legend(nEntries,relWidth,false,true);
0139   }
0140   static TLegend* legendBL(const int nEntries, const double relWidth=0.5) {
0141     return legend(nEntries,relWidth,true,false);
0142   }
0143   static TLegend* legendBR(const int nEntries, const double relWidth=0.5) {
0144     return legend(nEntries,relWidth,false,false);
0145   }
0146 
0147 
0148   // Returns a TPaveText object that fits into the top-right corner
0149   // of the current pad and that can be used for additional labels.
0150   // Its width, relative to the pad size (without margins), can be
0151   // specified. Its height is optimized for nEntries entries.
0152   static TPaveText* label(const int nEntries, const double relWidth=0.5) {
0153     return labelTR(nEntries,relWidth);
0154   }
0155 
0156   static TPaveText* label(TString position, const int nEntries, const double relWidth=0.5) {
0157     position.ToLower();
0158     if( !( position.Contains("top") || position.Contains("bottom") ) )
0159       position += "top";
0160     if( !( position.Contains("left") || position.Contains("right") ) )
0161       position += "right";
0162     TPaveText* label = nullptr;
0163     if(        position.Contains("top")    && position.Contains("right") ) {
0164       label = labelTR(nEntries,relWidth);
0165     } else if( position.Contains("top")    && position.Contains("left")  ) {
0166       label = labelTL(nEntries,relWidth);
0167     } else if( position.Contains("bottom") && position.Contains("right") ) {
0168       label = labelBR(nEntries,relWidth);
0169     } else if( position.Contains("bottom") && position.Contains("left")  ) {
0170       label = labelBL(nEntries,relWidth);
0171     } else {
0172       label = labelTR(nEntries,relWidth);
0173     }
0174 
0175     return label;
0176   }
0177 
0178   // Same but explicitly state position on pad
0179   static TPaveText* labelTL(const int nEntries, const double relWidth=0.5) {
0180     return label(nEntries,relWidth,true,true);
0181   }
0182   static TPaveText* labelTR(const int nEntries, const double relWidth=0.5) {
0183     return label(nEntries,relWidth,false,true);
0184   }
0185   static TPaveText* labelBL(const int nEntries, const double relWidth=0.5) {
0186     return label(nEntries,relWidth,true,false);
0187   }
0188   static TPaveText* labelBR(const int nEntries, const double relWidth=0.5) {
0189     return label(nEntries,relWidth,false,false);
0190   }
0191 
0192 
0193   static double lineHeight() { return lineHeight_; }
0194 
0195 
0196 private:
0197   static PublicationStatus publicationStatus_;
0198   static Era era_;
0199   static TString customTitle_;
0200   static TString customRightTitle_;
0201   static double lineHeight_;
0202   static double margin_;
0203 
0204   // creates a title
0205   static TString applyCMS(const TString& txt);
0206   static TPaveText* title(const TString& txt);
0207   static TPaveText* righttitle(const TString& txt);
0208 
0209   // returns the standard-title (CMS label 2015) depending
0210   // on the PublicationStatus 
0211   static TString header(const PublicationStatus status);
0212   static TString rightheader(const Era era);
0213 
0214   // NDC coordinates for TPave, TLegend,...
0215   static void setXCoordinatesL(const double relWidth, double& x0, double& x1);
0216   static void setXCoordinatesR(const double relWidth, double& x0, double& x1);
0217   static void setYCoordinatesT(const int nEntries, double& y0, double& y1);
0218   static void setYCoordinatesB(const int nEntries, double& y0, double& y1);
0219 
0220   static TLegend* legend(const int nEntries, const double relWidth, const bool left, const bool top);
0221   static TPaveText* label(const int nEntries, const double relWidth, const bool leftt, const bool top);
0222 };
0223 
0224 PublicationStatus TkAlStyle::publicationStatus_ = NO_STATUS;
0225 Era TkAlStyle::era_ = NONE;
0226 TString TkAlStyle::legendheader = "";
0227 TString TkAlStyle::legendoptions = "all";
0228 TString TkAlStyle::customTitle_ = "";
0229 TString TkAlStyle::customRightTitle_ = "";
0230 double TkAlStyle::lineHeight_ = 0.042;
0231 double TkAlStyle::margin_ = 0.04;
0232 double TkAlStyle::textSize = 0.035;
0233 
0234 
0235 // --------------------------------------------------------------
0236 void TkAlStyle::setXCoordinatesL(const double relWidth, double& x0, double& x1) {
0237   x0 = gStyle->GetPadLeftMargin()+margin_;
0238   x1 = x0 + relWidth*(1.-gStyle->GetPadLeftMargin()-gStyle->GetPadRightMargin()-2.*margin_);
0239 }
0240 
0241 
0242 // --------------------------------------------------------------
0243 void TkAlStyle::setXCoordinatesR(const double relWidth, double& x0, double& x1) {
0244   x0 = 1.-gStyle->GetPadRightMargin()-margin_-relWidth*(1.-gStyle->GetPadLeftMargin()-gStyle->GetPadRightMargin()-2.*margin_);
0245   x1 = 1.-gStyle->GetPadRightMargin()-margin_;
0246 }
0247 
0248 
0249 // --------------------------------------------------------------
0250 void TkAlStyle::setYCoordinatesT(const int nEntries, double& y0, double& y1) {
0251   y1 = 1.-gStyle->GetPadTopMargin()-margin_;
0252   y0 = y1-nEntries*lineHeight_;
0253 }
0254 
0255 
0256 // --------------------------------------------------------------
0257 void TkAlStyle::setYCoordinatesB(const int nEntries, double& y0, double& y1) {
0258   y1 = gStyle->GetPadBottomMargin()+margin_;
0259   y0 = y1+nEntries*lineHeight_;
0260 }
0261 
0262 
0263 // --------------------------------------------------------------
0264 TLegend* TkAlStyle::legend(const int nEntries, const double relWidth, const bool left, const bool top) {
0265   double x0 = 0.;
0266   double x1 = 0.;
0267   double y0 = 0.;
0268   double y1 = 0.;
0269   bool hasheader = (TkAlStyle::legendheader != "");
0270   if( left ) setXCoordinatesL(relWidth,          x0,x1);
0271   else       setXCoordinatesR(relWidth,          x0,x1);
0272   if( top  ) setYCoordinatesT(nEntries+hasheader,y0,y1);
0273   else       setYCoordinatesB(nEntries+hasheader,y0,y1);
0274 
0275   TLegend* leg = new TLegend(x0,y0,x1,y1);
0276   leg->SetBorderSize(0);
0277   leg->SetFillColor(0);
0278   leg->SetFillStyle(0);
0279   leg->SetTextFont(42);
0280   leg->SetTextSize(textSize);
0281   if (hasheader) leg->SetHeader(TkAlStyle::legendheader);
0282 
0283   return leg;
0284 }
0285 
0286 
0287 // --------------------------------------------------------------
0288 TPaveText* TkAlStyle::label(const int nEntries, const double relWidth, const bool left, const bool top) {
0289   double x0 = 0.;
0290   double x1 = 0.;
0291   double y0 = 0.;
0292   double y1 = 0.;
0293   if( left ) setXCoordinatesL(relWidth,x0,x1);
0294   else       setXCoordinatesR(relWidth,x0,x1);
0295   if( top  ) setYCoordinatesT(nEntries,y0,y1);
0296   else       setYCoordinatesB(nEntries,y0,y1);
0297 
0298   TPaveText* label = new TPaveText(x0,y0,x1,y1,"NDC");
0299   label->SetBorderSize(0);
0300   label->SetFillColor(0);
0301   label->SetFillStyle(0);
0302   label->SetTextFont(42);
0303   label->SetTextAlign(12);  // left adjusted and vertically centered
0304   label->SetTextSize(textSize);
0305   label->SetMargin(0.);
0306 
0307   return label;
0308 }
0309 
0310 // --------------------------------------------------------------
0311 //unfortunately no #definecommand in TLatex...
0312 //#CMS{text} gives CMS in big bold, text in italics
0313 //#CMS with no "argument" just gives CMS in big bold
0314 //#noCMS{text} gives text in italics
0315 TString TkAlStyle::applyCMS(const TString& txt) {
0316   TString newtxt = txt;
0317   newtxt.ReplaceAll("#CMS{","#scale[1.4]{#font[61]{CMS}} #font[52]{");
0318   newtxt.ReplaceAll("#noCMS{","#font[52]{");
0319   newtxt.ReplaceAll("#CMS","#scale[1.4]{#font[61]{CMS}}");
0320   return newtxt;
0321 }
0322 
0323 
0324 // --------------------------------------------------------------
0325 TPaveText* TkAlStyle::title(const TString& txt) {
0326   double x0 = gStyle->GetPadLeftMargin();
0327   double x1 = 1.-gStyle->GetPadRightMargin();
0328   double y0 = 1.-gStyle->GetPadTopMargin();
0329   double y1 = 1.;
0330   if (txt.Contains("#CMS")) y0 += .02;
0331   TPaveText* theTitle = new TPaveText(x0,y0,x1,y1,"NDC");
0332   theTitle->SetBorderSize(0);
0333   theTitle->SetFillColor(10);
0334   theTitle->SetFillStyle(0);
0335   theTitle->SetTextFont(42);
0336   theTitle->SetTextAlign(13);   // left bottom adjusted
0337   theTitle->SetTextSize(0.038);
0338   theTitle->SetMargin(0.);
0339   theTitle->AddText(applyCMS(txt));
0340 
0341   return theTitle;
0342 }
0343 
0344 
0345 // --------------------------------------------------------------
0346 TPaveText* TkAlStyle::righttitle(const TString& txt) {
0347   TString newtxt = applyCMS(txt);
0348   double x0 = gStyle->GetPadLeftMargin();
0349   double x1 = 1.-gStyle->GetPadRightMargin();
0350   double y0 = 1.-gStyle->GetPadTopMargin();
0351   double y1 = 1.;
0352   TPaveText* theTitle = new TPaveText(x0,y0,x1,y1,"NDC");
0353   theTitle->SetBorderSize(0);
0354   theTitle->SetFillColor(10);
0355   theTitle->SetFillStyle(0);
0356   theTitle->SetTextFont(42);
0357   theTitle->SetTextAlign(33);   // right bottom adjusted
0358   theTitle->SetTextSize(0.038);
0359   theTitle->SetMargin(0.);
0360   theTitle->AddText(newtxt);
0361   
0362   return theTitle;
0363 }
0364 
0365 
0366 // --------------------------------------------------------------
0367 TString TkAlStyle::header(const PublicationStatus status) {
0368   TString txt;
0369   if( status == NO_STATUS ) {
0370     std::cout << "Status not set yet!  Can't draw the title!" << std::endl;
0371   } else if( status == INTERNAL_SIMULATION ) {
0372     txt = "#noCMS{Simulation}";
0373   } else if( status == PRELIMINARY ) {
0374     txt = "#CMS{Preliminary}";
0375   } else if( status == PUBLIC ) {
0376     txt = "#CMS";
0377   } else if( status == SIMULATION ) {
0378     txt = "#CMS{Simulation}";
0379   } else if( status == UNPUBLISHED ) {
0380     txt = "#CMS{(unpublished)}";
0381   } else if( status == CUSTOM ) {
0382     txt = customTitle_;
0383   }
0384 
0385   return txt;
0386 }
0387 
0388 TString TkAlStyle::rightheader(const Era era)
0389 {
0390   TString txt = "";
0391   if( era != NONE ) {
0392     txt = toTString(era);
0393   } else {
0394     txt = customRightTitle_;
0395   }
0396   return txt;
0397 }
0398 
0399 
0400 // --------------------------------------------------------------
0401 void TkAlStyle::set(const PublicationStatus status, const Era era, const TString customTitle, const TString customRightTitle) {
0402   // Store the PublicationStatus for later usage, e.g. in the title
0403   publicationStatus_ = status;
0404   customTitle_ = customTitle;
0405   customRightTitle_ = customRightTitle;
0406   era_ = era;
0407   if (publicationStatus_ == CUSTOM && customTitle_ == "")
0408     std::cout << "Error: you are trying to use a custom title, but you don't provide it" << std::endl;
0409   if (publicationStatus_ != CUSTOM && customTitle_ != "")
0410     std::cout << "Error: you provide a custom title, but you don't indicate CUSTOM status.  Your title will not be used." << std::endl;
0411 
0412   // Suppress message when canvas has been saved
0413   gErrorIgnoreLevel = 1001;
0414 
0415   // Zero horizontal error bars
0416   gStyle->SetErrorX(0);
0417 
0418   //  For the canvas
0419   gStyle->SetCanvasBorderMode(0);
0420   gStyle->SetCanvasColor(kWhite);
0421   gStyle->SetCanvasDefH(800); //Height of canvas
0422   gStyle->SetCanvasDefW(800); //Width of canvas
0423   gStyle->SetCanvasDefX(0);   //Position on screen
0424   gStyle->SetCanvasDefY(0);
0425   
0426   //  For the frame
0427   gStyle->SetFrameBorderMode(0);
0428   gStyle->SetFrameBorderSize(10);
0429   gStyle->SetFrameFillColor(kBlack);
0430   gStyle->SetFrameFillStyle(0);
0431   gStyle->SetFrameLineColor(kBlack);
0432   gStyle->SetFrameLineStyle(0);
0433   gStyle->SetFrameLineWidth(2);
0434   gStyle->SetLineWidth(3);
0435     
0436   //  For the Pad
0437   gStyle->SetPadBorderMode(0);
0438   gStyle->SetPadColor(kWhite);
0439   gStyle->SetPadGridX(false);
0440   gStyle->SetPadGridY(false);
0441   gStyle->SetGridColor(0);
0442   gStyle->SetGridStyle(3);
0443   gStyle->SetGridWidth(1);
0444   
0445   //  Margins
0446   gStyle->SetPadTopMargin(0.08);
0447   gStyle->SetPadBottomMargin(0.13);
0448   gStyle->SetPadLeftMargin(0.16);
0449   gStyle->SetPadRightMargin(0.05);
0450 
0451   //  For the histo:
0452   gStyle->SetHistLineColor(kBlack);
0453   gStyle->SetHistLineStyle(0);
0454   gStyle->SetHistLineWidth(3);
0455   gStyle->SetMarkerSize(0.8);
0456   gStyle->SetEndErrorSize(4);
0457   gStyle->SetHatchesLineWidth(1);
0458 
0459   //  For the statistics box:
0460   gStyle->SetOptStat(0);
0461   
0462   //  For the axis
0463   gStyle->SetAxisColor(1,"XYZ");
0464   gStyle->SetTickLength(0.03,"XYZ");
0465   gStyle->SetNdivisions(510,"XYZ");
0466   gStyle->SetPadTickX(1);
0467   gStyle->SetPadTickY(1);
0468   gStyle->SetStripDecimals(kFALSE);
0469   
0470   //  For the axis labels and titles
0471   gStyle->SetTitleColor(1,"XYZ");
0472   gStyle->SetLabelColor(1,"XYZ");
0473   gStyle->SetLabelFont(42,"XYZ");
0474   gStyle->SetLabelOffset(0.007,"XYZ");
0475   gStyle->SetLabelSize(0.04,"XYZ");
0476   gStyle->SetTitleFont(42,"XYZ");
0477   gStyle->SetTitleSize(0.047,"XYZ");
0478   gStyle->SetTitleXOffset(1.2);
0479   gStyle->SetTitleYOffset(1.5);
0480 
0481   //  For the legend
0482   gStyle->SetLegendBorderSize(0);
0483 }
0484 
0485 void TkAlStyle::set(const TString customTitle)
0486 {
0487   set(CUSTOM, NONE, customTitle);
0488 }
0489 
0490 #endif