Giter Club home page Giter Club logo

mplhep's Introduction

scikit-hep: metapackage for Scikit-HEP

image

image

image

image

image

image

image

Project info

The Scikit-HEP project is a community-driven and community-oriented project with the aim of providing Particle Physics at large with an ecosystem for data analysis in Python embracing all major topics involved in a physicist's work. The project started in Autumn 2016 and its packages are actively developed and maintained.

It is not just about providing core and common tools for the community. It is also about improving the interoperability between HEP tools and the Big Data scientific ecosystem in Python, and about improving on discoverability of utility packages and projects.

For what concerns the project grand structure, it should be seen as a toolset rather than a toolkit.

Getting in touch

There are various ways to get in touch with project admins and/or users and developers.

scikit-hep package

scikit-hep is a metapackage for the Scikit-HEP project.

Installation

You can install this metapackage from PyPI with `pip`:

python -m pip install scikit-hep

or you can use Conda through conda-forge:

conda install -c conda-forge scikit-hep

All the normal best-practices for Python apply; you should be in a virtual environment, etc.

Package version and dependencies

Please check the setup.cfg and requirements.txt files for the list of Python versions supported and the list of Scikit-HEP project packages and dependencies included, respectively.

For any installed scikit-hep the following displays the actual versions of all Scikit-HEP dependent packages installed, for example:

>>> import skhep
>>> skhep.show_versions()

System:
    python: 3.10.10 | packaged by conda-forge | (main, Mar 24 2023, 20:08:06) [GCC 11.3.0]
executable: /srv/conda/envs/notebook/bin/python
   machine: Linux-5.15.0-72-generic-x86_64-with-glibc2.27

Python dependencies:
       pip: 23.1.2
     numpy: 1.24.3
     scipy: 1.10.1
    pandas: 2.0.2
matplotlib: 3.7.1

Scikit-HEP package version and dependencies:
        awkward: 2.2.2
boost_histogram: 1.3.2
  decaylanguage: 0.15.3
       hepstats: 0.6.1
       hepunits: 2.3.2
           hist: 2.6.3
     histoprint: 2.4.0
        iminuit: 2.21.3
         mplhep: 0.3.28
       particle: 0.22.0
          pylhe: 0.6.0
       resample: 1.6.0
          skhep: 2023.06.09
         uproot: 5.0.8
         vector: 1.0.0

Note on the versioning system:

This package uses Calendar Versioning (CalVer).

mplhep's People

Contributors

actions-user avatar agoose77 avatar andrzejnovak avatar bsathian avatar chrisburr avatar clelange avatar dantrim avatar dominic-stafford avatar eduardo-rodrigues avatar fmazzasc avatar graipher avatar hdembinski avatar henryiii avatar jdamp avatar jjhw3 avatar jonas-eschle avatar kpedro88 avatar kratsg avatar lgray avatar lmoureaux avatar lovelybuggies avatar marinang avatar matthewfeickert avatar ming-yan avatar pfackeldey avatar pfs avatar pre-commit-ci[bot] avatar swertz avatar veprbl avatar yimuchen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

mplhep's Issues

Add label default

In the style of:

mplhep.config.paper=True
mplhep.config.data=True
mplhep.config.lumi=10

Use 'ndim' instead of 'rank'

image

>>> boost_histogram.__version__, mplhep.__version__
('0.8.0', '0.1.22')

It was discussed in boost-histogram here: scikit-hep/boost-histogram#379

And now when you ask for the rank of a bh.Histogram, you get the above warning.

https://github.com/scikit-hep/boost-histogram/blob/f8b15b9f21f94691f5f4151cf800b29dc2688d68/src/boost_histogram/_internal/hist.py#L501-L508

I think this is where mplhep calls it:

mplhep/mplhep/plot.py

Lines 104 to 108 in 6b04c75

if hasattr(h, "rank") and hasattr(h, "to_numpy"):
# Boost histogram compat
if h.rank > 1:
raise ValueError("More than 1 axis")
h, bins = h.to_numpy()

