I need to make plots that visualize a known probability distribution on [0,1]^2. Specifically, when

z \sim \text{MvNormal}(\mu, \Sigma)

then

x = \text{logistic}(z_1) and y = \text{logistic}(z_2), which defines a pdf p(x, y \mid \mu, \Sigma) on [0,1]^2.

I could just draw z and transform, then use contour from Plots.jl.

But I thought that since I have p in closed form, I could just use that directly, but I don’t know where to start. Is there an example or a recommended workflow somewhere? BTW, if that matters, the ultimate target backend is pgfplots().

If I understand your objective correctly, a Logit-normal distribution should be what you’re looking for.
There’s a closed form pdf for the multivariate version which you could easily sample a grid over (0,1)^2 from.

I guess you’ve tried just passing your MvNormal Distribution object z to contourf(z) after using StatPlots? If that doesn’t work - it should be made to work, if I understand you correctly.

For plots like this, I’m finding I have to provide axis ranges, so

contour(0:0.005:1,0:0.005:1,mypdf) # for the OP case, with logit-normal sec. @benelsen
contour(-5:0.05:5,-5:0.05:5,(x,y)->Distributions.pdf(d,[x,y])) # for a typical MvNormal

I was not aware of contourf and I am nor sure how to use it, and could not find an example (there are two mentions in the manual, but they seem to do the same thing as contour?).

I can make it work with contour:

using Plots; pgfplots()
x = y = linspace(0, 1, 50)
f(x, y) = x + y
contour(x, y, f; levels = collect(linspace(0,1,5)))

except that I want a 2D plot, and pgfplots() does not seem to support levels (but maybe it does in a 2d plot). For the same code, gr() gives me a 2D plots, so now I am really confused.

contour and contourf are 2D plots (if I understand what you mean): contour draws level lines whereas contourf also fills the area between them (it is some sort of “discretized” heatmap). The confusing part is, I’m afraid, that not all backends implement everything correctly. pyplot has both and this is what they’re supposed to look like:

plot(
contour(x, y, f; levels = collect(linspace(0,1,5))),
contourf(x, y, f; levels = collect(linspace(0,1,5))),
size = (800, 400)
)

GR does not support contourf and will give a heatmap instead. PGFPlots I’m actually not sure as I don’t have it installed. If it looks significantly different from the above, it is probably worth opening an issue.

I recognized that there is no (easy) way to “trace” the level sets of a function, so just calculating the values on a grid is the best.

Specifically, from this thread I learned that contourf is what I am after (thanks!), but on gr() this does not work (#1024), and on pgfplots() neither, so I opened an issue: