DavMelchi commited on
Commit
f135ea9
·
1 Parent(s): 979c239

Process ADJL - 2G part 1st

Browse files
queries/process_adjl.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ from geopy.distance import geodesic # Imported but not used — consider removing
3
+
4
+ from queries.process_gsm import process_gsm_data
5
+ from queries.process_lte import process_lte_data
6
+ from queries.process_wcdma import process_wcdma_data
7
+ from utils.config_band import adjl_band
8
+ from utils.convert_to_excel import convert_dfs, save_dataframe
9
+ from utils.utils_vars import UtilsVars
10
+
11
+ # -------------------------------
12
+ # Constants
13
+ # -------------------------------
14
+ ADJL_GSM_COLUMNS = ["BSC", "BCF", "BTS", "ADJL", "earfcn", "lteAdjCellTac"]
15
+
16
+ ADJL_WCDMA_COLUMNS = ["RNC", "WBTS", "WCEL", "ADJL", "AdjLEARFCN"]
17
+
18
+ BTS_COLUMNS = ["ID_BTS", "name", "locationAreaIdLAC", "Code_Sector"]
19
+
20
+ LTE_COLUMNS_CONFIG = ["Code_Sector", "site_config_band"]
21
+
22
+ LTE_COLUMNS_TAC = ["Code_Sector", "tac", "band"]
23
+
24
+ LTE_COLUMNS_ADJL = ["Code_Sector", "site_config_band", "tac", "band"]
25
+
26
+
27
+ # -------------------------------
28
+ # Helper functions
29
+ # -------------------------------
30
+ def check_bands(row: pd.Series) -> bool:
31
+ """
32
+ Verify whether all configured site bands exist in ADJL created bands.
33
+ """
34
+ site_bands = (
35
+ set(str(row["site_config_band"]).split("/"))
36
+ if pd.notna(row["site_config_band"])
37
+ else set()
38
+ )
39
+ adjl_bands = (
40
+ set(str(row["adjl_created_band"]).split("/"))
41
+ if pd.notna(row["adjl_created_band"])
42
+ else set()
43
+ )
44
+ return site_bands.issubset(adjl_bands)
45
+
46
+
47
+ def missing_bands(row: pd.Series) -> str | None:
48
+ """
49
+ Return missing bands from ADJL compared to site configuration.
50
+ """
51
+ site_bands = (
52
+ set(str(row["site_config_band"]).split("/"))
53
+ if pd.notna(row["site_config_band"])
54
+ else set()
55
+ )
56
+ adjl_bands = (
57
+ set(str(row["adjl_created_band"]).split("/"))
58
+ if pd.notna(row["adjl_created_band"])
59
+ else set()
60
+ )
61
+ diff = site_bands - adjl_bands
62
+ return ",".join(diff) if diff else None
63
+
64
+
65
+ # -------------------------------
66
+ # Main Processing
67
+ # -------------------------------
68
+ def process_adjl_data(file_path: str) -> list[pd.DataFrame]:
69
+ """
70
+ Process ADJL data from an Excel file and return structured DataFrames.
71
+
72
+ Args:
73
+ file_path (str): Path to the input Excel file.
74
+
75
+ Returns:
76
+ list[pd.DataFrame]: [GSM_ADJL, WCDMA_ADJL, BTS, WCEL, LTE]
77
+ """
78
+ # Read Excel sheets
79
+ dfs = pd.read_excel(
80
+ file_path,
81
+ sheet_name=["ADJL", "BTS", "WCEL"],
82
+ engine="calamine",
83
+ skiprows=[0],
84
+ )
85
+
86
+ # ------------------- BTS -------------------
87
+ df_bts = process_gsm_data(file_path)[BTS_COLUMNS]
88
+
89
+ # ------------------- WCEL -------------------
90
+ df_wcel = process_wcdma_data(file_path)
91
+ df_wcel["ID_WCEL"] = (
92
+ df_wcel[["RNC", "WBTS", "WCEL"]].astype(str).agg("_".join, axis=1)
93
+ )
94
+
95
+ # ------------------- LTE -------------------
96
+ lte_fdd_df, lte_tdd_df = process_lte_data(file_path)
97
+ lte_tdd_df = lte_tdd_df.rename(columns={"earfcn": "earfcnDL"})
98
+ lte_df = pd.concat([lte_fdd_df, lte_tdd_df], ignore_index=True)[LTE_COLUMNS_ADJL]
99
+
100
+ # Config & TAC references
101
+ lte_df_config = lte_df[LTE_COLUMNS_CONFIG]
102
+ lte_df_global_tac = (
103
+ lte_df[["Code_Sector", "tac"]]
104
+ .drop_duplicates(subset=["Code_Sector"], keep="first")
105
+ .rename(columns={"tac": "global_tac"})
106
+ )
107
+
108
+ lte_df_band_tac = lte_df[LTE_COLUMNS_TAC].copy()
109
+ lte_df_band_tac["Code_Sector_band"] = (
110
+ lte_df_band_tac[["Code_Sector", "band"]].astype(str).agg("_".join, axis=1)
111
+ )
112
+ lte_df_band_tac = lte_df_band_tac.drop(columns=["Code_Sector"])
113
+
114
+ # ------------------- ADJL -------------------
115
+ df_adjl = dfs["ADJL"]
116
+ df_adjl.columns = df_adjl.columns.str.replace(r"[ ]", "", regex=True)
117
+
118
+ gsm_adjl_df = df_adjl[ADJL_GSM_COLUMNS]
119
+ wcdma_adjl_df = df_adjl[ADJL_WCDMA_COLUMNS]
120
+
121
+ # --- GSM ADJL ---
122
+ # Filter invalid rows
123
+ gsm_adjl_df = gsm_adjl_df[
124
+ gsm_adjl_df["BSC"].notna()
125
+ & gsm_adjl_df["BCF"].notna()
126
+ & gsm_adjl_df["BTS"].notna()
127
+ ].reset_index(drop=True)
128
+
129
+ # Build IDs and bands
130
+ gsm_adjl_df["ID_BTS"] = (
131
+ gsm_adjl_df[["BSC", "BCF", "BTS"]].astype(str).agg("_".join, axis=1)
132
+ )
133
+ gsm_adjl_df["ID_BTS"] = gsm_adjl_df["ID_BTS"].str.replace(".0", "", regex=False)
134
+ gsm_adjl_df["adjl_band"] = gsm_adjl_df["earfcn"].map(UtilsVars.lte_band)
135
+
136
+ # Merge BTS info
137
+ gsm_adjl_df = pd.merge(gsm_adjl_df, df_bts, on="ID_BTS", how="left")
138
+
139
+ # Aggregate ADJL band info
140
+ gsm_adjl_df_band = adjl_band(gsm_adjl_df, "ID_BTS", "adjl_band")
141
+ gsm_adjl_df = pd.merge(gsm_adjl_df, gsm_adjl_df_band, on="ID_BTS", how="left")
142
+
143
+ # Build Code_Sector_band
144
+ gsm_adjl_df["Code_Sector_band"] = (
145
+ gsm_adjl_df[["Code_Sector", "adjl_band"]].astype(str).agg("_".join, axis=1)
146
+ )
147
+
148
+ # Merge LTE references
149
+ gsm_adjl_df = gsm_adjl_df.merge(lte_df_config, on="Code_Sector", how="left")
150
+ gsm_adjl_df = gsm_adjl_df.merge(lte_df_band_tac, on="Code_Sector_band", how="left")
151
+ gsm_adjl_df = gsm_adjl_df.merge(lte_df_global_tac, on="Code_Sector", how="left")
152
+
153
+ # Final TAC
154
+ gsm_adjl_df["final_tac"] = gsm_adjl_df["tac"].fillna(gsm_adjl_df["global_tac"])
155
+
156
+ # Validations
157
+ gsm_adjl_df["check_bands"] = gsm_adjl_df.apply(check_bands, axis=1)
158
+ gsm_adjl_df["missing_bands"] = gsm_adjl_df.apply(missing_bands, axis=1)
159
+ gsm_adjl_df["check_tac"] = gsm_adjl_df["lteAdjCellTac"] == gsm_adjl_df["final_tac"]
160
+
161
+ # Drop intermediate columns
162
+ gsm_adjl_df = gsm_adjl_df.drop(
163
+ columns=["Code_Sector_band", "tac", "band", "global_tac"]
164
+ )
165
+
166
+ # Mark existing BTS
167
+ df_bts["exists"] = df_bts["ID_BTS"].isin(gsm_adjl_df["ID_BTS"])
168
+
169
+ return [gsm_adjl_df, wcdma_adjl_df, df_bts, df_wcel, lte_df]
170
+
171
+
172
+ def process_adjl_data_to_excel(file_path: str) -> None:
173
+ """
174
+ Process ADJL data and save the result into an Excel-like format via UtilsVars.
175
+ """
176
+ adjl_dfs = process_adjl_data(file_path)
177
+ UtilsVars.adjl_database = convert_dfs(
178
+ adjl_dfs, ["GSM_ADJL", "WCDMA_ADJL", "BTS", "WCEL", "LTE"]
179
+ )
utils/config_band.py CHANGED
@@ -123,3 +123,34 @@ def lte_mrbts_band(df: pd.DataFrame) -> pd.DataFrame:
123
  df_band.rename(columns={"band": "lte_config_band"}, inplace=True)
