8000 matplotlib eventplot not shows all the binary data for big number of events · Issue #20243 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

matplotlib eventplot not shows all the binary data for big number of events #20243

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
lorenzgutierrez opened this issue May 16, 2021 · 8 comments · May be fixed by #30053
Open

matplotlib eventplot not shows all the binary data for big number of events #20243

lorenzgutierrez opened this issue May 16, 2021 · 8 comments · May be fixed by #30053
Labels
backend: agg Difficulty: Hard https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues Good first issue Open a pull request against these issues if there are no active ones!

Comments

@lorenzgutierrez
Copy link
lorenzgutierrez commented May 16, 2021

Bug report

Bug summary

I noticed that when using eventplot to plot a big number of events, the plot doesn't shows all the binary data available, and is needed to increase the linelenghts parameter to increase the number of lines in the plot.

Code for reproduction

import matplotlib.pyplot as plt
import numpy as np

#simulate some raster (is needed for the number of events to be high
#I noticed missing lines for n_events > 200)
data = [np.random.random(np.random.randint(10)) for i in range(500)]
fig,axes = plt.subplots(2)
axes[0].eventplot(data,linelength = 1)
axes[1].eventplot(data,linelength = 2)

Actual outcome

imagen

Expected outcome
I would expect to have all the binary data plotted in the figure

Matplotlib version

  • Operating system: Arch Linux
  • Matplotlib version (import matplotlib; print(matplotlib.__version__)): 3.3.2
  • Matplotlib backend (print(matplotlib.get_backend())):module://ipykernel.pylab.backend_inline
  • Python version: 3.8.5
@tacaswell
Copy link
Member

The issue here is that the line length is the set in units of "number of sets" so a line length of 1 does not over lap with the set above or below, a line length of 2 half overlaps with its neighbors and so on. However, in this case because you have 500 sets and many fewer than 500 pixels of vertical height in each sub-plot. This means that many of the lines are less than a pixel long!

For less that 1 pixel long lines I think we are falling victim to a collaboration of snapping and maybe path simplification. For a variety of reasons, as part of the rasterization process we "snap" paths to their nearest pixel. Further, as part of drawing paths we simplify them to drop any points that do not contribute to the visual path (e.g. if you have a perfectly straight line we only keep the first and last point to rasterize!). However, when you have lines that are less than a pixel long I think that if both pixels get snapped to the same pixel, we either simplify it out of existence or the Agg renderer draws nothing. The lines you are seeing in the top are when the ends get snapped to adjacent pixels and we draw a (very short) line.

The visualization is further confounded by the anti-aliasing which makes the points look washed out because the line has a width that is several pixel wide, but a length that is less than 1 pixel! This results on any colored pixels only getting a fraction of the lines color composited which results in it looking like you have put a relatively high alpha on the color.

By disabling snapping on event_plot you can get all of the marks to show up:

import matplotlib.pyplot as plt
import numpy as np

#simulate some raster (is needed for the number of events to be high
#I noticed missing lines for n_events > 200)
data = [np.random.random(np.random.randint(10)) for i in range(500)]
fig,axes = plt.subplots(2)
axes[0].eventplot(data,linelength = 1, antialiased=True, snap=False);
axes[1].eventplot(data,linelength = 2);

so2

To conform that they are all there, if you get this in an interactive backend you can slowly resize the window. With snap=True the lines will flicker as events flip between getting simplified out of existence to not, and with snap=False there is not flickering.


I am pretty convinced that if the simplification logic is turning a 2 point line into a 1 point line, that is a bug in the simplification code. If passing a path with identical points to Agg is resulting in nothing drawn that might be defendable, but also might be a bug in Agg. It would be worth trying this example with mplcairo and / or saving to a vector format to see what they do.

A pragmatic fix would be to put a check in event_plot that if there are more than 100 data sets to turn snapping off! However, that is assuming a whole bunch of stuff about the expected output size (if you printed this the size of a building, there would be enough pixels that the lines would all hit more than one and render correctly!). I could also see the case for a warning with lareg number of data sets as at this point with the event plots you have lost the ability to differentiate between the rows (unless you plan to interactively zoom in!) and you may be better off using ax.plot(..., linestyle='', markerstyle='.') or scatter as both of those size the markers in screen space (rather than data space) which guarantees that they will not shrink out of existence.


I think digging into the c++ code to check what the simplification logic is going is a good first issue for someone who is comfortable with c++ (there is no API choices to make and the code is pretty self contained), but hard (as the processing chain is implemented via templates and there is some non-trivial logic to detect if "the line has changed"!).

@oscargus oscargus added Difficulty: Hard https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues Good first issue Open a pull request against these issues if there are no active ones! backend: agg labels Jun 4, 2022
@RohitP2005
Copy link

Hey @lorenzgutierrez I would like to work on the issue

@rcomer
Copy link
Member
rcomer commented Dec 17, 2024

Hi @RohitP2005 you are welcome to submit a pull request for any issue, but we do not assign them. Please see our contributors’ guide:
https://matplotlib.org/devdocs/devel/index.html

@RohitP2005
Copy link
RohitP2005 commented Dec 17, 2024

understood , i will definitely look into it
Thanks @rcomer

@ebubekir-pulat
Copy link

I am working on this issue in a group, and I have some questions. Which c++ files or functions are called upon by eventplot, and what would be the best way of debugging the code as it involves a mix of python and c++.

@timhoffm
Copy link
Member

Start digging down from EventCollection.draw(), which is inherited from Collection. Though, since you asked the above questions, I have concerns that you don't have the the capabilities to solve the issue on your own. Contributions are welcome, but we expect contributors to already have reasonable development skills. The Matplotlib core dev team has neither the ambition nor capacity to teach how to program or debug.

@story645
Copy link
Member

To add to @timhoffm's answer, specific to Matplotlib where code is located is documented in https://matplotlib.org/devdocs/devel/contribute.html#contribute-code and I strongly suggest that you build with the compile logs https://matplotlib.org/devdocs/devel/development_setup.html#build-options

@jklymak
Copy link
Member
jklymak commented May 14, 2025

I think that if both pixels get snapped to the same pixel, we either simplify it out of existence or the Agg renderer draws nothing.

I think this is the fundamental bug - we should not ever draw nothing if the user has asked us to draw something.

I actually think that in 2025 we should do away with pixel-snapping as a default. We typically have enough resolution to see most things, even if they are fuzzy, and that is preferable to disappearing data. I'm not sure pixel snapping can be fixed for data that is less than a pixel long without forcing it to make the lines too long.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend: agg Difficulty: Hard https://matplotlib.org/devdocs/devel/contribute.html#good-first-issues Good first issue Open a pull request against these issues if there are no active ones!
Projects
None yet
9 participants
0