Skip to content

Commit b7f0522

Browse files
Create main.py
1 parent c349af4 commit b7f0522

1 file changed

Lines changed: 138 additions & 0 deletions

File tree

‎main.py‎

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import html
2+
3+
import folium
4+
import pandas as pd
5+
import streamlit as st
6+
from streamlit_folium import st_folium
7+
8+
st.set_page_config(page_title="Cell Dump Analyzer", layout="wide")
9+
10+
st.title("📱 Cell Dump & CDR Analysis Tool")
11+
st.markdown(
12+
"Unggah data *cell dump* (format CSV/Excel) untuk melakukan analisis lokasi, "
13+
"target, dan pola komunikasi."
14+
)
15+
16+
uploaded_file = st.file_uploader(
17+
"Unggah File Cell Dump (CSV atau Excel)", type=["csv", "xlsx"]
18+
)
19+
20+
if uploaded_file is None:
21+
st.info("Silakan unggah file *cell dump* terlebih dahulu melalui panel di atas.")
22+
else:
23+
try:
24+
if uploaded_file.name.lower().endswith(".csv"):
25+
df = pd.read_csv(uploaded_file)
26+
else:
27+
df = pd.read_excel(uploaded_file)
28+
except (pd.errors.ParserError, ValueError, OSError) as error:
29+
st.error(f"File tidak dapat dibaca: {error}")
30+
st.stop()
31+
32+
if df.empty or len(df.columns) == 0:
33+
st.warning("File tidak berisi data atau kolom yang dapat dianalisis.")
34+
st.stop()
35+
36+
st.success(f"Berhasil memuat {len(df)} baris data.")
37+
38+
with st.expander("🔍 Lihat Preview Data Mentah"):
39+
st.dataframe(df.head())
40+
41+
st.sidebar.header("Filter Analisis")
42+
columns = df.columns.tolist()
43+
44+
msisdn_default = columns.index("MSISDN") if "MSISDN" in columns else 0
45+
imei_default = columns.index("IMEI") if "IMEI" in columns else min(1, len(columns) - 1)
46+
msisdn_col = st.sidebar.selectbox(
47+
"Pilih Kolom Nomor (MSISDN)", columns, index=msisdn_default
48+
)
49+
imei_col = st.sidebar.selectbox("Pilih Kolom IMEI", columns, index=imei_default)
50+
target_number = st.sidebar.text_input("Cari Nomor Target (MSISDN / IMEI):", "")
51+
52+
filtered_df = df.copy()
53+
if target_number:
54+
matching_number = (
55+
filtered_df[msisdn_col].astype("string").str.contains(
56+
target_number, case=False, na=False, regex=False
57+
)
58+
| filtered_df[imei_col].astype("string").str.contains(
59+
target_number, case=False, na=False, regex=False
60+
)
61+
)
62+
filtered_df = filtered_df[matching_number]
63+
64+
col1, col2, col3 = st.columns(3)
65+
col1.metric("Total Record", len(filtered_df))
66+
col2.metric("Target Unik (MSISDN)", filtered_df[msisdn_col].nunique())
67+
col3.metric(
68+
"Menara BTS Unik",
69+
filtered_df["Tower_ID"].nunique() if "Tower_ID" in filtered_df else 0,
70+
)
71+
72+
tab1, tab2, tab3 = st.tabs(
73+
["🗺️ Peta Lokasi (Mapping)", "📊 Analisis Frekuensi", "📋 Data Terfilter"]
74+
)
75+
76+
with tab1:
77+
st.subheader("Visualisasi Sebaran Lokasi BTS")
78+
if {"Lat", "Long"}.issubset(filtered_df.columns):
79+
locations = filtered_df.copy()
80+
locations["Lat"] = pd.to_numeric(locations["Lat"], errors="coerce")
81+
locations["Long"] = pd.to_numeric(locations["Long"], errors="coerce")
82+
locations = locations.dropna(subset=["Lat", "Long"])
83+
locations = locations[
84+
locations["Lat"].between(-90, 90)
85+
& locations["Long"].between(-180, 180)
86+
]
87+
88+
if locations.empty:
89+
st.warning("Tidak ada koordinat valid untuk ditampilkan pada peta.")
90+
else:
91+
map_lat = locations["Lat"].mean()
92+
map_lon = locations["Long"].mean()
93+
map_view = folium.Map(location=[map_lat, map_lon], zoom_start=13)
94+
95+
for _, row in locations.iterrows():
96+
msisdn = html.escape(str(row.get(msisdn_col, "-")))
97+
timestamp = html.escape(str(row.get("Timestamp", "-")))
98+
tower_id = html.escape(str(row.get("Tower_ID", "-")))
99+
popup_text = (
100+
f"MSISDN: {msisdn}<br>Waktu: {timestamp}<br>BTS: {tower_id}"
101+
)
102+
folium.CircleMarker(
103+
location=[row["Lat"], row["Long"]],
104+
radius=5,
105+
color="red",
106+
fill=True,
107+
fill_color="red",
108+
popup=folium.Popup(popup_text, max_width=300),
109+
).add_to(map_view)
110+
111+
st_folium(map_view, width=1000, height=500)
112+
else:
113+
st.warning(
114+
"Kolom 'Lat' dan 'Long' tidak ditemukan dalam dataset untuk membuat peta."
115+
)
116+
117+
with tab2:
118+
st.subheader("Statistik Komunikasi & Aktivitas")
119+
top_numbers = filtered_df[msisdn_col].value_counts().head(10)
120+
st.write("**Nomor Paling Sering Muncul (Top 10):**")
121+
st.bar_chart(top_numbers)
122+
123+
if "Tower_ID" in filtered_df.columns:
124+
top_towers = filtered_df["Tower_ID"].value_counts().head(10)
125+
st.write("**BTS Paling Sering Terhubung (Top 10):**")
126+
st.bar_chart(top_towers)
127+
128+
with tab3:
129+
st.subheader("Tabel Data Terfilter")
130+
st.dataframe(filtered_df)
131+
132+
csv = filtered_df.to_csv(index=False).encode("utf-8")
133+
st.download_button(
134+
label="Unduh Data Terfilter (CSV)",
135+
data=csv,
136+
file_name="hasil_analisa_cell_dump.csv",
137+
mime="text/csv",
138+
)

0 commit comments

Comments
 (0)