Skip to content
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

[BUG] savefig cannot generate high resolution output as is rendered #3360

Closed
ChasingZenith opened this issue Mar 21, 2021 · 9 comments
Closed

Comments

@ChasingZenith
Copy link

Details

I plot a graph of a function and save it with savefig.
I save it in png and pdf format, but find that both outputs have some very strange glitch around x=0

x=-0.02:0.000001:0.02
function f(x) 
    x==0 && return 0;
    x^2 * sin(1/x)
end

plot(x, f.(x),label=nothing)
savefig("fx.png")

I also try various parameters setting such as

gr(dpi=600)

plot(..., size=(1000,600), dpi=600)

but none of them can have any effect on the quality of the savefig output.

I try GR and Pyplot backends. Both give similar phenomenon.

You can see the difference by comparing the following two pictures:

screenshot

Screenshot_20210321_235833
It is exacly what I want and what the function looks like.

savefig output

fx

Backends

This bug occurs on ( insert x below )

Backend yes no untested
gr (default) x
pyplot x
plotly x
plotlyjs x
pgfplotsx x
inspectdr x

Versions

Plots.jl version:

[91a5bcdd] Plots v1.11.0

Backend version (]st -m):

[28b8d3ca] GR v0.55.0
[d2c73de3] GR_jll v0.53.0+0

Output of versioninfo():

Julia Version 1.5.4
Commit 69fcb5745b* (2021-03-11 19:13 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-10.0.1 (ORCJIT, skylake)
Environment:
JULIA_PKG_SERVER = https://mirrors.sjtug.sjtu.edu.cn/julia

@isentropic
Copy link
Member

I think it is rendering problem. Repl figures are svg as I believe. Perhaps try saving with svg format and see it happens again?

@ChasingZenith
Copy link
Author

I have tried svg just now.Same glitch appears.
There is no way to upload an svg in Github, but the picture is the same as the one above.

@isentropic
Copy link
Member

I think glitches are expected as you are trying to plot a diverging function. The closer you get to zero the more uncertain it is. I suggest you to plot to a certain cutoff near zero, and then call it zero past it. This is purely a numerical issue.

@isentropic
Copy link
Member

Maybe your function needs to have a slightly wider zero region?

function f(x) 
    if abs(x) < 0.001
        return 0; end
    x^2 * sin(1/x)
end

@ChasingZenith
Copy link
Author

ChasingZenith commented Mar 22, 2021

This function in fact converge to 0 as x approaches to 0 although it oscillating faster and faster. This is what make this function interesting and serves as a classical example as a function with discontinuous derivative in mathematical analysis.

As for your suggestion, in fact glitch begins to appear at around 0.004 which is not too small because I just plot the function on the internal -0.02 to 0.02. 0.004 is 1/10 of the length of the interval. I don't think I should add a zero region because this solution loss the interesting part of the functions.

I can produce the same plot using the Python code attached bellow, but do not observe glitch either in svg or png format.

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-0.02, 0.02, 0.000001)
def f(x):
    if x==0:        
        return 0
    else:
        return x**2 * np.sin(1/x)


f=np.vectorize(f)

plt.plot(x, f(x))
plt.title(r"$x^2 \sin(1/x)$")
plt.show()
plt.savefig("pyfx.svg", format="svg")
plt.savefig("pyfx.png", format="png")

Different SVG saving format

One thing that might be useful for you is that I open the svg file in a text editor and find that the python version and julia version seems to give different format in saving the line. Python saves point with more digits. Will this affect the quality of the plots?

Julia

points="
  411.487,869.446 411.592,872.214 411.698,874.983 411.803,877.754 411.908,880.527 412.014,883.301 412.119,886.077 412.224,888.854 412.33,891.632 412.435,894.412 
  412.541,897.194 412.646,899.977 412.751,902.761 412.857,905.547 412.962,908.334 413.067,911.122 413.173,913.912 413.278,916.703 413.384,919.495 413.489,922.289 
  413.594,925.083 413.7,927.879 413.805,930.677 413.91,933.475 414.016,936.275 414.121,939.076 414.226,941.878 414.332,944.681 414.437,947.485 414.543,950.29 

Python

...
    <path clip-path="url(#p8f309fcc32)" d="M 73.832727 140.442614 
L 76.779041 251.1941 
L 77.647514 274.404459 
L 78.313072 286.835141 
L 78.824416 292.778251 
L 79.205894 295.039328 
L 79.449391 295.486051 
L 79.579256 295.404018 
L 79.757821 294.926798 
L 80.017551 293.481252 
L 80.37468 290.054456 
...

Some sample picture

Plots.jl GR backend

Screenshot_20210322_212655

Screenshot_20210322_212851

matplotlib - use Python

python

@ChasingZenith
Copy link
Author

I think I have found it is the setting of Join in the SVG Stroke style that causes this strange glitch.

Since I am not an SVG expert I can only provide the process I find it.
I open the SVG with Inkscape and click on the graph of the function
In Fill and Stroke(Shift + Ctrl + F) -> Stroke style -> Join:
I find that Plots.jl (GR backend) and GRUtil.jl both use Miter join with parameter 4.0
while python use Round join.
BTW, There are total of 3 types of Join is shown in Inkscape where the third one is Bevel join.

If I modified this property from Miter join to Round join, the glitch disappears and becomes the same as matplotlib when using Python. If I make the parameter smaller, the phenomena mitigate a little.

Is there a special reason for preferring Miter join?

@isentropic
Copy link
Member

PyPlot uses miter because GR does, but if GR could use round, I think it not only looks better but also avoids this behavour

@ChasingZenith
Copy link
Author

I think it will be good if I provide some pictures so that it might ease your job

Miter join with parameter 4.0 ↓

Miter4

Miter join with parameter 0.0 ↓

Miter0

Bevel join ↓

Bevel

Round join ↓

Round

@ChasingZenith
Copy link
Author

It seems that GR and pyplot use round join now so this issue has been solved. GR.jl 0.57.5 (with GR run-time 0.57.3).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants