add KML generation options
Browse files- Changelog.md +5 -0
- README.md +1 -0
- app.py +1 -1
- apps/database_page.py +62 -5
- queries/process_gsm.py +34 -0
- queries/process_invunit.py +5 -0
- queries/process_lte.py +43 -0
- queries/process_wcdma.py +38 -0
- requirements.txt +0 -0
- test.py +1 -1
- utils/kml_creator.py +79 -0
- utils/utils_vars.py +21 -0
Changelog.md
CHANGED
@@ -1,6 +1,11 @@
|
|
1 |
|
2 |
# CHANGELOGS
|
3 |
|
|
|
|
|
|
|
|
|
|
|
4 |
## [0.2.3] - 2024-09-30
|
5 |
|
6 |
- Moving physical database to github storage repository
|
|
|
1 |
|
2 |
# CHANGELOGS
|
3 |
|
4 |
+
## [0.2.5] - 2024-09-30
|
5 |
+
|
6 |
+
- Add option to download KML file For 2G, 3G, and LTE
|
7 |
+
- Fix bug when LTE name is empty
|
8 |
+
|
9 |
## [0.2.3] - 2024-09-30
|
10 |
|
11 |
- Moving physical database to github storage repository
|
README.md
CHANGED
@@ -44,6 +44,7 @@ You can access the hosted version of the app at [https://davmelchi-db-query.hf.s
|
|
44 |
- [x] Add MRBTS with code
|
45 |
- [x] Check TCH from MAL sheet
|
46 |
- [x] Add Analitic dashboards for each database (Count of NE)
|
|
|
47 |
- [ ] Improve Dashboard
|
48 |
- [ ] Add the ability to select columns
|
49 |
- [ ] Error handling
|
|
|
44 |
- [x] Add MRBTS with code
|
45 |
- [x] Check TCH from MAL sheet
|
46 |
- [x] Add Analitic dashboards for each database (Count of NE)
|
47 |
+
- [x] Add kml generation
|
48 |
- [ ] Improve Dashboard
|
49 |
- [ ] Add the ability to select columns
|
50 |
- [ ] Error handling
|
app.py
CHANGED
@@ -6,7 +6,7 @@ st.set_page_config(
|
|
6 |
layout="wide",
|
7 |
initial_sidebar_state="expanded",
|
8 |
menu_items={
|
9 |
-
"About": "**📡 NPO DB Query v0.2.
|
10 |
},
|
11 |
)
|
12 |
|
|
|
6 |
layout="wide",
|
7 |
initial_sidebar_state="expanded",
|
8 |
menu_items={
|
9 |
+
"About": "**📡 NPO DB Query v0.2.5**",
|
10 |
},
|
11 |
)
|
12 |
|
apps/database_page.py
CHANGED
@@ -6,16 +6,16 @@ from st_aggrid import AgGrid, ColumnsAutoSizeMode
|
|
6 |
|
7 |
from apps.dump_analysis import dump_analysis_space
|
8 |
from queries.process_all_db import process_all_tech_db, process_all_tech_db_with_stats
|
9 |
-
from queries.process_gsm import process_gsm_data_to_excel
|
10 |
from queries.process_invunit import process_invunit_data_to_excel
|
11 |
-
from queries.process_lte import process_lte_data_to_excel
|
12 |
|
13 |
# from queries.process_mal import process_mal_data_to_excel
|
14 |
from queries.process_mrbts import process_mrbts_data_to_excel
|
15 |
from queries.process_neighbors import process_neighbors_data_to_excel
|
16 |
|
17 |
# from queries.process_trx import process_trx_with_bts_name_data_to_excel
|
18 |
-
from queries.process_wcdma import process_wcdma_data_to_excel
|
19 |
from utils.check_sheet_exist import DumpType, Technology, execute_checks_sheets_exist
|
20 |
from utils.utils_vars import GsmAnalysisData, UtilsVars, WcdmaAnalysisData
|
21 |
|
@@ -67,6 +67,37 @@ def download_button(database_type):
|
|
67 |
)
|
68 |
|
69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
def execute_process_all_tech_db(uploaded_file):
|
71 |
if uploaded_file is not None:
|
72 |
start_time = time.time()
|
@@ -94,8 +125,8 @@ def execute_process_all_tech_db_with_stats(uploaded_file: str):
|
|
94 |
download_button("All")
|
95 |
|
96 |
|
97 |
-
col1, col2, col3, col4 = st.columns(
|
98 |
-
|
99 |
if uploaded_file is not None:
|
100 |
# UtilsVars.file_path = uploaded_file
|
101 |
|
@@ -183,6 +214,32 @@ if uploaded_file is not None:
|
|
183 |
process_neighbors_data_to_excel, "NEI"
|
184 |
),
|
185 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
|
187 |
except Exception as e:
|
188 |
st.error(f"Error: {e}")
|
|
|
6 |
|
7 |
from apps.dump_analysis import dump_analysis_space
|
8 |
from queries.process_all_db import process_all_tech_db, process_all_tech_db_with_stats
|
9 |
+
from queries.process_gsm import process_gsm_data_to_excel, process_gsm_data_to_kml
|
10 |
from queries.process_invunit import process_invunit_data_to_excel
|
11 |
+
from queries.process_lte import process_lte_data_to_excel, process_lte_data_to_kml
|
12 |
|
13 |
# from queries.process_mal import process_mal_data_to_excel
|
14 |
from queries.process_mrbts import process_mrbts_data_to_excel
|
15 |
from queries.process_neighbors import process_neighbors_data_to_excel
|
16 |
|
17 |
# from queries.process_trx import process_trx_with_bts_name_data_to_excel
|
18 |
+
from queries.process_wcdma import process_wcdma_data_to_excel, process_wcdma_data_to_kml
|
19 |
from utils.check_sheet_exist import DumpType, Technology, execute_checks_sheets_exist
|
20 |
from utils.utils_vars import GsmAnalysisData, UtilsVars, WcdmaAnalysisData
|
21 |
|
|
|
67 |
)
|
68 |
|
69 |
|
70 |
+
def process_kml_database(process_func, database_type):
|
71 |
+
if uploaded_file is not None:
|
72 |
+
start_time = time.time()
|
73 |
+
process_func(uploaded_file)
|
74 |
+
execution_time = time.time() - start_time
|
75 |
+
st.write(
|
76 |
+
f"{database_type} database is generated. Execution time: {execution_time:.2f} seconds"
|
77 |
+
)
|
78 |
+
kml_download_button(database_type)
|
79 |
+
|
80 |
+
|
81 |
+
@st.fragment()
|
82 |
+
def kml_download_button(database_type):
|
83 |
+
if database_type == "2G":
|
84 |
+
data = UtilsVars.gsm_kml_file
|
85 |
+
file_name = f"2G kml_{datetime.now()}.kml"
|
86 |
+
elif database_type == "3G":
|
87 |
+
data = UtilsVars.wcdma_kml_file
|
88 |
+
file_name = f"3G kml_{datetime.now()}.kml"
|
89 |
+
elif database_type == "LTE":
|
90 |
+
data = UtilsVars.lte_kml_file
|
91 |
+
file_name = f"LTE kml_{datetime.now()}.kml"
|
92 |
+
st.download_button(
|
93 |
+
type="primary",
|
94 |
+
label=f"Download {database_type} KML File",
|
95 |
+
data=data,
|
96 |
+
file_name=file_name,
|
97 |
+
mime="application/vnd.google-earth.kml+xml",
|
98 |
+
)
|
99 |
+
|
100 |
+
|
101 |
def execute_process_all_tech_db(uploaded_file):
|
102 |
if uploaded_file is not None:
|
103 |
start_time = time.time()
|
|
|
125 |
download_button("All")
|
126 |
|
127 |
|
128 |
+
col1, col2, col3, col4, col5 = st.columns(5)
|
129 |
+
col6, col7, col8, col9, col10 = st.columns(5)
|
130 |
if uploaded_file is not None:
|
131 |
# UtilsVars.file_path = uploaded_file
|
132 |
|
|
|
214 |
process_neighbors_data_to_excel, "NEI"
|
215 |
),
|
216 |
)
|
217 |
+
if Technology.gsm == True:
|
218 |
+
with col8:
|
219 |
+
st.button(
|
220 |
+
"Generate 2G KML",
|
221 |
+
on_click=lambda: process_kml_database(
|
222 |
+
process_gsm_data_to_kml, "2G"
|
223 |
+
),
|
224 |
+
)
|
225 |
+
|
226 |
+
if Technology.wcdma == True:
|
227 |
+
with col9:
|
228 |
+
st.button(
|
229 |
+
"Generate 3G KML",
|
230 |
+
on_click=lambda: process_kml_database(
|
231 |
+
process_wcdma_data_to_kml, "3G"
|
232 |
+
),
|
233 |
+
)
|
234 |
+
|
235 |
+
if Technology.lte == True:
|
236 |
+
with col10:
|
237 |
+
st.button(
|
238 |
+
"Generate LTE KML",
|
239 |
+
on_click=lambda: process_kml_database(
|
240 |
+
process_lte_data_to_kml, "LTE"
|
241 |
+
),
|
242 |
+
)
|
243 |
|
244 |
except Exception as e:
|
245 |
st.error(f"Error: {e}")
|
queries/process_gsm.py
CHANGED
@@ -4,6 +4,7 @@ from queries.process_mal import process_mal_data, process_mal_with_bts_name
|
|
4 |
from queries.process_trx import process_trx_data, process_trx_with_bts_name
|
5 |
from utils.config_band import config_band
|
6 |
from utils.convert_to_excel import convert_dfs, save_dataframe
|
|
|
7 |
from utils.utils_vars import GsmAnalysisData, UtilsVars, get_physical_db
|
8 |
|
9 |
BTS_COLUMNS = [
|
@@ -56,6 +57,23 @@ BCF_COLUMNS = [
|
|
56 |
"site_name",
|
57 |
]
|
58 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
|
60 |
def compare_trx_tch_versus_mal(tch1, tch2):
|
61 |
# Split the strings by commas, convert to sets, and compare
|
@@ -185,6 +203,22 @@ def process_gsm_data_to_excel(file_path: str):
|
|
185 |
UtilsVars.final_gsm_database = convert_dfs(gsm_dfs, ["GSM", "MAL", "TRX"])
|
186 |
|
187 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
#############################GSM ANALYSIS#################################
|
189 |
|
190 |
|
|
|
4 |
from queries.process_trx import process_trx_data, process_trx_with_bts_name
|
5 |
from utils.config_band import config_band
|
6 |
from utils.convert_to_excel import convert_dfs, save_dataframe
|
7 |
+
from utils.kml_creator import generate_kml_from_df
|
8 |
from utils.utils_vars import GsmAnalysisData, UtilsVars, get_physical_db
|
9 |
|
10 |
BTS_COLUMNS = [
|
|
|
57 |
"site_name",
|
58 |
]
|
59 |
|
60 |
+
GSM_KML_COLUMNS = [
|
61 |
+
"code",
|
62 |
+
"name",
|
63 |
+
"Longitude",
|
64 |
+
"Latitude",
|
65 |
+
"Azimut",
|
66 |
+
"Hauteur",
|
67 |
+
"BSIC",
|
68 |
+
"cellId",
|
69 |
+
"locationAreaIdLAC",
|
70 |
+
"band",
|
71 |
+
"BCCH",
|
72 |
+
"TRX_TCH",
|
73 |
+
"number_trx_per_cell",
|
74 |
+
"number_trx_per_site",
|
75 |
+
]
|
76 |
+
|
77 |
|
78 |
def compare_trx_tch_versus_mal(tch1, tch2):
|
79 |
# Split the strings by commas, convert to sets, and compare
|
|
|
203 |
UtilsVars.final_gsm_database = convert_dfs(gsm_dfs, ["GSM", "MAL", "TRX"])
|
204 |
|
205 |
|
206 |
+
############################# KML CREATION #################################
|
207 |
+
|
208 |
+
|
209 |
+
def process_gsm_data_to_kml(file_path: str):
|
210 |
+
gsm_kml_df = process_gsm_data(file_path)
|
211 |
+
gsm_kml_df = gsm_kml_df[GSM_KML_COLUMNS]
|
212 |
+
# Add colors column base on "band" column
|
213 |
+
gsm_kml_df["color"] = gsm_kml_df["band"].map(UtilsVars.color_mapping)
|
214 |
+
# Add size column base on "band" column
|
215 |
+
gsm_kml_df["size"] = gsm_kml_df["band"].map(UtilsVars.size_mapping)
|
216 |
+
# Remove empty rows
|
217 |
+
gsm_kml_df = gsm_kml_df.dropna(subset=["Longitude", "Latitude", "Azimut"])
|
218 |
+
# Generate kml
|
219 |
+
UtilsVars.gsm_kml_file = generate_kml_from_df(gsm_kml_df)
|
220 |
+
|
221 |
+
|
222 |
#############################GSM ANALYSIS#################################
|
223 |
|
224 |
|
queries/process_invunit.py
CHANGED
@@ -76,6 +76,11 @@ def process_invunit_data(file_path: str) -> pd.DataFrame:
|
|
76 |
df_invunit = create_invunit_summary(df_invunit)
|
77 |
df_invunit["CODE"] = df_invunit["MRBTS"].apply(extract_code_from_mrbts)
|
78 |
df_invunit = df_invunit[["MRBTS", "CODE", "invunit_summary"]]
|
|
|
|
|
|
|
|
|
|
|
79 |
|
80 |
UtilsVars.all_db_dfs.append(df_invunit)
|
81 |
UtilsVars.all_db_dfs_names.append("INVUNIT")
|
|
|
76 |
df_invunit = create_invunit_summary(df_invunit)
|
77 |
df_invunit["CODE"] = df_invunit["MRBTS"].apply(extract_code_from_mrbts)
|
78 |
df_invunit = df_invunit[["MRBTS", "CODE", "invunit_summary"]]
|
79 |
+
# df_invunit = df_invunit.sort_values(
|
80 |
+
# by=["MRBTS", "CODE"],
|
81 |
+
# )
|
82 |
+
# df_invunit["MRBTS_NUM"] = df_invunit.groupby("CODE").cumcount() + 1
|
83 |
+
# df_invunit["MRBTS_NUM"] = "MRBTS_" + df_invunit["MRBTS_NUM"].astype(str)
|
84 |
|
85 |
UtilsVars.all_db_dfs.append(df_invunit)
|
86 |
UtilsVars.all_db_dfs_names.append("INVUNIT")
|
queries/process_lte.py
CHANGED
@@ -3,6 +3,7 @@ import pandas as pd
|
|
3 |
|
4 |
from utils.config_band import config_band
|
5 |
from utils.convert_to_excel import convert_dfs, save_dataframe
|
|
|
6 |
from utils.utils_vars import (
|
7 |
LteFddAnalysisData,
|
8 |
LteTddAnalysisData,
|
@@ -93,6 +94,21 @@ LNCEL_TDD_COLUMNS = [
|
|
93 |
"rootSeqIndex",
|
94 |
]
|
95 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
def process_lncel(file_path: str):
|
98 |
"""
|
@@ -113,6 +129,8 @@ def process_lncel(file_path: str):
|
|
113 |
df_lncel = dfs["LNCEL"]
|
114 |
df_lncel.columns = df_lncel.columns.str.replace(r"[ ]", "", regex=True)
|
115 |
df_lncel["final_name"] = df_lncel["name"].fillna(df_lncel["cellName"])
|
|
|
|
|
116 |
df_lncel["code"] = df_lncel["final_name"].str.split("_").str[0]
|
117 |
df_lncel["code"] = (
|
118 |
pd.to_numeric(df_lncel["code"], errors="coerce").fillna(0).astype(int)
|
@@ -220,6 +238,31 @@ def process_lte_data_to_excel(file_path: str):
|
|
220 |
UtilsVars.final_lte_database = convert_dfs(lte_dfs, ["LTE_FDD", "LTE_TDD"])
|
221 |
|
222 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
#############################LTE ANALYSIS#################################
|
224 |
|
225 |
|
|
|
3 |
|
4 |
from utils.config_band import config_band
|
5 |
from utils.convert_to_excel import convert_dfs, save_dataframe
|
6 |
+
from utils.kml_creator import generate_kml_from_df
|
7 |
from utils.utils_vars import (
|
8 |
LteFddAnalysisData,
|
9 |
LteTddAnalysisData,
|
|
|
94 |
"rootSeqIndex",
|
95 |
]
|
96 |
|
97 |
+
LTE_KML_COLUMNS = [
|
98 |
+
"code",
|
99 |
+
"final_name",
|
100 |
+
"Longitude",
|
101 |
+
"Latitude",
|
102 |
+
"Azimut",
|
103 |
+
"Hauteur",
|
104 |
+
"lcrId",
|
105 |
+
"pMax",
|
106 |
+
"phyCellId",
|
107 |
+
"tac",
|
108 |
+
"rootSeqIndex",
|
109 |
+
"band",
|
110 |
+
]
|
111 |
+
|
112 |
|
113 |
def process_lncel(file_path: str):
|
114 |
"""
|
|
|
129 |
df_lncel = dfs["LNCEL"]
|
130 |
df_lncel.columns = df_lncel.columns.str.replace(r"[ ]", "", regex=True)
|
131 |
df_lncel["final_name"] = df_lncel["name"].fillna(df_lncel["cellName"])
|
132 |
+
# Replace empty by 999999_empty
|
133 |
+
# df_lncel["final_name"] = df_lncel["final_name"].fillna("999999_empty")
|
134 |
df_lncel["code"] = df_lncel["final_name"].str.split("_").str[0]
|
135 |
df_lncel["code"] = (
|
136 |
pd.to_numeric(df_lncel["code"], errors="coerce").fillna(0).astype(int)
|
|
|
238 |
UtilsVars.final_lte_database = convert_dfs(lte_dfs, ["LTE_FDD", "LTE_TDD"])
|
239 |
|
240 |
|
241 |
+
############################# KML CREATION #################################
|
242 |
+
def process_lte_data_to_kml(file_path: str):
|
243 |
+
lte_kml_dfs = process_lte_data(file_path)
|
244 |
+
|
245 |
+
lte_fdd_klm_df = lte_kml_dfs[0]
|
246 |
+
lte_fdd_klm_df = lte_fdd_klm_df[LTE_KML_COLUMNS]
|
247 |
+
|
248 |
+
lte_tdd_klm_df = lte_kml_dfs[1]
|
249 |
+
lte_tdd_klm_df = lte_tdd_klm_df[LTE_KML_COLUMNS]
|
250 |
+
|
251 |
+
# Merge FDD and TDD dataframes
|
252 |
+
lte_kml_df = pd.concat([lte_fdd_klm_df, lte_tdd_klm_df], ignore_index=True)
|
253 |
+
|
254 |
+
# Rename "final_name" to "name"
|
255 |
+
lte_kml_df.rename(columns={"final_name": "name"}, inplace=True)
|
256 |
+
# Add colors column base on "band" column
|
257 |
+
lte_kml_df["color"] = lte_kml_df["band"].map(UtilsVars.color_mapping)
|
258 |
+
# Add size column base on "band" column
|
259 |
+
lte_kml_df["size"] = lte_kml_df["band"].map(UtilsVars.size_mapping)
|
260 |
+
# Remove empty rows
|
261 |
+
lte_kml_df = lte_kml_df.dropna(subset=["Longitude", "Latitude", "Azimut"])
|
262 |
+
# Generate kml
|
263 |
+
UtilsVars.lte_kml_file = generate_kml_from_df(lte_kml_df)
|
264 |
+
|
265 |
+
|
266 |
#############################LTE ANALYSIS#################################
|
267 |
|
268 |
|
queries/process_wcdma.py
CHANGED
@@ -3,6 +3,7 @@ import pandas as pd
|
|
3 |
from utils.config_band import config_band
|
4 |
from utils.convert_to_excel import convert_dfs, save_dataframe
|
5 |
from utils.extract_code import extract_code_from_mrbts
|
|
|
6 |
from utils.utils_vars import UtilsVars, WcdmaAnalysisData, get_physical_db
|
7 |
|
8 |
WCEL_COLUMNS = [
|
@@ -76,6 +77,21 @@ WNCEL_COLUMNS = [
|
|
76 |
"maxCarrierPower",
|
77 |
]
|
78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
|
80 |
def process_wcdma_data(file_path: str):
|
81 |
"""
|
@@ -183,6 +199,28 @@ def process_wcdma_data_to_excel(file_path: str):
|
|
183 |
UtilsVars.final_wcdma_database = convert_dfs([wcdma_dfs], ["WCDMA"])
|
184 |
|
185 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
############################ANALYTICSS AND STATISTICS############################
|
187 |
|
188 |
|
|
|
3 |
from utils.config_band import config_band
|
4 |
from utils.convert_to_excel import convert_dfs, save_dataframe
|
5 |
from utils.extract_code import extract_code_from_mrbts
|
6 |
+
from utils.kml_creator import generate_kml_from_df
|
7 |
from utils.utils_vars import UtilsVars, WcdmaAnalysisData, get_physical_db
|
8 |
|
9 |
WCEL_COLUMNS = [
|
|
|
77 |
"maxCarrierPower",
|
78 |
]
|
79 |
|
80 |
+
WCDMA_KML_COLUMNS = [
|
81 |
+
"code",
|
82 |
+
"name",
|
83 |
+
"Longitude",
|
84 |
+
"Latitude",
|
85 |
+
"Azimut",
|
86 |
+
"Hauteur",
|
87 |
+
"LAC",
|
88 |
+
"CId",
|
89 |
+
"LAC",
|
90 |
+
"UARFCN",
|
91 |
+
"PriScrCode",
|
92 |
+
"band",
|
93 |
+
]
|
94 |
+
|
95 |
|
96 |
def process_wcdma_data(file_path: str):
|
97 |
"""
|
|
|
199 |
UtilsVars.final_wcdma_database = convert_dfs([wcdma_dfs], ["WCDMA"])
|
200 |
|
201 |
|
202 |
+
############################# KML CREATION #################################
|
203 |
+
|
204 |
+
|
205 |
+
def process_wcdma_data_to_kml(file_path: str):
|
206 |
+
"""
|
207 |
+
Process WCDMA data from the specified file path and convert it to KML format
|
208 |
+
|
209 |
+
Args:
|
210 |
+
file_path (str): The path to the file.
|
211 |
+
"""
|
212 |
+
wcdma_kml_df = process_wcdma_data(file_path)
|
213 |
+
wcdma_kml_df = wcdma_kml_df[WCDMA_KML_COLUMNS]
|
214 |
+
# Add colors column base on "band" column
|
215 |
+
wcdma_kml_df["color"] = wcdma_kml_df["band"].map(UtilsVars.color_mapping)
|
216 |
+
# Add size column base on "band" column
|
217 |
+
wcdma_kml_df["size"] = wcdma_kml_df["band"].map(UtilsVars.size_mapping)
|
218 |
+
# Remove empty rows
|
219 |
+
wcdma_kml_df = wcdma_kml_df.dropna(subset=["Longitude", "Latitude", "Azimut"])
|
220 |
+
# Generate kml
|
221 |
+
UtilsVars.wcdma_kml_file = generate_kml_from_df(wcdma_kml_df)
|
222 |
+
|
223 |
+
|
224 |
############################ANALYTICSS AND STATISTICS############################
|
225 |
|
226 |
|
requirements.txt
CHANGED
Binary files a/requirements.txt and b/requirements.txt differ
|
|
test.py
CHANGED
@@ -19,7 +19,7 @@ class TestProcessAllDB:
|
|
19 |
def test_all_dbs(self):
|
20 |
filepath = r"C:\Users\David\Documents\PROJECTS\2023\PROJET 2023\DUMP\DUMP\NOVEMBRE\20241127_21145_27112024_Dump.xml.gz.xlsb"
|
21 |
all_dbs(filepath)
|
22 |
-
assert len(UtilsVars.all_db_dfs) ==
|
23 |
assert isinstance(UtilsVars.all_db_dfs[0], pd.DataFrame)
|
24 |
|
25 |
def test_process_all_tech_db(self):
|
|
|
19 |
def test_all_dbs(self):
|
20 |
filepath = r"C:\Users\David\Documents\PROJECTS\2023\PROJET 2023\DUMP\DUMP\NOVEMBRE\20241127_21145_27112024_Dump.xml.gz.xlsb"
|
21 |
all_dbs(filepath)
|
22 |
+
assert len(UtilsVars.all_db_dfs) == 8
|
23 |
assert isinstance(UtilsVars.all_db_dfs[0], pd.DataFrame)
|
24 |
|
25 |
def test_process_all_tech_db(self):
|
utils/kml_creator.py
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import io
|
2 |
+
import math
|
3 |
+
|
4 |
+
import numpy as np
|
5 |
+
import pandas as pd
|
6 |
+
import simplekml
|
7 |
+
|
8 |
+
|
9 |
+
def create_sector(kml: simplekml.Kml, row, arc_angle=65):
|
10 |
+
"""Create a sector shape for the telecom antenna in KML with sector details."""
|
11 |
+
code, name, azimuth, lon, lat, size, color = (
|
12 |
+
row["code"],
|
13 |
+
row["name"],
|
14 |
+
row["Azimut"],
|
15 |
+
row["Longitude"],
|
16 |
+
row["Latitude"],
|
17 |
+
row["size"],
|
18 |
+
row["color"],
|
19 |
+
)
|
20 |
+
|
21 |
+
num_points = 20 # Number of points for smooth arc
|
22 |
+
start_angle = azimuth - (arc_angle / 2)
|
23 |
+
end_angle = azimuth + (arc_angle / 2)
|
24 |
+
|
25 |
+
coords = [(lon, lat)] # Start with the site location (center point)
|
26 |
+
|
27 |
+
# Generate points for the sector arc
|
28 |
+
for angle in np.linspace(start_angle, end_angle, num_points):
|
29 |
+
angle_rad = math.radians(angle)
|
30 |
+
arc_lon = lon + (size / 111320) * math.sin(angle_rad)
|
31 |
+
arc_lat = lat + (size / 111320) * math.cos(angle_rad)
|
32 |
+
coords.append((arc_lon, arc_lat))
|
33 |
+
|
34 |
+
coords.append((lon, lat)) # Close the polygon
|
35 |
+
|
36 |
+
# Create the sector polygon
|
37 |
+
pol = kml.newpolygon(name=name, outerboundaryis=coords)
|
38 |
+
|
39 |
+
# Dynamically create the description from all DataFrame columns
|
40 |
+
description = "<b>Sector Details:</b><br>"
|
41 |
+
for column, value in row.items():
|
42 |
+
description += f"<b>{column}:</b> {value}<br>"
|
43 |
+
|
44 |
+
pol.description = description
|
45 |
+
pol.style.polystyle.color = color # Set color from DataFrame
|
46 |
+
pol.style.polystyle.outline = 1 # Outline enabled
|
47 |
+
pol.style.linestyle.color = "ff000000" # Black outline
|
48 |
+
|
49 |
+
|
50 |
+
def generate_kml_from_df(df: pd.DataFrame):
|
51 |
+
"""Generate a KML file from a Pandas DataFrame for telecom sectors."""
|
52 |
+
kml = simplekml.Kml()
|
53 |
+
site_added = set() # Keep track of sites already added to avoid duplicates
|
54 |
+
|
55 |
+
# Sort the DataFrame to ensure 900 MHz (smaller) is drawn last (on top)
|
56 |
+
df_sorted = df.sort_values(
|
57 |
+
by="size", ascending=False
|
58 |
+
) # Larger first, smaller on top
|
59 |
+
|
60 |
+
for _, row in df_sorted.iterrows():
|
61 |
+
code, lon, lat = row["code"], row["Longitude"], row["Latitude"]
|
62 |
+
|
63 |
+
# Add site name as a point only once
|
64 |
+
if code not in site_added:
|
65 |
+
pnt = kml.newpoint(name=code, coords=[(lon, lat)])
|
66 |
+
pnt.style.iconstyle.icon.href = (
|
67 |
+
"http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png"
|
68 |
+
)
|
69 |
+
pnt.style.labelstyle.scale = 1.2 # Adjust label size
|
70 |
+
pnt.description = f"Site: {code}<br>Location: {lat}, {lon}"
|
71 |
+
site_added.add(code)
|
72 |
+
|
73 |
+
create_sector(kml, row)
|
74 |
+
|
75 |
+
kml_data = io.BytesIO()
|
76 |
+
kml_str = kml.kml() # Get KML as string
|
77 |
+
kml_data.write(kml_str.encode("utf-8")) # Write KML to BytesIO
|
78 |
+
kml_data.seek(0) # Move to beginning of BytesIO
|
79 |
+
return kml_data
|
utils/utils_vars.py
CHANGED
@@ -33,6 +33,24 @@ class UtilsVars:
|
|
33 |
10787: "OML UTRA Band I",
|
34 |
10837: "OML UTRA Band I",
|
35 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
wcdma_band = {
|
37 |
3004: "U900",
|
38 |
3006: "U900",
|
@@ -65,6 +83,9 @@ class UtilsVars:
|
|
65 |
final_all_database = None
|
66 |
neighbors_database = ""
|
67 |
file_path = ""
|
|
|
|
|
|
|
68 |
# physisal_db = get_physical_db()
|
69 |
|
70 |
|
|
|
33 |
10787: "OML UTRA Band I",
|
34 |
10837: "OML UTRA Band I",
|
35 |
}
|
36 |
+
color_mapping = {
|
37 |
+
"U900": "7fff0000",
|
38 |
+
"U2100": "7f00ff00",
|
39 |
+
"G900": "7fff0000",
|
40 |
+
"G1800": "7f00ff00",
|
41 |
+
"L800": "7fff0000",
|
42 |
+
"L1800": "7f00ff00",
|
43 |
+
"L2300": "7f00ffff",
|
44 |
+
}
|
45 |
+
size_mapping = {
|
46 |
+
"U900": 100,
|
47 |
+
"U2100": 120,
|
48 |
+
"G900": 100,
|
49 |
+
"G1800": 120,
|
50 |
+
"L800": 100,
|
51 |
+
"L1800": 120,
|
52 |
+
"L2300": 90,
|
53 |
+
}
|
54 |
wcdma_band = {
|
55 |
3004: "U900",
|
56 |
3006: "U900",
|
|
|
83 |
final_all_database = None
|
84 |
neighbors_database = ""
|
85 |
file_path = ""
|
86 |
+
gsm_kml_file = None
|
87 |
+
wcdma_kml_file = None
|
88 |
+
lte_kml_file = None
|
89 |
# physisal_db = get_physical_db()
|
90 |
|
91 |
|