pythonplotlyheatmapsemantic-segmentation

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:

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.


Solution

  • 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.