Geom.contour in Gadfly.jl - How to use it?

I am trying to draw iso-density contours on a plot. Yet, it seems I am drawing lines all over the place – as opposed to contours representing different iso-densities (plot should be top-view of a mountain). I tried point and function representations, but my plot is wonky either way. I am missing something fundamental, but am not sure what it is? Any help is appreciated. Thanks!

Here is code to reproduce one of my wonky plots:

using Distributions, Gadfly, Format, DataFrames

## specify random variables
X = Beta(2,2)
unscaledBeta = Beta(2,8)
Y = LocationScale(0, 100000, Beta(2,8))

## calculate log pdf
function negLogDensFun(x::Real,y::Real)
    -logpdf(X,x) - logpdf(Y,y)  ## logpdf built-in to Distributions
end

## test it
negLogDensFun(0.5,25000)

## sample directly and show on grid
numDraws = 100
plotDF = DataFrame(winningsMultiplier = rand(X,numDraws),
                    maxWinnings = rand(Y,numDraws))
plotDF.negLogDens = negLogDensFun.(plotDF.winningsMultiplier,
                                  plotDF.maxWinnings)

# make plot
plot(plotDF, x = :winningsMultiplier,
             y = :maxWinnings,
        layer(Geom.point),
        layer(z=(x,y) -> negLogDensFun(x,y),
              Geom.contour(levels = 3)),
        Coord.cartesian(xmin =0, xmax = 1,
                        ymin = 0, ymax = 10^5),
        Scale.y_continuous(labels = x -> format(x, commas = true)))

Wonky plot (above), but I was hoping for contour lines akin to the ones shown in the gallery (below):

My plot would have just one mountain top though.

Have you checked this post?

1 Like

The above example should work (because z is a function), but the issue is the Inf values on the edges of the domain (which I assume cause a problem for Contour.jl).

plot(z=(x,y) -> negLogDensFun(x,y), Geom.contour(),
         xmin=[0.001], xmax=[0.999], ymin=[0.001], ymax=[10^4.9], 
    Theme(line_width=3pt)
    )

Contour

When a function is provided how many points Gadfly computes in order to produce the contours?

Another way using a matrix may allow some extra user control on the plot:

x = plotDF.winningsMultiplier
y = plotDF.maxWinnings
x0, y0 = sort(x), sort(y)
z0 = [negLogDensFun(x,y) for x in x0, y in y0]
Gadfly.plot( layer(z=z0, x=x0, y=y0, Geom.contour(levels=5)),
           layer(x=x, y=y) )

1 Like

Thanks for this tip. I was missing the sort step when I tried going the matrix route.

This is fabulous. Thank you for debugging this - I was out of ideas and very much appreciate the support :slight_smile: