|
1 | 1 | import os
|
| 2 | +import folium |
2 | 3 | import tempfile
|
3 | 4 | import subprocess
|
4 | 5 | import pandas as pd
|
5 | 6 | import streamlit as st
|
| 7 | +from streamlit_folium import st_folium |
6 | 8 |
|
7 | 9 | #Page Setup
|
8 | 10 | st.set_page_config(
|
|
13 | 15 | initial_sidebar_state="expanded",
|
14 | 16 | )
|
15 | 17 |
|
| 18 | +# Session setup |
| 19 | +if 'calculate_clicked' not in st.session_state: |
| 20 | + st.session_state.calculate_clicked = False |
| 21 | +if 'calculation_completed' not in st.session_state: |
| 22 | + st.session_state.calculation_completed = False |
| 23 | +if 'calculated_data' not in st.session_state: |
| 24 | + st.session_state.calculated_data = {} |
| 25 | +if 'filter_type' not in st.session_state: |
| 26 | + st.session_state.filter_type = None |
| 27 | +if 'filter_value' not in st.session_state: |
| 28 | + st.session_state.filter_value = None |
| 29 | + |
| 30 | + |
| 31 | +#Maps setup |
| 32 | +m = folium.Map(location=[27.7007, 85.3001], zoom_start=12, ) |
| 33 | +fg = folium.FeatureGroup(name="Allocated Centers") |
| 34 | + |
16 | 35 | #Sidebar
|
17 | 36 | with st.sidebar:
|
18 | 37 |
|
19 |
| - add_side_header = st.sidebar.title( |
20 |
| - "Random Center Calculator" |
21 |
| - ) |
| 38 | + add_side_header = st.sidebar.title("Random Center Calculator") |
| 39 | + |
22 | 40 | schools_file = st.sidebar.file_uploader("Upload School/College file", type="tsv")
|
23 | 41 | centers_file = st.sidebar.file_uploader("Upload Centers file", type="tsv")
|
24 | 42 | prefs_file = st.sidebar.file_uploader("Upload Preferences file", type="tsv")
|
@@ -65,50 +83,99 @@ def run_center_randomizer(schools_tsv, centers_tsv, prefs_tsv):
|
65 | 83 | cmd = f"python school_center.py {schools_tsv} {centers_tsv} {prefs_tsv}"
|
66 | 84 | subprocess.run(cmd, shell=True)
|
67 | 85 |
|
| 86 | +#Function to filter the data |
| 87 | +def filter_data(df, filter_type, filter_value): |
| 88 | + if filter_type in df.columns: |
| 89 | + df = df[df[filter_type] == filter_value] |
| 90 | + return df |
| 91 | + else: |
| 92 | + st.error(f"{filter_type} is not a valid column in the DataFrame.") |
| 93 | + return pd.DataFrame() |
| 94 | + |
68 | 95 | # Run logic after the button is clicked
|
69 | 96 | if calculate:
|
70 |
| - |
| 97 | + st.session_state.calculate_clicked = True |
| 98 | + |
71 | 99 | def save_file_to_temp(file_obj):
|
72 | 100 | with tempfile.NamedTemporaryFile(delete=False) as temp_file:
|
73 | 101 | file_obj.seek(0) # Go to the start of the file
|
74 | 102 | temp_file.write(file_obj.read())
|
75 | 103 | return temp_file.name
|
76 | 104 |
|
77 |
| - # Ensure all files are uploaded |
78 |
| - if schools_file and centers_file and prefs_file: |
79 |
| - schools_path = save_file_to_temp(schools_file) |
80 |
| - centers_path = save_file_to_temp(centers_file) |
81 |
| - prefs_path = save_file_to_temp(prefs_file) |
82 |
| - |
83 |
| - # Run the program with the temporary file paths |
84 |
| - run_center_randomizer(schools_path, centers_path, prefs_path) |
85 |
| - |
86 |
| - # Set the paths for the output files |
87 |
| - school_center_file = "results/school-center.tsv" |
88 |
| - school_center_distance_file = "results/school-center-distance.tsv" |
89 |
| - |
90 |
| - # Delete the temporary files after use |
91 |
| - os.unlink(schools_path) |
92 |
| - os.unlink(centers_path) |
93 |
| - os.unlink(prefs_path) |
94 |
| - |
95 |
| - # Display data in the specified tabs |
96 |
| - if school_center_file: |
97 |
| - df = pd.read_csv(school_center_file, sep="\t") |
98 |
| - tab1.dataframe(df) |
99 |
| - else: |
100 |
| - tab1.error("School Center file not found.") |
101 |
| - |
102 |
| - if school_center_distance_file: |
103 |
| - df = pd.read_csv(school_center_distance_file, sep="\t") |
104 |
| - tab2.dataframe(df) |
| 105 | + if st.session_state.calculate_clicked: |
| 106 | + # Ensure all files are uploaded |
| 107 | + if schools_file and centers_file and prefs_file: |
| 108 | + schools_path = save_file_to_temp(schools_file) |
| 109 | + centers_path = save_file_to_temp(centers_file) |
| 110 | + prefs_path = save_file_to_temp(prefs_file) |
| 111 | + |
| 112 | + # Run the program with the temporary file paths |
| 113 | + run_center_randomizer(schools_path, centers_path, prefs_path) |
| 114 | + st.toast("Calculation successful!", icon="🎉") |
| 115 | + st.session_state.calculation_completed = True |
| 116 | + |
| 117 | + # Delete the temporary files after use |
| 118 | + os.unlink(schools_path) |
| 119 | + os.unlink(centers_path) |
| 120 | + os.unlink(prefs_path) |
| 121 | + |
| 122 | + # Set the paths for the output files[UPDATE LATER TO BE FLEXIBLE] |
| 123 | + school_center_file = "results/school-center.tsv" |
| 124 | + school_center_distance_file = "results/school-center-distance.tsv" |
| 125 | + |
| 126 | + # Store calculated data in session state |
| 127 | + if school_center_file and school_center_distance_file: |
| 128 | + st.session_state.calculated_data['school_center'] = school_center_file |
| 129 | + st.session_state.calculated_data['school_center_distance'] = school_center_distance_file |
| 130 | + else: |
| 131 | + tab1.error("Calculated data not found", icon="🚨") |
| 132 | + |
105 | 133 | else:
|
106 |
| - tab2.error("School Center Distance file not found.") |
| 134 | + st.sidebar.error("Please upload all required files.", icon="🚨") |
107 | 135 |
|
108 |
| - st.toast("Calculation successful!", icon="🎉") |
109 |
| - |
110 |
| - else: |
111 |
| - st.sidebar.error("Please upload all required files.", icon="🚨") |
112 |
| -else: |
| 136 | +elif not st.session_state.calculate_clicked: |
113 | 137 | tab1_msg = tab1.info("Results will be shown only after the calculation is completed.", icon="ℹ️")
|
114 | 138 | tab2_msg = tab2.info("Results will be shown only after the calculation is completed.", icon="ℹ️")
|
| 139 | + |
| 140 | +if st.session_state.calculate_clicked and st.session_state.calculation_completed: |
| 141 | + # Display data from session state |
| 142 | + if 'school_center' in st.session_state.calculated_data: |
| 143 | + df_school_center = pd.read_csv(st.session_state.calculated_data['school_center'], sep="\t") |
| 144 | + allowed_filter_types = ['scode', 'school', 'cscode', 'center'] |
| 145 | + st.session_state.filter_type = tab1.radio("Choose a filter type:", allowed_filter_types) |
| 146 | + |
| 147 | + # Display an input field based on the selected filter type |
| 148 | + if st.session_state.filter_type: |
| 149 | + st.session_state.filter_value = tab1.selectbox(f"Select a value for {st.session_state.filter_type}:", df_school_center[st.session_state.filter_type].unique()) |
| 150 | + # Filter the DataFrame based on the selected filter type and value |
| 151 | + if st.session_state.filter_value: |
| 152 | + filtered_df = filter_data(df_school_center, st.session_state.filter_type, st.session_state.filter_value) |
| 153 | + tab1.dataframe(filtered_df) |
| 154 | + tab1.subheader('Map') |
| 155 | + tab1.divider() |
| 156 | + for index, center in filtered_df.iterrows(): |
| 157 | + fg.add_child( |
| 158 | + folium.Marker( |
| 159 | + location=[center.center_lat, center.center_long], |
| 160 | + popup=f"{(center.center).title()}\nAllocation: {center.allocation}", |
| 161 | + tooltip=f"{center.center}", |
| 162 | + icon=folium.Icon(color="red") |
| 163 | + ) |
| 164 | + ) |
| 165 | + m.add_child(fg) |
| 166 | + with tab1: |
| 167 | + st_folium( m, width=1200, height=400 ) |
| 168 | + |
| 169 | + tab1.divider() |
| 170 | + tab1.subheader('All Data') |
| 171 | + tab1.dataframe(df_school_center) |
| 172 | + else: |
| 173 | + tab1.info("No calculated data available.", icon="ℹ️") |
| 174 | + |
| 175 | + if 'school_center_distance' in st.session_state.calculated_data: |
| 176 | + df = pd.read_csv(st.session_state.calculated_data['school_center_distance'], sep="\t") |
| 177 | + tab2.dataframe(df) |
| 178 | + else: |
| 179 | + tab2.error("School Center Distance file not found.") |
| 180 | +elif st.session_state.calculate_clicked and not st.session_state.calculated_data: |
| 181 | + tab1.error("School Center data not found in session state.") |
0 commit comments