holoviz / holoviews

With Holoviews, your data visualizes itself.
https://holoviews.org
BSD 3-Clause "New" or "Revised" License
2.71k stars 404 forks source link

Aliasing artefacts when rendering images in Jupyter #1204

Closed VolkerH closed 4 years ago

VolkerH commented 7 years ago

I see block-like aliasing artefacts when rendering the sine wave from the Holoviews showcase.

untitled

I know that the circular sine wave with varying frequency is very sensitive in this regard, if the images get rescales/resampled with inappropriate smoothing filters at any point in the rendering pipeline you will obtain visible artefacts. I also see the artefacts in the images on the documentation http://holoviews.org/Tutorials/Showcase.html

jlstevens commented 7 years ago

Thanks for filing the issue!

We've noticed these artefacts for a while now but have no idea what causes them. As far as I know this is just how matplotlib renders this type of data as opposed to anything to do with HoloViews itself. Do you agree @philippjfr ?

jbednar commented 7 years ago

I've always thought that those artifacts were the result of rendering at one resolution but then displaying at a slightly different resolution. But I just checked by right clicking on the image from the tutorial and viewing it in a different tab where I could zoom in, and the artifacts remained, suggesting that they were present when first rendered. So yes, I would assume they come directly from matplotlib, though it would be nice to replicate the issue outside of HoloViews to be sure.

VolkerH commented 7 years ago

I don't know enough about matplotlib, but as I understand matplotlib can use various backends. I'm wondering whether it depends on the particular backend or is present in another.

Implicit scaling appears to be happening with almost every image in matplotlib as a n by m array will usually not be displayed using m by n actual screen pixels. If this rescaling isn't done properly I am not surprised that there are some aliasing artefacts.

jbednar commented 7 years ago

Good point; the mismatch between the array in which the function has been evaluated and the resolution at which mpl is rendering it would be sufficient to explain this. If so, I don't see anything that could be done, as we'd have to figure out what the eventual size in pixels will be on screen and then evaluate the original function with that specific pixel size.

Maybe just use SVG output?

VolkerH commented 7 years ago

I just spent the better part of an hour to try and reproduce these artefacts with plain Matplotlib in a jupyter notebook and experiment with different interpolation settings. Preliminary summary: I also get aliasing but it looks different. I don't see the same cube-shape structure in the test images. I will try to place a sample jupyter notebook somewhere, hopefully today.

VolkerH commented 7 years ago

Uploaded a notebook here: https://github.com/VolkerH/interpolation_and_aliasing_matplotlib/blob/master/Interpolation%2Band%2BAliasing.ipynb

To me, the kind of artefacts I get with plain matplotlib look different. In particular, I can't reproduce this effect in matplotlib which I observe with holoviews:

artefact

Edit: actually, on a closer look I'm not so sure anymore. Can I easily change the inerpolation mode in holoviews ?

philippjfr commented 7 years ago

Can I easily change the inerpolation mode in holoviews ?

Here's your gist adapted to holoviews:

import numpy as np
import holoviews as hv
hv.notebook_extension()

# play around with the following two parameters
numpoints = 128
freq = 100 

def sine(x, phase=0, freq=100):
    return np.sin((freq * x + phase))

dist = np.linspace(-0.5,0.5,128)   # Linear spatial sampling
x,y = np.meshgrid(dist, dist)
grid = (x**2+y**2)                 # 2D spatial sampling

testpattern = sine(grid, freq=freq)

methods = ['none', 'nearest', 'bilinear', 'bicubic', 'spline16',
           'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric',
           'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos']

hv.Layout([hv.Image(testpattern, label=interp)(style=dict(interpolation=interp))
           for interp in methods])

image

jlstevens commented 7 years ago

@philippjfr Could you include a screenshot? I am curious as to what that layout looks like.

Thanks!

philippjfr commented 7 years ago

Updated my post above.

jlstevens commented 7 years ago

The differences are pretty subtle! None and 'nearest' are the same, I see a difference with 'hanning' and all the rest look pretty much the same to me.

I can't see the aliasing issue anymore, maybe because it is harder to see with the hot colormap?

philippjfr commented 7 years ago

Also can't spot the artifacts in that plot and it looks the same with Greys to me.

philippjfr commented 7 years ago

By accident I just found out that the artifacts go away when you increase the size of the plot.

jlstevens commented 7 years ago

@philippjfr Does that mean there is a suitable fix?

Can this issue either spawn a new issue/PR or otherwise be closed?

VolkerH commented 7 years ago

Well, I suspect that the issue is created whenever the image is downsampled for output (if the plotsize is so small that it is required). Without looking into the source codeI suspect the downsampling is not done in a proper way (e.g. not adequate smoothing before downsampling or an error when calculating the indexes with which the image is evaluated).

Therefore I am not surprised that the error goes away once the plot size is large enough for the image to be no longer downsampled.

philippjfr commented 4 years ago

In the end this is not a HoloViews issue but rather an issue with matplotlib under certain conditions. I'll close but please reopen if there are any suggestions on improving this in HoloViews itself.

github-actions[bot] commented 3 weeks ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.