update CIQ app
Browse files- apps/ciq_2g_generator.py +62 -3
- apps/ciq_3g_generator.py +20 -0
- apps/ciq_4g_generator.py +20 -0
- queries/process_ciq_2g.py +16 -0
- samples/CIQ_2G.xlsx +0 -0
- samples/CIQ_3G.xlsx +0 -0
- samples/CIQ_LTE.xlsx +0 -0
- samples/FORBIDEN_SCF.xlsx +0 -0
apps/ciq_2g_generator.py
CHANGED
|
@@ -1,9 +1,39 @@
|
|
|
|
|
|
|
|
| 1 |
import pandas as pd
|
| 2 |
import streamlit as st
|
| 3 |
|
| 4 |
-
from queries.process_ciq_2g import generate_ciq_2g_excel
|
| 5 |
|
| 6 |
st.title("CIQ 2G Generator")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
col1, col2 = st.columns(2)
|
| 9 |
with col1:
|
|
@@ -26,11 +56,40 @@ with col3:
|
|
| 26 |
with col4:
|
| 27 |
mnc = st.number_input("MNC", value=2, step=1, min_value=0, key="ciq2g_mnc")
|
| 28 |
|
| 29 |
-
if dump_file is None
|
| 30 |
st.info("Upload dump xlsb + CIQ brut Excel to generate CIQ 2G.")
|
| 31 |
st.stop()
|
| 32 |
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
try:
|
| 35 |
with st.spinner("Generating CIQ 2G... (dump is heavy)"):
|
| 36 |
sheets, excel_bytes = generate_ciq_2g_excel(
|
|
|
|
| 1 |
+
from pathlib import Path
|
| 2 |
+
|
| 3 |
import pandas as pd
|
| 4 |
import streamlit as st
|
| 5 |
|
| 6 |
+
from queries.process_ciq_2g import generate_ciq_2g_excel, generate_free_bcf_excel
|
| 7 |
|
| 8 |
st.title("CIQ 2G Generator")
|
| 9 |
+
st.markdown(
|
| 10 |
+
"""
|
| 11 |
+
Génère les exports CIQ 2G à partir du dump OML + CIQ brut.
|
| 12 |
+
- **Dump** : obligatoire (format .xlsb)
|
| 13 |
+
- **CIQ brut 2G** : obligatoire pour générer le CIQ
|
| 14 |
+
- **BCF forbidden** : optionnel (colonnes BSC/BCF ou BSCID/BCFID)
|
| 15 |
+
"""
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
st.subheader("📄 Sample files")
|
| 19 |
+
samples_dir = Path(__file__).resolve().parents[1] / "samples"
|
| 20 |
+
sample_ciq_2g = samples_dir / "CIQ_2G.xlsx"
|
| 21 |
+
sample_forbidden = samples_dir / "FORBIDEN_SCF.xlsx"
|
| 22 |
+
|
| 23 |
+
if sample_ciq_2g.exists():
|
| 24 |
+
st.download_button(
|
| 25 |
+
label="Download CIQ 2G sample",
|
| 26 |
+
data=sample_ciq_2g.read_bytes(),
|
| 27 |
+
file_name=sample_ciq_2g.name,
|
| 28 |
+
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
| 29 |
+
)
|
| 30 |
+
if sample_forbidden.exists():
|
| 31 |
+
st.download_button(
|
| 32 |
+
label="Download BCF forbidden sample",
|
| 33 |
+
data=sample_forbidden.read_bytes(),
|
| 34 |
+
file_name=sample_forbidden.name,
|
| 35 |
+
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
| 36 |
+
)
|
| 37 |
|
| 38 |
col1, col2 = st.columns(2)
|
| 39 |
with col1:
|
|
|
|
| 56 |
with col4:
|
| 57 |
mnc = st.number_input("MNC", value=2, step=1, min_value=0, key="ciq2g_mnc")
|
| 58 |
|
| 59 |
+
if dump_file is None:
|
| 60 |
st.info("Upload dump xlsb + CIQ brut Excel to generate CIQ 2G.")
|
| 61 |
st.stop()
|
| 62 |
|
| 63 |
+
st.subheader("✅ Génération BCF libre")
|
| 64 |
+
if st.button("Generate BCF libre", type="secondary"):
|
| 65 |
+
try:
|
| 66 |
+
with st.spinner("Generating BCF libre..."):
|
| 67 |
+
free_bcf_df, free_bcf_bytes = generate_free_bcf_excel(
|
| 68 |
+
dump_file, forbidden_file=forbidden_file
|
| 69 |
+
)
|
| 70 |
+
st.session_state["ciq2g_free_bcf_df"] = free_bcf_df
|
| 71 |
+
st.session_state["ciq2g_free_bcf_bytes"] = free_bcf_bytes
|
| 72 |
+
st.success("BCF libre generated")
|
| 73 |
+
except Exception as e:
|
| 74 |
+
st.error(f"Error: {e}")
|
| 75 |
+
|
| 76 |
+
free_bcf_df = st.session_state.get("ciq2g_free_bcf_df")
|
| 77 |
+
free_bcf_bytes = st.session_state.get("ciq2g_free_bcf_bytes")
|
| 78 |
+
if free_bcf_df is not None:
|
| 79 |
+
st.dataframe(free_bcf_df, use_container_width=True)
|
| 80 |
+
if free_bcf_bytes:
|
| 81 |
+
st.download_button(
|
| 82 |
+
label="Download BCF libre",
|
| 83 |
+
data=free_bcf_bytes,
|
| 84 |
+
file_name="BCF_LIBRE.xlsx",
|
| 85 |
+
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
| 86 |
+
)
|
| 87 |
+
|
| 88 |
+
st.subheader("✅ Génération CIQ 2G")
|
| 89 |
+
if ciq_file is None:
|
| 90 |
+
st.info("Upload CIQ brut 2G Excel to generate CIQ 2G.")
|
| 91 |
+
|
| 92 |
+
if ciq_file is not None and st.button("Generate", type="primary"):
|
| 93 |
try:
|
| 94 |
with st.spinner("Generating CIQ 2G... (dump is heavy)"):
|
| 95 |
sheets, excel_bytes = generate_ciq_2g_excel(
|
apps/ciq_3g_generator.py
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
|
|
|
|
|
| 1 |
import pandas as pd
|
| 2 |
import streamlit as st
|
| 3 |
|
| 4 |
from queries.process_ciq_3g import generate_ciq_3g_excel
|
| 5 |
|
| 6 |
st.title("CIQ 3G Generator")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
ciq_file = st.file_uploader(
|
| 9 |
"Upload CIQ brut 3G (Excel)", type=["xlsx", "xls"], key="ciq3g_ciq"
|
|
|
|
| 1 |
+
from pathlib import Path
|
| 2 |
+
|
| 3 |
import pandas as pd
|
| 4 |
import streamlit as st
|
| 5 |
|
| 6 |
from queries.process_ciq_3g import generate_ciq_3g_excel
|
| 7 |
|
| 8 |
st.title("CIQ 3G Generator")
|
| 9 |
+
st.markdown(
|
| 10 |
+
"""
|
| 11 |
+
Génère les exports CIQ 3G (WBTS + WCEL) à partir du CIQ brut.
|
| 12 |
+
- **CIQ brut 3G** : obligatoire (format Excel)
|
| 13 |
+
"""
|
| 14 |
+
)
|
| 15 |
+
|
| 16 |
+
st.subheader("📄 Sample files")
|
| 17 |
+
samples_dir = Path(__file__).resolve().parents[1] / "samples"
|
| 18 |
+
sample_ciq_3g = samples_dir / "CIQ_3G.xlsx"
|
| 19 |
+
|
| 20 |
+
if sample_ciq_3g.exists():
|
| 21 |
+
st.download_button(
|
| 22 |
+
label="Download CIQ 3G sample",
|
| 23 |
+
data=sample_ciq_3g.read_bytes(),
|
| 24 |
+
file_name=sample_ciq_3g.name,
|
| 25 |
+
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
| 26 |
+
)
|
| 27 |
|
| 28 |
ciq_file = st.file_uploader(
|
| 29 |
"Upload CIQ brut 3G (Excel)", type=["xlsx", "xls"], key="ciq3g_ciq"
|
apps/ciq_4g_generator.py
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
|
|
|
|
|
| 1 |
import pandas as pd
|
| 2 |
import streamlit as st
|
| 3 |
|
| 4 |
from queries.process_ciq_4g import generate_ciq_4g_excel
|
| 5 |
|
| 6 |
st.title("CIQ 4G Generator")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
ciq_file = st.file_uploader(
|
| 9 |
"Upload CIQ brut 4G (Excel)", type=["xlsx", "xls"], key="ciq4g_ciq"
|
|
|
|
| 1 |
+
from pathlib import Path
|
| 2 |
+
|
| 3 |
import pandas as pd
|
| 4 |
import streamlit as st
|
| 5 |
|
| 6 |
from queries.process_ciq_4g import generate_ciq_4g_excel
|
| 7 |
|
| 8 |
st.title("CIQ 4G Generator")
|
| 9 |
+
st.markdown(
|
| 10 |
+
"""
|
| 11 |
+
Génère les exports CIQ 4G à partir du CIQ brut.
|
| 12 |
+
- **CIQ brut 4G** : obligatoire (format Excel)
|
| 13 |
+
"""
|
| 14 |
+
)
|
| 15 |
+
|
| 16 |
+
st.subheader("📄 Sample files")
|
| 17 |
+
samples_dir = Path(__file__).resolve().parents[1] / "samples"
|
| 18 |
+
sample_ciq_4g = samples_dir / "CIQ_LTE.xlsx"
|
| 19 |
+
|
| 20 |
+
if sample_ciq_4g.exists():
|
| 21 |
+
st.download_button(
|
| 22 |
+
label="Download CIQ 4G sample",
|
| 23 |
+
data=sample_ciq_4g.read_bytes(),
|
| 24 |
+
file_name=sample_ciq_4g.name,
|
| 25 |
+
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
| 26 |
+
)
|
| 27 |
|
| 28 |
ciq_file = st.file_uploader(
|
| 29 |
"Upload CIQ brut 4G (Excel)", type=["xlsx", "xls"], key="ciq4g_ciq"
|
queries/process_ciq_2g.py
CHANGED
|
@@ -425,6 +425,22 @@ def _build_bcf_sheet_from_assigned_sites(
|
|
| 425 |
return pd.DataFrame(rows)
|
| 426 |
|
| 427 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 428 |
def _build_free_bcf_sheet(
|
| 429 |
dump_bts: pd.DataFrame, forbidden_by_bsc: dict[int, set[int]] | None = None
|
| 430 |
) -> pd.DataFrame:
|
|
|
|
| 425 |
return pd.DataFrame(rows)
|
| 426 |
|
| 427 |
|
| 428 |
+
def generate_free_bcf_excel(
|
| 429 |
+
dump_file, forbidden_file=None
|
| 430 |
+
) -> tuple[pd.DataFrame, bytes]:
|
| 431 |
+
dump_bts = _read_dump_bts_required_columns(dump_file)
|
| 432 |
+
forbidden_by_bsc, forbidden_df = _read_forbidden_bcfs(forbidden_file)
|
| 433 |
+
df_bcf_free = _build_free_bcf_sheet(dump_bts, forbidden_by_bsc=forbidden_by_bsc)
|
| 434 |
+
|
| 435 |
+
bytes_io = io.BytesIO()
|
| 436 |
+
with pd.ExcelWriter(bytes_io, engine="xlsxwriter") as writer:
|
| 437 |
+
df_bcf_free.to_excel(writer, sheet_name="BCF_LIBRE", index=False)
|
| 438 |
+
if not forbidden_df.empty:
|
| 439 |
+
forbidden_df.to_excel(writer, sheet_name="BCF_FORBIDDEN", index=False)
|
| 440 |
+
|
| 441 |
+
return df_bcf_free, bytes_io.getvalue()
|
| 442 |
+
|
| 443 |
+
|
| 444 |
def _build_free_bcf_sheet(
|
| 445 |
dump_bts: pd.DataFrame, forbidden_by_bsc: dict[int, set[int]] | None = None
|
| 446 |
) -> pd.DataFrame:
|
samples/CIQ_2G.xlsx
ADDED
|
Binary file (11 kB). View file
|
|
|
samples/CIQ_3G.xlsx
ADDED
|
Binary file (11.1 kB). View file
|
|
|
samples/CIQ_LTE.xlsx
ADDED
|
Binary file (10.1 kB). View file
|
|
|
samples/FORBIDEN_SCF.xlsx
ADDED
|
Binary file (8.96 kB). View file
|
|
|