scikit-hep / mplhep

Extended histogram plotting on top of matplotlib and HEP collaboration compatible styling
https://mplhep.readthedocs.io
MIT License
188 stars 66 forks source link

IndexError when using plot() or scatter() with values that cross 0 using ATLAS style #512

Open Benkendorfer opened 3 months ago

Benkendorfer commented 3 months ago

I have encountered a strange crash when I try to use axes with the ATLAS style. The following MWE

from matplotlib import gridspec, pyplot as plt
import mplhep as hep

x_vals = [0, 1]
y_vals = [1, -1] # changing y_vals to not cross 0 stops error

hep.style.use(hep.style.ATLAS) # necessary for error

fig = plt.figure(figsize=(6, 5)) # changing figsize stops error
gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1]) # changing height_ratios stops error
ax1 = plt.subplot(gs[0])

ax2 = plt.subplot(gs[1])
ax2.plot(x_vals, y_vals) # also occurs with scatter()

plt.show()

produces an IndexError

Traceback (most recent call last):
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/backend_bases.py", line 1233, in _on_timer
    ret = func(*args, **kwargs)
          ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/backends/backend_macosx.py", line 68, in callback_func
    callback()
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/backends/backend_macosx.py", line 90, in _draw_idle
    self.draw()
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/backends/backend_macosx.py", line 53, in draw
    super().draw()
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/backends/backend_agg.py", line 388, in draw
    self.figure.draw(self.renderer)
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/artist.py", line 95, in draw_wrapper
    result = draw(artist, renderer, *args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/artist.py", line 72, in draw_wrapper
    return draw(artist, renderer)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/figure.py", line 3154, in draw
    mimage._draw_list_compositing_images(
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/image.py", line 132, in _draw_list_compositing_images
    a.draw(renderer)
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/artist.py", line 72, in draw_wrapper
    return draw(artist, renderer)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/axes/_base.py", line 3012, in draw
    self._unstale_viewLim()
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/axes/_base.py", line 844, in _unstale_viewLim
    self.autoscale_view(**{f"scale{name}": scale
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/axes/_base.py", line 2939, in autoscale_view
    handle_single_axis(
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/axes/_base.py", line 2932, in handle_single_axis
    x0, x1 = locator.view_limits(x0, x1)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/ticker.py", line 2168, in view_limits
    return self._raw_ticks(dmin, dmax)[[0, -1]]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/keesbenkendorfer/miniconda3/envs/ttZ_MVA/lib/python3.11/site-packages/matplotlib/ticker.py", line 2112, in _raw_ticks
    istep = np.nonzero(large_steps)[0][0]
            ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^
IndexError: index 0 is out of bounds for axis 0 with size 0

I made the following observations:

I guess somehow there is a sizing problem that messes with auto-tick placement in the ATLAS style. Perhaps a secret logarithmic transformation is being applied? It seems a bit deeper than I can dig into at this moment.

andrzejnovak commented 3 months ago

That seems rather quirky. hep.style.ATLAS is just a dictionary of standard mpl rc options, so this seems almost like a pure mpl issue. When you have a moment, could you loop through the settings in hep.style.ATLAS and apply them selectively to the demo with https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.rc_context.html