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"<