I am using heatmap from Plotly. I want to use a logarithmic scale for the color but cannot find how to do so. Here is a MWE:
import plotly.graph_objects as go
import numpy as np
z = [[1e-4,1e-3,1e-2],
[1e-1, 1, 1e1],
[1e2, 1e3, 1e4]]
go.Figure(
data = go.Heatmap(
z = z,
)
).show()
go.Figure(
data = go.Heatmap(
z = np.log(z),
)
).show()
In the MWE I manually calculate the logarithm of the data. I want the color map to be shown as in the second figure but without having to manually transform the data, and also displaying the real z values in the color scale, not the logarithm.
There is an example on the plotly homepage which I adapted to use the viridis colorscale. It's not perfect... you can play with the colorscale denominator to adapt it as you need.
import plotly.graph_objects as go
import plotly.express as px
import numpy as np
viridis = px.colors.sequential.Viridis
z = [[1e-4,1e-3,1e-2],
[1e-1, 1, 1e1],
[1e2, 1e3, 1e4]]
fig1 = go.Figure(
data = go.Heatmap(
z = z,
colorscale = [
[0, viridis[0]],
[1./1000000, viridis[2]],
[1./10000, viridis[4]],
[1./100, viridis[7]],
[1., viridis[9]],
],
colorbar= dict(
tick0= 0,
tickmode= 'array',
tickvals= [0, 1000, 10000]
)
)
)
Another option would be to use:
colorscale = [
[0, viridis[0]],
[1./1000000, viridis[2]],
[1./10000, viridis[4]],
[1./100, viridis[7]],
[1., viridis[9]],
]
px.imshow(z, color_continuous_scale=colorscale, height=600, width=600)
The first one gives you (the second option is rather similar...):

I got tired of manually doing this every time so I wrote a simple function to automate this, which can be found here and is called imshow_logscale. It is fully compatible with plotly.express.imshow, it displays the real value (i.e. not the log) in the hover box as well as in the color scale, and it is really a logarithmic. Below a working example.
import plotly_utils # https://github.com/SengerM/plotly_utils
import numpy
z1 = numpy.random.randint(1,100000,(33,33))
z2 = numpy.random.randint(1,500,(33,33))
for title,img in {'spanning many orders of magnitude':z1,'spanning few orders of magnitude':z2}.items():
fig = plotly_utils.imshow_logscale(img, title=title)
fig.show()


I recently added the option to draw contours:

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With