2 Utilities for plotting ROOT histograms in matplotlib. 5 from builtins
import range
7 Copyright (c) 2009-2010 Jeff Klukas <klukas@wisc.edu> 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 from rootplot
import utilities
36 import matplotlib
as mpl
37 import matplotlib.pyplot
as plt
38 import matplotlib.transforms
as transforms
43 _all_whitespace_string = re.compile(
r'\s*$')
49 """A container to hold the parameters from a 2D ROOT histogram.""" 52 if 'replacements' in kwargs:
54 utilities.Hist2D.__init__(self, *args, **kwargs)
56 """Draw a contour plot.""" 57 cs = plt.contour(self.
x, self.
y, self.
content, **kwargs)
58 plt.clabel(cs, inline=1, fontsize=10)
64 def col(self, **kwargs):
65 """Draw a colored box plot using :func:`matplotlib.pyplot.imshow`.""" 67 kwargs[
'cmap'] = plt.get_cmap(kwargs[
'cmap'])
68 plot = plt.imshow(self.
content, interpolation=
'nearest',
71 aspect=
'auto', origin=
'lower', **kwargs)
75 Draw a colored box plot with a colorbar using 76 :func:`matplotlib.pyplot.imshow`. 78 plot = self.
col(**kwargs)
81 def box(self, maxsize=40, **kwargs):
83 Draw a box plot with size indicating content using 84 :func:`matplotlib.pyplot.scatter`. 86 The data will be normalized, with the largest box using a marker of 87 size maxsize (in points). 89 x = np.hstack([self.
x for i
in range(self.
nbinsy)])
90 y = np.hstack([[yval
for i
in range(self.
nbinsx)]
for yval
in self.
y])
95 plot = plt.scatter(x, y, sizes, marker=
's', **kwargs)
98 """Return a ROOT.TH2F object with contents of this Hist2D.""" 99 th2f = ROOT.TH2F(name,
"",
103 for ix
in range(self.
nbinsx):
104 for iy
in range(self.
nbinsy):
105 th2f.SetBinContent(ix + 1, iy + 1, self.
content[iy][ix])
109 """A container to hold the parameters from a ROOT histogram.""" 112 if 'replacements' in kwargs:
114 utilities.Hist.__init__(self, *args, **kwargs)
116 """Apply bounds and text labels on x axis.""" 120 rotation=rotation, ha=alignment)
124 """Apply bounds and text labels on y axis.""" 128 rotation=rotation, va=alignment)
132 """Print the title and axis labels to the current figure.""" 133 replacements = kwargs.get(
'replacements',
None)
or self.
replacements 137 def hist(self, label_rotation=0, label_alignment='center', **kwargs):
139 Generate a matplotlib hist figure. 141 All additional keyword arguments will be passed to 142 :func:`matplotlib.pyplot.hist`. 144 kwargs.pop(
'fmt',
None)
145 replacements = kwargs.get(
'replacements',
None)
or self.
replacements 149 weights = [1.e-10] * self.
nbins 150 plot = plt.hist(self.
x, weights=weights, bins=self.
xedges,
154 def errorbar(self, xerr=False, yerr=False, label_rotation=0,
155 label_alignment=
'center', **kwargs):
157 Generate a matplotlib errorbar figure. 159 All additional keyword arguments will be passed to 160 :func:`matplotlib.pyplot.errorbar`. 163 kwargs[
'xerr'] = self.
xerr 165 kwargs[
'yerr'] = self.
yerr 166 replacements = kwargs.get(
'replacements',
None)
or self.
replacements 167 errorbar = plt.errorbar(self.
x, self.
y,
172 def errorbarh(self, xerr=False, yerr=False, label_rotation=0,
173 label_alignment=
'center', **kwargs):
175 Generate a horizontal matplotlib errorbar figure. 177 All additional keyword arguments will be passed to 178 :func:`matplotlib.pyplot.errorbar`. 180 if xerr: kwargs[
'xerr'] = self.
yerr 181 if yerr: kwargs[
'yerr'] = self.
xerr 182 replacements = kwargs.get(
'replacements',
None)
or self.
replacements 183 errorbar = plt.errorbar(self.
y, self.
x,
188 def bar(self, xerr=False, yerr=False, xoffset=0., width=0.8,
189 label_rotation=0, label_alignment=
'center', **kwargs):
191 Generate a matplotlib bar figure. 193 All additional keyword arguments will be passed to 194 :func:`matplotlib.pyplot.bar`. 196 kwargs.pop(
'fmt',
None)
197 if xerr: kwargs[
'xerr'] = self.
av_xerr()
198 if yerr: kwargs[
'yerr'] = self.
av_yerr()
199 replacements = kwargs.get(
'replacements',
None)
or self.
replacements 200 ycontent = [self.
xedges[i] + self.
width[i] * xoffset
201 for i
in range(len(self.
xedges) - 1)]
202 width = [x * width
for x
in self.
width]
203 bar = plt.bar(ycontent, self.
y, width,
207 def barh(self, xerr=False, yerr=False, yoffset=0., width=0.8,
208 label_rotation=0, label_alignment=
'center', **kwargs):
210 Generate a horizontal matplotlib bar figure. 212 All additional keyword arguments will be passed to 213 :func:`matplotlib.pyplot.bar`. 215 kwargs.pop(
'fmt',
None)
216 if xerr: kwargs[
'xerr'] = self.
av_yerr()
217 if yerr: kwargs[
'yerr'] = self.
av_xerr()
218 replacements = kwargs.get(
'replacements',
None)
or self.
replacements 219 xcontent = [self.
xedges[i] + self.
width[i] * yoffset
220 for i
in range(len(self.
xedges) - 1)]
221 width = [x * width
for x
in self.
width]
222 barh = plt.barh(xcontent, self.
y, width,
230 A container to hold Hist objects for plotting together. 232 When plotting, the title and the x and y labels of the last Hist added 233 will be used unless specified otherwise in the constructor. 236 if 'replacements' in kwargs:
238 utilities.HistStack.__init__(self, *args, **kwargs)
241 def hist(self, label_rotation=0, **kwargs):
243 Make a matplotlib hist plot. 245 Any additional keyword arguments will be passed to 246 :func:`matplotlib.pyplot.hist`, which allows a vast array of 247 possibilities. Particlularly, the *histtype* values such as 248 ``'barstacked'`` and ``'stepfilled'`` give substantially different 249 results. You will probably want to include a transparency value 250 (i.e. *alpha* = 0.5). 252 contents = np.dstack([hist.y
for hist
in self.
hists])
253 xedges = self.
hists[0].xedges
254 x = np.dstack([hist.x
for hist
in self.
hists])[0]
255 labels = [hist.label
for hist
in self.
hists]
257 clist = [item[
'color']
for item
in self.
kwargs]
258 plt.gca().set_color_cycle(clist)
262 plot = plt.hist(x, weights=contents, bins=xedges,
263 label=labels, **kwargs)
266 from mpl_toolkits.mplot3d
import Axes3D
271 for i, hist
in enumerate(self.
hists):
272 if self.
title is not None: hist.title = self.
title 275 labels.append(hist.label)
276 all_kwargs = copy.copy(kwargs)
277 all_kwargs.update(self.
kwargs[i])
278 bar = ax.bar(hist.x, hist.y, zs=i, zdir=
'y', width=hist.width,
281 from matplotlib.ticker
import FixedLocator
282 locator = FixedLocator(
list(range(len(labels))))
283 ax.w_yaxis.set_major_locator(locator)
284 ax.w_yaxis.set_ticklabels(labels)
285 ax.set_ylim3d(-1, len(labels))
289 Make a matplotlib bar plot, with each Hist stacked upon the last. 291 Any additional keyword arguments will be passed to 292 :func:`matplotlib.pyplot.bar`. 296 for i, hist
in enumerate(self.
hists):
297 if self.
title is not None: hist.title = self.
title 300 all_kwargs = copy.copy(kwargs)
301 all_kwargs.update(self.
kwargs[i])
302 bar = hist.bar(bottom=bottom, **all_kwargs)
304 if not bottom: bottom = [0.
for i
in range(self.
hists[0].nbins)]
305 bottom = [sum(pair)
for pair
in zip(bottom, hist.y)]
309 Make a matplotlib hist plot, with each Hist stacked upon the last. 311 Any additional keyword arguments will be passed to 312 :func:`matplotlib.pyplot.hist`. 317 for i, hist
in enumerate(self.
hists):
319 cumhist = hist + cumhist
321 cumhist = copy.copy(hist)
322 if self.
title is not None: cumhist.title = self.
title 323 if self.
xlabel is not None: cumhist.xlabel = self.
xlabel 324 if self.
ylabel is not None: cumhist.ylabel = self.
ylabel 325 all_kwargs = copy.copy(kwargs)
326 all_kwargs.update(self.
kwargs[i])
327 zorder = 0 +
float(len(self) - i)/len(self)
328 plot = cumhist.hist(zorder=zorder, **all_kwargs)
333 Make a clustered bar plot. 335 Any additional keyword arguments will be passed to 336 :func:`matplotlib.pyplot.bar`. 339 spacer = (1. - width) / 2
340 width = width / len(self.
hists)
341 for i, hist
in enumerate(self.
hists):
342 if self.
title is not None: hist.title = self.
title 345 all_kwargs = copy.copy(kwargs)
346 all_kwargs.update(self.
kwargs[i])
347 bar = hist.bar(xoffset=width*i + spacer, width=width, **all_kwargs)
350 def barh(self, width=0.8, **kwargs):
352 Make a horizontal clustered matplotlib bar plot. 354 Any additional keyword arguments will be passed to 355 :func:`matplotlib.pyplot.bar`. 358 spacer = (1. - width) / 2
359 width = width / len(self.
hists)
360 for i, hist
in enumerate(self.
hists):
361 if self.
title is not None: hist.title = self.
title 364 all_kwargs = copy.copy(kwargs)
365 all_kwargs.update(self.
kwargs[i])
366 bar = hist.barh(yoffset=width*i + spacer, width=width, **all_kwargs)
371 Make a bar plot, with all Hists in the stack overlaid. 373 Any additional keyword arguments will be passed to 374 :func:`matplotlib.pyplot.bar`. You will probably want to set a 375 transparency value (i.e. *alpha* = 0.5). 378 for i, hist
in enumerate(self.
hists):
379 if self.
title is not None: hist.title = self.
title 382 all_kwargs = copy.copy(kwargs)
383 all_kwargs.update(self.
kwargs[i])
384 bar = hist.bar(**all_kwargs)
389 Make a matplotlib errorbar plot, with all Hists in the stack overlaid. 391 Passing 'offset=True' will slightly offset each dataset so overlapping 392 errorbars are still visible. Any additional keyword arguments will 393 be passed to :func:`matplotlib.pyplot.errorbar`. 396 for i, hist
in enumerate(self.
hists):
397 if self.
title is not None: hist.title = self.
title 400 all_kwargs = copy.copy(kwargs)
401 all_kwargs.update(self.
kwargs[i])
402 transform = plt.gca().transData
404 index_offset = (len(self.
hists) - 1)/2.
405 pixel_offset = 1./72 * (i - index_offset)
406 transform = transforms.ScaledTranslation(
407 pixel_offset, 0, plt.gcf().dpi_scale_trans)
408 transform = plt.gca().transData + transform
409 errorbar = hist.errorbar(transform=transform, **all_kwargs)
410 plots.append(errorbar)
414 Make a horizontal matplotlib errorbar plot, with all Hists in the 417 Any additional keyword arguments will be passed to 418 :func:`matplotlib.pyplot.errorbar`. 421 for i, hist
in enumerate(self.
hists):
422 if self.
title is not None: hist.title = self.
title 425 all_kwargs = copy.copy(kwargs)
426 all_kwargs.update(self.
kwargs[i])
427 errorbar = hist.errorbarh(**all_kwargs)
428 plots.append(errorbar)
434 """A wrapper for TFiles, allowing easier access to methods.""" 435 def get(self, object_name, path=None):
437 return utilities.RootFile.get(self, object_name, path,
439 except ReferenceError
as e:
440 raise ReferenceError(e)
446 Modify a string based on a list of patterns and substitutions. 448 replacements should be a list of two-entry tuples, the first entry giving 449 a string to search for and the second entry giving the string with which 450 to replace it. If replacements includes a pattern entry containing 451 'use_regexp', then all patterns will be treated as regular expressions 456 if 'use_regexp' in [x
for x,y
in replacements]:
457 for pattern, repl
in [x
for x
in replacements
458 if x[0] !=
'use_regexp']:
459 string = re.sub(pattern, repl, string)
461 for pattern, repl
in replacements:
462 string = string.replace(pattern, repl)
463 if re.match(_all_whitespace_string, string):
def histstack(self, kwargs)
def errorbar(self, offset=False, kwargs)
def contour(self, kwargs)
def box(self, maxsize=40, kwargs)
def __init__(self, args, kwargs)
def barstack(self, kwargs)
def replace(string, replacements)
def hist(self, label_rotation=0, kwargs)
def show_titles(self, kwargs)
def _prepare_yaxis(self, rotation=0, alignment='center')
def _prepare_xaxis(self, rotation=0, alignment='center')
def __init__(self, args, kwargs)
def hist(self, label_rotation=0, label_alignment='center', kwargs)
def get(self, object_name, path=None)
OutputIterator zip(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp)
def errorbar(self, xerr=False, yerr=False, label_rotation=0, label_alignment='center', kwargs)
def barh(self, xerr=False, yerr=False, yoffset=0., width=0.8, label_rotation=0, label_alignment='center', kwargs)
def __init__(self, args, kwargs)
def bar(self, xerr=False, yerr=False, xoffset=0., width=0.8, label_rotation=0, label_alignment='center', kwargs)
def barh(self, width=0.8, kwargs)
def errorbarh(self, xerr=False, yerr=False, label_rotation=0, label_alignment='center', kwargs)
def errorbarh(self, kwargs)
def barcluster(self, width=0.8, kwargs)
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run
def show_titles(self, kwargs)