improve lac distribution plot with plotly
Browse files- apps/dump_analysis.py +29 -2
- queries/process_gsm.py +26 -3
- queries/process_wcdma.py +18 -1
- requirements.txt +0 -0
- utils/rnc_bsc_lac_count_chart.py +89 -0
apps/dump_analysis.py
CHANGED
@@ -1,5 +1,10 @@
|
|
|
|
1 |
import streamlit as st
|
2 |
|
|
|
|
|
|
|
|
|
3 |
from utils.utils_vars import (
|
4 |
GsmAnalysisData,
|
5 |
LteFddAnalysisData,
|
@@ -79,7 +84,14 @@ def dump_analysis_space():
|
|
79 |
with number_of_cell_per_lac_data_col:
|
80 |
st.write(GsmAnalysisData.number_of_cell_per_lac)
|
81 |
with number_of_cell_per_lac_plot_col:
|
82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
|
84 |
st.markdown("***")
|
85 |
st.markdown(":blue[**TRX AdminState Distribution**]")
|
@@ -90,6 +102,12 @@ def dump_analysis_space():
|
|
90 |
st.write(GsmAnalysisData.trx_administate_distribution)
|
91 |
with trx_administate_distribution_plot_col:
|
92 |
st.bar_chart(GsmAnalysisData.trx_administate_distribution)
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
####################### WCDMA ANALYTICS DATA #######################################
|
95 |
st.subheader(":green[WCDMA ANALYTICS DATA]")
|
@@ -129,6 +147,7 @@ def dump_analysis_space():
|
|
129 |
with number_of_site_per_rnc_data_col:
|
130 |
st.write(WcdmaAnalysisData.number_of_site_per_rnc)
|
131 |
with number_of_site_per_rnc_plot_col:
|
|
|
132 |
st.bar_chart(WcdmaAnalysisData.number_of_site_per_rnc)
|
133 |
|
134 |
st.markdown("***")
|
@@ -137,8 +156,16 @@ def dump_analysis_space():
|
|
137 |
number_of_cell_per_lac_data_col, number_of_cell_per_lac_plot_col = st.columns(2)
|
138 |
with number_of_cell_per_lac_data_col:
|
139 |
st.write(WcdmaAnalysisData.number_of_cell_per_lac)
|
|
|
140 |
with number_of_cell_per_lac_plot_col:
|
141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
|
143 |
st.markdown("***")
|
144 |
st.markdown(":green[**WCEL AdminState Distribution**]")
|
|
|
1 |
+
import plotly.express as px
|
2 |
import streamlit as st
|
3 |
|
4 |
+
from utils.rnc_bsc_lac_count_chart import (
|
5 |
+
create_bar_chart,
|
6 |
+
create_lac_count_per_controller_subplots,
|
7 |
+
)
|
8 |
from utils.utils_vars import (
|
9 |
GsmAnalysisData,
|
10 |
LteFddAnalysisData,
|
|
|
84 |
with number_of_cell_per_lac_data_col:
|
85 |
st.write(GsmAnalysisData.number_of_cell_per_lac)
|
86 |
with number_of_cell_per_lac_plot_col:
|
87 |
+
fig = create_lac_count_per_controller_subplots(
|
88 |
+
df=GsmAnalysisData.number_of_cell_per_lac,
|
89 |
+
controller_column="BSC",
|
90 |
+
lac_column="LAC",
|
91 |
+
count_column="count",
|
92 |
+
fig_title="Number of Cell per LAC and BSC",
|
93 |
+
)
|
94 |
+
st.plotly_chart(fig)
|
95 |
|
96 |
st.markdown("***")
|
97 |
st.markdown(":blue[**TRX AdminState Distribution**]")
|
|
|
102 |
st.write(GsmAnalysisData.trx_administate_distribution)
|
103 |
with trx_administate_distribution_plot_col:
|
104 |
st.bar_chart(GsmAnalysisData.trx_administate_distribution)
|
105 |
+
# fig = create_bar_chart(
|
106 |
+
# df=GsmAnalysisData.trx_administate_distribution,
|
107 |
+
# title="TRX AdminState Distribution",
|
108 |
+
# )
|
109 |
+
|
110 |
+
# st.plotly_chart(fig)
|
111 |
|
112 |
####################### WCDMA ANALYTICS DATA #######################################
|
113 |
st.subheader(":green[WCDMA ANALYTICS DATA]")
|
|
|
147 |
with number_of_site_per_rnc_data_col:
|
148 |
st.write(WcdmaAnalysisData.number_of_site_per_rnc)
|
149 |
with number_of_site_per_rnc_plot_col:
|
150 |
+
# fig = px.bar
|
151 |
st.bar_chart(WcdmaAnalysisData.number_of_site_per_rnc)
|
152 |
|
153 |
st.markdown("***")
|
|
|
156 |
number_of_cell_per_lac_data_col, number_of_cell_per_lac_plot_col = st.columns(2)
|
157 |
with number_of_cell_per_lac_data_col:
|
158 |
st.write(WcdmaAnalysisData.number_of_cell_per_lac)
|
159 |
+
|
160 |
with number_of_cell_per_lac_plot_col:
|
161 |
+
fig = create_lac_count_per_controller_subplots(
|
162 |
+
df=WcdmaAnalysisData.number_of_cell_per_lac,
|
163 |
+
controller_column="RNC",
|
164 |
+
lac_column="LAC",
|
165 |
+
count_column="LAC_Count",
|
166 |
+
fig_title="Number of Cell per LAC and RNC",
|
167 |
+
)
|
168 |
+
st.plotly_chart(fig)
|
169 |
|
170 |
st.markdown("***")
|
171 |
st.markdown(":green[**WCEL AdminState Distribution**]")
|
queries/process_gsm.py
CHANGED
@@ -204,8 +204,31 @@ def gsm_analaysis(file_path: str):
|
|
204 |
GsmAnalysisData.number_of_bcch_empty = gsm_df["BCCH"].isna().sum()
|
205 |
GsmAnalysisData.bts_administate_distribution = gsm_df["adminState"].value_counts()
|
206 |
GsmAnalysisData.trx_administate_distribution = trx_df["adminState"].value_counts()
|
207 |
-
|
208 |
-
#
|
|
|
|
|
|
|
|
|
209 |
# )
|
210 |
|
211 |
-
GsmAnalysisData.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
GsmAnalysisData.number_of_bcch_empty = gsm_df["BCCH"].isna().sum()
|
205 |
GsmAnalysisData.bts_administate_distribution = gsm_df["adminState"].value_counts()
|
206 |
GsmAnalysisData.trx_administate_distribution = trx_df["adminState"].value_counts()
|
207 |
+
|
208 |
+
# GsmAnalysisData.trx_administate_distribution = (
|
209 |
+
# trx_df["adminState"]
|
210 |
+
# .value_counts()
|
211 |
+
# .reset_index()
|
212 |
+
# .rename(columns={"index": "value", 0: "count"})
|
213 |
# )
|
214 |
|
215 |
+
GsmAnalysisData.number_of_trx_per_bsc = trx_df["BSC"].value_counts()
|
216 |
+
# GsmAnalysisData.number_of_cell_per_lac = gsm_df["locationAreaIdLAC"].value_counts()
|
217 |
+
GsmAnalysisData.number_of_cell_per_lac = (
|
218 |
+
gsm_df.groupby(["BSC", "locationAreaIdLAC"]).size().reset_index(name="count")
|
219 |
+
)
|
220 |
+
# Rename columns
|
221 |
+
GsmAnalysisData.number_of_cell_per_lac.rename(
|
222 |
+
columns={"BSC": "BSC", "locationAreaIdLAC": "LAC", "count": "count"},
|
223 |
+
inplace=True,
|
224 |
+
)
|
225 |
+
# Add "BSC_" and "LAC_" prefix to LAC column
|
226 |
+
GsmAnalysisData.number_of_cell_per_lac["LAC"] = (
|
227 |
+
"LAC_" + GsmAnalysisData.number_of_cell_per_lac["LAC"].astype(str)
|
228 |
+
)
|
229 |
+
GsmAnalysisData.number_of_cell_per_lac["BSC"] = (
|
230 |
+
"BSC_" + GsmAnalysisData.number_of_cell_per_lac["BSC"].astype(str)
|
231 |
+
)
|
232 |
+
GsmAnalysisData.number_of_cell_per_lac = GsmAnalysisData.number_of_cell_per_lac[
|
233 |
+
["BSC", "LAC", "count"]
|
234 |
+
]
|
queries/process_wcdma.py
CHANGED
@@ -186,5 +186,22 @@ def wcdma_analaysis(filepath: str):
|
|
186 |
WcdmaAnalysisData.wcel_administate_distribution = wcdma_df[
|
187 |
"AdminCellState"
|
188 |
].value_counts()
|
189 |
-
WcdmaAnalysisData.number_of_cell_per_lac = wcdma_df["LAC"].value_counts()
|
190 |
WcdmaAnalysisData.psc_distribution = wcdma_df["PriScrCode"].value_counts()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
WcdmaAnalysisData.wcel_administate_distribution = wcdma_df[
|
187 |
"AdminCellState"
|
188 |
].value_counts()
|
|
|
189 |
WcdmaAnalysisData.psc_distribution = wcdma_df["PriScrCode"].value_counts()
|
190 |
+
# Manage Cells count per LAC and RNC
|
191 |
+
# Pivot RNC and LAC
|
192 |
+
WcdmaAnalysisData.number_of_cell_per_lac = (
|
193 |
+
wcdma_df.groupby(["RNC", "LAC"]).size().reset_index(name="count")
|
194 |
+
)
|
195 |
+
# Rename columns
|
196 |
+
WcdmaAnalysisData.number_of_cell_per_lac = (
|
197 |
+
WcdmaAnalysisData.number_of_cell_per_lac.rename(
|
198 |
+
columns={"RNC": "RNC", "LAC": "LAC", "count": "LAC_Count"}
|
199 |
+
)
|
200 |
+
)
|
201 |
+
# Add "RNC_" and "LAC_" prefix
|
202 |
+
WcdmaAnalysisData.number_of_cell_per_lac["RNC"] = (
|
203 |
+
"RNC_" + WcdmaAnalysisData.number_of_cell_per_lac["RNC"].astype(str)
|
204 |
+
)
|
205 |
+
WcdmaAnalysisData.number_of_cell_per_lac["LAC"] = (
|
206 |
+
"LAC_" + WcdmaAnalysisData.number_of_cell_per_lac["LAC"].astype(str)
|
207 |
+
)
|
requirements.txt
CHANGED
Binary files a/requirements.txt and b/requirements.txt differ
|
|
utils/rnc_bsc_lac_count_chart.py
ADDED
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
import plotly.express as px
|
3 |
+
import plotly.graph_objects as go
|
4 |
+
from plotly.subplots import make_subplots
|
5 |
+
|
6 |
+
|
7 |
+
# Reusable function to create subplots
|
8 |
+
def create_lac_count_per_controller_subplots(
|
9 |
+
df: pd.DataFrame,
|
10 |
+
controller_column: str,
|
11 |
+
lac_column: str,
|
12 |
+
count_column: str,
|
13 |
+
fig_title: str,
|
14 |
+
):
|
15 |
+
# Get unique controller_IDs
|
16 |
+
unique_controllers = df[controller_column].unique()
|
17 |
+
|
18 |
+
# Calculate the number of rows needed (4 subplots per row)
|
19 |
+
rows_needed = (len(unique_controllers) + 3) // 4 # Round up to ensure enough rows
|
20 |
+
|
21 |
+
# Create subplot structure with a dynamic number of rows and 4 columns per row
|
22 |
+
fig = make_subplots(
|
23 |
+
rows=rows_needed,
|
24 |
+
cols=4,
|
25 |
+
shared_xaxes=False,
|
26 |
+
subplot_titles=unique_controllers,
|
27 |
+
)
|
28 |
+
|
29 |
+
# Add a counter for positioning the subplots
|
30 |
+
subplot_position = 1
|
31 |
+
|
32 |
+
# Iterate over each controller_ID
|
33 |
+
for controller in unique_controllers:
|
34 |
+
# Filter data for each controller_ID (create a small dataframe per controller_ID)
|
35 |
+
controller_data = df[df[controller_column] == controller]
|
36 |
+
|
37 |
+
# Determine the row and column for the current subplot
|
38 |
+
row = (subplot_position - 1) // 4 + 1
|
39 |
+
col = (subplot_position - 1) % 4 + 1
|
40 |
+
|
41 |
+
# Add bar chart to the subplot
|
42 |
+
fig.add_trace(
|
43 |
+
go.Bar(
|
44 |
+
x=controller_data[lac_column],
|
45 |
+
y=controller_data[count_column],
|
46 |
+
name=controller,
|
47 |
+
text=controller_data[count_column],
|
48 |
+
),
|
49 |
+
row=row,
|
50 |
+
col=col,
|
51 |
+
)
|
52 |
+
|
53 |
+
# Move to the next subplot position
|
54 |
+
subplot_position += 1
|
55 |
+
|
56 |
+
# Update layout to make it more readable and fit all subplots
|
57 |
+
fig.update_layout(
|
58 |
+
height=300 * rows_needed,
|
59 |
+
title_text=fig_title,
|
60 |
+
showlegend=False,
|
61 |
+
)
|
62 |
+
|
63 |
+
# Show the plot
|
64 |
+
# fig.show()
|
65 |
+
|
66 |
+
return fig
|
67 |
+
|
68 |
+
|
69 |
+
def create_bar_chart(df: pd.DataFrame, title: str = "Chart Title") -> px.bar:
|
70 |
+
"""
|
71 |
+
Create a bar chart using Plotly Express with the first column as x and the second column as y.
|
72 |
+
|
73 |
+
Args:
|
74 |
+
df (pd.DataFrame): Input DataFrame
|
75 |
+
|
76 |
+
Returns:
|
77 |
+
fig (px.bar): Bar chart figure
|
78 |
+
"""
|
79 |
+
fig = px.bar(
|
80 |
+
df,
|
81 |
+
x=df.columns[0],
|
82 |
+
y=df.columns[1],
|
83 |
+
text_auto=True,
|
84 |
+
title=title,
|
85 |
+
height=300,
|
86 |
+
width=600,
|
87 |
+
)
|
88 |
+
fig.update_xaxes(tickvals=df[df.columns[0]].unique())
|
89 |
+
return fig
|