# Contour plot of separate, intersecting levels

**URL:** <https://discourse.julialang.org/t/contour-plot-of-separate-intersecting-levels/47400>\
**Category:** Visualization\
**Created:** [September 28, 2020, 12:00pm UTC](https://discourse.julialang.org/t/contour-plot-of-separate-intersecting-levels/47400 "2020-09-28T12:00:07Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![ric.cioffi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ric.cioffi/32/18373_2.png) [@ric.cioffi](https://discourse.julialang.org/u/ric.cioffi)\
**Post date:** [September 28, 2020, 12:00pm UTC](https://discourse.julialang.org/t/contour-plot-of-separate-intersecting-levels/47400/1 "2020-09-28T12:00:07Z")

</div>

### Problem

Hi, I’m having a hard time figuring out how to do the following, though I’m sure there must be some “easy” solution that I just cannot find.

I have a 3-dimensional array of booleans and I’d like to see the “contours” of it (i.e. when it changes from `false` to `true`) along the first two-dimensions and how such contours change along the third.

Something in the lines of:

```julia-auto
using Plots
pyplot()

V = falses(20, 10, 3);
[V[i, j, k] = i/20 + j/10 - k/3 > 0 for i in 1:20, j in 1:10, k in 1:3]

pl = plot(V[:, :, 1], st = :contour, levels = 1)
plot!(pl, V[:, :, 2], st = :contour, levels = 1)
plot!(pl, V[:, :, 3], st = :contour, levels = 1)

```

I have a couple of issues with the above plot:

1. Each contour plot actually includes 2 contour lines and I’d like that to be only 1
2. I’d like to label each contour line for its `k`-th level
3. It seems clunky and excessive

* * *

### Imperfect solutions

One option I could do is change the value of `V` to match the `k`-th level, something like:

```julia-auto
VV = [V[i, j, k].*k for i in 1:20, j in 1:10, k in 1:3]

pl = plot(VV[:, :, 1], st = :contour, levels = 1)
plot!(pl, VV[:, :, 2], st = :contour, levels = 1)
plot!(pl, VV[:, :, 3], st = :contour, levels = 1)

```

however that doesn’t solve problem 1 and it looks like an especially clunky workaround.

A somewhat better option could be to just define the sum and do the contour plot of that.

```julia-auto
VVV = sum(V, dims = 3)
plot(VVV[:, :], st = :contour, levels = 2)

```

This works in this simple example but in my actual use case the levels might actually intersect and I’d still like to know which level goes where.

Thanks a lot in advance for any help 🙂

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [September 28, 2020, 3:05pm UTC](https://discourse.julialang.org/t/contour-plot-of-separate-intersecting-levels/47400/2 "2020-09-28T15:05:28Z")

</div>

> [@ric.cioffi](#):
>
> I have a 3-dimensional array of booleans

Is this fundamentally true in your problem, or is it created like `V`, where you have a floating point value and you are checking its relation to 0? I ask because working directly with the floating point values and setting `levels = [0.0]` might just be a lot easier.

> [@ric.cioffi](#):
>
> - Each contour plot actually includes 2 contour lines and I’d like that to be only 1

I’m not seeing this with any backend I try, including PyPlot. I see only one contour per plot command…

> [@ric.cioffi](#):
>
> - I’d like to label each contour line for its `k` -th level

In the legend? You can set the color with e.g. `color = :blue` if that’s what you mean (assuming based on your second solution). I don’t think you’ll be able to add a legend/label to a contour plot, although I’m not sure of this.

> [@ric.cioffi](#):
>
> This works in this simple example but in my actual use case the levels might actually intersect and I’d still like to know which level goes where.

I think you can still accomplish this with a sum, as long as you first differentiate each layer sufficiently. For example, if you multiple each slice by `2^k` before taking the sum, intersections should remain unique. I.e. there is only one case that will give 0, 1, 4 etc., (I think this rule is general for any number of slices `K`, but that’s just instinct…)

```julia
julia> V2 = [V[i,j,k] * 2^k for i in axes(V, 1), j in axes(V,2), k in axes(V, 3)];

julia> sumV = dropdims(sum(V2, dims = 3), dims=3);

julia> contour(sumV, levels = sort(unique(sumV)))

```

You get the color “labels” for free using this method.

I’m not sure how readable the result is, but I think setting the color manually for each slice suffers from the same problem, depending on what you wanted? A cummulative sum might be another way

```julia
julia> let V = cumsum(V, dims=3)
       pl = plot(V[:, :, 2], st = :contour, levels = 1, colorbar = false)
       plot!(pl, V[:, :, 3], st = :contour, levels = 1, color = :blue)
       end

```

---

<div class="post-metadata">

**Author:** ![ric.cioffi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ric.cioffi/32/18373_2.png) [@ric.cioffi](https://discourse.julialang.org/u/ric.cioffi)\
**Post date:** [September 28, 2020, 6:13pm UTC](https://discourse.julialang.org/t/contour-plot-of-separate-intersecting-levels/47400/3 "2020-09-28T18:13:30Z")

</div>

> [@tomerarnon](#):
>
> > [@ric.cioffi](#):
> >
> > I have a 3-dimensional array of booleans
> 
> Is this fundamentally true in your problem, or is it created like `V`, where you have a floating point value and you are checking its relation to 0? I ask because working directly with the floating point values and setting `levels = [0.0]` might just be a lot easier.

Yes, in my problem I also have arrays of booleans

> [@tomerarnon](#):
>
> > [@ric.cioffi](#):
> >
> > - Each contour plot actually includes 2 contour lines and I’d like that to be only 1
> 
> I’m not seeing this with any backend I try, including PyPlot. I see only one contour per plot command…

Weird, this is what I get from the first MWE I posted on julia@v1.5.2, Plots@v1.6.7:  
 ![mwe](https://global.discourse-cdn.com/julialang/original/3X/e/d/ed361c922dcebd8a0c9732769cbe4c16dac232b3.png)

As you see I have two contour lines for each “level” of `V`, one for the `false`s and one for the `true`s. Does yours look different?

> [@tomerarnon](#):
>
> > [@ric.cioffi](#):
> >
> > - I’d like to label each contour line for its `k` -th level
> 
> In the legend? You can set the color with e.g. `color = :blue` if that’s what you mean (assuming based on your second solution). I don’t think you’ll be able to add a legend/label to a contour plot, although I’m not sure of this.

What I mean is if I have 1 contour line for each k-level then I can label them singularly (kinda like your example with `sumV`)

> [@tomerarnon](#):
>
> > [@ric.cioffi](#):
> >
> > This works in this simple example but in my actual use case the levels might actually intersect and I’d still like to know which level goes where.
> 
> I think you can still accomplish this with a sum, as long as you first differentiate each layer sufficiently. For example, if you multiple each slice by `2^k` before taking the sum, intersections should remain unique. I.e. there is only one case that will give 0, 1, 4 etc., (I think this rule is general for any number of slices `K`, but that’s just instinct…)
> 
> ```julia
> julia> V2 = [V[i,j,k] * 2^k for i in axes(V, 1), j in axes(V,2), k in axes(V, 3)];
> 
> julia> sumV = dropdims(sum(V2, dims = 3), dims=3);
> 
> julia> contour(sumV, levels = sort(unique(sumV)))
> 
> ```
> 
> You get the color “labels” for free using this method.
> 
> I’m not sure how readable the result is, but I think setting the color manually for each slice suffers from the same problem, depending on what you wanted? A cummulative sum might be another way
> 
> ```julia
> julia> let V = cumsum(V, dims=3)
> pl = plot(V[:, :, 2], st = :contour, levels = 1, colorbar = false)
> plot!(pl, V[:, :, 3], st = :contour, levels = 1, color = :blue)
> end
> 
> ```

This is actually a nice solution thank you, but it doesn’t really work because, if the contour lines intersect than I lose the ability to know which was which. For example here I changed it slightly to make the contour lines intersect

```julia
V = falses(20, 10, 3);
[V[i, j, k] = i/20 + (-1/2)^(k - 1)*j/10 - k/3 > 0 for i in 1:20, j in 1:10, k in 1:3]
V2 = [V[i,j,k] * 2^k for i in axes(V, 1), j in axes(V,2), k in axes(V, 3)];
sumV = dropdims(sum(V2, dims = 3), dims=3);
contour(sumV, levels = sort(unique(sumV)))

```

 ![mwe](https://global.discourse-cdn.com/julialang/original/3X/9/1/91c81ec932134127dd275be47c07012ddcb972c8.png)

As you see it does appropriately separate the levels but now there is an additional level which becomes even harder to track once the number of levels and intersections increase .

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [September 28, 2020, 7:19pm UTC](https://discourse.julialang.org/t/contour-plot-of-separate-intersecting-levels/47400/4 "2020-09-28T19:19:53Z")

</div>

Did you try the `cumsum` method as well?

---

<div class="post-metadata">

**Author:** ![ric.cioffi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ric.cioffi/32/18373_2.png) [@ric.cioffi](https://discourse.julialang.org/u/ric.cioffi)\
**Post date:** [September 28, 2020, 7:39pm UTC](https://discourse.julialang.org/t/contour-plot-of-separate-intersecting-levels/47400/5 "2020-09-28T19:39:54Z")

</div>

> [@tomerarnon](#):
>
> ```julia
> let V = cumsum(V, dims=3)
> pl = plot(V[:, :, 2], st = :contour, levels = 1, colorbar = false)
> plot!(pl, V[:, :, 3], st = :contour, levels = 1, color = :blue)
> end
> 
> ```

Yes, that also doesn’t work in the presence of intersections:

 ![mwe](https://global.discourse-cdn.com/julialang/original/3X/6/8/6840c8aebf1dac1a9913f5578a95c47d6805f0d2.png)

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [September 28, 2020, 7:41pm UTC](https://discourse.julialang.org/t/contour-plot-of-separate-intersecting-levels/47400/6 "2020-09-28T19:41:59Z")

</div>

Works if you take the cumsum of `V2` though, right?

---

<div class="post-metadata">

**Author:** ![ric.cioffi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ric.cioffi/32/18373_2.png) [@ric.cioffi](https://discourse.julialang.org/u/ric.cioffi)\
**Post date:** [September 28, 2020, 7:47pm UTC](https://discourse.julialang.org/t/contour-plot-of-separate-intersecting-levels/47400/7 "2020-09-28T19:47:35Z")

</div>

Ah. You might be right, now I only need to figure out a way of “isolating” the levels, but that should just be bookkeeping.

Thanks a lot! 😀
