Skip to content

Commit

Permalink
enh: add initial streamlit dashboard setup
Browse files Browse the repository at this point in the history
  • Loading branch information
munterfi committed Oct 4, 2024
1 parent d4339b7 commit 9de68e8
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 0 deletions.
43 changes: 43 additions & 0 deletions rssched/app/pages/01_runinfo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import pandas as pd
import streamlit as st

from rssched.app.utils.io import get_uploaded_data

st.title(f"Run Info")

# Retrieve uploaded request and response data
request, response, instance_name = get_uploaded_data()


request_summary_df = pd.DataFrame(
{
"Locations": [len(request.vehicle_types)],
"Vehicle types": [len(request.vehicle_types)],
"Depots": [len(request.depots)],
"Depot capacity": [sum(depot.capacity for depot in request.depots)],
"Routes": [len(request.routes)],
"Departures": [len(request.departures)],
"Maintenance tracks": [
sum(slot.track_count for slot in request.maintenance_slots)
],
}
)

response_summary_df = pd.DataFrame(
{
"Unserved passengers": [response.objective_value.unserved_passengers],
"Maintenance violoation": [response.objective_value.maintenance_violation],
"Vehicle count": [response.objective_value.vehicle_count],
"Costs": [response.objective_value.costs],
}
)

st.write(f"**Instance:** {instance_name}")

st.subheader("Request Summary")
st.write(f"**File:** {st.session_state.request_file.name}")
st.dataframe(request_summary_df, hide_index=True)

st.subheader("Response Summary")
st.write(f"**File:** {st.session_state.response_file.name}")
st.dataframe(response_summary_df, hide_index=True)
43 changes: 43 additions & 0 deletions rssched/app/pages/02_schedule.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import streamlit as st

from rssched.app.utils.io import get_uploaded_data
from rssched.visualization.vehicle_type_gantt import plot_gantt_per_vehicle_type

st.title("Schedule")

request, response, instance_name = get_uploaded_data()

plots = plot_gantt_per_vehicle_type(response, instance_name)

tabs = st.tabs(plots.keys())

for tab, (title, fig) in zip(tabs, plots.items()):
with tab:
st.plotly_chart(fig)

"""
from rssched.visualization.vehicle_utilization import plot_vehicle_utilization
from rssched.visualization.fleet_efficiency import plot_fleet_efficiency
from rssched.visualization.active_events import plot_active_events_over_time
tabs = st.tabs(
[
"Gantt Chart",
"Active Events",
"Vehicle Utilization",
"Fleet Efficiency",
]
)
with tabs[0]:
st.plotly_chart(plot_gantt_per_vehicle_type(response, instance_name)[0])
with tabs[1]:
st.plotly_chart(plot_active_events_over_time(response, instance_name))
with tabs[2]:
st.plotly_chart(plot_vehicle_utilization(response, instance_name))
with tabs[3]:
st.plotly_chart(plot_fleet_efficiency(response, instance_name))
"""
22 changes: 22 additions & 0 deletions rssched/app/pages/03_fleet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import streamlit as st

from rssched.app.utils.io import get_uploaded_data
from rssched.visualization.active_events import plot_active_events_over_time
from rssched.visualization.fleet_efficiency import plot_fleet_efficiency
from rssched.visualization.vehicle_utilization import plot_vehicle_utilization

st.title("Fleet")

request, response, instance_name = get_uploaded_data()


tabs = st.tabs(["Active Events", "Vehicle Utilization", "Efficiency"])

with tabs[0]:
st.plotly_chart(plot_active_events_over_time(response, instance_name))

with tabs[1]:
st.plotly_chart(plot_vehicle_utilization(response, instance_name))

with tabs[2]:
st.plotly_chart(plot_fleet_efficiency(response, instance_name))
7 changes: 7 additions & 0 deletions rssched/app/pages/04_depots.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import streamlit as st

from rssched.app.utils.io import get_uploaded_data

st.title("Depots")

request, response, instance_name = get_uploaded_data()
57 changes: 57 additions & 0 deletions rssched/app/upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import streamlit as st

from rssched.app.utils.io import import_request, import_response

st.title("RSSched Analyzer")
st.markdown(
"""
### About
This page provides an aggregated summary of the request data uploaded by the user.
You can see important statistics such as the number of locations, vehicle types, depots,
routes, and other relevant metrics. Additionally, an objective value from the response is also displayed below.
"""
)

st.subheader("Upload Data")

# Session state to store file uploads
if "request_file" not in st.session_state:
st.session_state.request_file = None
if "response_file" not in st.session_state:
st.session_state.response_file = None

# Upload Request and Response Files
request_file = st.file_uploader(
"Set request file (JSON)", type=["json"], key="request_uploader"
)
response_file = st.file_uploader(
"Set response file (JSON)", type=["json"], key="response_uploader"
)

# If both files are uploaded, process them
if request_file is not None and response_file is not None:
request_instance_name = ".".join(request_file.name.split(".")[:2])
response_instance_name = ".".join(response_file.name.split(".")[:2])

if request_instance_name != response_instance_name:
st.warning(
f"Instance of request '{request_instance_name}' and response '{response_instance_name}' not the same."
)

st.session_state.rssched_instance_name = request_instance_name
st.session_state.request_file = request_file
st.session_state.response_file = response_file
st.session_state.instance_name = response_file
st.session_state.request_data = import_request(st.session_state.request_file)
st.session_state.response_data = import_response(st.session_state.response_file)

st.success("Files uploaded and processed successfully!")


# Reset button to clear the uploaded files and session state
if st.button("Reset"):
st.session_state.request_file = None
st.session_state.response_file = None
st.session_state.request_data = None
st.session_state.response_data = None
st.rerun()
33 changes: 33 additions & 0 deletions rssched/app/utils/io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import json
from typing import Tuple

import streamlit as st

from rssched.io.reader import convert_keys_to_snake_case
from rssched.model.request import Request
from rssched.model.response import Info, ObjectiveValue, Response, Schedule


def import_request(file_obj) -> Request:
data = convert_keys_to_snake_case(json.load(file_obj))
return Request(**data)


def import_response(file_obj) -> Response:
data = convert_keys_to_snake_case(json.load(file_obj))

info = Info(**data["info"])
objective_value = ObjectiveValue(**data["objective_value"])
schedule = Schedule(**data["schedule"])

return Response(info=info, objective_value=objective_value, schedule=schedule)


def get_uploaded_data() -> Tuple[Request, Response, str]:
if st.session_state.get("request_data") and st.session_state.get("response_data"):
request_data = st.session_state["request_data"]
response_data = st.session_state["response_data"]
return request_data, response_data, st.session_state["rssched_instance_name"]
else:
st.warning("Please upload both request and response files on the main page.")
st.stop()

0 comments on commit 9de68e8

Please sign in to comment.