From 927d14e68778299c691861877d82c6a9108e9e09 Mon Sep 17 00:00:00 2001 From: Oscar Gonzalez Lopez Date: Thu, 12 Dec 2024 15:13:20 +0100 Subject: [PATCH] Improving the routines to write the CMS logo and the luminosity messages and some of the documentation --- README.md | 28 +++++++ src/cmsstyle.C | 35 +++++---- src/cmsstyle.H | 1 + src/cmsstyle/cmsstyle.py | 164 ++++++++++++++++++++++----------------- tests/test_cmsCanvas.py | 6 +- 5 files changed, 143 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index 29285bb..2b215c4 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,34 @@ add something like the following to the rootlogon.C macro (or equivalent): ``` In fact a similar configuration may be achieved by modifying the ``${HOME}/.rootrc`` instead. +## Installation inside the CMSSW + +If you use a CMSSW that supports the _scram-venv_ you may use that to achieve +the installation of the python package with pip already locally, as described +in [this page](http://cms-sw.github.io/venv.html) using the following instructions: +```scram-venv +cmsenv + +pip install cmstyle +``` + +It should be remarked that after installation of the _venv_ (done by +_scram-venv_) that step is no longer needed, but the working directory should +be used always in the virtual enviroment (that should be already setup when +doing the commonly required _cmsenv_ command. + +Remark that if you have a local installacion of cmsstyle, it may collide with +the virtual environment, so you may want to do +```export PYTHONNOUSERSITE=True +``` +to prevent the conflicts. + +In the case of the C++ code, it is possible to add the code as source code but +downloading the packages as mentioned above. Keep in mind that the repository +does not follows the required structure for CMSSW packages, so you may +encounter difficulties to integrate. _Do not hesitate to contact us for the use +case_. + ## Documentation Documentation for the Python implementation is available at [cmsstyle.readthedocs.io](https://cmsstyle.readthedocs.io/). C++ implementation is analogous. diff --git a/src/cmsstyle.C b/src/cmsstyle.C index 56aae81..f840447 100644 --- a/src/cmsstyle.C +++ b/src/cmsstyle.C @@ -30,6 +30,7 @@ #include #include #include +#include // Globals from ROOT @@ -438,21 +439,24 @@ void CMS_lumi (TPad *ppad, Int_t iPosX, Float_t scaleLumi) if (outOfFrame) { // CMS logo and extra text out of the frame if (useCmsLogo.length()>0) { // Using CMS Logo instead of the text label (uncommon!) - + std::cerr<<"WARNING: Usage of (graphical) CMS-logo outside the frame is not currently supported!"< H) scale = H/ float(W); // For a rectangle; + l += 0.043 * (extraTextFont * t * cmsTextSize) * scale; } - 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); - } + if (extraText.length()!=0) { // Only if something to write + drawText(extraText.c_str(),l,outOfFrame_posY,extraTextFont,align_,extraOverCmsTextSize * cmsTextSize * t); + } + if (additionalInfo.size()!=0) { // We do not support this! + std::cerr<<"WARNING: Additional Info for the CMS-info part outside the frame is not currently supported!"<0) { // Using CMS Logo instead of the text label @@ -486,9 +490,9 @@ void CMS_lumi (TPad *ppad, Int_t iPosX, Float_t scaleLumi) // ---------------------------------------------------------------------- void setRootObjectProperties (TObject *obj, std::map confs) - + // This is a (mostly internal) method to setup the parameters of the provided + // object in a "serialized" way. { - 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)); @@ -626,7 +630,7 @@ TPaveStats *changeStatsBox (TPad *pcanv, // ---------------------------------------------------------------------- void changeStatsBox (TPaveStats *pstats, Float_t x1pos, Float_t y1pos, Float_t x2pos, Float_t y2pos, - const std::map &confs = std::map()) + const std::map &confs) // This method allows to modify the properties and similar of the provided Stats Box. { setRootObjectProperties(pstats,confs); @@ -689,7 +693,6 @@ TPaveStats *changeStatsBox (TPad *pcanv, y1 = 1-pcanv->GetTopMargin()-ysize*yfactor-textsize; x2 = pcanv->GetLeftMargin()+xsize*0.33+textsize; y2 = 1-pcanv->GetTopMargin()-ysize*0.03; - std::cout<<"JODER "<GetLeftMargin()+xsize*0.03; diff --git a/src/cmsstyle.H b/src/cmsstyle.H index a2fa1fc..89d3f92 100644 --- a/src/cmsstyle.H +++ b/src/cmsstyle.H @@ -17,6 +17,7 @@ #include #include +#include #include diff --git a/src/cmsstyle/cmsstyle.py b/src/cmsstyle/cmsstyle.py index 4f99c3a..81c7201 100644 --- a/src/cmsstyle/cmsstyle.py +++ b/src/cmsstyle/cmsstyle.py @@ -601,8 +601,8 @@ def CMS_lumi(pad, iPosX=11, scaleLumi=1): b = pad.GetBottomMargin() outOfFrame_posY = 1 - t + lumiTextOffset * t pad.cd() - lumiText = "" - lumiText += cms_lumi + + lumiText = cms_lumi if cms_energy != "": lumiText += " (" + cms_energy + ")" @@ -615,81 +615,58 @@ def CMS_lumi(pad, iPosX=11, scaleLumi=1): size=lumiTextSize * t * scaleLumi, ) - if outOfFrame: - drawText( - text=cmsText, - posX=l, - posY=outOfFrame_posY, - font=cmsTextFont, - align=11, - size=cmsTextSize * t, - ) + # Now we go to the CMS message: + posX_ = 0 - if iPosX % 10 <= 1: - posX_ = l + relPosX * (1 - l - r) - elif iPosX % 10 == 2: - posX_ = l + 0.5 * (1 - l - r) - elif iPosX % 10 == 3: - posX_ = 1 - r - relPosX * (1 - l - r) + if (iPosX % 10 <= 1): posX_ = l + relPosX * (1 - l - r) + elif (iPosX % 10 == 2): posX_ = l + 0.5 * (1 - l - r) + elif (iPosX % 10 == 3): posX_ = 1 - r - relPosX * (1 - l - r) + posY_ = 1 - t - relPosY * (1 - t - b) - if not outOfFrame: - if drawLogo: + + if outOfFrame: # CMS logo and extra text out of the frame + if (len(useCmsLogo)>0): # Using CMS Logo instead of the text label (uncommon and discouraged!) + print("WARNING: Usage of (graphical) CMS-logo outside the frame is not currently supported!") +# else { + if (len(cmsText)>0): + drawText(cmsText,l,outOfFrame_posY,cmsTextFont,11,cmsTextSize * t) + + # Checking position of the extraText after the CMS logo text. + scale=1 + if (W > H): scale = H/ float(W) # For a rectangle; + l += 0.043 * (extraTextFont * t * cmsTextSize) * scale + + if (len(extraText)>0): # Only if something to write + drawText(extraText,l,outOfFrame_posY,extraTextFont,align_,extraOverCmsTextSize * cmsTextSize * t) + + if (len(additionalInfo)>0): # This is currently not supported! + print("WARNING: Additional Info for the CMS-info part outside the frame is not currently supported!") + + else: # In the frame! + if (len(useCmsLogo)>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) - xl_0 = posX_ - yl_0 = posY_ - 0.15 - xl_1 = posX_ + 0.15 * H / W - yl_1 = posY_ - CMS_logo = rt.TASImage("CMS-BW-label.png") - pad_logo = rt.TPad("logo", "logo", xl_0, yl_0, xl_1, yl_1) - pad_logo.Draw() - pad_logo.cd() - CMS_logo.Draw("X") - pad_logo.Modified() - pad.cd() + # Note this is only for TCanvas! + addCmsLogo(pad, posX_,posY_ - 0.15,posX_ + 0.15 * H / W,posY_) + else: - drawText( - text=cmsText, - posX=posX_, - posY=posY_, - font=cmsTextFont, - align=align_, - size=cmsTextSize * t, - ) - if writeExtraText: - posY_ -= relExtraDY * cmsTextSize * t - drawText( - text=extraText, - posX=posX_, - posY=posY_, - font=extraTextFont, - align=align_, - size= extraOverCmsTextSize * cmsTextSize * t, - ) - if len(additionalInfo) != 0: - latex.SetTextSize(extraTextSize * t) - latex.SetTextFont(additionalInfoFont) - for ind, tt in enumerate(additionalInfo): - latex.DrawLatex( - posX_, - posY_ - - 0.004 - - (relExtraDY * extraOverCmsTextSize * cmsTextSize * t / 2 + 0.02) * (ind + 1), - tt, - ) - elif writeExtraText: - if outOfFrame: - scale = float(H) / W if W > H else 1 - posX_ = l + 0.043 * (extraTextFont * t * cmsTextSize) * scale - posY_ = outOfFrame_posY - drawText( - text=extraText, - posX=posX_, - posY=posY_, - font=extraTextFont, - align=align_, - size= extraOverCmsTextSize * cmsTextSize * t, - ) + if (len(cmsText)>0): + drawText(cmsText,posX_,posY_,cmsTextFont,align_,cmsTextSize * t) + # Checking position of the extraText after the CMS logo text. + posY_ -= relExtraDY * cmsTextSize * t; + + if (len(extraText)>0): # Only if something to write + drawText(extraText,posX_,posY_,extraTextFont,align_,extraOverCmsTextSize * cmsTextSize * t) + else: posY_ += relExtraDY * cmsTextSize * t # Preparing for additional text! + + for ind, tt in enumerate(additionalInfo): + drawText(tt, + posX_, + posY_ - 0.004 - (relExtraDY * extraOverCmsTextSize * cmsTextSize * t / 2 + 0.02) * (ind + 1), + additionalInfoFont, + align_, + extraOverCmsTextSize * cmsTextSize * t) + UpdatePad(pad) # # # # @@ -714,6 +691,47 @@ def drawText (text, posX, posY, font, align, size): latex.SetTextSize(size) latex.DrawLatex(posX, posY, text) +# # # # +def addCmsLogo (canv,x0,y0,x1,y1,logofile=None): + """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. + + Args: + canv (TCanvas): CMSCanvas that needs to be used to plot the CMSLogo. + x0 (float): X position (in relative dimensions) of the lower-left corner of the logo + y0 (float): Y position (in relative dimensions) of the lower-left corner of the logo. + x1 (float): X position (in relative dimensions) of the upper-left corner of the logo. + y1 (floar): Y position (in relative dimensions) of the upper-left corner of the logo. + logofile (str,optional): filename (with path) for the logo picture (see SetCmsLogoFilename for details) + """ + + if logofile is not None: SetCmsLogoFilename(logofile) # Trying to load the picture file! + + if (len(useCmsLogo)==0): + print("ERROR: Not possible to add the CMS Logo as the file is not properly defined (not found?)") + return + + # Checking we actually have a TCanvas: + + if (canv.Class().GetName()!='TCanvas'): # For now reporting an error! + print("ERROR: You cannot use a picture for the CMS logo if you do not provide a TCanvas for the plot") + return + + # Addint a TPad with the picture! + + CMS_logo = rt.TASImage(useCmsLogo) + + oldpad = rt.gPad + + pad_logo = rt.TPad("logo", "logo", x0, y0, x1, y1) + pad_logo.Draw() + pad_logo.cd() + CMS_logo.Draw("X") + pad_logo.Modified() + + oldpad.cd() + UpdatePad() # For gPad # ######## ## ####### ######## ######## #### ## ## ###### ## ## ### ###### ######## ####### ###### # ## ## ## ## ## ## ## ## ### ## ## ## ### ### ## ## ## ## ## ## ## ## ## ## @@ -1165,7 +1183,7 @@ def changeStatsBox (canv,ipos_x1=None,y1pos=None,x2pos=None,y2pos=None,**kwargs) """ stbox = canv - if (canv.Class().GetName()!='TPaveStats'): # VEry likely a TPad or TCanvas + if (canv.Class().GetName()!='TPaveStats'): # Very likely a TPad or TCanvas canv.Update() # To be sure we have created the statistic box stbox = canv.GetPrimitive('stats') diff --git a/tests/test_cmsCanvas.py b/tests/test_cmsCanvas.py index 5377965..c640876 100644 --- a/tests/test_cmsCanvas.py +++ b/tests/test_cmsCanvas.py @@ -39,7 +39,9 @@ def test_cmsCanvas (): cmsstyle.SetLumi(45.00,"fb","Run 3",-1) c = cmsstyle.cmsCanvas("Testing",0.0,10.0,0.08,3*cmsstyle.cmsReturnMaxY(h1,h2,hdata), - "X var [test]","Y var",square=True,iPos=0); + "X var [test]","Y var",square=True, + #iPos=0 + ) ROOT.gPad.SetLogy() @@ -51,7 +53,7 @@ def test_cmsCanvas (): FillColor=cmsstyle.p6.kYellow, FillStyle=1001) - if True: # To test the use of the changeStatsBox + if False: # To test the use of the changeStatsBox ROOT.gStyle.SetOptStat('mr') cmsstyle.cmsObjectDraw(hdata,"SE",MarkerStyle=ROOT.kFullCircle) cmsstyle.changeStatsBox(c,'tl')