diff --git a/.github/workflows/softwarecheck.yml b/.github/workflows/softwarecheck.yml
new file mode 100644
index 0000000..cbcf026
--- /dev/null
+++ b/.github/workflows/softwarecheck.yml
@@ -0,0 +1,40 @@
+name: Software_check
+on:
+ push:
+ pull_request:
+ types: [opened]
+jobs:
+ py3-job:
+ runs-on: ubuntu-latest
+ container: cmscloud/al9-cms:latest
+ steps:
+ - name: Checking_python_3.9
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ - run: |
+ python3 -V
+ ls
+ pwd
+ python3 -m py_compile src/cmsstyle/cmsstyle.py
+ python3 -m py_compil src/cmsstyle/cmsstyle.py
+ - run: |
+ cd src
+ echo '{gROOT->LoadMacro("cmsstyle.C++");}' > hola.C
+ root -q hola.C
+ ls cmsstyle_C.sod
+#
+ py2-job:
+ runs-on: ubuntu-latest
+ container: cmscloud/cc7-cms:latest
+ steps:
+ - name: Checking_python_2.7
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ - run: |
+ python -V
+ ls
+ pwd
+ python -m py_compile src/cmsstyle/cmsstyle.py
+#
diff --git a/scripts/setup_cmstyle b/scripts/setup_cmstyle
index 26bb368..2f7367c 100644
--- a/scripts/setup_cmstyle
+++ b/scripts/setup_cmstyle
@@ -6,6 +6,7 @@
# 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]}
@@ -13,26 +14,26 @@ if [ ".${fich_::1}" != "./" ] ; then # Relative directory
fich_="$PWD/${fich_}"
fi
-# Setting up the variables:
+# 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
-export CMSSTYLE_DIR=${fich_::-22}
echo "Using CMSStyle located in $CMSSTYLE_DIR"
+# Setting up the related variables:
+
if [[ ! $ROOT_INCLUDE_PATH == *"${CMSSTYLE_DIR}/src"* ]]; then
- if [[ -z "$ROOT_INCLUDE_PATH" ]] ; then
- export ROOT_INCLUDE_PATH=${CMSSTYLE_DIR}/src
- else
- export ROOT_INCLUDE_PATH=${CMSSTYLE_DIR}/src:$ROOT_INCLUDE_PATH
- fi
+ 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
- if [[ -z ${PYTHONPATH} ]] ; then
- export PYTHONPATH=${CMSSTYLE_DIR}/src
- else
- export PYTHONPATH=${CMSSTYLE_DIR}/src:${PYTHONPATH}
- fi
+ export PYTHONPATH=${CMSSTYLE_DIR}/src${PYTHONPATH:+":$PYTHONPATH"}
fi
#
# Note:
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
index a323ef5..5a5128f 100644
--- a/src/cmsstyle.C
+++ b/src/cmsstyle.C
@@ -5,6 +5,9 @@
///
/// 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
@@ -19,9 +22,13 @@
#include
#include
#include
+#include
+#include
+#include
#include
#include
+#include
// Globals from ROOT
@@ -143,14 +150,27 @@ void setCMSStyle (bool force)
// 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);
- }
+#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.
@@ -168,7 +188,61 @@ void SetEnergy (float energy, const std::string &unit)
}
// ----------------------------------------------------------------------
+void SetCmsLogoFilename (const std::string &filename)
+ // 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.
+{
+ if (filename.length()==0) useCmsLogo ="";
+
+ // We just check for it!
+ else if (FILE *file = fopen(filename.c_str(),"r")) {
+ useCmsLogo = filename;
+ fclose(file);
+ }
+
+ else { // We may look inside the CMSStyle directory if the variable is defined.
+ char *x = std::getenv("CMSSTYLE_DIR");
+ useCmsLogo ="";
+
+ if (x!=nullptr) {
+ useCmsLogo = std::string(x) + std::string("/") + filename;
+
+ if (FILE *file = fopen(useCmsLogo.c_str(),"r")) {
+ fclose(file);
+ }
+ else useCmsLogo ="";
+ }
+ if (useCmsLogo.length()==0) {
+ std::cerr<<"ERROR: Indicated file for CMS Logo: "< objs)
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
-TCanvas *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,
- Int_t iPos,
- Float_t extraSpace,
- Bool_t with_z_axis,
- Float_t scaleLumi,
- Float_t yTitOffset)
- // his method defines and returns the TCanvas for a normal/basic plot.
+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,
+ Int_t iPos,
+ Float_t extraSpace,
+ Bool_t with_z_axis,
+ Float_t scaleLumi,
+ Float_t yTitOffset)
+ // This method defines and returns the TCmsCanvas (a wrapper for TCanvas) for
+ // a normal/basic plot.
{
// Set CMS style if not set already
if (cmsStyle==nullptr) setCMSStyle();
@@ -241,7 +316,7 @@ TCanvas *cmsCanvas (const char *canvName,
Float_t R = 0.03 * H;
// Setting up the TCanvas
- TCanvas *canv = new TCanvas(canvName, canvName, 50, 50, W, H);
+ TCmsCanvas *canv = new TCmsCanvas(canvName, canvName, 50, 50, W, H);
canv->SetFillColor(0);
canv->SetBorderMode(0);
canv->SetFrameFillStyle(0);
@@ -288,8 +363,86 @@ void CMS_lumi (TPad *ppad, Int_t iPosX, Float_t scaleLumi)
/// 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; iSetTextSize(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
+}
+
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
diff --git a/src/cmsstyle.H b/src/cmsstyle.H
index 02eb9ec..58914b6 100644
--- a/src/cmsstyle.H
+++ b/src/cmsstyle.H
@@ -10,10 +10,10 @@
#ifndef CMSSTYLE_CMSSTYLE__H_
#define CMSSTYLE_CMSSTYLE__H_
+#include "TCmsCanvas.H"
#include
-#include
-#include
+//OLD #include
#include
#include
@@ -23,24 +23,55 @@
namespace cmsstyle {
-// Some global variables:
+// 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)
@@ -54,7 +85,45 @@ void setCMSStyle (bool force=kTRUE);
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.
@@ -70,7 +139,9 @@ Float_t cmsReturnMaxY (const std::vector objs);
// Plotting and related methods
// ///////////////////////////////////////////////
-/// This method defines and returns the TCanvas for a normal/basic plot.
+/// 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.
@@ -82,26 +153,26 @@ Float_t cmsReturnMaxY (const std::vector objs);
/// 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 0.75 (see CMS_lumi method for further details).
+/// 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 TCanvas. It is created with a new command... calling
+/// The produced TCmsCanvas. It is created with a new command... calling
/// method takes responsability of its deletion.
///
-TCanvas *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 = 0.75,
- Float_t yTitOffset = -999);
+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.
@@ -110,11 +181,11 @@ TCanvas *cmsCanvas (const char *canvName,
/// 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 0 (out of frame, in exceptional cases).
+/// 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 0.75.
+/// 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=0.75);
+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.
@@ -139,6 +210,56 @@ 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
// ///////////////////////////////////////////////
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
index c105e16..2fc3c76 100644
--- a/src/colorsets.H
+++ b/src/colorsets.H
@@ -13,7 +13,7 @@
#ifndef CMSSTYLE_COLORSETS__H_
#define CMSSTYLE_COLORSETS__H_
-#include "TColor.h"
+#include
namespace cmsstyle {
@@ -36,21 +36,14 @@ struct p6 {
const int p6::kRed = kP6Red;
const int p6::kGrape = kP6Grape;
const int p6::kGray = kP6Gray;
-//SEE BELOW const int p6::kViolet = kP6Violet;
+ 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");
-// SEE BELOW const int p6::kViolet = TColor::GetColor("#7a21dd");
-#endif
-
-// kP6Violet is wrong in some versions...
-#if ROOT_VERSION_CODE < ROOT_VERSION(6,35,0)
const int p6::kViolet = TColor::GetColor("#7a21dd");
-#else
- const int p6::kViolet = kP6Violet;
#endif
/// ///////////////////
diff --git a/tests/test_cmsCanvas.C b/tests/test_cmsCanvas.C
index 768a08d..38aa38d 100644
--- a/tests/test_cmsCanvas.C
+++ b/tests/test_cmsCanvas.C
@@ -30,12 +30,26 @@ void test_cmsCanvas ()
}
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
- TCanvas *c = cmsstyle::cmsCanvas("Testing",0.0,10.0,0.08,cmsstyle::cmsReturnMaxY({&h1,&h2}),
- "X var [test]","Y var");
+// 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();
@@ -44,12 +58,25 @@ void test_cmsCanvas ()
{"FillStyle", 1001},
} );
- cmsstyle::cmsObjectDraw(&h2,"",{ {"LineColor", cmsstyle::p6::kGrape},
- {"FillColor", cmsstyle::p6::kGrape},
+ 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);
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()
+
+# #######################################################################