# How can I plot a scatter plot over a heatmap with a different color gradient?

**URL:** <https://discourse.julialang.org/t/how-can-i-plot-a-scatter-plot-over-a-heatmap-with-a-different-color-gradient/116493>\
**Category:** Visualization\
**Tags:** question, plots\
**Created:** [July 1, 2024, 8:56pm UTC](https://discourse.julialang.org/t/how-can-i-plot-a-scatter-plot-over-a-heatmap-with-a-different-color-gradient/116493 "2024-07-01T20:56:16Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![schwob](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schwob/32/49423_2.png) [@schwob](https://discourse.julialang.org/u/schwob)\
**Post date:** [July 1, 2024, 8:56pm UTC](https://discourse.julialang.org/t/how-can-i-plot-a-scatter-plot-over-a-heatmap-with-a-different-color-gradient/116493/1 "2024-07-01T20:56:16Z")

</div>

I want to overlay a scatter plot onto a heatmap, where the points in the scatter plot are colored based on values at those points. If the values of the scatter points are in the same range as the heatmap’s values, this is pretty easy. However, if the scatter points have a different range/scale than the heatmap, then the plot with the smaller range of variables gets washed out.

For example, in the following code, the heatmap values in `Grid_mat` fall in [0,1] and Y~N(0,5), which results in a significantly larger range than the `Grid_mat` values. So, the heatmap becomes less informative, because the color limits are linked between the two plots. I even tried specifying different `clim`s for the two plots, but that didn’t fix the problem.

```julia
using Plots, Distributions
using Plots.PlotMeasures

# Example data
x = 1:10
y = 1:10
Grid_mat = rand(1, 100)
ngridpoints = 10
n=50
locs = [rand(Uniform(1, 10), n) rand(Uniform(1, 10), n)]
Y = rand(Normal(0, 5), n)

# Create the heatmap with the first color scale
heatmap(x, y, reshape(Grid_mat[1, :], ngridpoints, ngridpoints),
    color = :viridis, title = "", xlabel = "", ylabel = "",
    clim = (minimum(Grid_mat[1, :]), maximum(Grid_mat[1, :])), alpha = 0.5, legend = false)
scatter!(locs[:, 1], locs[:, 2], marker_z = Y,
    clim = (minimum(Y), maximum(Y)), color = :viridis, msw = 0.25, c = :viridis, legend = false, colorbar = true)

```

How can I plot the heatmap such that the color limits are for the heatmap values and overlay a scatter plot with color limits that are only for the scatter point values? Note that I do not want to rescale `Grid_mat` nor `Y`.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [July 2, 2024, 12:25am UTC](https://discourse.julialang.org/t/how-can-i-plot-a-scatter-plot-over-a-heatmap-with-a-different-color-gradient/116493/2 "2024-07-02T00:25:10Z")

</div>

Using Plots.jl and `pgfplotsx()` you can get something like this:

 ![Plots_pgfplotsx_heatmap_scatter_dual_colorbar](https://global.discourse-cdn.com/julialang/original/3X/7/c/7c7871fb77e151287ca0ee5e418e94455363cd42.png)

> **Plots.jl dual colorbar code**
>
> ```Julia
> using Distributions, Measures, Plots, pgfplotsx()
> 
> # Example data
> x = y = 1:10
> Grid_mat = rand(100)
> ngridpoints, n = 10, 50
> locs = [rand(Uniform(1, 10), n) rand(Uniform(1, 10), n)]
> Y = rand(Normal(0, 5), n)
> 
> # Create the heatmap with the first color scale
> heatmap(x, y, reshape(Grid_mat, ngridpoints, ngridpoints),
> color=:grays, title="", label="", widen=false,
> clim=extrema(Grid_mat), alpha=0.5, legend=false, colorbar=:left,
> xlims=extrema(x), ylims=extrema(y)
> 
> )
> 
> scatter!(twinx(), eachcol(locs)..., marker_z=Y, xmirror=true, widen=false,
> clim=extrema(Y), color=:viridis, msw=0.25, legend=false, colorbar=:right,
> xlims=extrema(x), ylims=extrema(y)
> )
> 
> ```

---

<div class="post-metadata">

**Author:** ![anowacki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/anowacki/32/17375_2.png) [@anowacki](https://discourse.julialang.org/u/anowacki)\
**Post date:** [July 2, 2024, 12:32pm UTC](https://discourse.julialang.org/t/how-can-i-plot-a-scatter-plot-over-a-heatmap-with-a-different-color-gradient/116493/3 "2024-07-02T12:32:28Z")

</div>

Unfortunately this isn’t possible in general with Plots.jl as far as I understand it:

> <https://github.com/JuliaPlots/Plots.jl/issues/1669>
>
> As far as I understand, it isn't currently possible to plot multiple times with …different 'z' axes on the same 2D subplot. Being able to do this would be very helpful. By this I mean that one can plot using different colour maps and limits on these and each layer preserves its original limits.
> 
> I have often wanted the following to work:
> 
> \`\`\`julia
> julia\> using Plots
> 
> julia\> x1 = y1 = 0:π/11:π
> x2 = y2 = 0:π/101:π
> nx1, ny1 = length.((x1, y1))
> p = heatmap(x1, y1, rand(nx1, ny1).+10, c=:gray, cbar=false)
> contour!(p, x2, y2, sin.(x2).\*sin.(y2)', c=:rainbow, xlim=extrema(x2), ylim=extrema(y2), levels=0:0.2:1, cbar=true, clim=(0,1))
> \`\`\`
> 
> What I expect to happen is that the underlying heatmap has limits automatically scaled to be in the range \[10,11\], and the overlying contours are plotted with their own scale in \[0,1\], and we would see some contours on top of a heatmap. Ideally, one would be able to have multiple colourbars, but I recognise that's hard whilst Plots uses native colourbars.
> 
> If we issue these commands in series we can see how the limits are changed and the heatmap becomes invisible:
> 
> \`\`\`julia
> julia\> x1 = y1 = 0:π/11:π
> x2 = y2 = 0:π/101:π
> nx1, ny1 = length.((x1, y1))
> p = heatmap(x1, y1, rand(nx1, ny1).+10, c=:gray, cbar=false)
> \`\`\`
> 
> !\[heatmap\](https://user-images.githubusercontent.com/1231209/44221159-87207980-a178-11e8-85a6-fd9ae7d59481.png)
> which is as expected,
> 
> \`\`\`julia
> julia\> contour!(p, x2, y2, sin.(x2).\*sin.(y2)', c=:rainbow, xlim=extrema(x2), ylim=extrema(y2), levels=0:0.2:1, cbar=true, clim=(0,1))
> \`\`\`
> 
> !\[contour\](https://user-images.githubusercontent.com/1231209/44221195-a28b8480-a178-11e8-9d90-3356cc09e3e6.png)
> whereas now the heatmap colour scale is saturated at the new z scale.
> 
> In the past I have hacked around this by scaling all the different layers to have the same limits (e.g. for \[this figure\](https://ars.els-cdn.com/content/image/1-s2.0-S0377027317306571-gr4.jpg) where I plot topography, colours and contours) but it would be great if this could be done automatically.

---

<div class="post-metadata">

**Author:** ![schwob](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schwob/32/49423_2.png) [@schwob](https://discourse.julialang.org/u/schwob)\
**Post date:** [July 2, 2024, 5:15pm UTC](https://discourse.julialang.org/t/how-can-i-plot-a-scatter-plot-over-a-heatmap-with-a-different-color-gradient/116493/4 "2024-07-02T17:15:16Z")

</div>

That looks great! What is the code that you used to generate this graphic?

---

<div class="post-metadata">

**Author:** ![schwob](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/schwob/32/49423_2.png) [@schwob](https://discourse.julialang.org/u/schwob)\
**Post date:** [July 2, 2024, 5:15pm UTC](https://discourse.julialang.org/t/how-can-i-plot-a-scatter-plot-over-a-heatmap-with-a-different-color-gradient/116493/5 "2024-07-02T17:15:49Z")

</div>

Is there a different plotting library in Julia that would work? I’m not tied to the `Plots` package.

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [July 2, 2024, 5:26pm UTC](https://discourse.julialang.org/t/how-can-i-plot-a-scatter-plot-over-a-heatmap-with-a-different-color-gradient/116493/6 "2024-07-02T17:26:18Z")

</div>

I’m not sure if I understand the problem, but Makie should work fine:

```julia
using Distributions, GLMakie

# Example data
x = 1:10
y = 1:10
Grid_mat = rand(1, 100)
ngridpoints = 10
n = 50
locs = [rand(Uniform(1, 10), n) rand(Uniform(1, 10), n)]
Y = rand(Normal(0, 5), n)

# Create the heatmap with the first color scale
f, ax, pl = heatmap(x, y, reshape(Grid_mat[1, :], ngridpoints, ngridpoints),
    colormap=:viridis, 
    colorrange=(minimum(Grid_mat[1, :]), maximum(Grid_mat[1, :])), alpha=0.5)

scatter!(ax, locs[:, 1], locs[:, 2], color=Y, colorrange=(minimum(Y), maximum(Y)), colormap=:viridis, )
f

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/a/a/aa897dd56ca08c3bb70863a37e748cd735c97736.png)

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [July 2, 2024, 5:51pm UTC](https://discourse.julialang.org/t/how-can-i-plot-a-scatter-plot-over-a-heatmap-with-a-different-color-gradient/116493/7 "2024-07-02T17:51:56Z")

</div>

In Plots/GR you can set the colorscale of the markers by hand, like:

```julia-repl
julia> using Plots

julia> m = [sin(x * y) for x in x, y in y];

julia> heatmap(m)

julia> scatter!(1:10, 1:10; markercolor = [Plots.cgrad(:viridis)[i*20] for i in 10:-1:1])

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/1/9/19741bd855247d0ae75a9dfb45bd664b0cb3b50b.png)

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [July 2, 2024, 7:32pm UTC](https://discourse.julialang.org/t/how-can-i-plot-a-scatter-plot-over-a-heatmap-with-a-different-color-gradient/116493/8 "2024-07-02T19:32:06Z")

</div>

> [@schwob](#):
>
> What is the code that you used to generate this graphic?

Please find below the image above the Plots.jl code used to generate a dual colorbar scatterplot on top of a heatmap.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [July 2, 2024, 8:04pm UTC](https://discourse.julialang.org/t/how-can-i-plot-a-scatter-plot-over-a-heatmap-with-a-different-color-gradient/116493/9 "2024-07-02T20:04:15Z")

</div>

Another option

```julia
using GMT

G = peaks(N=128);

# Interpolate the grid on scattered locations
xy = [(rand(50)*6 .- 3) (rand(50)*6 .- 3)];
Dxyz = grdtrack(G, xy);

# Colormaps for the image and the scatter
cmap1 = makecpt(G, C=:gray);
cmap2 = makecpt(G, C=:turbo);

grdimage(G, cmap=cmap1, colorbar=true)
scatter!(Dxyz, marker=:circ, color=cmap2, zcolor=Dxyz[:,3], colorbar=(position=(outside=true,anchor=:MR, offset=(2,0)), frame=:auto), show=1)

```

 ![GMTjl_j](https://global.discourse-cdn.com/julialang/original/3X/f/1/f188b348bc6ca207fac3e1dacf2f4d0de7c2ac03.png)