124
 
125
  return df_band
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  df_band.rename(columns={"band": "lte_config_band"}, inplace=True)
124
 
125
  return df_band
126
+
127
+
128
+ def adjl_band(df: pd.DataFrame, id_col: str, band_col: str) -> pd.DataFrame:
129
+ """
130
+ Create a dataframe that contains the adjl configuration band for each adjl ID.
131
+
132
+ Parameters
133
+ ----------
134
+ df : pd.DataFrame
135
+ The dataframe containing the adjl information, with columns "ID" and "band"
136
+
137
+ Returns
138
+ -------
139
+ pd.DataFrame
140
+ The dataframe containing the adjl configuration band for each adjl ID, with columns "ID" and "adjl_config_band"
141
+ """
142
+ df_band = df[[id_col, band_col]].copy()
143
+ df_band["ID"] = df_band[[id_col, band_col]].astype(str).apply("_".join, axis=1)
144
+ # remove duplicates ID
145
+ df_band = df_band.drop_duplicates(subset=["ID"])
146
+ df_band = df_band[[id_col, band_col]]
147
+ df_band[band_col] = df_band[band_col].fillna("empty")
148
+ df_band = (
149
+ df_band.groupby(id_col)[band_col]
150
+ .apply(lambda x: "/".join(sorted(x)))
151
+ .reset_index()
152
+ )
153
+ # rename band to config
154
+ df_band.rename(columns={band_col: "adjl_created_band"}, inplace=True)
155
+
156
+ return df_band
utils/utils_vars.py CHANGED
@@ -71,6 +71,13 @@ class UtilsVars:
71
  "L2300": 90,
72
  "L2600": 80,
73
  }
 
 
 
 
 
 
 
74
  wcdma_band = {
75
  3004: "U900",
76
  3006: "U900",
@@ -109,6 +116,7 @@ class UtilsVars:
109
  gsm_kml_file = None
110
  wcdma_kml_file = None
111
  lte_kml_file = None
 
112
  # physisal_db = get_physical_db()
113
 
114
 
 
71
  "L2300": 90,
72
  "L2600": 80,
73
  }
74
+ lte_band = {
75
+ 1786: "L1800",
76
+ 6350: "L800",
77
+ 3050: "L2600",
78
+ 38750: "L2300",
79
+ 1761: "L1800",
80
+ }
81
  wcdma_band = {
82
  3004: "U900",
83
  3006: "U900",
 
116
  gsm_kml_file = None
117
  wcdma_kml_file = None
118
  lte_kml_file = None
119
+ adjl_database = None
120
  # physisal_db = get_physical_db()
121
 
122