2 Utilities for plotting ROOT histograms in matplotlib. 6 Copyright (c) 2009-2010 Jeff Klukas <klukas@wisc.edu> 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 34 from rootplot
import utilities
35 import matplotlib
as mpl
36 import matplotlib.pyplot
as plt
37 import matplotlib.transforms
as transforms
42 _all_whitespace_string = re.compile(
r'\s*$')
48 """A container to hold the parameters from a 2D ROOT histogram.""" 51 if 'replacements' in kwargs:
53 utilities.Hist2D.__init__(self, *args, **kwargs)
55 """Draw a contour plot.""" 56 cs = plt.contour(self.
x, self.
y, self.
content, **kwargs)
57 plt.clabel(cs, inline=1, fontsize=10)
63 def col(self, **kwargs):
64 """Draw a colored box plot using :func:`matplotlib.pyplot.imshow`.""" 66 kwargs[
'cmap'] = plt.get_cmap(kwargs[
'cmap'])
67 plot = plt.imshow(self.
content, interpolation=
'nearest',
70 aspect=
'auto', origin=
'lower', **kwargs)
74 Draw a colored box plot with a colorbar using 75 :func:`matplotlib.pyplot.imshow`. 77 plot = self.
col(**kwargs)
80 def box(self, maxsize=40, **kwargs):
82 Draw a box plot with size indicating content using 83 :func:`matplotlib.pyplot.scatter`. 85 The data will be normalized, with the largest box using a marker of 86 size maxsize (in points). 88 x = np.hstack([self.
x for i
in range(self.
nbinsy)])
89 y = np.hstack([[yval
for i
in range(self.
nbinsx)]
for yval
in self.
y])
94 plot = plt.scatter(x, y, sizes, marker=
's', **kwargs)
97 """Return a ROOT.TH2F object with contents of this Hist2D.""" 98 th2f = ROOT.TH2F(name,
"",
102 for ix
in range(self.
nbinsx):
103 for iy
in range(self.
nbinsy):
104 th2f.SetBinContent(ix + 1, iy + 1, self.
content[iy][ix])
108 """A container to hold the parameters from a ROOT histogram.""" 111 if 'replacements' in kwargs:
113 utilities.Hist.__init__(self, *args, **kwargs)
115 """Apply bounds and text labels on x axis.""" 119 rotation=rotation, ha=alignment)
123 """Apply bounds and text labels on y axis.""" 127 rotation=rotation, va=alignment)
131 """Print the title and axis labels to the current figure.""" 132 replacements = kwargs.get(
'replacements',
None)
or self.
replacements 136 def hist(self, label_rotation=0, label_alignment='center', **kwargs):
138 Generate a matplotlib hist figure. 140 All additional keyword arguments will be passed to 141 :func:`matplotlib.pyplot.hist`. 143 kwargs.pop(
'fmt',
None)
144 replacements = kwargs.get(
'replacements',
None)
or self.
replacements 148 weights = [1.e-10] * self.
nbins 149 plot = plt.hist(self.
x, weights=weights, bins=self.
xedges,
153 def errorbar(self, xerr=False, yerr=False, label_rotation=0,
154 label_alignment=
'center', **kwargs):
156 Generate a matplotlib errorbar figure. 158 All additional keyword arguments will be passed to 159 :func:`matplotlib.pyplot.errorbar`. 162 kwargs[
'xerr'] = self.
xerr 164 kwargs[
'yerr'] = self.
yerr 165 replacements = kwargs.get(
'replacements',
None)
or self.
replacements 166 errorbar = plt.errorbar(self.
x, self.
y,
171 def errorbarh(self, xerr=False, yerr=False, label_rotation=0,
172 label_alignment=
'center', **kwargs):
174 Generate a horizontal matplotlib errorbar figure. 176 All additional keyword arguments will be passed to 177 :func:`matplotlib.pyplot.errorbar`. 179 if xerr: kwargs[
'xerr'] = self.
yerr 180 if yerr: kwargs[
'yerr'] = self.
xerr 181 replacements = kwargs.get(
'replacements',
None)
or self.
replacements 182 errorbar = plt.errorbar(self.
y, self.
x,
187 def bar(self, xerr=False, yerr=False, xoffset=0., width=0.8,
188 label_rotation=0, label_alignment=
'center', **kwargs):
190 Generate a matplotlib bar figure. 192 All additional keyword arguments will be passed to 193 :func:`matplotlib.pyplot.bar`. 195 kwargs.pop(
'fmt',
None)
196 if xerr: kwargs[
'xerr'] = self.
av_xerr()
197 if yerr: kwargs[
'yerr'] = self.
av_yerr()
198 replacements = kwargs.get(
'replacements',
None)
or self.
replacements 199 ycontent = [self.
xedges[i] + self.
width[i] * xoffset
200 for i
in range(len(self.
xedges) - 1)]
201 width = [x * width
for x
in self.
width]
202 bar = plt.bar(ycontent, self.
y, width,
206 def barh(self, xerr=False, yerr=False, yoffset=0., width=0.8,
207 label_rotation=0, label_alignment=
'center', **kwargs):
209 Generate a horizontal matplotlib bar figure. 211 All additional keyword arguments will be passed to 212 :func:`matplotlib.pyplot.bar`. 214 kwargs.pop(
'fmt',
None)
215 if xerr: kwargs[
'xerr'] = self.
av_yerr()
216 if yerr: kwargs[
'yerr'] = self.
av_xerr()
217 replacements = kwargs.get(
'replacements',
None)
or self.
replacements 218 xcontent = [self.
xedges[i] + self.
width[i] * yoffset
219 for i
in range(len(self.
xedges) - 1)]
220 width = [x * width
for x
in self.
width]
221 barh = plt.barh(xcontent, self.
y, width,
229 A container to hold Hist objects for plotting together. 231 When plotting, the title and the x and y labels of the last Hist added 232 will be used unless specified otherwise in the constructor. 235 if 'replacements' in kwargs:
237 utilities.HistStack.__init__(self, *args, **kwargs)
240 def hist(self, label_rotation=0, **kwargs):
242 Make a matplotlib hist plot. 244 Any additional keyword arguments will be passed to 245 :func:`matplotlib.pyplot.hist`, which allows a vast array of 246 possibilities. Particlularly, the *histtype* values such as 247 ``'barstacked'`` and ``'stepfilled'`` give substantially different 248 results. You will probably want to include a transparency value 249 (i.e. *alpha* = 0.5). 251 contents = np.dstack([hist.y
for hist
in self.
hists])
252 xedges = self.
hists[0].xedges
253 x = np.dstack([hist.x
for hist
in self.
hists])[0]
254 labels = [hist.label
for hist
in self.
hists]
256 clist = [item[
'color']
for item
in self.
kwargs]
257 plt.gca().set_color_cycle(clist)
261 plot = plt.hist(x, weights=contents, bins=xedges,
262 label=labels, **kwargs)
265 from mpl_toolkits.mplot3d
import Axes3D
270 for i, hist
in enumerate(self.
hists):
271 if self.
title is not None: hist.title = self.
title 274 labels.append(hist.label)
275 all_kwargs = copy.copy(kwargs)
276 all_kwargs.update(self.
kwargs[i])
277 bar = ax.bar(hist.x, hist.y, zs=i, zdir=
'y', width=hist.width,
280 from matplotlib.ticker
import FixedLocator
281 locator = FixedLocator(range(len(labels)))
282 ax.w_yaxis.set_major_locator(locator)
283 ax.w_yaxis.set_ticklabels(labels)
284 ax.set_ylim3d(-1, len(labels))
288 Make a matplotlib bar plot, with each Hist stacked upon the last. 290 Any additional keyword arguments will be passed to 291 :func:`matplotlib.pyplot.bar`. 295 for i, hist
in enumerate(self.
hists):
296 if self.
title is not None: hist.title = self.
title 299 all_kwargs = copy.copy(kwargs)
300 all_kwargs.update(self.
kwargs[i])
301 bar = hist.bar(bottom=bottom, **all_kwargs)
303 if not bottom: bottom = [0.
for i
in range(self.
hists[0].nbins)]
304 bottom = [sum(pair)
for pair
in zip(bottom, hist.y)]
308 Make a matplotlib hist plot, with each Hist stacked upon the last. 310 Any additional keyword arguments will be passed to 311 :func:`matplotlib.pyplot.hist`. 316 for i, hist
in enumerate(self.
hists):
318 cumhist = hist + cumhist
320 cumhist = copy.copy(hist)
321 if self.
title is not None: cumhist.title = self.
title 322 if self.
xlabel is not None: cumhist.xlabel = self.
xlabel 323 if self.
ylabel is not None: cumhist.ylabel = self.
ylabel 324 all_kwargs = copy.copy(kwargs)
325 all_kwargs.update(self.
kwargs[i])
326 zorder = 0 +
float(len(self) - i)/len(self)
327 plot = cumhist.hist(zorder=zorder, **all_kwargs)
332 Make a clustered bar plot. 334 Any additional keyword arguments will be passed to 335 :func:`matplotlib.pyplot.bar`. 338 spacer = (1. - width) / 2
339 width = width / len(self.
hists)
340 for i, hist
in enumerate(self.
hists):
341 if self.
title is not None: hist.title = self.
title 344 all_kwargs = copy.copy(kwargs)
345 all_kwargs.update(self.
kwargs[i])
346 bar = hist.bar(xoffset=width*i + spacer, width=width, **all_kwargs)
349 def barh(self, width=0.8, **kwargs):
351 Make a horizontal clustered matplotlib bar plot. 353 Any additional keyword arguments will be passed to 354 :func:`matplotlib.pyplot.bar`. 357 spacer = (1. - width) / 2
358 width = width / len(self.
hists)
359 for i, hist
in enumerate(self.
hists):
360 if self.
title is not None: hist.title = self.
title 363 all_kwargs = copy.copy(kwargs)
364 all_kwargs.update(self.
kwargs[i])
365 bar = hist.barh(yoffset=width*i + spacer, width=width, **all_kwargs)
370 Make a bar plot, with all Hists in the stack overlaid. 372 Any additional keyword arguments will be passed to 373 :func:`matplotlib.pyplot.bar`. You will probably want to set a 374 transparency value (i.e. *alpha* = 0.5). 377 for i, hist
in enumerate(self.
hists):
378 if self.
title is not None: hist.title = self.
title 381 all_kwargs = copy.copy(kwargs)
382 all_kwargs.update(self.
kwargs[i])
383 bar = hist.bar(**all_kwargs)
388 Make a matplotlib errorbar plot, with all Hists in the stack overlaid. 390 Passing 'offset=True' will slightly offset each dataset so overlapping 391 errorbars are still visible. Any additional keyword arguments will 392 be passed to :func:`matplotlib.pyplot.errorbar`. 395 for i, hist
in enumerate(self.
hists):
396 if self.
title is not None: hist.title = self.
title 399 all_kwargs = copy.copy(kwargs)
400 all_kwargs.update(self.
kwargs[i])
401 transform = plt.gca().transData
403 index_offset = (len(self.
hists) - 1)/2.
404 pixel_offset = 1./72 * (i - index_offset)
405 transform = transforms.ScaledTranslation(
406 pixel_offset, 0, plt.gcf().dpi_scale_trans)
407 transform = plt.gca().transData + transform
408 errorbar = hist.errorbar(transform=transform, **all_kwargs)
409 plots.append(errorbar)
413 Make a horizontal matplotlib errorbar plot, with all Hists in the 416 Any additional keyword arguments will be passed to 417 :func:`matplotlib.pyplot.errorbar`. 420 for i, hist
in enumerate(self.
hists):
421 if self.
title is not None: hist.title = self.
title 424 all_kwargs = copy.copy(kwargs)
425 all_kwargs.update(self.
kwargs[i])
426 errorbar = hist.errorbarh(**all_kwargs)
427 plots.append(errorbar)
433 """A wrapper for TFiles, allowing easier access to methods.""" 434 def get(self, object_name, path=None):
436 return utilities.RootFile.get(self, object_name, path,
438 except ReferenceError
as e:
439 raise ReferenceError(e)
445 Modify a string based on a list of patterns and substitutions. 447 replacements should be a list of two-entry tuples, the first entry giving 448 a string to search for and the second entry giving the string with which 449 to replace it. If replacements includes a pattern entry containing 450 'use_regexp', then all patterns will be treated as regular expressions 455 if 'use_regexp' in [x
for x,y
in replacements]:
456 for pattern, repl
in [x
for x
in replacements
457 if x[0] !=
'use_regexp']:
458 string = re.sub(pattern, repl, string)
460 for pattern, repl
in replacements:
461 string = string.replace(pattern, repl)
462 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)
def show_titles(self, kwargs)