Hi,
I’m trying to create a panel which i’ll be running on a local server (with panel serve “name.ipynb” --port —>open in browser)
I want to have a FileInput button and a figure under it which will update according to file uploaded.
the process is as follows: click on upload button->choose csv file->csv processing->plot results.
I need the csv data to be available for further operations.
i’ve managed to do this with Dash but as far as i can tell, the dash api lacks the option to get current state of a legend in graph (specifically, i need to know which plots are hidden and which plots are shown)
I tried different implementations methods and callbacks with panel but none is working.
can someone provide a working example of such button please?
below is a working code i’ve written with dash. this is the desired behaviour i want to implement with panel.
import plotly.offline as pyo
import plotly.graph_objs as go
import pandas as pd
import base64
import io
from dash.dependencies import Input, Output, State
import dash
import dash_core_components as dcc
import dash_html_components as html
import threading
from test_ui import Ui_MainWindow
def run_dash():
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
html.Div(children='''
Dash: A web application framework for Python.
'''),
dcc.Upload(
id='upload',
children=html.Div([
'Drag and Drop or ',
html.A('Select a File')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
}
)
,
dcc.Graph(
id='example-graph',
)
])
return app
def parse_contents(contents, filename):
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(
io.StringIO(decoded.decode('utf-8')))
elif 'xls' in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
except Exception as e:
print(e)
return html.Div([
'There was an error processing this file.'
])
return df
def setupFilteredDataframe(df):
assert ("Voltage" in df.columns) and ("Time" in df.columns), "no columns voltage and time"
df = (df.loc[df['Voltage'] != 'Invalid/Calib']).copy(deep=True)
df['Voltage'] = df['Voltage'].apply(lambda x: float(x))
df.reset_index()
traces = []
if "FubId" in df.columns:
"""filter it to contain measurments from a single vdm.
then set the transformed and filtered data for next steps"""
df = df[['FubId', 'Time', 'Voltage']]
fubIds = df['FubId'].copy(deep=True)
fubIds = fubIds.drop_duplicates()
lFubIds = fubIds.tolist()
for fub in lFubIds:
curr_df = df.loc[df['FubId'] == fub].copy(deep=True)
traces.append(go.Scatter(
x=curr_df['Time'],
y=curr_df['Voltage'],
mode='lines',
name=fub
))
else:
curr_df = df
traces.append(go.Scatter(
x=curr_df['Time'],
y=curr_df['Voltage'],
mode='lines',
name='Waveform'))
return traces
def printAppLayout():
print(app.layout)
app = run_dash()
# callback figure creation
@app.callback(Output('example-graph', 'figure'),
[Input('upload', 'contents')],
[State('upload', 'filename')])
def update_output(contents, filename):
if contents is not None:
dff = parse_contents(contents, filename)
print(dff.head())
data = setupFilteredDataframe(dff)
return {
'data': data,
'layout': dict(
title='Time series with range slider and selectors',
xaxis=dict(rangeslider=dict(visible=True)))
}
else:
return {}
if __name__ == '__main__':
app.run_server(debug=True,port=3003)