Personally, I use len(array.shape) because this always works. It dates back to antiquity, though array.ndim is pretty old, too:

>>> # This is a sandbox; not the version of NumPy I really use!
>>> numpy.__version__
'1.10.4'
>>> len(array.shape)
3
>>> array.ndim
3
>>> array.rank
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'numpy.ndarray' object has no attribute 'rank'

Stacking a single histogram

Hi,

I am wondering about the explicit check of the number of histograms in a stack here.

I run into this check a lot when I e.g. select datasets in my coffea histograms to be overlaid using a regular expression. In order to produce many plots in an automated way, I'd like to be able to use the same plotting code whether my regex matches 1 or N>1 data sets.

I tried simply removing the check and the code runs fine, which is also what I'd have expected since a single-histogram stack is well-defined. Are there any strong reasons to abort plotting in this case?

Figure -> HEPData table

The data associated to figures often goes into HEPData.

Could consider a utility that exports data for a figure in HEPData table format.
This might be considered out of scope for the package.

LHCb style and duplication

There is a LHCb mplstyle file around and a lhcb_style.py, they seem to be duplicated. What is the purpose of this, shouldn't one be removed in favor of the other? Or how are they meant to be used?

Furthermore, the style used seems, at least for our usecase of plotting a function and a hist, overlaying both, non-optimized: the line is drawn as points, the fonts look to large. Is there a reason (e.g. official lhcb guidelines) that the current LHCb style is the way it is or was it simply contributed to reflect something close enough?

Buggy plotting of histogram

I gave mplhep another try, but I immediately found a bug. I cannot recommend a tool to my students and colleagues, when it is so brittle.

Version: mplhep-0.1.33

import numpy as np
import mplhep

edges = np.array([ 990.,  991.,  992.,  993.,  994.,  995.,  996.,  997.,  998.,
        999., 1000., 1001., 1002., 1003., 1004., 1005., 1006., 1007.,
       1008., 1009., 1010., 1011., 1012., 1013., 1014., 1015., 1016.,
       1017., 1018., 1019., 1020., 1021., 1022., 1023., 1024., 1025.,
       1026., 1027., 1028., 1029., 1030., 1031., 1032., 1033., 1034.,
       1035., 1036., 1037., 1038., 1039., 1040., 1041., 1042., 1043.,
       1044., 1045., 1046., 1047., 1048., 1049., 1050.])

w = np.array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  0., 82.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])

mplhep.histplot(w, edges)

produces
example

The plot should start at the lower edge of the lowest bin, but it starts at zero. histplot should support the automatic range selection of matplotlib, that is used by pyplot.plot, etc.

It works fine with my own plotting tool which predates mplhep, pyik.mplext.plot_hist, because I use plt.plot to do the actual drawing.

ratio plot

Hi,

for some of my work I created a somehwat drop-in-ish replacement for plt.subplots but for ratio plots.. is this something that'd be interesting for this package?

I didn't immediatly see functionality for this in mplhep yet

cc @kratsg @matthewfeickert

screenshot

Install .mplstyles files

Can the setup.py copy the .mplstyle files to the appropriate location automatically (I.e., the user directory where he other styles in plt.style.available are stored)?

I would like this so that the styles are treated in an equal footing with all the other ones.

Iโ€™m actually a bit confused about the duplication of mpl styles - we have the .mplstyle files and dictionaries containing similar (possibly identical) information.

hist2dplot should not require transposing

In this example on the frontpage

import numpy as np
import matplotlib.pyplot as plt
import mplhep as hep

fig, ax = plt.subplots()

xedges = [0, 1, 3, 5]
yedges = [0, 2, 3, 4, 6,7]
x = np.random.normal(2, 1, 100)
y = np.random.normal(4, 1, 100)
H, xedges, yedges = np.histogram2d(x, y, bins=(xedges, yedges))
H = H.T

hep.hist2dplot(H, xedges, yedges)

