Adding a plot#
In this exercise we will again return to the treatment centre model. We will enhance the app by adding in a simple plot.
Imports#
import plotly.express as px
from treat_sim.model import Scenario, multiple_replications
Exercise 1#
Create a new python file called app_with_plot.py and copy as paste in the code from app_with_sidebar.py shown below
'''
Script to complete a basic run of the model and display a table of
results in a streamlit app.
The model is imported from a pypi package 'treat_sim'
Full documentation and source code for `treat_sim` is available as
* Jupyter Book: https://tommonks.github.io/treatment-centre-sim/
* github: https://github.com/TomMonks/treatment-centre-sim
A conda environment has been provided locally,but the model can be pip installed
`pip install treat_sim==1.0.0`
'''
from treat_sim.model import Scenario, multiple_replications
import streamlit as st
INTRO_FILE = 'resources/overview.md'
def read_file_contents(file_name):
''''
Read the contents of a file.
Params:
------
file_name: str
Path to file.
Returns:
-------
str
'''
with open(file_name) as f:
return f.read()
# give the page a title
st.title('Treatment Centre Simulation Model')
# show the introductory markdown
st.markdown(read_file_contents(INTRO_FILE))
################################################################################
# MODIFICATION: create a sidebar for sliders
with st.sidebar:
n_triage = st.slider('Triage bays', 1, 5, 1)
n_exam = st.slider('Exam rooms', 1, 5, 3)
n_cubicles_1 = st.slider('Non-Trauma Treatment cubicles', 1, 5, 1,
help='Set the number of non trauma pathway '
+ 'treatment cubicles')
# examination mean
exam_mean = st.slider('Mean examination time', 10.0, 45.0,
16.0, 1.0)
# runs
replications = st.slider('No. replications', 1, 50, 10)
################################################################################
# Setup scenario using supplied variables
args = Scenario(n_triage=n_triage, n_exam=n_exam, n_cubicles_1=n_cubicles_1,
exam_mean=exam_mean)
# Only execute model if a streamlit button is pressed.
if st.button('Simulate treatment centre'):
# in this example run a single replication of the model.
with st.spinner('Simulating the treatment centre...'):
results = multiple_replications(args, n_reps=replications)
st.success('Done!')
# display results using st.table (or st.dataframe)
st.table(results.mean().round(1))
Exercise 2#
The code below creates apandas.DataFrame called results in the same format as code in the app_with_plot.py.
Each row in the DataFrame is a replication and each column is a performance measure. You can quickly run the code and view the format.
Task:
Create a function called
create_hist(). The function should acceptresultsand create a histogram of the results of a performance measure of your choice. For example,03a_examination_wait.The function should return a
plotlyfigure object to the calling code. It is recommended you use thefignaming convention.Include a violin plot above the histogram using plotly express.
Hints:
It is recommended that you complete this exercise in the Jupyter notebook before modifying
app_with_plot.pyAt the top of this notebook we have imported
plotly.expressTo have a useful histogram you may want to run more than 10 replications. e.g. 50 to 100.
Jupyter notebooks will render the histogram with calling
fig.show(), just leave the last line of code in a cell asfig. In a python module you will need to callfig.show()
default_scenario = Scenario()
results = multiple_replications(default_scenario, n_reps=50)
results.info()
<class 'pandas.core.frame.DataFrame'>
Index: 50 entries, 1 to 50
Data columns (total 16 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 00_arrivals 50 non-null float64
1 01a_triage_wait 50 non-null float64
2 01b_triage_util 50 non-null float64
3 02a_registration_wait 50 non-null float64
4 02b_registration_util 50 non-null float64
5 03a_examination_wait 50 non-null float64
6 03b_examination_util 50 non-null float64
7 04a_treatment_wait(non_trauma) 50 non-null float64
8 04b_treatment_util(non_trauma) 50 non-null float64
9 05_total_time(non-trauma) 50 non-null float64
10 06a_trauma_wait 50 non-null float64
11 06b_trauma_util 50 non-null float64
12 07a_treatment_wait(trauma) 50 non-null float64
13 07b_treatment_util(trauma) 50 non-null float64
14 08_total_time(trauma) 50 non-null float64
15 09_throughput 50 non-null float64
dtypes: float64(16)
memory usage: 6.6 KB
def create_hist(results, column, value_label, marginal='box'):
'''
Create and return a plotly express histogram of
the results column
Params:
-------
results: pd.DataFrame
Rows = replications, columns = KPIs
column: str
Name of column in results to use
value_label: str
X-axis label
marginal: str, optional (default='box')
An additional plot to render above the histogram
options to try: box, violin, rug
Returns:
------
plotly.figure
'''
fig = px.histogram(results[column], labels={'value':value_label},
marginal=marginal)
# hide legend
fig.update(layout_showlegend=False)
return fig
fig = create_hist(results, column='03a_examination_wait',
value_label='Mean examination waiting time',
marginal='violin')
fig
Exercise 3:#
Modify app_with_plot.py to use create_hist() and display histogram of your chosen KPI to a user.
Hints:
Don’t forget to import
plotly.express
An example solution:
"""
Script to complete a basic run of the model and display a table of
results and a plotly histogram in a streamlit app.
The model is imported from a pypi package 'treat_sim'
Full documentation and source code for `treat_sim` is available as
* Jupyter Book: https://tommonks.github.io/treatment-centre-sim/
* github: https://github.com/TomMonks/treatment-centre-sim
A conda environment has been provided locally,but the model can be pip installed
`pip install treat_sim==1.0.0`
"""
from treat_sim.model import Scenario, multiple_replications
import streamlit as st
import plotly.express as px
INTRO_FILE = 'resources/overview.md'
def read_file_contents(file_name):
''''
Read the contents of a file.
Params:
------
file_name: str
Path to file.
Returns:
-------
str
'''
with open(file_name) as f:
return f.read()
##################################################################
# MODIFICATION: Function to create plotly histogram
def create_hist(results, column, value_label, marginal='box'):
'''
Create and return a plotly express histogram of
the results column
Params:
-------
results: pd.DataFrame
Rows = replications, columns = KPIs
column: str
Name of column in results to use
value_label: str
X-axis label
marginal: str, optional (default='box')
An additional plot to render above the histogram
options to try: box, violin, rug
Returns:
------
plotly.figure
'''
fig = px.histogram(results[column], labels={'value':value_label},
marginal=marginal)
# hide legend
fig.update(layout_showlegend=False)
return fig
#####################################################################
# give the page a title
st.title('Treatment Centre Simulation Model')
# show the introductory markdown
st.markdown(read_file_contents(INTRO_FILE))
# create a sidebar for sliders
with st.sidebar:
n_triage = st.slider('Triage bays', 1, 5, 1)
n_exam = st.slider('Exam rooms', 1, 5, 3)
n_cubicles_1 = st.slider('Non-Trauma Treatment cubicles', 1, 5, 1,
help='Set the number of non trauma pathway '
+ 'treatment cubicles')
# examination mean
exam_mean = st.slider('Mean examination time', 10.0, 45.0,
16.0, 1.0)
# runs
replications = st.slider('No. replications', 1, 50, 10)
# Setup scenario using supplied variables
args = Scenario(n_triage=n_triage, n_exam=n_exam, n_cubicles_1=n_cubicles_1,
exam_mean=exam_mean)
# Only execute model if a streamlit button is pressed.
if st.button('Simulate treatment centre'):
# in this example run a single replication of the model.
with st.spinner('Simulating the treatment centre...'):
results = multiple_replications(args, n_reps=replications)
st.success('Done!')
# display results using st.table (or st.dataframe)
st.table(results.mean().round(1))
# ######################################################################
# MODIFICATION: Show results of a KPI as histogram
fig = create_hist(results, column='03a_examination_wait',
value_label='Mean examination waiting time',
marginal='violin')
st.plotly_chart(fig, use_container_width=True)
########################################################################
import plotly.graph_objects as go
def create_user_controlled_hist(results):
'''
Create a plotly histogram that includes a drop down list that allows a user
to select which KPI is displayed as a histogram
Params:
-------
results: pd.Dataframe
rows = replications, cols = KPIs
Returns:
-------
plotly.figure
Source:
------
The code in this function was adapted from:
https://stackoverflow.com/questions/59406167/plotly-how-to-filter-a-pandas-dataframe-using-a-dropdown-menu
'''
# create a figure
fig = go.Figure()
# set up ONE trace
fig.add_trace(go.Histogram(x=results[results.columns[0]]))
buttons = []
# create list of drop down items - KPIs
# the params in the code would need to vary depending on the type of chart.
for col in results.columns:
buttons.append(dict(method='restyle',
label=col,
visible=True,
args=[{'x':[results[col]],
'type':'histogram'}, [0]],
)
)
# create update menu and parameters
updatemenu = []
your_menu = dict()
updatemenu.append(your_menu)
updatemenu[0]['buttons'] = buttons
updatemenu[0]['direction'] = 'down'
updatemenu[0]['showactive'] = True
# add dropdown menus to the figure
fig.update_layout(showlegend=False, updatemenus=updatemenu)
return fig
create_user_controlled_hist(results)