2

I am currently trying to plot a matrix with heatmap using the following command

function plot_full_matrix(px, py, matrix)
    full_px = vcat(reverse(-px)[1:end-1],px)
    full_py = vcat(reverse(-py)[1:end-1],py)
    heatmap(full_px, full_py, matrix, xticks=-4:1:4, yticks=-4:1:4, c = cgrad(:grayC, scale=:log))
end

The 1999x1999 matrix has values between 10^-12 and about 1, I therefore really need the logarithmic scaling of the colors. I am not sure what is wrong here. I am on version 1.38.8 of Plots.jl.

I have tried the gr() and pythonplot() backends. Neither resolved the issue.

edit: I am expecting something like this: (Which was done in python but preferably I would not need to resort to a python solution) Done with Matplotlib in python

Instead I get: Julia plot

derdotte
  • 81
  • 7
  • I have added a bit more content with what I expected. Hopefully this helps with understanding the issue I am facing. If necessary I upload the .csv files used to generate the julia plot. They are a bit large and require a bit of processing before they can be plotted but that code I can also edit in. – derdotte Mar 19 '23 at 11:12

1 Answers1

2

Two ideas for you:

1: I think you can use the pyplot backend and pass the ticks yourself via colorbar_ticks as it looks like maybe the tick levels are just in the wrong place for log scaling (see here for an example: Modifying label and tick on color bar of Plots.jl plot) and that might fix the issue?

2: if you want to use the default backend (GR) then (as of this writing) you can't pass the ticks manually. To work around this, just take the log of your data! i.e. change your last line to heatmap(full_px, full_py, log10.(matrix), xticks=-4:1:4, yticks=-4:1:4, c = cgrad(:grayC)). Then the colorbar ticks will be in terms of log10 as well (i.e. -2 = 1e-2) so you just have to remember that. Here's a sample of what that looks like (here I made a meshgrid of the Normal distribution function since I don't have your data):

enter image description here

If (like me) you are annoyed with the lack of customization re: heatmaps and the colorbars, here's a fun example of some code I hacked together to "make my own" colorbar + do a discrete color scale, which produces this plot:

enter image description here

using Plots
f(x) = 1/√(2π)*exp(-1/2*x^2) #gaussian
x = range(-5,stop=5,length=1000)
y = f.(x)
mesh = y .+ y'

levels = [-0.1*i for i=0:10]
colors = palette([:white,:black],length(levels)-1)
clrticks = ["$(round(level,sigdigits=2))" for level in reverse(levels)]
n = length(levels)
yt = range(0,1,n)[1:n] #.+ 0.5/n add the half if levels are centered

xx = range(0,1,100)
zz = zero(xx)' .+ xx
p = plot(x,x,log.(mesh),seriestype=:heatmap,colorbar=false,c=colors,guidefont="Computer Modern",tickfont="Computer Modern")
p = plot!(title="",inset=(1,bbox(1/40,1/10,0.1,0.5)),titlefont="Computer Modern")
p = plot!(p[2],xx, xx, zz, ticks=false, ratio=10, legend=false, fc=colors, lims=(0,1),title="log10 f(x)",
            framestyle=:box, right_margin=20*Plots.Measures.mm,seriestype=:heatmap,cbar=false,titlefontsize=10,titlefontcolor=:red,tickfontcolor=:red)

for (yi,ti) in zip(yt,clrticks)
    p=plot!(p[2],annotations=(1.5,yi,text(ti, 7, "Computer Modern","red")))
end
display(p)
kirklong
  • 203
  • 1
  • 2
  • 9
  • 1
    Your second solution is definitely the simplest. I have decided to go with the python solution and letting matplotlib do the work. Heatmaps should certainly be improved though as its used a lot for visualizations of this kind of data. – derdotte Mar 24 '23 at 13:00