db_query / apps /ciq_verification.py
DavMelchi's picture
adding CIQ verification app
53c4407
"""
CIQ Verification App
Streamlit interface to verify CIQ parameters against dump database.
Supports 2G, 3G, and LTE verification with optional file uploads.
"""
import pandas as pd
import streamlit as st
from queries.verify_ciq import (
generate_verification_report,
process_dump_gsm,
process_dump_lte,
process_dump_wcdma,
read_ciq_file,
verify_2g,
verify_3g,
verify_lte,
)
st.title("🔍 CIQ Verification")
st.markdown(
"""
Vérifiez que les paramètres CIQ correspondent aux valeurs du dump OML.
- **Dump** : Obligatoire (format .xlsb)
- **CIQ** : Au moins un fichier CIQ (2G, 3G ou LTE) est requis
"""
)
# File uploaders
st.subheader("📁 Fichiers d'entrée")
dump_file = st.file_uploader(
"Upload Dump (xlsb)", type=["xlsb"], key="verify_dump", help="Fichier dump obligatoire"
)
col1, col2, col3 = st.columns(3)
with col1:
ciq_2g_file = st.file_uploader(
"CIQ 2G (optionnel)", type=["xlsx", "xls"], key="verify_ciq_2g"
)
with col2:
ciq_3g_file = st.file_uploader(
"CIQ 3G (optionnel)", type=["xlsx", "xls"], key="verify_ciq_3g"
)
with col3:
ciq_lte_file = st.file_uploader(
"CIQ LTE (optionnel)", type=["xlsx", "xls"], key="verify_ciq_lte"
)
# Validation
if dump_file is None:
st.info("⬆️ Veuillez uploader le fichier dump (xlsb).")
st.stop()
if ciq_2g_file is None and ciq_3g_file is None and ciq_lte_file is None:
st.warning("⚠️ Au moins un fichier CIQ (2G, 3G ou LTE) est requis.")
st.stop()
# Verify button
if st.button("🔎 Vérifier", type="primary"):
try:
results_2g = None
results_3g = None
results_lte = None
with st.spinner("Traitement en cours..."):
# Process 2G if provided
if ciq_2g_file is not None:
st.text("📶 Traitement 2G...")
dump_gsm = process_dump_gsm(dump_file)
dump_file.seek(0) # Reset file pointer
ciq_2g_df = read_ciq_file(ciq_2g_file)
results_2g = verify_2g(ciq_2g_df, dump_gsm)
# Process 3G if provided
if ciq_3g_file is not None:
st.text("📶 Traitement 3G...")
dump_wcdma = process_dump_wcdma(dump_file)
dump_file.seek(0) # Reset file pointer
ciq_3g_df = read_ciq_file(ciq_3g_file)
results_3g = verify_3g(ciq_3g_df, dump_wcdma)
# Process LTE if provided
if ciq_lte_file is not None:
st.text("📶 Traitement LTE...")
dump_lte = process_dump_lte(dump_file)
dump_file.seek(0) # Reset file pointer
ciq_lte_df = read_ciq_file(ciq_lte_file)
results_lte = verify_lte(ciq_lte_df, dump_lte)
# Generate report
sheets, excel_bytes = generate_verification_report(
results_2g=results_2g,
results_3g=results_3g,
results_lte=results_lte,
)
st.session_state["verify_results_2g"] = results_2g
st.session_state["verify_results_3g"] = results_3g
st.session_state["verify_results_lte"] = results_lte
st.session_state["verify_sheets"] = sheets
st.session_state["verify_excel_bytes"] = excel_bytes
st.success("✅ Vérification terminée!")
except Exception as e:
st.error(f"❌ Erreur: {e}")
import traceback
st.code(traceback.format_exc())
# Display results
results_2g = st.session_state.get("verify_results_2g")
results_3g = st.session_state.get("verify_results_3g")
results_lte = st.session_state.get("verify_results_lte")
sheets = st.session_state.get("verify_sheets")
excel_bytes = st.session_state.get("verify_excel_bytes")
def display_stats(stats: dict, tech: str):
"""Display verification statistics."""
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("Total Cells", stats["total_cells"])
with col2:
st.metric("✅ OK", stats["ok_count"])
with col3:
st.metric("⚠️ Mismatch", stats["mismatch_count"])
with col4:
st.metric("❓ Not Found", stats["not_found_count"])
def style_results(df: pd.DataFrame) -> pd.DataFrame:
"""Apply styling to highlight mismatches."""
def highlight_status(val):
if val == "OK":
return "background-color: #d4edda; color: #155724;"
elif val == "MISMATCH":
return "background-color: #f8d7da; color: #721c24;"
elif val == "NOT_FOUND":
return "background-color: #fff3cd; color: #856404;"
return ""
def highlight_match(val):
if val is True:
return "background-color: #d4edda;"
elif val is False:
return "background-color: #f8d7da;"
return ""
# Get status column name
status_col = "Status"
# Apply styling (using map instead of deprecated applymap)
styled = df.style.map(
highlight_status, subset=[status_col]
)
# Highlight match columns
match_cols = [c for c in df.columns if c.endswith("_Match")]
if match_cols:
styled = styled.map(highlight_match, subset=match_cols)
return styled
if sheets:
st.divider()
st.subheader("📊 Résultats de la vérification")
tabs = []
tab_names = []
if results_2g:
tab_names.append("2G")
if results_3g:
tab_names.append("3G")
if results_lte:
tab_names.append("LTE")
if tab_names:
tabs = st.tabs(tab_names)
tab_idx = 0
if results_2g:
with tabs[tab_idx]:
st.markdown("### 📶 Vérification 2G")
display_stats(results_2g[1], "2G")
st.dataframe(
style_results(results_2g[0]),
use_container_width=True,
hide_index=True,
)
tab_idx += 1
if results_3g:
with tabs[tab_idx]:
st.markdown("### 📶 Vérification 3G")
display_stats(results_3g[1], "3G")
st.dataframe(
style_results(results_3g[0]),
use_container_width=True,
hide_index=True,
)
tab_idx += 1
if results_lte:
with tabs[tab_idx]:
st.markdown("### 📶 Vérification LTE")
display_stats(results_lte[1], "LTE")
st.dataframe(
style_results(results_lte[0]),
use_container_width=True,
hide_index=True,
)
if excel_bytes:
st.divider()
st.download_button(
label="📥 Télécharger le rapport de vérification (Excel)",
data=excel_bytes,
file_name="CIQ_Verification_Report.xlsx",
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
type="primary",
)