|
import pandas as pd |
|
import plotly.express as px |
|
import streamlit as st |
|
|
|
from process_kpi.process_lcg_capacity import load_and_process_lcg_data |
|
from utils.convert_to_excel import convert_dfs |
|
|
|
|
|
class LcgCapacity: |
|
final_results = None |
|
|
|
|
|
|
|
st.title(" 📊 LCG Analysis") |
|
doc_col, image_col = st.columns(2) |
|
|
|
with doc_col: |
|
st.write( |
|
"""This app allows you to analyze the LCG of a network. |
|
It provides insights into the utilization of LCG resources, |
|
helping you identify potential capacity issues and plan for upgrades. |
|
|
|
The report should be run with a minimum of 3 days of data. |
|
- Daily Aggregated |
|
- LCG level |
|
- Exported in CSV format. |
|
""" |
|
) |
|
|
|
with image_col: |
|
st.image("./assets/lcg_analysis.png", width=250) |
|
|
|
uploaded_file = st.file_uploader("Upload LCG report in CSV format", type="csv") |
|
|
|
param_col1, param_col2, param_col3 = st.columns(3) |
|
param_col4, param_col5, param_col6 = st.columns(3) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if uploaded_file is not None: |
|
LcgCapacity.final_results = None |
|
with param_col1: |
|
num_last_days = st.number_input( |
|
"Number of days for analysis", |
|
min_value=3, |
|
max_value=30, |
|
value=7, |
|
) |
|
with param_col2: |
|
num_threshold_days = st.number_input( |
|
"Number of days for threshold", |
|
min_value=1, |
|
max_value=30, |
|
value=2, |
|
) |
|
with param_col3: |
|
lcg_utilization_threshold = st.number_input( |
|
"LCG Utilization Threshold (%)", |
|
min_value=0, |
|
max_value=100, |
|
value=80, |
|
) |
|
with param_col4: |
|
difference_between_lcgs = st.number_input( |
|
"Difference between LCgs (%)", |
|
min_value=0, |
|
max_value=100, |
|
value=20, |
|
) |
|
if st.button("Analyze Data", type="primary"): |
|
|
|
try: |
|
if num_threshold_days > num_last_days: |
|
st.warning( |
|
"Number of threshold days cannot be greater than number of analysis days" |
|
) |
|
st.stop() |
|
|
|
if num_last_days < 3: |
|
st.warning( |
|
"Analysis period should be at least 3 days for meaningful results" |
|
) |
|
st.stop() |
|
|
|
if lcg_utilization_threshold <= 0 or lcg_utilization_threshold > 100: |
|
st.warning("LCG utilization threshold must be between 1 and 100") |
|
st.stop() |
|
|
|
with st.spinner("Processing data..."): |
|
results = load_and_process_lcg_data( |
|
uploaded_file, |
|
num_last_days, |
|
num_threshold_days, |
|
lcg_utilization_threshold, |
|
difference_between_lcgs, |
|
) |
|
except Exception as e: |
|
st.error(f"An error occurred during input validation: {str(e)}") |
|
st.stop() |
|
if results is not None: |
|
lcg_analysis_df = results[0] |
|
kpi_df = results[1] |
|
LcgCapacity.final_results = convert_dfs( |
|
[lcg_analysis_df, kpi_df], ["lcg_analysis", "kpi"] |
|
) |
|
st.download_button( |
|
on_click="ignore", |
|
type="primary", |
|
label="Download the Analysis Report", |
|
data=LcgCapacity.final_results, |
|
file_name="LCG_Capacity_Report.xlsx", |
|
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", |
|
) |
|
st.write(lcg_analysis_df) |
|
|
|
st.markdown("***") |
|
st.markdown(":blue[**Final comment distribution**]") |
|
final_comments_df = ( |
|
lcg_analysis_df.groupby("final_comments") |
|
.size() |
|
.reset_index(name="count") |
|
.sort_values(by="count", ascending=False) |
|
) |
|
final_comments_df["percent"] = ( |
|
final_comments_df["count"] / final_comments_df["count"].sum() |
|
) * 100 |
|
final_comments_col1, final_comments_col2 = st.columns((1, 3)) |
|
with final_comments_col1: |
|
st.write(final_comments_df) |
|
with final_comments_col2: |
|
fig = px.pie( |
|
final_comments_df, |
|
names="final_comments", |
|
values="count", |
|
hover_name="final_comments", |
|
hover_data=["count", "percent"], |
|
title="Final Comments Distribution", |
|
) |
|
fig.update_layout(height=600) |
|
fig.update_traces( |
|
texttemplate="<b>%{label}</b><br> %{value} <b>(%{customdata[1]:.1f}%)</b>", |
|
textfont_size=15, |
|
textposition="outside", |
|
) |
|
st.plotly_chart(fig) |
|
|
|
|
|
st.markdown("***") |
|
st.markdown(":blue[**Final comment distribution per Region**]") |
|
final_comments_df = ( |
|
lcg_analysis_df.groupby(["Region", "final_comments"]) |
|
.size() |
|
.reset_index(name="count") |
|
.sort_values(by="count", ascending=False) |
|
) |
|
final_comments_col1, final_comments_col2 = st.columns((1, 3)) |
|
with final_comments_col1: |
|
st.write(final_comments_df) |
|
with final_comments_col2: |
|
fig = px.bar( |
|
final_comments_df, |
|
x="Region", |
|
y="count", |
|
color="final_comments", |
|
title="Final Comments Distribution per Region", |
|
text="count", |
|
) |
|
fig.update_traces(textposition="outside") |
|
fig.update_layout(height=600) |
|
st.plotly_chart(fig) |
|
|
|
|
|
st.markdown("***") |
|
st.markdown(":blue[**Final comments distribution**]") |
|
final_comments_map_df = lcg_analysis_df[ |
|
["code", "Longitude", "Latitude", "final_comments"] |
|
].dropna(subset=["code", "Longitude", "Latitude", "final_comments"]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
final_comments_map_df["size"] = 20 |
|
|
|
fig = px.scatter_map( |
|
final_comments_map_df, |
|
lat="Latitude", |
|
lon="Longitude", |
|
color="final_comments", |
|
size="size", |
|
zoom=10, |
|
height=600, |
|
title="Final Comments Distribution", |
|
hover_data={ |
|
"code": True, |
|
"final_comments": True, |
|
}, |
|
hover_name="code", |
|
) |
|
fig.update_layout(mapbox_style="open-street-map") |
|
st.plotly_chart(fig) |
|
|