proplot icon indicating copy to clipboard operation
proplot copied to clipboard

Artefacts in hist2d and hexbin output

Open Jhsmit opened this issue 3 years ago • 3 comments

When I'm making hist2d or hexbin plots in proplot, I have an issue where in the hist2d the rectangles arent correctly shaped, specifically it seems the lowest pixel row, and when I use hexbin, some of the hexes appear to be smaller or below other hexes.

Proplot code:

import proplot as pplt
import numpy as np
import matplotlib.pyplot as plt

# Sample data
N = 500
state = np.random.RandomState(51423)
x = state.normal(size=(N,))
y = state.normal(size=(N,))
bins = pplt.arange(-3, 3, 0.25)

fig, axs = pplt.subplots(refaspect=1, width='50mm')

axs[0].hist2d(
    x, y, bins, vmin=0, vmax=10,
    cmap='Blues',
)

Proplot result:

proplot_example_hist2d

Zoom of the rectangles:

image

Matplotlib code:

import numpy as np
import matplotlib.pyplot as plt

# Sample data
N = 500
state = np.random.RandomState(51423)
x = state.normal(size=(N,))
y = state.normal(size=(N,))
bins = np.arange(-3, 3.2, 0.25)

fig, ax = plt.subplots()
ax.set_aspect(1)

ax.hist2d(x, y, bins, cmap='Blues', vmin=0, vmax=10)

Matplotlib result

matplotlib_hist2d

For the hist2d it isnt too bad, especially with high resolutions (since its appears only to be the lowest pixel line). pdf output has the same effect.

The hexbin looks like this:

Proplot:

...
axs[0].hexbin(
    x, y, gridsize=20, vmin=0, vmax=10,
    cmap='Blues',
)

proplot_example_hexbin

Matplotlib:

ax.hexbin(x, y, cmap='Blues', gridsize=20, vmin=0, vmax=10)

matplotlib_hexbin

Version info: proplot==0.9.5 matplotlib==3.4.3

Using py39 on windows 11

Jhsmit avatar Feb 16 '22 11:02 Jhsmit

This is related to the "edgefix" feature that tries to repair an issue where distracting white lines appear in saved vector graphics. See the box at the top of this page of the proplot docs, and see this github repo for examples of the problem.

Adding "edges" to cover those white lines can produce weird results for some types of plots... I try to make the width small enough to avoid this, and it mostly works for pcolor plots, but I can see how for hexbin plots it's definitely noticeable. I'll play with decreasing the edge width or disabling edgefix for hexbin plots in the next version.

For now you can disable "edgefix" globally using pplt.rc.edgefix = False, locally using ax.hexbin(..., edgefix=False), or choose a different linewidth with e.g. ax.hexbin(..., edgefix=0.1).

lukelbd avatar Feb 16 '22 18:02 lukelbd

Just remembered that I chose a default edge width of 0.3 so that it would cover white lines in both bitmap (e.g. PNG) and vector (e.g. PDF) outputs. It looks like smaller line widths will start showing white lines in bitmap outputs (see the examples in that github repo showing linewidths of 0.2 and below).

So, decreasing the default edge width further is not an option. I guess the question is whether we prefer "white lines" or "nubs"... because there's no way to perfectly eliminate both.

lukelbd avatar Feb 16 '22 18:02 lukelbd

Thanks! I did run into the white lines issue before in vector graphics. Very frustrating, nice to see there is a fix.

If I use edgefix=False for histd2, my issue is resolved. However, for hexbin it raises an error, and also globally changing the setting has no effect.

axs[0].hexbin(
    x, y, gridsize=20, vmin=0, vmax=10,
    cmap='Blues', edgefix=False,
)

Results in:


  File ...\site-packages\matplotlib\artist.py", line 1062, in update
    raise AttributeError(f"{type(self).__name__!r} object "
AttributeError: 'PolyCollection' object has no property 'edgefix'

Jhsmit avatar Feb 17 '22 10:02 Jhsmit