Gadfly plot failing (suspect numerical issues)

I have a situation where I am trying to plot errors, which are small but are nowhere near subnormal numbers in Float64.

Unfortunately, plot() is producing an incorrect graph, using Gadfly 1.3.1 in Julia 1.5.3.

Here is a simple demonstration of problem:

using Gadfly;

xvals =  range( 0.0, 1.0, length=20 );

yvals = [ 0.0 , 1.5770373161480791e-18 , 2.983115103490406e-18 , 4.197248008233336e-18 , 5.3945317696645016e-18 , 6.844316881913259e-18 , 8.708236700751923e-18 , 1.0863668278404468e-17 , 1.2894457644236792e-17 , 1.4317750840733128e-17 , 1.4965586158467704e-17 , 1.5276181431484313e-17 , 1.6182869477102057e-17 , 1.8443012277801592e-17 , 2.1692238089739158e-17 , 2.4126051771260834e-17 , 2.4010574742241276e-17 , 2.306119442978225e-17 , 2.6917955234178657e-17 , 2.575849671298423e-17 ];

# this plots a line of zeros along the x axis
plot( x = xvals, y = yvals )

# this (still) plots a line of zeros
plot( x = xvals, y = yvals * 8  )

# this plots something that looks right, but its choice of yscale labels is strange
# and of course the scale is not correct :(
plot( x = xvals, y = yvals * 9  )

# this plots the correct shape
# but of course the scale is not correct :(
plot( x = xvals, y = yvals * 10 )

While I have worked around the problem for this data set, it raises the issue that the graphs are not necessarily reliable, which is obviously troubling for future use.

A good graph never comes out of the box automatically out of any box.
It’s not the tool I have to rely on, whenever I have to interprete a graph, but it is the creator of the graph, which is you, in this case.

Having said this and out of the way, I would recommend to change the order of magnitude of the y axis by 10^17, e.g. with:

plot( x = xvals, y = yvals * 10^17 , Guide.ylabel("y x 10^17"))

This is much easier to comprehend by the box (Gadfly) and by the viewer.

Regarding this

# this plots a line of zeros along the x axis
plot( x = xvals, y = yvals )

there obviously takes place some rounding or something similar for the purpose of pretty printing the numbers on the y axis. If you want more reliability from Gadfly in the future, you should open an issue about this at Issues · GiovineItalia/Gadfly.jl · GitHub . A short search didn’t come up with an existing issue.

1 Like

Gadfly uses the function optimize_ticks to work out the axis ticks.

import Gadfly: optimize_ticks
# yvals from above example
sc = 9
# sc = 1e17
extrema(yvals*sc)
optimize_ticks(extrema(yvals*sc)...)

Improvements for small numbers welcome!

I didn’t check in detail and didn’t tested it, but it seems to me that the usage of

eps()

in function optimize_ticks_typed in ticks.jl line 66 may be the problem.

For Float64 eps() isn’t a constant, but dependend of the value itself.
So for Numbers I would propose to use a variable e which is calculated as:

e = maximum((eps(x_min),eps(x_max)))

which is in the case of above yvals:

julia> e = maximum((eps(minimum(yvals)),eps(maximum(yvals))))
3.0814879110195774e-33

Compare this to:

julia> eps()
2.220446049250313e-16

What do you think? Does this make sense?

2 Likes

Thank you!

Looking at the code, I conjecture it needs to be used in two places in optimize_ticks_typed() in ticks.jl

The following had my graphs working.

line 73

    one_t = oneunit(T)
-   if x_max - x_min < eps() * one_t
+   epsilon = eps( max( abs(x_min), abs(x_max) ) )
+   if x_max - x_min < epsilon * one_t
        R = typeof(1.0 * one_t)
        return R[x_min], x_min - one_t, x_min + one_t
    end

line 100

                stp = q*10.0^z
-               if stp < eps()
+               if stp < epsilon
                    continue

But a sample of one is not testing.

1 Like