# Contour plot of density function

**URL:** <https://discourse.julialang.org/t/contour-plot-of-density-function/7806>\
**Category:** Visualization\
**Tags:** question\
**Created:** [December 16, 2017, 11:51am UTC](https://discourse.julialang.org/t/contour-plot-of-density-function/7806 "2017-12-16T11:51:48Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [December 16, 2017, 11:51am UTC](https://discourse.julialang.org/t/contour-plot-of-density-function/7806/1 "2017-12-16T11:51:48Z")

</div>

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()`.

---

<div class="post-metadata">

**Author:** ![benelsen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/benelsen/32/1620_2.png) [@benelsen](https://discourse.julialang.org/u/benelsen)\
**Post date:** [December 16, 2017, 3:09pm UTC](https://discourse.julialang.org/t/contour-plot-of-density-function/7806/2 "2017-12-16T15:09:47Z")

</div>

If I understand your objective correctly, a [Logit-normal distribution](https://en.wikipedia.org/wiki/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.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [December 16, 2017, 3:15pm UTC](https://discourse.julialang.org/t/contour-plot-of-density-function/7806/3 "2017-12-16T15:15:40Z")

</div>

Sure; but the question is how to **plot** contours nicely without binning and/or sampling 😉

I realized that to determine [HPD](https://en.wikipedia.org/wiki/Credible_interval) cutoffs, I need to sample anyway. Then I can make a really dense grid, and just use `contour`.

There are some hints [here](https://discourse.julialang.org/t/implicit-plot-with-plots/6585) about what I want, but ATM just using `contour` on a very dense grid is probably the easiest solution.

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [December 16, 2017, 9:18pm UTC](https://discourse.julialang.org/t/contour-plot-of-density-function/7806/4 "2017-12-16T21:18:55Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Ralph\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ralph_smith/32/10344_2.png) [@Ralph\_Smith](https://discourse.julialang.org/u/Ralph_Smith)\
**Post date:** [December 17, 2017, 4:13am UTC](https://discourse.julialang.org/t/contour-plot-of-density-function/7806/5 "2017-12-17T04:13:05Z")

</div>

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

```julia
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

```

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [December 17, 2017, 9:23am UTC](https://discourse.julialang.org/t/contour-plot-of-density-function/7806/6 "2017-12-17T09:23:54Z")

</div>

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`:

```julia
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.

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [December 17, 2017, 11:08am UTC](https://discourse.julialang.org/t/contour-plot-of-density-function/7806/7 "2017-12-17T11:08:34Z")

</div>

`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:

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

```

 ![contour](https://global.discourse-cdn.com/julialang/original/3X/1/5/151e2fbcc2848149faa2df92efc33c2cb9fda386.png)

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.

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [December 17, 2017, 11:31am UTC](https://discourse.julialang.org/t/contour-plot-of-density-function/7806/8 "2017-12-17T11:31:01Z")

</div>

Ugh, yes contour is totally broken on pgfplots:

 ![05](https://global.discourse-cdn.com/julialang/original/3X/6/4/644db7f170e09d16679aa477f167ecdb9f46cb4b.jpeg)

This should be fixable Plots side, as pgfplots natively supports filled contour plots. Def worth an issue.

---

<div class="post-metadata">

**Author:** ![mkborregaard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkborregaard/32/556_2.png) [@mkborregaard](https://discourse.julialang.org/u/mkborregaard)\
**Post date:** [December 17, 2017, 11:32am UTC](https://discourse.julialang.org/t/contour-plot-of-density-function/7806/9 "2017-12-17T11:32:44Z")

</div>

Just to make sure I understand, are you getting the behaviour you were after on gr?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [December 17, 2017, 12:00pm UTC](https://discourse.julialang.org/t/contour-plot-of-density-function/7806/10 "2017-12-17T12:00:21Z")

</div>

There are two parts to the answer:

1. 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.

2. Specifically, from this thread I learned that `contourf` is what I am after (thanks!), but on `gr()` this does not work ([#1024](https://github.com/JuliaPlots/Plots.jl/issues/1024)), and on `pgfplots()` neither, so I opened an issue:

[https://github.com/JuliaPlots/Plots.jl/issues/1321](https://github.com/JuliaPlots/Plots.jl/issues/1321)
