So I am working on Dash Plotly. The webpage should have a text box and a button. The idea is that when I write an image name and then select the button, it will show the image from a local directory.
I tried to divide the whole work into 2 parts.
First, I have this code which shows you whatever you write in the text box and click the button. The code:
# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import os
from PIL import Image
import numpy as np
import plotly.express as px
os.chdir(os.path.dirname(os.path.abspath(__file__)))
external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(
[
html.I("Try typing the image name in input and observe it"),
html.Br(),
dcc.Input(id="input", type="text", placeholder=""),
html.Div(id="output"),
]
)
@app.callback(
Output("output", "children"),
Input("input", "value")
)
def update_output(input):
return u'Input {}'.format(input)
if __name__ == "__main__":
app.run_server(debug=True)
Next, I have this code which when run locally, just shows you the image in the webpage. Point: the python file and the image are in same local directory. The code:
import os
from PIL import Image
import numpy as np
import plotly.express as px
# Change working dir to current running script dir:
print('[change directory]')
os.chdir(os.path.dirname(os.path.abspath(__file__)))
def test():
# load the image
img = np.array(Image.open('img name.tiff'))
fig = px.imshow(img, color_continuous_scale='gray')
fig.update_layout(coloraxis_showscale=False)
fig.update_xaxes(showticklabels=False)
fig.update_yaxes(showticklabels=False)
fig.show()
test()
Now, I need a way to add these 2 codes so that when I write 'img name.tiff' in the text box and select the button, it will show me the picture in the webpage.
I am very new in Dash and Plotly. I have no idea how to do it. I tried to study it but could not find anything helpful. Can anyone help?
You could change your callback to something like this:
@app.callback(Output("output", "children"), Input("input", "value"))
def update_output(input):
if not input:
raise PreventUpdate
try:
img = np.array(Image.open(f"assets/{input}"))
except OSError:
raise PreventUpdate
fig = px.imshow(img, color_continuous_scale="gray")
fig.update_layout(coloraxis_showscale=False)
fig.update_xaxes(showticklabels=False)
fig.update_yaxes(showticklabels=False)
return dcc.Graph(figure=fig)
If there's no input value or the image with the user specified path can't be opened, we use PreventUpdate:
In certain situations, you don't want to update the callback output. You can achieve this by raising a PreventUpdate exception in the callback function.
Note: this example assumes the image is stored in the assets folder.
Update: Implementation using button
@app.callback(
Output("output", "children"),
Input("input", "value"),
Input("show-image", "n_clicks"),
prevent_initial_call=True,
)
def update_output(input, n_clicks):
if not input:
raise PreventUpdate
ctx = dash.callback_context
if ctx.triggered[0]["prop_id"].split(".")[0] != "show-image":
raise PreventUpdate
try:
img = np.array(Image.open(f"assets/{input}"))
except OSError:
raise PreventUpdate
fig = px.imshow(img, color_continuous_scale="gray")
fig.update_layout(coloraxis_showscale=False)
fig.update_xaxes(showticklabels=False)
fig.update_yaxes(showticklabels=False)
return dcc.Graph(figure=fig)
In the previous example on finding an image that can be opened the callback returns the graph with the image. If you want to defer showing the image until a button is clicked you can add a button to the layout
html.Button("Show Image", id="show-image", n_clicks=0)
and use callback_context to determine which Input triggered the button. If the id of this input equals "show-input" (the id of our button) we show the graph and image.
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