diff --git "a/pages/1_\360\237\232\266\342\200\215\342\231\202\357\270\217_Simulating_Arrivals.py" "b/pages/1_\360\237\232\266\342\200\215\342\231\202\357\270\217_Simulating_Arrivals.py" index 5c15a80..abe1d99 100644 --- "a/pages/1_\360\237\232\266\342\200\215\342\231\202\357\270\217_Simulating_Arrivals.py" +++ "b/pages/1_\360\237\232\266\342\200\215\342\231\202\357\270\217_Simulating_Arrivals.py" @@ -4,17 +4,17 @@ Allows users to interact with an increasingly more complex treatment simulation ''' import time -import streamlit as st +import asyncio +import datetime as dt +import gc import numpy as np import plotly.express as px import pandas as pd -import asyncio -import datetime as dt +import streamlit as st -from helper_functions import read_file_contents, add_logo, mermaid +from helper_functions import add_logo, mermaid from model_classes import Scenario, multiple_replications from distribution_classes import Exponential -# from st_pages import show_pages_from_config, add_page_title st.set_page_config( page_title="Simulating Arrivals", @@ -22,10 +22,6 @@ initial_sidebar_state="expanded", ) -# add_page_title() - -# show_pages_from_config() - add_logo() with open("style.css") as css: @@ -187,8 +183,8 @@ class B,B1,B2,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z unlight; with col1_2: mean_arrivals_per_day = st.slider("How many patients should arrive per day on average?", - 10, 1000, - step=5, value=200) + 10, 500, + step=5, value=150) # Will need to convert mean arrivals per day into interarrival time and share that exp_dist = Exponential(mean=60/(mean_arrivals_per_day/24), random_seed=seed) @@ -338,7 +334,7 @@ class B,B1,B2,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z unlight; total_fig = px.histogram( results[['00_arrivals']], - nbins=int(np.ceil(n_reps/2)) + nbins=5 ) total_fig.layout.update(showlegend=False) @@ -365,7 +361,7 @@ class B,B1,B2,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z unlight; daily_average_fig = px.histogram( (results[['00_arrivals']]/run_time_days).round(1), - nbins=int(np.ceil(n_reps/2)) + nbins=5 ) daily_average_fig.layout.update(showlegend=False) @@ -416,4 +412,6 @@ class B,B1,B2,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z unlight; time_plot.update_layout(yaxis_title="Simulation Run (Replication)", xaxis_title="Time") - st.plotly_chart(time_plot, use_container_width=True) \ No newline at end of file + st.plotly_chart(time_plot, use_container_width=True) + +gc.collect() \ No newline at end of file diff --git "a/pages/2_\360\237\233\217\357\270\217_Using_A_Simple_Resource.py" "b/pages/2_\360\237\233\217\357\270\217_Using_A_Simple_Resource.py" index 7537cc2..7e4cd83 100644 --- "a/pages/2_\360\237\233\217\357\270\217_Using_A_Simple_Resource.py" +++ "b/pages/2_\360\237\233\217\357\270\217_Using_A_Simple_Resource.py" @@ -3,17 +3,18 @@ Allows users to interact with an increasingly more complex treatment simulation ''' -import streamlit as st +import asyncio +import gc import pandas as pd import plotly.express as px import plotly.graph_objects as go -import numpy as np -from output_animation_functions import reshape_for_animations, animate_queue_activity_bar_chart, animate_activity_log -import asyncio +import streamlit as st -from helper_functions import read_file_contents, add_logo, mermaid +from helper_functions import add_logo, mermaid from model_classes import Scenario, multiple_replications from distribution_classes import Normal +from output_animation_functions import reshape_for_animations, animate_queue_activity_bar_chart, animate_activity_log + # Set page parameters st.set_page_config( page_title="Using a Simple Resource", @@ -158,13 +159,13 @@ step=1, value=10) run_time_days = st.slider("How many days should we run the simulation for each time?", - 1, 60, + 1, 40, step=1, value=15) mean_arrivals_per_day = st.slider("How many patients should arrive per day on average?", - 10, 500, - step=5, value=300) + 10, 300, + step=5, value=120) # A user must press a streamlit button to run the model button_run_pressed = st.button("Run simulation") @@ -209,10 +210,12 @@ animation_dfs_log = reshape_for_animations( full_event_log=full_event_log[ (full_event_log['rep']==1) & - ((full_event_log['event_type']=='queue') | (full_event_log['event_type']=='resource_use') | (full_event_log['event_type']=='arrival_departure')) + ((full_event_log['event_type']=='queue') | (full_event_log['event_type']=='resource_use') | (full_event_log['event_type']=='arrival_departure')) & + # Limit to first 5 days + (full_event_log['time'] <= 60*24*5) ], every_x_minutes=5 - ) + )['full_patient_df'] if button_run_pressed: tab1, tab2, tab3 = st.tabs( ["Animated Log", "Simple Graphs", "Advanced Graphs"] @@ -223,7 +226,7 @@ st.subheader("Animated Model Output") with st.spinner('Generating the animated patient log...'): st.plotly_chart(animate_activity_log( - animation_dfs_log['full_patient_df'], + full_patient_df=animation_dfs_log[animation_dfs_log["minute"]<=60*24*5], event_position_df = event_position_df, scenario=args, include_play_button=True, @@ -413,12 +416,12 @@ ### Waits """) wait_box = px.box( - results.reset_index().melt(id_vars=["rep"]).set_index('variable').filter(like="wait", axis=0).reset_index(), + results.reset_index().melt(id_vars=["rep"]).set_index('variable').filter(like="01a", axis=0).reset_index(), y="variable", x="value", points="all", height=200, - range_x=[0, results.reset_index().melt(id_vars=["rep"]).set_index('variable').filter(like="wait", axis=0).reset_index().max().value] + range_x=[0, results.reset_index().melt(id_vars=["rep"]).set_index('variable').filter(like="01a", axis=0).reset_index().max().value] ) wait_box.update_layout(yaxis_title="", xaxis_title="Average Wait in Model Run") @@ -472,7 +475,7 @@ x="value", points="all", height=200, - range_x=[0, results.reset_index().melt(id_vars=["rep"]).set_index('variable').filter(like='throughput', axis=0).reset_index().max().value] + range_x=[0, 1.1] ) throughput_box.update_layout(yaxis_title="", xaxis_title="Throughput in Model Run") @@ -488,4 +491,6 @@ - # st.write(full_event_log) \ No newline at end of file + # st.write(full_event_log) + +gc.collect() \ No newline at end of file diff --git "a/pages/4_\360\237\217\245_The_Full_Model.py" "b/pages/4_\360\237\217\245_The_Full_Model.py" index 0f32e46..df4d805 100644 --- "a/pages/4_\360\237\217\245_The_Full_Model.py" +++ "b/pages/4_\360\237\217\245_The_Full_Model.py" @@ -3,16 +3,16 @@ Allows users to interact with an increasingly more complex treatment simulation ''' -import streamlit as st -import pandas as pd +import gc import asyncio +import pandas as pd import plotly.express as px -import gc import plotly.graph_objects as go +import streamlit as st -from helper_functions import read_file_contents, add_logo, mermaid +from helper_functions import add_logo, mermaid from model_classes import Scenario, multiple_replications -from output_animation_functions import reshape_for_animations, animate_queue_activity_bar_chart, animate_activity_log +from output_animation_functions import reshape_for_animations, animate_activity_log st.set_page_config( page_title="The Full Model", @@ -33,7 +33,6 @@ st.title("Discrete Event Simulation Playground") st.subheader("How can we optimise the full system?") - tab1, tab2, tab3, tab4 = st.tabs(["Introduction", "Exercises", "Playground", "Compare Scenario Outputs"]) with tab1: st.markdown(""" @@ -245,7 +244,7 @@ class T ZZ5a results_for_state['Probability patient\nis a trauma patient'] = args.prob_trauma results_for_state['Probability non-trauma patients\nrequire treatment'] = args.non_trauma_treat_p results_for_state['Model Run'] = len(st.session_state['session_results']) + 1 - results_for_state['Random Seed'] = args.random_number_set + results_for_state['Random Seed'] = seed # Reorder columns column_order = ['Model Run', 'Triage\nCubicles', 'Registration\nClerks', 'Examination\nRooms', @@ -281,10 +280,12 @@ class T ZZ5a animation_dfs_log = reshape_for_animations( full_event_log=full_event_log[ (full_event_log['rep']==1) & - ((full_event_log['event_type']=='queue') | (full_event_log['event_type']=='resource_use') | (full_event_log['event_type']=='arrival_departure')) + ((full_event_log['event_type']=='queue') | (full_event_log['event_type']=='resource_use') | (full_event_log['event_type']=='arrival_departure')) & + # Limit to first 5 days + (full_event_log['time'] <= 60*24*5) ], every_x_minutes=5 - ) + )['full_patient_df'] del full_event_log gc.collect() @@ -314,29 +315,41 @@ class T ZZ5a # {'event': 'arrival', 'x': 10, 'y': 250, 'label': "Arrival" }, # Triage - minor and trauma - {'event': 'triage_wait_begins', 'x': 160, 'y': 400, 'label': "Waiting for
Triage" }, - {'event': 'triage_begins', 'x': 160, 'y': 315, 'resource':'n_triage', 'label': "Being Triaged" }, + {'event': 'triage_wait_begins', + 'x': 160, 'y': 400, 'label': "Waiting for
Triage" }, + {'event': 'triage_begins', + 'x': 160, 'y': 315, 'resource':'n_triage', 'label': "Being Triaged" }, # Minors (non-trauma) pathway - {'event': 'MINORS_registration_wait_begins', 'x': 300, 'y': 145, 'label': "Waiting for
Registration" }, - {'event': 'MINORS_registration_begins', 'x': 300, 'y': 85, 'resource':'n_reg', 'label':'Being
Registered' }, + {'event': 'MINORS_registration_wait_begins', + 'x': 300, 'y': 145, 'label': "Waiting for
Registration" }, + {'event': 'MINORS_registration_begins', + 'x': 300, 'y': 85, 'resource':'n_reg', 'label':'Being
Registered' }, - {'event': 'MINORS_examination_wait_begins', 'x': 465, 'y': 145, 'label': "Waiting for
Examination" }, - {'event': 'MINORS_examination_begins', 'x': 465, 'y': 85, 'resource':'n_exam', 'label': "Being
Examined" }, + {'event': 'MINORS_examination_wait_begins', + 'x': 465, 'y': 145, 'label': "Waiting for
Examination" }, + {'event': 'MINORS_examination_begins', + 'x': 465, 'y': 85, 'resource':'n_exam', 'label': "Being
Examined" }, - {'event': 'MINORS_treatment_wait_begins', 'x': 630, 'y': 145, 'label': "Waiting for
Treatment" }, - {'event': 'MINORS_treatment_begins', 'x': 630, 'y': 85, 'resource':'n_cubicles_1', 'label': "Being
Treated" }, + {'event': 'MINORS_treatment_wait_begins', + 'x': 630, 'y': 145, 'label': "Waiting for
Treatment" }, + {'event': 'MINORS_treatment_begins', + 'x': 630, 'y': 85, 'resource':'n_cubicles_1', 'label': "Being
Treated" }, # Trauma pathway - {'event': 'TRAUMA_stabilisation_wait_begins', 'x': 300, 'y': 560, 'label': "Waiting for
Stabilisation" }, - {'event': 'TRAUMA_stabilisation_begins', 'x': 300, 'y': 500, 'resource':'n_trauma', 'label': "Being
Stabilised" }, - - {'event': 'TRAUMA_treatment_wait_begins', 'x': 630, 'y': 560, 'label': "Waiting for
Treatment" }, - {'event': 'TRAUMA_treatment_begins', 'x': 630, 'y': 500, 'resource':'n_cubicles_2', 'label': "Being
Treated" } + {'event': 'TRAUMA_stabilisation_wait_begins', + 'x': 300, 'y': 560, 'label': "Waiting for
Stabilisation" }, + {'event': 'TRAUMA_stabilisation_begins', + 'x': 300, 'y': 500, 'resource':'n_trauma', 'label': "Being
Stabilised" }, + + {'event': 'TRAUMA_treatment_wait_begins', + 'x': 630, 'y': 560, 'label': "Waiting for
Treatment" }, + {'event': 'TRAUMA_treatment_begins', + 'x': 630, 'y': 500, 'resource':'n_cubicles_2', 'label': "Being
Treated" } ]) animated_plot = animate_activity_log( - animation_dfs_log['full_patient_df'], + full_patient_df=animation_dfs_log[animation_dfs_log["minute"]<=60*24*5], event_position_df = event_position_df, scenario=args, include_play_button=True, @@ -352,7 +365,7 @@ class T ZZ5a # show_animated_clock=True, # animated_clock_coordinates = [100, 50], add_background_image="https://raw.githubusercontent.com/Bergam0t/Teaching_DES_Concepts_Streamlit/main/resources/Full%20Model%20Background%20Image%20-%20Horizontal%20Layout.drawio.png", - ) + ) st.plotly_chart(animated_plot, use_container_width=False) @@ -769,4 +782,6 @@ class T ZZ5a st.write(all_run_results.groupby('Model Run').median().T) else: - st.markdown("No scenarios yet run. Go to the 'Playground' tab and click 'Run simulation'.") \ No newline at end of file + st.markdown("No scenarios yet run. Go to the 'Playground' tab and click 'Run simulation'.") + +gc.collect() \ No newline at end of file