the line H = H.T shouldn't be necessary. You need to transpose for pcolor, but because pcolor was never made for histograms, it was made for images. hist2dplot should not copy this unnecessary step, since it is specifically for histograms.

Experiment labels should be subclasses of Text

Creating a subclass of ~Axes.Text for experiment labels would allow for solving #61 with simple functions like:

def rename(text, ax=ax):
    children = ax.get_children()
    # iterate over children until object is type(ExperimentLabel)
    ExperimentLabel.set_secondary_text(text)
    # possibly add autosave

ATLAS style axis labels incorrect

Axis labels in ATLAS style are much too large and positions incorrect. Here are the options I made to fix:
plt.style.use([hep.style.ATLAS, {'axes.labelsize': 20}, {'axes.labelpad': 20}, {'axes.titlelocation': 'right'}, ])
Incidentally the {'axes.titlelocation': 'right'} doesn't seem to change anything, and neither does plt.xlabel(r"xlabel", ha='right'). I'm not sure if that's an issue with mplhep or matplotlib

PyPI release v0.0.13 is broken upon import

@andrzejnovak The current release of mplhep on PyPI (v0.0.13) is broken upon import due to a missing module:

ModuleNotFoundError: No module named 'mplhep.error_estimation'

Minimal failing example

$ python --version
Python 3.7.5rc1
$ python -m venv test-example
$ source ~/test-example/bin/activate
(test-example) $ pip install --upgrade pip setuptools wheel
(test-example) $ pip list
Package       Version
------------- -------
pip           19.3.1 
pkg-resources 0.0.0  
setuptools    41.6.0 
wheel         0.33.6 
(test-example) $ pip install mplhep
(test-example) $ pip list | grep mplhep
mplhep          0.0.13
(test-example) $ python
Python 3.7.5rc1 (default, Oct  8 2019, 16:47:45) 
[GCC 9.2.1 20191008] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib.pyplot as plt
>>> import mplhep as hep
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/feickert/.venvs/test-example/lib/python3.7/site-packages/mplhep/__init__.py", line 5, in <module>
    from . import cms
  File "/home/feickert/.venvs/test-example/lib/python3.7/site-packages/mplhep/cms.py", line 6, in <module>
    from . import plot
  File "/home/feickert/.venvs/test-example/lib/python3.7/site-packages/mplhep/plot.py", line 7, in <module>
    from .error_estimation import poisson_interval
ModuleNotFoundError: No module named 'mplhep.error_estimation'

Setting histplot color when specifying yerr or w2

It seems that when one requests yerr or w2 when calling histplot for a 'step' histtype, the user no longer can specify the color of the histogram. This is because the color='blah' argument from the histplot call gets passed in the kwargs in the call to errorbar, while at the same time color=_s.get_color() is passed explicitly to errorbar. Thus a conflict arises and the user receives the error: TypeError: errorbar() got multiple values for keyword argument 'color'

setup.py should not require libraries outside of the standard library

At the moment setup.py uses six to determine the version of matplotlib to install

https://github.com/andrzejnovak/mplhep/blob/d7e2c57a53ab2a5dc454174a5ddbe92498b33701/setup.py#L1-L9

However, as six is not in the standard library then from a fresh virtual environment installation of mplhep fails

