Subplots with images using dash

Hi,
I am new to dash, and I am trying to build a web application where one of the figures has subplots, and each of these subplots is actually an image.

Here is the code snippet that I am using for my purpose:

@app.callback(Output('galaxy_images', 'figure'),
            [Input('gal_name', 'value'),
            Input('r_mag_range', 'value')])

def display_galaxy_images(gal_name, r_mag_range):
    fld, gal_id = re.findall(r'\d+', gal_name)
    obj = "FDS{}DWARF{}".format(fld, gal_id).ljust(12)

    obj_direc = "/home/data/{}/{}/".format(r_mag_range, obj)
    bands = get_all_bands(obj_direc)
    n = len(bands)


    # b='r'
    # img, hdr = fits.getdata(obj_direc+"{}F{}D{}_final.fits".format(b, fld, gal_id),\
    #                     header=True)
    # fig = px.imshow(img, origin='lower', zmin=-0.5e-11, zmax=1e-11)

    fig = make_subplots(rows=1, cols=n, shared_yaxes=True)
    for i in range(n):
        b = bands[i]
        img = fits.getdata(obj_direc+"{}F{}D{}_final.fits".format(b, fld, gal_id))
        fig.add_trace(
                    go.Image(z=img),\
                    # px.imshow(img, origin='lower', zmin=-0.5e-11, zmax=1e-11),\
                    row=1, col=i+1
                    )

    fig.update_layout(height=400, width=n*400,
                  title_text="Multi-band images of the {}".format(gal_name))

    return fig

The commented lines in the code above are able to produce the desired result i.e. displaying one image. But when I try to put all the images in the subplots using plotly_express , I get an error: Callback error updating galaxy_images.figure
I also tried using plotly’s graphing_objects , and it did not give me any error but the images are still not displayed although the figure layout is (see image below).

To test if using subplots in dash is an issue, I tried this code:

from plotly.subplots import make_subplots
import plotly.graph_objects as go

fig = make_subplots(rows=1, cols=2)
for i in range(2):
    fig.add_trace(
        go.Scatter(x=[1, 2, 3], y=[4, 5, 6]),
        row=1, col=i+1
    )

fig.update_layout(height=600, width=800, title_text="Side By Side Subplots")
fig.show()

And this works perfectly fine.

Does anyone know how to make this work?

hello, just checking if anyone has a solution for this yet.
Thanks in advance!

@shivangee

px.imshow(image) returns a Figure, and fig.add_trace() expects a trace (in this case an Image type trace), not a Figure. That’s why it works with commnented px.imshow(), but not otherwise.

A solution is as follows:

fig = make_subplots(rows=1, cols=n, shared_yaxes=True)
    for i in range(n):
        b = bands[i]
        img = fits.getdata(obj_direc+"{}F{}D{}_final.fits".format(b, fld, gal_id))
        fig_img = px.imshow(img, origin='lower', zmin=-0.5e-11, zmax=1e-11)
        fig.add_trace(fig_img.data[0], row=1, col=i+1)                   

Now fig_img.data[0] is an Image trace.

@empet thank you for your reply!
I do not get any error now, but I still cannot seem to be able to display images, just getting empty plots. (please see the attached image)

Do you know what could be the issue here?

What format have your images? Are they png or jpg imaqges? I cannot see where are you reading them.

Currently, to try it out, I am using a png file as in the code below:

fig = make_subplots(rows=1, cols=n, shared_yaxes=True)
from skimage import io
img = io.imread('https://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Crab_Nebula.jpg/240px-Crab_Nebula.jpg')

fig.add_trace(px.imshow(img).data[0], 1, 1)
fig.add_trace(px.imshow(img).data[0], 1, 2)
fig.add_trace(px.imshow(img).data[0], 1, 3)
fig.add_trace(px.imshow(img).data[0], 1, 4)

@shivangee

Are the images displayed or not?
With your code, but the subplots definition like this:

fig = make_subplots(rows=1, cols=4, shared_yaxes=True, horizontal_spacing=0.0025)

and this update:

fig.update_layout(width=1200, height=450)

I got:

No, the images are not displayed for me in the dash app.
Are you using dash?

@shivangee

No, I’m using Jupyter Notebook.

@empet maybe thats the difference…
I too was able to make the subplots using plotly in jupyter-lab.