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: