Skip to content
Advertisement

How to set heatmap aspect ratio

I have a single-channel image where each integer pixel value maps to a string. For example 5 -> ‘person’. I’m trying to create an interactive image where hovering over a pixel will display it’s corresponding string.

I figured using plotly heatmaps might be the way to do this. The issues I’m having are:

  • It’s really slow. If I make my numpy array even (100,100) size it takes minutes to load. I’m thinking it might be because my code is not efficient?
  • I can’t figure out how to maintain aspect ratio. So if my image is a size (100,100) numpy array, I’d like the plot to also be (100,100) pixels.
  • using blank values for z_text seems like a bad workaround, but setting annotation_text=None doesn’t seem to work.

Can anyone help me out here? Here’s what I’ve got:

import numpy as np
import plotly.graph_objs as go
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)
import plotly.figure_factory as ff

z = np.random.randint(0,6, size=(10, 10))
z_text = np.full(z.shape, '', dtype=str)

d = {0:'a', 1:'b', 2:'c', 3:'d', 4:'e', 5:'f'}
class_mat = np.vectorize(d.get)(z)

fig = ff.create_annotated_heatmap(z, annotation_text=z_text, text=class_mat, hoverinfo='text', colorscale='Viridis', )
fig.layout.title = 'Semantic Segmentation'

iplot(fig, filename='annotated_heatmap_text')

And here’s what it currently looks like:

enter image description here

Also if a plotly heatmap is not the best way to go about this I’d love to hear any alternatives!

Note: I’m currently displaying inside jupyterlab.

Advertisement

Answer

I’m not sure if I’ve gotten every detail correct here, but the code in the snippet below will produce the following plot in a Jupyter Notebook. The line that handles the aspect ratio is:

fig['layout']['yaxis']['scaleanchor']='x'

You can also use:

fig.update_layout(yaxis = dict(scaleanchor = 'x'))

Plot 1:

enter image description here

Plot 2:

Just make sure to include:

fig.update_layout(plot_bgcolor='rgba(0,0,0,0)')

Or else you’ll end up with this:

enter image description here

Code 1 – My edits to your sample:

fig.data[0]['hoverinfo'] = 'all'
fig['layout']['yaxis']['scaleanchor']='x'
fig['layout']['xaxis']['gridcolor'] = 'rgba(0, 0, 0, 0)'
fig['layout']['yaxis']['gridcolor'] = 'rgba(0, 0, 0, 0)'
fig['layout']['yaxis']['color'] = 'rgba(0, 0, 0, 0)'

Code 2 – The whole thing for an easy copy&paste:

import numpy as np
import plotly.graph_objs as go
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)
import plotly.figure_factory as ff

#%qtconsole

z = np.random.randint(0,6, size=(10, 10))
z_text = np.full(z.shape, '', dtype=str)

d = {0:'a', 1:'b', 2:'c', 3:'d', 4:'e', 5:'f'}
class_mat = np.vectorize(d.get)(z)

fig = ff.create_annotated_heatmap(z, annotation_text=z_text,
                                  text=class_mat, hoverinfo='text', colorscale='Viridis',
#                                   x = list('ABCDEFGHIJ'),
#                                   y = list('ABCDEFGHIJ')
                                 )
fig.layout.title = 'Semantic Segmentation'

# My suggestions:
fig.data[0]['hoverinfo'] = 'all'
fig['layout']['yaxis']['scaleanchor']='x'

fig['layout']['xaxis']['gridcolor'] = 'rgba(0, 0, 0, 0)'
fig['layout']['yaxis']['gridcolor'] = 'rgba(0, 0, 0, 0)'
fig['layout']['yaxis']['color'] = 'rgba(0, 0, 0, 0)'

fig.update_layout(plot_bgcolor='rgba(0,0,0,0)')

fig.show()

Speed:

Even this small figure takes some time to plot, but so far I do not have any suggestions on how to speed things up.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement