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 acceptresults
and create a histogram of the results of a performance measure of your choice. For example,03a_examination_wait
.The function should return a
plotly
figure object to the calling code. It is recommended you use thefig
naming 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.py
At the top of this notebook we have imported
plotly.express
To 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)