$ pip list
Package    Version
---------- -------
pip        19.3.1 
setuptools 41.6.0 
wheel      0.33.6 
$ cat requirements.txt 
mplhep~=0.0
$ pip install -r requirements.txt 
Collecting mplhep~=0.0
  Downloading https://files.pythonhosted.org/packages/ff/ef/f00b74a3027a4ece7661c3dda8431d36392240e06dbd31cba146d0e05159/mplhep-0.0.11.tar.gz (6.3MB)
     |โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 6.3MB 5.3MB/s 
    ERROR: Command errored out with exit status 1:
     command: /home/mcf/venvs/fork-func_adl_electrons/bin/python3.6 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-rao1ybnx/mplhep/setup.py'"'"'; __file__='"'"'/tmp/pip-install-rao1ybnx/mplhep/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-install-rao1ybnx/mplhep/pip-egg-info
         cwd: /tmp/pip-install-rao1ybnx/mplhep/
    Complete output (5 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-rao1ybnx/mplhep/setup.py", line 4, in <module>
        import six
    ModuleNotFoundError: No module named 'six'
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

I would suggest using if sys.version_info.major < 3 instead.

MPLHEP Not installing

Hi,

MPLHEP is not getting instaled, I'm doing PIp install from Miniconda python v3.7.

Here are the logs

Collecting mplhep Using cached https://files.pythonhosted.org/packages/9a/fc/ebc62df8eb5ba82ef6a8ea2ac654057f198595ffba259a0112525602898d/mplhep-0.0.17.tar.gz ERROR: Command errored out with exit status 1: command: /cms/base/Miniconda/miniconda/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-_xj4eiz9/mplhep/setup.py'"'"'; __file__='"'"'/tmp/pip-install-_xj4eiz9/mplhep/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-install-_xj4eiz9/mplhep/pip-egg-info cwd: /tmp/pip-install-_xj4eiz9/mplhep/ Complete output (15 lines): Traceback (most recent call last): File "<string>", line 1, in <module> File "/cvmfs/oasis.opensciencegrid.org/mis/osg-wn-client/3.4/3.4.39/el7-x86_64/usr/lib/python2.7/site-packages/setuptools/__init__.py", line 2, in <module> from setuptools.extension import Extension, Library File "/cvmfs/oasis.opensciencegrid.org/mis/osg-wn-client/3.4/3.4.39/el7-x86_64/usr/lib/python2.7/site-packages/setuptools/extension.py", line 5, in <module> from setuptools.dist import _get_unpatched File "/cvmfs/oasis.opensciencegrid.org/mis/osg-wn-client/3.4/3.4.39/el7-x86_64/usr/lib/python2.7/site-packages/setuptools/dist.py", line 7, in <module> from setuptools.command.install import install File "/cvmfs/oasis.opensciencegrid.org/mis/osg-wn-client/3.4/3.4.39/el7-x86_64/usr/lib/python2.7/site-packages/setuptools/command/__init__.py", line 8, in <module> from setuptools.command import install_scripts File "/cvmfs/oasis.opensciencegrid.org/mis/osg-wn-client/3.4/3.4.39/el7-x86_64/usr/lib/python2.7/site-packages/setuptools/command/install_scripts.py", line 3, in <module> from pkg_resources import Distribution, PathMetadata, ensure_directory File "/cvmfs/oasis.opensciencegrid.org/mis/osg-wn-client/3.4/3.4.39/el7-x86_64/usr/lib/python2.7/site-packages/pkg_resources.py", line 1545, in <module> register_loader_type(importlib_bootstrap.SourceFileLoader, DefaultProvider) AttributeError: module 'importlib._bootstrap' has no attribute 'SourceFileLoader' ---------------------------------------- ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

[feat] Could orientation="vertical" be added?

Hello,

We are designing a lib based on boost-histogram and mplhep. We want to build a plotting function that can draw the 2d histogram and its projections with respect to different axes - plot2d_full in scikit-hep/hist#80.

Everything goes well except this:

import boost_histogram as bh
import mplhep
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.transforms as transforms


h = bh.Histogram(bh.axis.Regular(50, -5, 5),
                 bh.axis.Regular(50, -5, 5))

h.fill(
    np.random.normal(size=50_000), np.random.normal(size=50_000)
)

fig = plt.figure(figsize=(5, 5))
grid = fig.add_gridspec(5, 5, hspace=0, wspace=0)

ax1 = fig.add_subplot(grid[1:5, 0:4])
ax2 = fig.add_subplot(grid[0:1, 0:4], sharex=ax1)
ax3 = fig.add_subplot(grid[1:5, 4:5], sharey=ax1)

ax1 = mplhep.hist2dplot(h, ax=ax1, cbar=False)
ax2 = mplhep.histplot(
            h.project(1),
            ax=ax2,
            lw=4
        )


base = plt.gca().transData
rot = transforms.Affine2D().rotate_deg(270)
ax3 = mplhep.histplot(
    h.project(0),
    ax=ax3,
    transform=rot + base,
    lw=4,
)

We expect an output like this:

image

But actually it comes to this:

image

And I find the rotation is not properly displayed:

mplhep.histplot(
    h.project(0),
    transform=rot + base,
    lw=4
)

image

Could you help to find if there is any problem with histplot or where I do mistakenly?

By the way, @henryiii thought using Line2d and QuadMesh, etc. would be a better idea for the return types of histplot/2d, do you think so?

Thanks!

Setting the style causes an error with Matplotlib 3.1.0

I'm using mplhep-0.1.29 from pip on LCG 98, which has Matplotlib 3.1.0. I get an exception when doing plt.style.use(hep.style.ROOT) as documented:

>>> import matplotlib as mpl
>>> mpl.__version__
'3.1.0'
>>> import mplhep as hep
>>> hep.__version__
'0.1.29'
>>> mpl.style.use(hep.style.ROOT)
Traceback (most recent call last):
  File "/cvmfs/sft.cern.ch/lcg/views/LCG_98python3/x86_64-slc6-gcc8-opt/lib/python3.6/site-packages/matplotlib/__init__.py", line 789, in __setitem__
    cval = self.validate[key](val)
KeyError: 'xaxis.labellocation'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/cvmfs/sft.cern.ch/lcg/views/LCG_98python3/x86_64-slc6-gcc8-opt/lib/python3.6/site-packages/matplotlib/style/core.py", line 101, in use
    _apply_style(style)
  File "/cvmfs/sft.cern.ch/lcg/views/LCG_98python3/x86_64-slc6-gcc8-opt/lib/python3.6/site-packages/matplotlib/style/core.py", line 62, in _apply_style
    mpl.rcParams.update(_remove_blacklisted_style_params(d, warn=warn))
  File "/cvmfs/sft.cern.ch/lcg/releases/Python/3.6.5-6b228/x86_64-slc6-gcc8-opt/lib/python3.6/_collections_abc.py", line 841, in update
    self[key] = other[key]
  File "/cvmfs/sft.cern.ch/lcg/views/LCG_98python3/x86_64-slc6-gcc8-opt/lib/python3.6/site-packages/matplotlib/__init__.py", line 795, in __setitem__
    f"{key} is not a valid rc parameter (see rcParams.keys() for "
KeyError: 'xaxis.labellocation is not a valid rc parameter (see rcParams.keys() for a list of valid parameters)'

cmstext not working with scientific notation

When one has very large numbers on the y axis, one can make use of scientific notation to make things more readable in matplotplib using ax.ticklabel_format(axis="y", style="sci", scilimits=(0, 0)). Matplotlib then will write e.g. 2.0 instead of 20000 as tick label and a 1e5 on the top left of the plot. Unfortunately this is exactly where mplhep.cms.cmstext places the "CMS" label and so they are on top of each other.

I understand one can adjust the location with the loc parameter, but that one only offers to move the label inside the plot. It would be preferable if one could place the "CMS" label next to the tick scale (outside the plot).

cmslabel() doesn't work as documented

The README gives the following example:

ax = hep.cms.cmslabel(ax, data=False, paper=False, year='2017')

However this syntax fails:

Traceback (most recent call last):
  File "plot-migration-maps.py", line 52, in <module>
    ax = hep.cms.cmslabel(ax, data=False, paper=False, year='2017')
TypeError: cmslabel() takes 0 positional arguments but 1 was given

One needs to pass ax=ax as the first argument. The original syntax was working in January, I'm not sure if the change was intended, but either the README should be updated or the argument list fixed ;)

btw thank you for this great library!

Add CONTRIBUTING.md

If you want me and others to follow rules when contributing, please write this down or accept that I cannot follow rules that are not stated.

Cite mplhep.

Can a Zenodo DOI be created? I would like to cite mplhep in my thesis :D.

Wrong default display for mplhep.histplot

The command
hep.histplot(h, bins, ax=axs[0])
does not produce a histogram in HEP-style. It draws markers at the edges, which is wrong, and the lines of the histogram do not go down to zero.

hep.histplot(h, bins, edges=True, ax=axs[1])
is closer to the expected skyline, but the markers are still wrong. Apart from the wrong markers, this should be the default. In fact, I cannot imagine that one ever wants to have edges=False.

Color not supported with multi-entry stacked histplot

If color= is passed to histplot we get a single color for all histograms (the first entry in the list). Since it's a keyword argument just passed off to matplotlib in a loop here here:

mplhep/mplhep/plot.py

Lines 173 to 179 in 8481869

for i in range(_nh):
if not _mpl_up:
_h = np.r_[h[i], h[i][-1]]
else:
_h = h[i]
ax.fill_between(bins, _h, step=_where,
label=_labels[i], **kwargs)

It looks like color needs to be addressed in the loop so we use color[i]. Since the whole list of colors is being fed to Matplotlib on each iteration of the loop I guess it just takes the first entry. I'll try to come up with a patch when I have some time, but for now I just wanted to share.

minimal reproducer:

import matplotlib as mpl
mpl.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
from mplhep import histplot

bins = np.linspace(-3, 3, 20)
x = np.random.randn(10000)
h1, _ = np.histogram(x, bins=bins)
h2, _ = np.histogram(x, bins=bins, weights=np.ones_like(x) * 0.50)
h3, _ = np.histogram(x, bins=bins, weights=np.ones_like(x) * 0.25)

fig, ax = plt.subplots()
histplot(
    h=[h1, h2, h3],
    bins=bins,
    label=["1", "2", "3"],
    stack=True,
    histtype="fill",
    color=["C2", "C5", "C0"],
    ax=ax,
)

fig.savefig("test.png")

test

If the color argument is removed we get auto coloring

test

[Discussion] prebinned spec

Alright, since we're separating this from the discussion in #100. To summarize the consensus there:

  • We want to revamp the primary 1D hist plot functions
  • Call it prebinned to signify its purpose of plotting "prebinned" histograms and differentiate it from pyplot.hist
  • Primary design goal - keep API as close as possible to pyplot.hist to minimize difficulty transitioning

Minimal docstring/spec below from histplot, excluding extra kwargs.

"""
Create a 1D histogram plot from `np.histogram`-like inputs.
    Parameters
    ----------
        h : histogram object or sequence of histogram objects
            Input histogram, either single or multiple.
            A histogram object contains at least values.
            The following should be interpretable
            - [ ] `np.histogram` tuple 
            - [ ] `boost_histogram` object or any object with a `to_numpy()` method
            - [ ] array of values
        bins : iterable, optional
            Histogram bins, if not part of ``h``. I.e. when ``h`` is array of values.

    Keyword-only Parameters
    ----------
        yerr : iterable or bool, optional
            Histogram uncertainties. Following modes are supported:
            - ``True``, automated error calculation
               - sqrt(h) errors or Poissonian interval when ``w2`` is specified
            - shape(N) array of for one-sided errors or list thereof
            - shape(Nx2) array of for two-sided errors or list thereof
        w2 : iterable, optional
            Sum of the histogram weights squared for Poissonian interval error calculation
        histtype : {'step', 'stepfilled', 'errorbar', 'band', 'step-error'}, default: 'step'
            The type of histogram to draw.
            - 'step' generates a lineplot that is unfilled.
            - 'stepfilled' generates a lineplot that is filled.
            - 'errorbar' gives equivalent result the `pyplot.errorbar` with ``xerr`` set to binwidth 
               (by default not plotted)
            - 'band' generates a fill_between plot withing the ``yerr`` values
            - 'step-error' combination of "step" and "errorbar"
            - 'bar' - raise warning, default to "step"        
        ax : matplotlib.axes.Axes, optional
            Axes object (if None, last one is fetched or one is created)
        **kwargs :
            Keyword arguments passed to underlying matplotlib artist - ``Line2D``.
    Returns
    -------
        ax : matplotlib.axes.Axes
            A matplotlib `Axes <https://matplotlib.org/3.1.1/api/axes_api.html>`_ object
"""

@HDembinski Let's sort these out and we can discuss the rest of the kwargs later.

I expect that one point of contention is allowing to set the bins directly.

hep.prebinned([3,4,5,3], [0,1,2,3,4])

I don't think there's a strong argument, why "bins" needs to be an arg, but I think it makes sense to not force the user to only use it as a kwarg, because I don't see what bad behaviour would be prevented by that. Plus it works in pyplot.hist

Kudos

I just wanted to send kudos for the fabiola style. Well done!

Better function names

The chosen function names are not ideal.

histplot -> hist

  • histplot is not Pythonic snake_case, it should have been hist_plot for better readability but actually...
  • since it is supposed to mimic plt.hist, it should have the same name

hist2dplot -> hist2 or hist2d

  • theplot at the end is superfluous, and again it is not proper snake_case

Altair dependency

Installing 0.0.17 results shows the following error

ERROR: altair 3.2.0 requires entrypoints, which is not installed.
ERROR: altair 3.2.0 requires jinja2, which is not installed.
ERROR: altair 3.2.0 requires jsonschema, which is not installed.

I was not aware of altair dependency. @matthewfeickert Do you have an idea where this could have been introduced?

Support for matplotlib 3.1?

Is FontManager critical? i.e. could we detect mpl version on import and do the appropriate so we can still use mplhep with (slightly) older mpl

ATLAS style susceptible to matplotlib math font bugs

@andrzejnovak I know that you're already aware of this, as you were the one to open up the matplotlib issue matplotlib/matplotlib#14829, but the example that you reported there affects ATLAS style as can be seen here:

import numpy as np
import matplotlib.pyplot as plt
import mplhep


def make_plot(title=None):
    fig, ax = plt.subplots()
    x = np.linspace(0, 10, 101)
    y = np.square(x)
    ax.plot(x, y)
    ax.semilogy()

    ax.set_xlabel("$x$")
    ax.set_ylabel("$x^2$")
    if title is not None:
        ax.set_title(title)

    return fig, ax


def main():
    image_types = ["pdf", "png"]
    fig, ax = make_plot("Default matplotlib settings")

    for type in image_types:
        fig.savefig(f"default.{type}")

    plt.style.use(mplhep.style.ATLAS)
    fig, ax = make_plot("mplhep ATLAS style")
    for type in image_types:
        fig.savefig(f"ATLAS_style.{type}")

    plt.style.use(mplhep.style.CMS)
    fig, ax = make_plot("mplhep CMS style")
    for type in image_types:
        fig.savefig(f"CMS_style.{type}")


if __name__ == "__main__":
    main()

which produces, along with the known font failure warnings,

Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
Font 'default' does not have a glyph for '-' [U+2212], substituting with a dummy symbol.
findfont: Font family ['cursive'] not found. Falling back to DejaVu Sans.
'texgyreheros-regular.otf' can not be subsetted into a Type 3 font. The entire font will be embedded in the output.

the plots default.png

default

ATLAS_style.png

ATLAS_style

and CMS_style.png

CMS_style

As it might take some noise on matplotlib/matplotlib#14829 to get that addressed is it possible to change the fonts in

ATLAS = {
# From https://github.com/kratsg/ATLASstylempl
"lines.linewidth": 1,
"font.family": "sans-serif",
"font.sans-serif": [
"helvetica",
"Helvetica",
"Nimbus Sans L",
"Mukti Narrow",
"FreeSans",
],
"font.size": 22,
"mathtext.fontset": "stixsans",
"mathtext.default": "rm",

to something less "correct" but at least renders?

Automatically zero the ylim

When plotting in matplotlib, if a plot has some entries at zero and the others positive, then the zero point will be shown on the y-axis. The default style in matplotlib is to set the minimum value on the y-axis to be slightly below zero, I presume to be better able to see which markers or points on the line are at zero. However, the CMS style is to set ymin=0. It would be nice if mplhep automatically zeroed the y-axis, unless specified by the user or there are negative values.

Add docs

As @HDembinski mentioned in issue #96, more generally, we should add docs. Buiding docs using Sphinx and RTD like boost-histogram is a good option.

plt.yscale and mplhep.histplot / histogram log scale on y?

Hi All,
Very glad to see there are people dedicated to making matplotlib a suitable plotting solution for HEP data.

I have a problem with setting a log scale on the y-axis when plotting a pre-binned histogram (uproot reads variable from root tree --> np.histogram)

Am I missing something or doing something wrong here?

    plt.figure(figsize=(6,6))
    hep.histplot(histnom[0], histnom[1], label='Nominal')
    hep.histplot(histmisal[0], histmisal[1], label='Misaligned')
    plt.legend(fontsize='x-small')
    plt.gca().xaxis.set_minor_locator(AutoMinorLocator())
    plt.gca().yaxis.set_minor_locator(AutoMinorLocator())
    plt.title("Momentum resolution (deent)", fontsize=16)
    plt.xlabel("$p - p_{MC}$ [MeV]", fontsize=14)
    plt.ylabel("Tracks / %.1f MeV" % (bin_sz), fontsize=14)
    plt.yticks(fontsize=14)
    plt.xticks(fontsize=14)
    plt.yscale('log')

Here is the produced plot:
ylogscale

Works without plt.yscale

Change default mpl histogram legend marker

The default legend marker style for an Matplotlib histogram (i.e. ax.hist()) is a filled box, even if the histogram is a colored line with no fill. The CMS style is to use a colored lined in this instance. The way I handled this was:

handles, labels = ax.get_legend_handles_labels()
new_handles = [Line2D([], [], c=h.get_edgecolor()) if type(h)==mpl.patches.Polygon else h for h in handles]
legend = ax.legend(handles=new_handles[::-1], labels=labels[::-1], loc='upper right', fontsize=18)

It would be nice if mplhep would handle this automatically.

Functionality like root, SetLogz

Dear experts

I am a newbie of python. Forgive me if I make a stupid question.

I tried to play with 2d histograms with mplhep. I am trying to plot it like ROOT code

TH2D::Draw("COLZ");
TCanvas::SetLogz();

Do we have such functionality in this package or we have to rely on other packages?

Could you please give an example regarding this need?

I found we can use matplotlib.pyplot.yscal('log') to modify x and y axes. But I cannot find any stuff for z axis.

Many thanks in advance.

Create multiple versions of plots with different annotations

Feature request:

Often we need to make multiple versions of the same plot for different stages of approval.
Could consider a utility that creates the same plot with several different annotations ("in progress", "internal", official) with some standard naming convention or folder structure.

No such file error on import: ".VERSION"

The update from #45 seems to break my ability to import mplhep. I encounter this issue on both my laptop and github actions, with py 3.6 and 3.7

Error looks like this:

>>> import mplhep
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/albert/code/virtualenv/bucoffea/lib/python3.7/site-packages/mplhep/__init__.py", line 39, in <module>
    with open(os.path.join(_base_dir, '.VERSION')) as version_file:
FileNotFoundError: [Errno 2] No such file or directory: '/home/albert/code/virtualenv/bucoffea/lib/python3.7/site-packages/.VERSION'

I figure the file is missing from the packaged version?

Examples.ipynb outdated

Executing Examples.ipynb produces deprecation warnings:

mplhep/tools.py:61: DeprecationWarning: 'ROOT' style dict is deprecated, please use 'LHCb' instead
  warnings.warn(self.message, category=DeprecationWarning, stacklevel=1)

Add Jupyter notebooks as demos/tutorials

The documention in the README is pretty good, but it would be even better to include Jupyter notebooks in the repository under a directory "tutorials" or "examples" which show how to make typical plots.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.