diff --git a/.github/workflows/softwarecheck.yml b/.github/workflows/softwarecheck.yml new file mode 100644 index 0000000..e610729 --- /dev/null +++ b/.github/workflows/softwarecheck.yml @@ -0,0 +1,52 @@ +name: Software_check +on: + push: + pull_request: + types: [opened] +jobs: + check_compile-job: + runs-on: ubuntu-latest + container: + image: cmscloud/al9-cms:latest + options: --user root + steps: + - name: Checking_out_code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Checking_python_3.9 + run: | + python3 -V + ls + pwd + python3 -m py_compile src/cmsstyle/cmsstyle.py + ls -lh src/cmsstyle/__pycache__/ + - name: Checking_Cpp_compilation + run: | + cd src + echo '{gROOT->LoadMacro("cmsstyle.C++");}' > hola.C + + dnf install -y root + echo 'ROOT VERSION='`root-config --version` + root -q hola.C + ls -lh cmsstyle_C.so +# + py2-job: + runs-on: ubuntu-latest + container: + image: cmscloud/cc7-cms:latest + options: --user root + steps: + - name: Checking_python_2.7 +# uses: actions/checkout@v4 +# with: +# fetch-depth: 0 + run: | + python -V + ls + git clone --depth 1 https://github.com/oglez/cmsstyle.git + cd cmsstyle + pwd + python -m py_compile src/cmsstyle/cmsstyle.py + ls -lh src/cmsstyle/cmsstyle.pyc +# diff --git a/.gitignore b/.gitignore index dc4d386..a4293ee 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ __pycache__/ # C extensions *.so +*.d +*.pcm # Distribution / packaging .Python diff --git a/scripts/setup_cmstyle b/scripts/setup_cmstyle new file mode 100644 index 0000000..2f7367c --- /dev/null +++ b/scripts/setup_cmstyle @@ -0,0 +1,44 @@ +# +# This script, to be run in bash to setup the CMSStyle for ROOT (C++ version) +# +# Called with +# source .../scripts/setup_cmstyle +# using the directory of the actual implementation we want to use of CMSStyle. +# +# Written by O. Gonzalez (2024_11_12) +# 2024_12_01 Changing the used directory for a real one. +# +fich_=${BASH_SOURCE[0]} + +if [ ".${fich_::1}" != "./" ] ; then # Relative directory + fich_="$PWD/${fich_}" +fi + +# Getting the simplest name of the directory +if [[ ${fich_:(-22):1} == "/" ]] ; then + cd ${fich_::-21} >& /dev/null +else # We are in scripts! + cd .. >& /dev/null +fi +export CMSSTYLE_DIR=`pwd -P` +cd - >& /dev/null + +echo "Using CMSStyle located in $CMSSTYLE_DIR" + +# Setting up the related variables: + +if [[ ! $ROOT_INCLUDE_PATH == *"${CMSSTYLE_DIR}/src"* ]]; then + export ROOT_INCLUDE_PATH=${CMSSTYLE_DIR}/src${ROOT_INCLUDE_PATH:+":$ROOT_INCLUDE_PATH"} +fi + +# We also put the same version for python, in case... +if [[ ".${PYTHONPATH}" != *"${CMSSTYLE_DIR}/src"* ]] ; then + export PYTHONPATH=${CMSSTYLE_DIR}/src${PYTHONPATH:+":$PYTHONPATH"} +fi +# +# Note: +# The following command allows to get the location of the CMSStyle that +# it is used/setup already for python: +# +# $ python3 -c "import cmsstyle ; print(cmsstyle.__file__)" +# diff --git a/src/TCmsCanvas.H b/src/TCmsCanvas.H new file mode 100644 index 0000000..1460ca8 --- /dev/null +++ b/src/TCmsCanvas.H @@ -0,0 +1,100 @@ +///@file +/// +/// This code contains the declaration and definition of the class TCmsCanvas +/// that inherits from a normal TCanvas en ROOT but keep track of created +/// objects that are not visible to the user, for its proper deletion as the +/// TCanvas is destroyed. +/// +///
+/// Written by O. Gonzalez (2024_11_12)
+/// 
+/// + +#ifndef CMSSTYLE_TCMSCANVAS__H_ +#define CMSSTYLE_TCMSCANVAS__H_ + +#include +#include + +#include + +namespace cmsstyle { + + +/// This is the class that CMSStyle (in the C++ version) uses to handle the +/// TCanvases that are defined to be plotted, but one has to keep in mind that +/// externally + +class TCmsCanvas : public TCanvas { + + // Internal variables (pointers to keep track) + + TASImage *CMS_logo; ///< CMS Logo when used in the TCanvas. + TPad *pad_logo; ///< TPad containing the CMS logo, when used. + + // Internal methods + + /// Initialization of the internal variables... + void Initialize (void) { + CMS_logo=nullptr; + pad_logo=nullptr; + } + +public: + + /// Normal constructor: It just creates the Canvas using the arguments and + /// the corresponding constructor method ot eh TCanvas. It also initializes + /// the values to keep track of when needed. + /// + /// Arguments: + /// name: Name of the created object + /// title: Title for the TCanvas + /// wtopx: X position of the top left corner of the canvas in pixels. + /// wtopy: Y position of the top left corner of the canvas in pixels + /// ww: the window size in pixels along X. + /// wh: the window size in pixels along Y. + /// + TCmsCanvas (const char *name, + const char *title, + Int_t wtopx, + Int_t wtopy, + Int_t ww, + Int_t wh) : TCanvas(name,title,wtopx,wtopy,ww,wh) { + Initialize(); + } + + /// Destructor of the class, as the most important object since it handles + /// the deletion of objects defined + ~TCmsCanvas () { + if (CMS_logo!=nullptr) delete CMS_logo; + if (pad_logo!=nullptr) delete pad_logo; + } + + + /// Method to draw the CMS Logo in the defined TCanvas in a TPad set at the indicated location + /// of the currently used TPad. + void AddCmsLogo (Float_t x0, Float_t y0, Float_t x1, Float_t y1, const char *logofile) + { + if (CMS_logo!=nullptr) delete CMS_logo; + CMS_logo = new TASImage(logofile); + + auto oldpad = gPad; + + if (pad_logo!=nullptr) delete pad_logo; + pad_logo = new TPad("logo", "logo", x0, y0, x1, y1); + pad_logo->Draw(); + pad_logo->cd(); + CMS_logo->Draw("X"); + pad_logo->Modified(); + + oldpad->cd(); + } + + + + +}; + +} // Namespace cmsstyle +#endif +///---------------------------------------------------------------------- diff --git a/src/cmsstyle.C b/src/cmsstyle.C new file mode 100644 index 0000000..5a5128f --- /dev/null +++ b/src/cmsstyle.C @@ -0,0 +1,588 @@ +/// @file +///
+/// This file contains the method associated to the CMSStyle package. It is the one to be used
+/// when compiling the version using any of the following command:
+///
+///       root[] .L cmsstyle.C++   (or equivalently with CompileMacro() or LoadMacro())
+///
+/// or simply from the command line (example to just compile)
+///       echo '{gROOT->LoadMacro("cmsstyle.C++");}' > /tmp/hola.C ; root -q /tmp/hola.C
+///
+/// but it can also be loaded from an interactive session of ROOT as
+///
+///       root[] .L cmsstyle.C
+///
+/// 
+ +#include "colorsets.H" + +#include "cmsstyle.H" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// Globals from ROOT + +extern TROOT *gROOT; +#include // Included definition of gPad + +namespace cmsstyle { + +// ---------------------------------------------------------------------- +void setCMSStyle (bool force) + // Method to setup the style for the ROOT session! +{ + if (cmsStyle!=nullptr) delete cmsStyle; // Starting from scratch! + + cmsStyle = new TStyle("cmsStyle", "Style for P-CMS"); + + gROOT->SetStyle(cmsStyle->GetName()); + gROOT->ForceStyle(force); + + // For the canvas: + + cmsStyle->SetCanvasBorderMode(0); + cmsStyle->SetCanvasColor(kWhite); + cmsStyle->SetCanvasDefH(600); // Height of canvas + cmsStyle->SetCanvasDefW(600); // Width of canvas + cmsStyle->SetCanvasDefX(0); // Position on screen + cmsStyle->SetCanvasDefY(0); + cmsStyle->SetPadBorderMode(0); + cmsStyle->SetPadColor(kWhite); + cmsStyle->SetPadGridX(kFALSE); + cmsStyle->SetPadGridY(kFALSE); + cmsStyle->SetGridColor(0); + cmsStyle->SetGridStyle(3); + cmsStyle->SetGridWidth(1); + + // For the frame: + cmsStyle->SetFrameBorderMode(0); + cmsStyle->SetFrameBorderSize(1); + cmsStyle->SetFrameFillColor(0); + cmsStyle->SetFrameFillStyle(0); + cmsStyle->SetFrameLineColor(1); + cmsStyle->SetFrameLineStyle(1); + cmsStyle->SetFrameLineWidth(1); + + // For the histo: + cmsStyle->SetHistLineColor(1); + cmsStyle->SetHistLineStyle(0); + cmsStyle->SetHistLineWidth(1); + cmsStyle->SetEndErrorSize(2); + cmsStyle->SetMarkerStyle(20); + + // For the fit/function: + cmsStyle->SetOptFit(1); + cmsStyle->SetFitFormat("5.4g"); + cmsStyle->SetFuncColor(2); + cmsStyle->SetFuncStyle(1); + cmsStyle->SetFuncWidth(1); + + // For the date: + cmsStyle->SetOptDate(0); + + // For the statistics box: + cmsStyle->SetOptFile(0); + cmsStyle->SetOptStat(0); // To display the mean and RMS: SetOptStat('mr') + cmsStyle->SetStatColor(kWhite); + cmsStyle->SetStatFont(42); + cmsStyle->SetStatFontSize(0.025); + cmsStyle->SetStatTextColor(1); + cmsStyle->SetStatFormat("6.4g"); + cmsStyle->SetStatBorderSize(1); + cmsStyle->SetStatH(0.1); + cmsStyle->SetStatW(0.15); + + // Margins: + cmsStyle->SetPadTopMargin(0.05); + cmsStyle->SetPadBottomMargin(0.13); + cmsStyle->SetPadLeftMargin(0.16); + cmsStyle->SetPadRightMargin(0.02); + + // For the Global title: + cmsStyle->SetOptTitle(0); + cmsStyle->SetTitleFont(42); + + cmsStyle->SetTitleColor(1); + cmsStyle->SetTitleTextColor(1); + cmsStyle->SetTitleFillColor(10); + cmsStyle->SetTitleFontSize(0.05); + + // For the axis titles: + cmsStyle->SetTitleColor(1, "XYZ"); + cmsStyle->SetTitleFont(42, "XYZ"); + cmsStyle->SetTitleSize(0.06, "XYZ"); + cmsStyle->SetTitleXOffset(0.9); + cmsStyle->SetTitleYOffset(1.25); + + // For the axis labels: + cmsStyle->SetLabelColor(1, "XYZ"); + cmsStyle->SetLabelFont(42, "XYZ"); + cmsStyle->SetLabelOffset(0.012, "XYZ"); + cmsStyle->SetLabelSize(0.05, "XYZ"); + + // For the axis: + cmsStyle->SetAxisColor(1, "XYZ"); + cmsStyle->SetStripDecimals(kTRUE); + cmsStyle->SetTickLength(0.03, "XYZ"); + cmsStyle->SetNdivisions(510, "XYZ"); + cmsStyle->SetPadTickX(1); // To get tick marks on the opposite side of the frame + cmsStyle->SetPadTickY(1); + + // Change for log plots: + cmsStyle->SetOptLogx(0); + cmsStyle->SetOptLogy(0); + cmsStyle->SetOptLogz(0); + + // Postscript options: + cmsStyle->SetPaperSize(20.0, 20.0); + cmsStyle->SetHatchesLineWidth(5); + cmsStyle->SetHatchesSpacing(0.05); + + // Some additional parameters we need to set as "style" + +#if (ROOT_VERSION_MAJOR>6 || (ROOT_VERSION_MINOR>=32 && ROOT_VERSION_MAJOR==6)) // Not available before 6.32! + TColor::DefinedColors(1); +#endif + + // Using the Style. + cmsStyle->cd(); +} + +// ---------------------------------------------------------------------- +void ResetCmsDescriptors (void) + // This method allows to reset all the values for the CMS-related dataset // descriptors to the default. +{ + cms_lumi = "Run 2, 138 fb^{#minus1}"; + cms_energy = "13 TeV"; + + cmsText = "CMS"; + extraText = "Preliminary"; + + additionalInfo.clear(); +} + +// ---------------------------------------------------------------------- +void SetEnergy (float energy, const std::string &unit) + // This methos sets the centre-of-mass energy value and unit to be displayed. +{ + if (energy==0) cms_energy=unit; + else { + if (fabs(energy-13)<0.001) cms_energy="13 "; + else if (fabs(energy-13.6)<0.001) cms_energy="13.6 "; + else { + std::cerr<<"ERROR: Unsupported value of the energy... use manual setting of the cms_energy value"< objs) + // Returns the maximum value associated to the objects that are going to be + // plotted. +{ + Float_t maxval=0; + + for (auto xobj : objs) { + if (xobj->InheritsFrom(TH1::Class())) { // An Histogram + Float_t value = ((TH1*) xobj)->GetBinContent(((TH1*) xobj)->GetMaximumBin()); + value += ((TH1*) xobj)->GetBinError(((TH1*) xobj)->GetMaximumBin()); + + if (maxvalInheritsFrom(TGraph::Class())) { + // TGraph are special as GetMaximum exists but it is a bug value. + Float_t value = 0; + + Int_t i = ((TGraph *) xobj)->GetN(); + Double_t *y = ((TGraph *) xobj)->GetY(); + Double_t *ey = ((TGraph *) xobj)->GetEY(); + + while (i>0) { + i -= 1; + + Float_t ivalue = y[i]; + ivalue += std::max(ey[i],((TGraph *) xobj)->GetErrorYhigh(i)); + } + + if (maxvalSetFillColor(0); + canv->SetBorderMode(0); + canv->SetFrameFillStyle(0); + canv->SetFrameBorderMode(0); + canv->SetLeftMargin(L / W + extraSpace); + + canv->SetRightMargin(R / W); + if (with_z_axis) canv->SetRightMargin(B / W + 0.03); + + canv->SetTopMargin(T / H); + canv->SetBottomMargin(B / H + 0.02); + + // Draw the frame for plotting things and set axis labels + TH1 *h = canv->DrawFrame(x_min, y_min, x_max, y_max); + + Float_t y_offset = 0.78; + if (yTitOffset<-998) { + y_offset = 0.78; + if (square) y_offset = 1.0; + } + else y_offset = yTitOffset; + + h->GetYaxis()->SetTitleOffset(y_offset); + h->GetXaxis()->SetTitleOffset(0.9); + h->GetXaxis()->SetTitle(nameXaxis); + h->GetYaxis()->SetTitle(nameYaxis); + h->Draw("AXIS"); + + // Draw CMS logo and update canvas + CMS_lumi(canv, iPos, scaleLumi); + + UpdatePad(canv); + canv->GetFrame()->Draw(); + + return canv; +} + +// ---------------------------------------------------------------------- +void CMS_lumi (TPad *ppad, Int_t iPosX, Float_t scaleLumi) + // This is the method to draw the "CMS" seal (logo and text) and put the + // luminosity value. +{ + /// This is the key method about forcing the CMSStyle. The original python + /// implementation was complicated and obscure, so rewritten here with a + /// cleaner coding. + + Float_t relPosX = 0.035; + Float_t relPosY = 0.035; + Float_t relExtraDY = 1.2; + + Bool_t outOfFrame = (int(iPosX / 10) == 0); + Int_t alignX_ = max(int(iPosX / 10), 1); + Int_t alignY_ = (iPosX==0)?1:3; + Int_t align_ = 10 * alignX_ + alignY_; + + Float_t H = ppad->GetWh() * ppad->GetHNDC(); + Float_t W = ppad->GetWw() * ppad->GetWNDC(); + Float_t l = ppad->GetLeftMargin(); + Float_t t = ppad->GetTopMargin(); + Float_t r = ppad->GetRightMargin(); + Float_t b = ppad->GetBottomMargin(); + Float_t outOfFrame_posY = 1 - t + lumiTextOffset * t; + + ppad->cd(); + + std::string lumiText(cms_lumi); + if (cms_energy != "") lumiText += " (" + cms_energy + ")"; + + //OLD if (scaleLumi) lumiText = ScaleText(lumiText, scaleLumi); + + drawText(lumiText.c_str(),1-r,outOfFrame_posY,42,31,lumiTextSize * t * scaleLumi); + + + // Now we go to the CMS message: + + Float_t posX_ = 0; + if (iPosX % 10 <= 1) posX_ = l + relPosX * (1 - l - r); + else if (iPosX % 10 == 2) posX_ = l + 0.5 * (1 - l - r); + else if (iPosX % 10 == 3) posX_ = 1 - r - relPosX * (1 - l - r); + + Float_t posY_ = 1 - t - relPosY * (1 - t - b); + + if (outOfFrame) { // CMS logo and extra text out of the frame + if (useCmsLogo.length()>0) { // Using CMS Logo instead of the text label (uncommon!) + + } + else { + if (cmsText.length()!=0) { + drawText(cmsText.c_str(),l,outOfFrame_posY,cmsTextFont,11,cmsTextSize * t); + // Checking position of the extraText after the CMS logo text. + Float_t scale=1; + if (W > H) scale = H/ float(W); // For a rectangle; + l += 0.043 * (extraTextFont * t * cmsTextSize) * scale; + } + + if (extraText.length()!=0) { // Only if something to write + drawText(extraText.c_str(),l,outOfFrame_posY,extraTextFont,align_,extraOverCmsTextSize * cmsTextSize * t); + } + } + } + else { // In the frame! + if (useCmsLogo.length()>0) { // Using CMS Logo instead of the text label + posX_ = l + 0.045 * (1 - l - r) * W / H; + posY_ = 1 - t - 0.045 * (1 - t - b); + // This is only for TCanvas! + addCmsLogo((TCmsCanvas*) ppad, posX_,posY_ - 0.15,posX_ + 0.15 * H / W,posY_); + } + else { + if (cmsText.length()!=0) { + drawText(cmsText.c_str(),posX_,posY_,cmsTextFont,align_,cmsTextSize * t); + // Checking position of the extraText after the CMS logo text. + posY_ -= relExtraDY * cmsTextSize * t; + } + if (extraText.length()!=0) { // Only if something to write + drawText(extraText.c_str(),posX_,posY_,extraTextFont,align_,extraOverCmsTextSize * cmsTextSize * t); + } + else posY_ += relExtraDY * cmsTextSize * t; // Preparing for additional text! + } + + for (UInt_t i=0; i confs) + +{ + + for ( auto xcnf : confs ) { + if (xcnf.first=="SetLineColor" || xcnf.first=="LineColor") dynamic_cast(obj)->SetLineColor(Int_t(xcnf.second+0.5)); + else if (xcnf.first=="SetLineStyle" || xcnf.first=="LineStyle") dynamic_cast(obj)->SetLineStyle(Int_t(xcnf.second+0.5)); + else if (xcnf.first=="SetLineWidth" || xcnf.first=="LineWidth") dynamic_cast(obj)->SetLineWidth(xcnf.second); + + else if (xcnf.first=="SetFillColor" || xcnf.first=="FillColor") dynamic_cast(obj)->SetFillColor(Int_t(xcnf.second+0.5)); + else if (xcnf.first=="SetFillStyle" || xcnf.first=="FillStyle") dynamic_cast(obj)->SetFillStyle(1001); //Int_t(xcnf.second+0.5)); + + else if (xcnf.first=="SetMarkerColor" || xcnf.first=="MarkerColor") dynamic_cast(obj)->SetMarkerColor(Int_t(xcnf.second+0.5)); + else if (xcnf.first=="SetMarkerSize" || xcnf.first=="MarkerSize") dynamic_cast(obj)->SetMarkerSize(xcnf.second); + else if (xcnf.first=="SetMarkerStyle" || xcnf.first=="MarkerStyle") dynamic_cast(obj)->SetMarkerStyle(Int_t(xcnf.second+0.5)); + + + + + } + + +} + +// ---------------------------------------------------------------------- +void cmsObjectDraw(TObject *obj, + Option_t *option, + std::map confs) + +{ + setRootObjectProperties(obj,confs); + + std::string prefix(option); + if (prefix.find("SAME")==std::string::npos) prefix=std::string("SAME")+prefix; + + obj->Draw(prefix.c_str()); + + + +} + +// ---------------------------------------------------------------------- +TLegend *cmsLeg(Float_t x1, Float_t y1, Float_t x2, Float_t y2, + Float_t textSize, + Style_t textFont, + Color_t textColor, + Int_t columns) + // This is the method to setup a legend according to the style! +{ + TLegend *leg = new TLegend(x1, y1, x2, y2, "", "brNDC"); + + leg->SetTextSize(textSize); + leg->SetTextFont(textFont); + leg->SetTextColor(textColor); + leg->SetBorderSize(0); + leg->SetFillStyle(0); + leg->SetFillColor(0); + + if (columns!=0) leg->SetNColumns(columns); + leg->Draw(); + + return leg; +} + +// ---------------------------------------------------------------------- +void drawText(const char *text, Float_t posX, Float_t posY, + Font_t font, Short_t align, Float_t size) + // This is a method to write a Text in a simplified and straightforward // (i.e. user-friendly) way. +{ + TLatex latex; + latex.SetNDC(); + latex.SetTextAngle(0); + latex.SetTextColor(kBlack); + + latex.SetTextFont(font); + latex.SetTextAlign(align); + latex.SetTextSize(size); + + latex.DrawLatex(posX, posY, text); +} + +// ---------------------------------------------------------------------- +void addCmsLogo (TCmsCanvas *canv,Float_t x0, Float_t y0, Float_t x1, Float_t y1, const char *logofile) + // This is a method to draw the CMS logo (that should be set using the + // corresponding method or on the fly) in a TPad set at the indicated location + // of the currently used TPad. +{ + if (logofile!=nullptr) { + SetCmsLogoFilename(logofile); // Trying to load the file) + } + + if (useCmsLogo.length()==0) { + std::cerr<<"ERROR: Not possible to add the CMS Logo as the file is not properly defined (not found?)"<AddCmsLogo(x0,y0,x1,y1,useCmsLogo.c_str()); + UpdatePad(); // For gPad +} + +// ---------------------------------------------------------------------- +// ---------------------------------------------------------------------- + + + +// ---------------------------------------------------------------------- +void UpdatePad (TPad *ppad) + // This method updates the provided TPad or TCanvas. +{ + if (ppad==nullptr) { + gPad->RedrawAxis(); + gPad->Modified(); + gPad->Update(); + } + else { + ppad->RedrawAxis(); + ppad->Modified(); + ppad->Update(); + } +} + +// ---------------------------------------------------------------------- +TH1 *GetcmsCanvasHist (TPad *pcanv) + // This method returns the Frame object used to define the cmsCanvas (but it can be used also for any TPad). +{ + return (TH1*) pcanv->GetListOfPrimitives()->FindObject("hframe"); +} + +// ---------------------------------------------------------------------- +// ---------------------------------------------------------------------- +// ---------------------------------------------------------------------- + + + + +} // Namespace cmsstyle + +// ////////////////////////////////////////////////////////////////////// diff --git a/src/cmsstyle.H b/src/cmsstyle.H new file mode 100644 index 0000000..58914b6 --- /dev/null +++ b/src/cmsstyle.H @@ -0,0 +1,289 @@ +/// @file +/// +/// This is the main file loading the CMSStyle parameters and methods to be +/// used in ROOT. +/// +///
+/// Written by O. Gonzalez (2024_11_19)
+/// 
+ +#ifndef CMSSTYLE_CMSSTYLE__H_ +#define CMSSTYLE_CMSSTYLE__H_ + +#include "TCmsCanvas.H" + +#include +//OLD #include +#include + +#include + +#include + + +namespace cmsstyle { + +// Some global variables (do not access directly, use the corresponding methods +// to access them or change them! + +std::string cms_lumi = "Run 2, 138 fb^{#minus1}"; +std::string cms_energy = "13 TeV"; + +std::string cmsText = "CMS"; +std::string extraText = "Preliminary"; + +TStyle *cmsStyle = nullptr; + +std::vector usingPalette2D; // To define a color palette for 2-D histograms + +Float_t lumiTextSize = 0.6; // text sizes and text offsets with respect to the top frame in unit of the top margin size +Float_t lumiTextOffset = 0.2; +Float_t cmsTextSize = 0.75; +Float_t cmsTextOffset = 0.1; + +std::string useCmsLogo = ""; // To draw the CMS Logo (filename with path must be provided, may be relative to $CMSSTYLE_DIR) + +//OLD Bool_t writeExtraText = kTRUE; // For the extra and addtional text + +Font_t cmsTextFont = 61; // default is helvetic-bold +Font_t extraTextFont = 52; // default is helvetica-italics +Font_t additionalInfoFont = 42; + +std::vector additionalInfo; ///< For extra info, text set under the extra text, for in-frame descriptor. + +Float_t extraOverCmsTextSize = 0.76; // ratio of 'CMS' and extra text size + +/// Method to setup the style for the ROOT session! +/// Arguments: +/// force; allows to force the style within the ROOT seassion. +void setCMSStyle (bool force=kTRUE); + +/// Method to access the CMSStyle variable. It should be easier to access the +/// gROOT->gStyle pointer after setting the CMSStyle, but in case. +TStyle *getCMSStyle (void) {return cmsStyle;} + + +// /////////////////////////////////////////////// +// Configuration methods +// /////////////////////////////////////////////// + +/// This method allows to reset all the values for the CMS-related dataset +/// descriptors to the default. +/// +void ResetCmsDescriptors (void); + +/// This method sets the centre-of-mass energy value and unit to be displayed. +/// Arguments: +/// energy: The centre-of-mass energy value. If 0 the "unit part if the used string) +/// unit: The energy unit. Defaults to "TeV". +/// +/// NOTE: This method is probably a bad implementation due to the original implementation of CMSStyle. Using +/// +/// cms_energy = "13.6 TeV"; +/// +/// would be the actual way to go! +void SetEnergy (float energy, const std::string &unit="TeV"); + + +/// This allows to set the location of the file with the CMS Logo in case we +/// want to use that instead of the "CMS" text. +/// When not set (default), the text version is written. +/// +/// Arguments: +/// filename: path and filename of the file to be drawn. It can be relative to +/// the CMSSTYLE_DIR path (when set). +void SetCmsLogoFilename (const std::string &filename); + +/// This allows to set the extra text. If set to an empty string, nothing +/// extra is written. +/// +/// Arguments: +/// text: string to be used as extra text. Empty string means "no extra text", +/// "p" is shortcut for Preliminary (default), +/// "s" is shortcut for Simulation +/// "su" is shortcut for Supplementary +/// "wip" is shortcut for "Work in progress" +/// "pw" is shortcut for "Private work (CMS data)" +/// +/// The shortcuts are provided to the recommended values explained in +/// https://cms-analysis.docs.cern.ch/guidelines/plotting/general/#cms-label-requirements +/// +/// Note that combinations are possibles, but not with the shortcuts! i.e. to +/// write "Simulation Preliminary" the only text value is the full expression. +/// +/// Furthermore, when "Private" is included in the text, the CMS logo is not DRAWN/WRITTEN! +/// +void SetExtraText (const std::string &text); + +/// This methods allows to append additional information to be displayed, +/// e.g. a string identifying a region, or selection cuts in an automatic way +/// below the CMS-logo-related information (ExtraText, if any) when that is +/// drawn/written inside the frame. +/// +/// Arguments: +/// text: string to be appended as a new line of information. +/// +void AppendAdditionalInfo(const std::string &text) {additionalInfo.push_back(text);} + +/// Returns the maximum value associated to the objects that are going to be +/// plotted. +/// +/// Arguments: +/// objs: vector with the pointers to the objects to be drawn (or the ones including to +/// check the maximum) +/// +Float_t cmsReturnMaxY (const std::vector objs); + + +// /////////////////////////////////////////////// +// Plotting and related methods +// /////////////////////////////////////////////// + +/// This method defines and returns the TCmsCanvas (a wrapper for TCanvas) for +/// a normal/basic plot. +/// +/// Arguments: +/// canvName: Name of the canvas +/// x_max: The minimum value of the x-axis. +/// y_max: The minimum value of the y-axis. +/// y_max: The maximum value of the y-axis. +/// nameXaxis: The label for the x-axis. +/// nameYaxis: The label for the y-axis. +/// square (optional): Whether to create a square canvas. Defaults to True. +/// iPos (optional): The position of the CMS logo. Defaults to 11 (see CMS_lumi method for further details). +/// extraSpace (optional): Additional space to add to the left margin to fit labels. Defaults to 0. +/// with_z_axis (optional): Whether to include a z-axis for 2D histograms. Defaults to False. +/// scaleLumi (optional): Scaling factor for the luminosity text size. Defaults to 1 (see CMS_lumi method for further details). +/// yTitOffset (optional): Set the value for the Y-axis title offset in case default is not good. Defaults to -999 (ignored) +/// +/// Returns: +/// The produced TCmsCanvas. It is created with a new command... calling +/// method takes responsability of its deletion. +/// +TCmsCanvas *cmsCanvas (const char *canvName, + Float_t x_min, + Float_t x_max, + Float_t y_min, + Float_t y_max, + const char *nameXaxis, + const char *nameYaxis, + Bool_t square = kTRUE, + Int_t iPos = 11, + Float_t extraSpace = 0, + Bool_t with_z_axis = kFALSE, + Float_t scaleLumi = 1.0, + Float_t yTitOffset = -999); + +/// This is the method to draw the "CMS" seal (logo and text) and put the +/// luminosity value. +/// +/// Arguments: +/// ppad: The pad where to draw the "CMS" seal +/// iPos (optional): Position of the "CMS" seal. Defaults to 11 (top-left, left-aligned). +/// Alternatives are 33 (top-right, right-aligned), 22 (center, centered) +/// and 0x (out of frame, in exceptional cases). +/// Position is calculated as 10*(alignment 1/2/3) + position (1/2/3 = l/c/r). +/// scaleLumi (optional): Scaling factor for the luminosity text size. Defaults to 1.0 +/// +void CMS_lumi (TPad *ppad, Int_t iPosX=11, Float_t scaleLumi=1.0); + +/// This is a (mostly internal) method to setup the parameters of the provided +/// object in a "serialized" way. +/// +/// Arguments: +/// obj: Point to TObject to be configured +/// confs: Map with "methods" to be used to configure the object on the fly. +/// Only some methods are actually supported (see code for details) +/// +void setRootObjectProperties (TObject *obj, + std::map confs); + +/// This is the basic and most general method to plot things on the plot. +/// +/// Arguments: +/// obj: Point to TObject to be drawn +/// option: ROOT-style object +/// confs: Map with "methods" to be used to configure the object on the fly. Only some methods are +/// actually supported (see method setRootObjectProperties for details) +/// +void cmsObjectDraw (TObject *obj, + Option_t *option = "", + std::map confs = std::map()); + +/// This is the method to setup a legend according to the style! +/// +/// Arguments: +/// x1: The left position of the legend in NDC (0-1). +/// y1: The bottom position of the legend in NDC (0-1). +/// x2: The right position of the legend in NDC (0-1). +/// y2: The top position of the legend in NDC (0-1). +/// textSize (optional): The text size of the legend entries. Defaults to 0.04. +/// textFont (optional): The font of the legend entries. Defaults to 42 (helvetica). +/// textColor (optional): The color of the legend entries. Defaults to kBlack. +/// columns (optional): The number of columns in the legend. +/// +/// Note that parameters may be override later on. +/// +/// Returns: +/// A pointer to the defined TLegend. It is created with a new command, so +/// the calling routine must take care of the deletion. +TLegend *cmsLeg(Float_t x1, Float_t y1, Float_t x2, Float_t y2, + Float_t textSize=0.04, + Style_t textFont=42, + Color_t textColor=kBlack, + Int_t columns=0); + +/// This is a method to write a Text in a simplified and straightforward +/// (i.e. user-friendly) way. +/// +/// Arguments: +/// text: Text to be written on the plot. +/// posX: Position in X dimension of the text (in NDC coordinates [0,1] +/// posY: Position in Y dimension of the text (in NDC coordinates [0,1] +/// font: Font to be used for the text +/// align: Code for the alignment of the text with respect to the position +/// size: Size of the font +/// +void drawText(const char *text, Float_t posX, Float_t posY, Font_t font, Short_t align, Float_t size); + +/// This is a method to draw the CMS logo (that should be set using the +/// corresponding method or on the fly) in a TPad set at the indicated location +/// of the currently used TPad. +/// +/// Arguments: +/// canv: CMSCanvas that needs to be used to plot the CMSLogo. +/// x0: X position (in relative dimensions) of the lower-left corner of the logo +/// y0: Y position (in relative dimensions) of the lower-left corner of the logo. +/// x1: X position (in relative dimensions) of the upper-left corner of the logo. +/// y1: Y position (in relative dimensions) of the upper-left corner of the logo. +/// logofile (optional): filename (with path) for the logo picture (see SetCmsLogoFilename for details) +/// +void addCmsLogo (TCmsCanvas *canv,Float_t x0, Float_t y0, Float_t x1, Float_t y1, const char *logofile=nullptr); + +// /////////////////////////////////////////////// +// Modifiers and accesors for the Style or Canvas +// /////////////////////////////////////////////// + + +/// This method updates the provided TPad or TCanvas. If Update the currently +/// active TPad (gPad) if no argument is provided. +/// Arguments: +/// ppad: pointer to the TPad or TCanvas we want to Update +/// +void UpdatePad (TPad *ppad = nullptr); + +/// This method returns the FRam object used to define the cmsCanvas (but it +/// can be used also for any TPad). +/// +/// Arguments: +/// pcanv: A pointer to the cmsCanvas or TPad. +/// +/// Returns: +/// The TH1 framne associated to the definition of the TCanvas. +TH1 *GetcmsCanvasHist (TPad *pcanv); + + + +} // Namespace cmsstyle +#endif +// ////////////////////////////////////////////////////////////////////// diff --git a/src/cmsstyle/cmsstyle.py b/src/cmsstyle/cmsstyle.py index e8d8817..c269fc1 100644 --- a/src/cmsstyle/cmsstyle.py +++ b/src/cmsstyle/cmsstyle.py @@ -18,6 +18,9 @@ cms_lumi = "Run 2, 138 fb^{#minus1}" cms_energy = "13 TeV" +cmsText = "CMS" +extraText = "Preliminary" + cmsStyle = None usingPalette2D = None # To define a color palette for 2-D histograms @@ -85,10 +88,6 @@ def SetLumi (lumi, unit="fb", round_lumi=False): else: cms_lumi = lumi - -cmsText = "CMS" -extraText = "Preliminary" - def SetCmsText(text): """ Function that allows to edit the default @@ -184,6 +183,7 @@ class p6: kGrape = rt.kP6Grape kGray = rt.kP6Gray if (rt.GetColor(rt.kP6Violet).GetTitle=='#7a21dd'): # There was a bug in the first implementation in ROOT + # (I think no "released" version is affected. 6.34.00 is already OK) kViolet = rt.kP6Violet else: kViolet = rt.TColor.GetColor("#7a21dd") @@ -324,6 +324,7 @@ def SetCMSPalette(): cmsStyle.SetPalette(rt.kViridis) #cmsStyle.SetPalette(rt.kCividis) +# # # # def GetPalette(hist): """ Get the colour palette object associated with a histogram. @@ -532,6 +533,13 @@ def setCMSStyle(force=rt.kTRUE): # Using the Style. cmsStyle.cd() +# # # # +def getCMSStyle (): + """This returns the CMSStyle variable, in case it is required externally, + although usually it should be accessed via ROOT.gStyle after setting it. + """ + return cmsStyle + # ###### ## ## ###### ## ## ## ## ## #### # ## ## ### ### ## ## ## ## ## ### ### ## # ## #### #### ## ## ## ## #### #### ## @@ -542,6 +550,7 @@ def setCMSStyle(force=rt.kTRUE): def CMS_lumi(pad, iPosX=11, scaleLumi=None): + """ Draw the CMS text and luminosity information on the specified pad. @@ -1183,7 +1192,7 @@ def setRootObjectProperties (obj,**kwargs): elif hasattr(obj,xkey): method = xkey else: - print(f"Indicated argument for configuration is invalid: {xkey} {xval} {type(obj)}") + print("Indicated argument for configuration is invalid: {} {} {}".format(xkey, xval, type(obj))) raise AttributeError("Invalid argument") if xval is None: diff --git a/src/colorsets.H b/src/colorsets.H new file mode 100644 index 0000000..2fc3c76 --- /dev/null +++ b/src/colorsets.H @@ -0,0 +1,137 @@ +///@file +/// +/// This code contains the definition of the colors to be used in CMSStyle, +/// as they can be loaded to use in other projects. +/// +/// Contains the definitions of Petroff color schemes used in CMSStyle. +/// +///
+/// Written by O. Gonzalez (2024_11_12)
+/// 
+/// + +#ifndef CMSSTYLE_COLORSETS__H_ +#define CMSSTYLE_COLORSETS__H_ + +#include + +namespace cmsstyle { + +/// /////////////////// +/// This is the Petroff color scheme with 6 colors. +/// /////////////////// +struct p6 { + static const int kBlue; //= TColor::GetColor("#5790fc"); + static const int kYellow; //= TColor::GetColor("#f89c20"); + static const int kRed; //= TColor::GetColor("#e42536"); + static const int kGrape; //= TColor::GetColor("#964a8b"); + static const int kGray; //= TColor::GetColor("#9c9ca1"); + static const int kViolet; //= TColor::GetColor("#7a21dd"); +}; + +// Initialize! Depending on version as ROOT added +#if ROOT_VERSION_CODE >= ROOT_VERSION(6,34,0) + const int p6::kBlue = kP6Blue; + const int p6::kYellow = kP6Yellow; + const int p6::kRed = kP6Red; + const int p6::kGrape = kP6Grape; + const int p6::kGray = kP6Gray; + const int p6::kViolet = kP6Violet; // It should be fine! +#else + const int p6::kBlue = TColor::GetColor("#5790fc"); + const int p6::kYellow = TColor::GetColor("#f89c20"); + const int p6::kRed = TColor::GetColor("#e42536"); + const int p6::kGrape = TColor::GetColor("#964a8b"); + const int p6::kGray = TColor::GetColor("#9c9ca1"); + const int p6::kViolet = TColor::GetColor("#7a21dd"); +#endif + +/// /////////////////// +/// This is the Petroff color scheme with 8 colors. +/// /////////////////// +struct p8 { + static const int kBlue; //= rt.TColor.GetColor("#1845fb") + static const int kOrange; //= rt.TColor.GetColor("#ff5e02") + static const int kRed; //= rt.TColor.GetColor("#c91f16") + static const int kPink; //= rt.TColor.GetColor("#c849a9") + static const int kGreen; //= rt.TColor.GetColor("#adad7d") + static const int kCyan; //= rt.TColor.GetColor("#86c8dd") + static const int kAzure; //= rt.TColor.GetColor("#578dff") + static const int kGray; //= TColor::GetColor("#656364") +}; + +// Initialize! Depending on version as ROOT added +#if ROOT_VERSION_CODE >= ROOT_VERSION(6,34,0) + const int p8::kBlue = kP8Blue; + const int p8::kOrange = kP8Orange; + const int p8::kRed = kP8Red; + const int p8::kPink = kP8Pink; + const int p8::kGreen = kP8Green; + const int p8::kCyan = kP8Cyan; + const int p8::kAzure = kP8Azure; + const int p8::kGray = kP8Gray; +#else + const int p8::kBlue = TColor::GetColor("#1845fb"); + const int p8::kOrange = TColor::GetColor("#ff5e02"); + const int p8::kRed = TColor::GetColor("#c91f16"); + const int p8::kPink = TColor::GetColor("#c849a9"); + const int p8::kGreen = TColor::GetColor("#adad7d"); + const int p8::kCyan = TColor::GetColor("#86c8dd"); + const int p8::kAzure = TColor::GetColor("#578dff"); + const int p8::kGray = TColor::GetColor("#656364"); +#endif + +/// /////////////////// +/// This is the Petroff color scheme with 10 colors. +/// /////////////////// +struct p10 { + static const int kBlue; //= TColor::GetColor("#3f90da") + static const int kYellow; //= TColor::GetColor("#ffa90e") + static const int kRed; //= TColor::GetColor("#bd1f01") + static const int kGray; //= TColor::GetColor("#94a4a2") + static const int kViolet; //= TColor::GetColor("#832db6") + static const int kBrown; //= TColor::GetColor("#a96b59") + static const int kOrange; //= TColor::GetColor("#e76300") + static const int kGreen; //= TColor::GetColor("#b9ac70") + static const int kAsh; //= TColor::GetColor("#717581") + static const int kCyan; //= TColor::GetColor("#92dadd") +}; + +// Initialize! Depending on version as ROOT added +#if ROOT_VERSION_CODE >= ROOT_VERSION(6,34,0) + const int p10::kBlue = kP10Blue; + const int p10::kYellow = kP10Yellow; + const int p10::kRed = kP10Red; + const int p10::kGray = kP10Gray; + const int p10::kViolet = kP10Violet; + const int p10::kBrown = kP10Brown; + const int p10::kOrange = kP10Orange; + const int p10::kGreen = kP10Green; + const int p10::kAsh = kP10Ash; + const int p10::kCyan = KP10Cyan; +#else + const int p10::kBlue = TColor::GetColor("#3f90da"); + const int p10::kYellow = TColor::GetColor("#ffa90e"); + const int p10::kRed = TColor::GetColor("#bd1f01"); + const int p10::kGray = TColor::GetColor("#94a4a2"); + const int p10::kViolet = TColor::GetColor("#832db6"); + const int p10::kBrown = TColor::GetColor("#a96b59"); + const int p10::kOrange = TColor::GetColor("#e76300"); + const int p10::kGreen = TColor::GetColor("#b9ac70"); + const int p10::kAsh = TColor::GetColor("#717581"); + const int p10::kCyan = TColor::GetColor("#92dadd"); +#endif + +/// /////////////////// +/// Pair-sets of colors for the limit plots ("Brazilian flag plots") +/// From https://cms-analysis.docs.cern.ch/guidelines/plotting/colors/#brazilian-flag-limit-plots +/// /////////////////// +const int kLimit68 = TColor::GetColor("#607641"); // Internal band, default set +const int kLimit95 = TColor::GetColor("#F5BB54"); // External band, default set + +const int kLimit68cms = TColor::GetColor("#85D1FBff"); // Internal band, CMS-logo set +const int kLimit95cms = TColor::GetColor("#FFDF7Fff"); // External band, CMS-logo set + +} // Namespace cmsstyle +#endif +///---------------------------------------------------------------------- diff --git a/tests/test_cmsCanvas.C b/tests/test_cmsCanvas.C new file mode 100644 index 0000000..38aa38d --- /dev/null +++ b/tests/test_cmsCanvas.C @@ -0,0 +1,86 @@ +///@file +/// + +/// This file contains a C++-ROOT macro to perform tests of the basic plots +/// using the CMSStyle using the C++-based implementation. +/// + +/// To run it just execute: +/// $ source scripts/setup_cmstyle # From the CMSStyle-package top directory +/// $ root -q test_cmsCanvas.C +/// +/// It will produce the file test_cmsCanvas.png file. +/// +///
+/// Written by O. Gonzalez (2024_11_26)
+/// 
+ +#include "cmsstyle.C" + +void test_cmsCanvas () +{ + // Producing the histograms to plot + + TH1F h1("test","test",60,0.0,10.0); + TH1F h2("test","test",60,0.0,10.0); + + for (int i=1;i<=60;++i) { + h1.SetBinContent(i,10*exp(-i/5.0)); + h2.SetBinContent(i,8*exp(-i/15.0)); + } + h1.Add(&h2); + + auto *hdata = (TH1F*) h1.Clone("data"); + for (int i=1;i<=60;++i) { + hdata->SetBinError(i,0.12*hdata->GetBinContent(i)); + hdata->SetBinContent(i, hdata->GetBinContent(i)*(1+0.1*cos(6.28*i/20.))); + } + + // Plotting the histogram! + + cmsstyle::setCMSStyle(); // Setting the style + +// cmsstyle::SetCmsLogoFilename("CMS-BW-Label.png"); // e.g. +// cmsstyle::SetExtraText("Private work (CMS data)"); // e.g. +// cmsstyle::AppendAdditionalInfo("Doing our job"); // e.g. + + + TCanvas *c = cmsstyle::cmsCanvas("Testing",0.0,10.0,0.08,3*cmsstyle::cmsReturnMaxY({&h1,&h2,hdata}), + "X var [test]","Y var" + ,kTRUE // Square? + //,0 // position of the Logo: 0 is out-of-frame, default is 11. + ); + + gPad->SetLogy(); + + cmsstyle::cmsObjectDraw(&h1,"",{ {"LineColor", cmsstyle::p6::kGray}, + {"FillColor", cmsstyle::p6::kGray}, + {"FillStyle", 1001}, + } ); + + cmsstyle::cmsObjectDraw(&h2,"",{ {"LineColor", cmsstyle::p6::kYellow}, + {"FillColor", cmsstyle::p6::kYellow}, + {"FillStyle", 1001}, + } ); + + cmsstyle::cmsObjectDraw(hdata,"E",{ {"MarkerStyle", kFullCircle} + } ); + + + // The legend! + + auto *plotlegend = cmsstyle::cmsLeg (0.55,0.65,0.9,0.9); + + plotlegend->AddEntry(hdata,"Data","p"); + plotlegend->AddEntry(&h1,"Sample Number 1","f"); + plotlegend->AddEntry(&h2,"Sample Number 2","f"); +// cmsstyle::cmsObjectDraw(plotlegend); + + // Saving the result! + + cmsstyle::UpdatePad(c); + + c->SaveAs("test_cmsCanvas.png"); +} + +// ////////////////////////////////////////////////////////////////////// diff --git a/tests/test_cmsCanvas.py b/tests/test_cmsCanvas.py new file mode 100644 index 0000000..de69be2 --- /dev/null +++ b/tests/test_cmsCanvas.py @@ -0,0 +1,71 @@ +# +# This python macro +# +# Written by O. Gonzalez (2024_12_02) +# + +import math + +import ROOT + +import cmsstyle + +# # # # +def test_cmsCanvas (): + """Make the plot with the histograms on the fly. + + """ + + # Producing the histograms to plot + h1 = ROOT.TH1F("test1","test1",60,0.0,10.0) + h2 = ROOT.TH1F("test2","test2",60,0.0,10.0) + + for i in range(1,61): + h1.SetBinContent(i,10*math.exp(-i/5.0)) + h2.SetBinContent(i,8*math.exp(-i/15.0)) + + h1.Add(h2) + + hdata = h1.Clone("data") + for i in range(1,61): + hdata.SetBinError(i,0.12*hdata.GetBinContent(i)) + hdata.SetBinContent(i, hdata.GetBinContent(i)*(1+0.1*math.cos(6.28*i/20.))) + + # Plotting the histogram! + + cmsstyle.setCMSStyle() # Setting the style + + c = cmsstyle.cmsCanvas("Testing",0.0,10.0,0.08,3*cmsstyle.cmsReturnMaxY(h1,h2,hdata), + "X var [test]","Y var"); + + ROOT.gPad.SetLogy() + + cmsstyle.cmsObjectDraw(h1,"",LineColor=cmsstyle.p6.kGray, + FillColor=cmsstyle.p6.kGray, + FillStyle=1001) + + cmsstyle.cmsObjectDraw(h2,"",LineColor=cmsstyle.p6.kYellow, + FillColor=cmsstyle.p6.kYellow, + FillStyle=1001) + + cmsstyle.cmsObjectDraw(hdata,"E",MarkerStyle=ROOT.kFullCircle) + + # The legend! + + plotlegend = cmsstyle.cmsLeg(0.5,0.8,0.5,0.8) + + plotlegend.AddEntry(hdata,"Data","p") + plotlegend.AddEntry(h1,"Sample Number 1","f") + plotlegend.AddEntry(h2,"Sample Number 2","f") + + # Saving the result! + cmsstyle.UpdatePad(c) + + c.SaveAs("test_cmsCanvas.png") + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# For running as a shell command to get the list of files (comma-separated) +if __name__ == '__main__': + test_cmsCanvas() + +# ####################################################################### diff --git a/tests/test_color_sets.C b/tests/test_color_sets.C new file mode 100644 index 0000000..d1ee375 --- /dev/null +++ b/tests/test_color_sets.C @@ -0,0 +1,139 @@ +///@file +/// +/// This file contains an example to show how is the aspect of the color sets +/// that are defined in the style. +/// +/// To run it we need: +/// $ source scripts/setup_cmstyle # From the CMSStyle-package top directory +/// $ root -q tests/test_color_sets.C # Can be run from any location (or from inside ROOT directly!). +/// +/// It will produce the file test_color_sets.png file. +/// +///
+/// Written by O. Gonzalez (2024_11_19)
+/// 
+ +#include "colorsets.H" + +void test_color_sets (void) { + + // Vectors of pair values to access the + + std::vector> colorset_p6({{"p6::kBlue",&cmsstyle::p6::kBlue}, + {"p6::kYellow",&cmsstyle::p6::kYellow}, + {"p6::kRed",&cmsstyle::p6::kRed}, + {"p6::kGrape",&cmsstyle::p6::kGrape}, + {"p6::kGray",&cmsstyle::p6::kGray}, + {"p6::kViolet",&cmsstyle::p6::kViolet}}); + + std::vector> colorset_p8({{"p8::kBlue",&cmsstyle::p8::kBlue}, + {"p8::kOrange",&cmsstyle::p8::kOrange}, + {"p8::kRed",&cmsstyle::p8::kRed}, + {"p8::kPink",&cmsstyle::p8::kPink}, + {"p8::kGreen",&cmsstyle::p8::kGreen}, + {"p8::kCyan",&cmsstyle::p8::kCyan}, + {"p8::kAzure",&cmsstyle::p8::kAzure}, + {"p8::kGray",&cmsstyle::p8::kGray}}); + + std::vector> colorset_p10({{"p10::kBlue",&cmsstyle::p10::kBlue}, + {"p10::kYellow",&cmsstyle::p10::kYellow}, + {"p10::kRed",&cmsstyle::p10::kRed}, + {"p10::kGray",&cmsstyle::p10::kGray}, + {"p10::kViolet",&cmsstyle::p10::kViolet}, + {"p10::kBrown",&cmsstyle::p10::kBrown}, + {"p10::kOrange",&cmsstyle::p10::kOrange}, + {"p10::kGreen",&cmsstyle::p10::kGreen}, + {"p10::kAsh",&cmsstyle::p10::kAsh}, + {"p10::kCyan",&cmsstyle::p10::kCyan}}); + + + + // Create the TCanvas + auto *c = new TCanvas("colors","Color sets in CMSStyle",800,400); + + unsigned int jdx=-1; + for (auto xset : {&colorset_p10,&colorset_p8,&colorset_p6}) { + ++jdx; + + unsigned int idx=-1; + for (auto xcol : *xset) { + ++idx; + auto *tt = new TPaveLabel(0.02+idx*0.097,0.07+jdx*0.2,0.01+0.097*(1+idx),0.12+jdx*0.2,xcol.first.c_str()); + tt->SetTextColor(kWhite); + + tt->SetBorderSize(1); + tt->SetLineColor(*xcol.second); + tt->SetFillColor(*xcol.second); + + tt->Draw(); + + tt = new TPaveLabel(0.02+idx*0.097,0.15+jdx*0.2,0.01+0.097*(idx+1),0.2+jdx*0.2,xcol.first.c_str()); + tt->SetTextColor(*xcol.second); + + tt->SetBorderSize(1); + tt->SetLineColor(kWhite); + tt->SetFillColor(kWhite); + + tt->Draw(); + } + } + + // Also plots for the limit plots: + + auto *tt = new TPaveLabel(0,0.7,0.25,0.8,"Stats/Limit Bands:"); + + tt->SetBorderSize(1); + tt->SetLineColor(kWhite); + tt->SetFillColor(kWhite); + + tt->Draw(); + + auto *tb = new TBox(0.3,0.75,0.6,0.95); + tb->SetLineColor(cmsstyle::kLimit95); + tb->SetFillColor(cmsstyle::kLimit95); + tb->Draw(); + + tb = new TBox(0.3,0.8,0.6,0.9); + tb->SetLineColor(cmsstyle::kLimit68); + tb->SetFillColor(cmsstyle::kLimit68); + tb->Draw(); + + auto *tl = new TLine(0.3,0.85,0.6,0.85); + tl->Draw(); + + tt = new TPaveLabel(0.35,0.63,0.55,0.73,"Usual/Default"); + + tt->SetBorderSize(1); + tt->SetLineColor(kWhite); + tt->SetFillColor(kWhite); + + tt->Draw(); + + + tb = new TBox(0.65,0.75,0.95,0.95); + tb->SetLineColor(cmsstyle::kLimit95cms); + tb->SetFillColor(cmsstyle::kLimit95cms); + tb->Draw(); + + tb = new TBox(0.65,0.8,0.95,0.9); + tb->SetLineColor(cmsstyle::kLimit68cms); + tb->SetFillColor(cmsstyle::kLimit68cms); + tb->Draw(); + + tl = new TLine(0.65,0.85,0.95,0.85); + tl->Draw(); + + tt = new TPaveLabel(0.7,0.63,0.9,0.73,"CMS-logo colors"); + + tt->SetBorderSize(1); + tt->SetLineColor(kWhite); + tt->SetFillColor(kWhite); + + tt->Draw(); + + c->SaveAs("test_color_sets.png"); + + std::cout<<"Finished: produced file test_color_sets.png"<