SUNGJIN LEE
commited on
Commit
โข
312b9eb
1
Parent(s):
299fe51
Initial commit
Browse files- .devcontainer/devcontainer.json +33 -0
- .gitignore +3 -0
- app.py +54 -0
- chart.py +16 -0
- config.yaml +12 -0
- data.py +48 -0
- js.py +41 -0
- map.py +35 -0
- map_recommend.py +40 -0
- pages/About.py +30 -0
- pages/Dashboard.py +107 -0
- pages/Recommendation System.py +91 -0
- requirements.txt +37 -0
.devcontainer/devcontainer.json
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "Python 3",
|
3 |
+
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
4 |
+
"image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
|
5 |
+
"customizations": {
|
6 |
+
"codespaces": {
|
7 |
+
"openFiles": [
|
8 |
+
"README.md",
|
9 |
+
"Home.py"
|
10 |
+
]
|
11 |
+
},
|
12 |
+
"vscode": {
|
13 |
+
"settings": {},
|
14 |
+
"extensions": [
|
15 |
+
"ms-python.python",
|
16 |
+
"ms-python.vscode-pylance"
|
17 |
+
]
|
18 |
+
}
|
19 |
+
},
|
20 |
+
"updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y <packages.txt; [ -f requirements.txt ] && pip3 install --user -r requirements.txt; pip3 install --user streamlit; echo 'โ
Packages installed and Requirements met'",
|
21 |
+
"postAttachCommand": {
|
22 |
+
"server": "streamlit run Home.py --server.enableCORS false --server.enableXsrfProtection false"
|
23 |
+
},
|
24 |
+
"portsAttributes": {
|
25 |
+
"8501": {
|
26 |
+
"label": "Application",
|
27 |
+
"onAutoForward": "openPreview"
|
28 |
+
}
|
29 |
+
},
|
30 |
+
"forwardPorts": [
|
31 |
+
8501
|
32 |
+
]
|
33 |
+
}
|
.gitignore
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
generate_keys.py
|
2 |
+
__pycache__/
|
3 |
+
.streamlit/
|
app.py
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from streamlit.logger import get_logger
|
3 |
+
import streamlit_authenticator as stauth
|
4 |
+
import yaml
|
5 |
+
|
6 |
+
LOGGER = get_logger(__name__)
|
7 |
+
|
8 |
+
def run():
|
9 |
+
st.set_page_config(
|
10 |
+
page_title="SKT AI Fellowship Team ASAP",
|
11 |
+
page_icon="๐ก",
|
12 |
+
layout="centered"
|
13 |
+
)
|
14 |
+
|
15 |
+
st.write("# SKT AI Fellowship Team ASAP ๐")
|
16 |
+
|
17 |
+
def st_authenticator():
|
18 |
+
with open('config.yaml') as file:
|
19 |
+
config = yaml.load(file, Loader=stauth.SafeLoader)
|
20 |
+
|
21 |
+
authenticator = stauth.Authenticate(
|
22 |
+
config['credentials'],
|
23 |
+
config['cookie']['name'],
|
24 |
+
config['cookie']['key'],
|
25 |
+
config['cookie']['expiry_days'],
|
26 |
+
config['preauthorized']
|
27 |
+
)
|
28 |
+
|
29 |
+
return authenticator
|
30 |
+
|
31 |
+
if __name__ == "__main__":
|
32 |
+
run()
|
33 |
+
authenticator = st_authenticator()
|
34 |
+
|
35 |
+
if 'authentication_status' not in st.session_state:
|
36 |
+
st.session_state['authentication_status'] = None
|
37 |
+
st.session_state['username'] = None
|
38 |
+
|
39 |
+
name, authentication_status, username = authenticator.login("main", "Login")
|
40 |
+
|
41 |
+
if authentication_status:
|
42 |
+
st.session_state['authentication_status'] = True
|
43 |
+
st.session_state['username'] = username
|
44 |
+
st.success(f"{name}๋, ํ์ํฉ๋๋ค!")
|
45 |
+
authenticator.logout('Logout', 'main', key='unique_key')
|
46 |
+
|
47 |
+
elif authentication_status is False:
|
48 |
+
st.session_state['authentication_status'] = False
|
49 |
+
st.error('์์ด๋/๋น๋ฐ๋ฒํธ๊ฐ ์๋ชป๋์์ต๋๋ค.')
|
50 |
+
|
51 |
+
elif authentication_status is None:
|
52 |
+
st.session_state['authentication_status'] = None
|
53 |
+
st.warning('์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.')
|
54 |
+
|
chart.py
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
import altair as alt
|
3 |
+
|
4 |
+
def create_area_chart(filtered_data_long, selected_cell):
|
5 |
+
chart = alt.Chart(filtered_data_long).mark_area().encode(
|
6 |
+
x=alt.X('timestamp:T', title='Timestamp'),
|
7 |
+
y=alt.Y('Value:Q', title='RB Used'),
|
8 |
+
color=alt.Color('RB:N', title='RB Type'),
|
9 |
+
tooltip=['timestamp:T', 'RB:N', 'Value:Q']
|
10 |
+
).properties(
|
11 |
+
width=800,
|
12 |
+
height=400,
|
13 |
+
title=f'RB Usage for Cell ID: {selected_cell}'
|
14 |
+
).interactive()
|
15 |
+
|
16 |
+
return chart
|
config.yaml
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
cookie:
|
2 |
+
expiry_days: 1
|
3 |
+
key: some_signature_key
|
4 |
+
name: streamlit-cookie
|
5 |
+
credentials:
|
6 |
+
usernames:
|
7 |
+
asap:
|
8 |
+
name: asap
|
9 |
+
password: $2b$12$T657ZXBqAyJuartbrwlUMOP9G.n94O8qsdsuyDZRxUKQ2Yj.TsJHu
|
10 |
+
preauthorized:
|
11 |
+
emails:
|
12 |
data.py
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
import streamlit as st
|
3 |
+
from google.oauth2.service_account import Credentials
|
4 |
+
from googleapiclient.discovery import build
|
5 |
+
from googleapiclient.http import MediaIoBaseDownload
|
6 |
+
import io
|
7 |
+
|
8 |
+
# Google Drive ๋ฐ Sheets API ์ธ์ฆ
|
9 |
+
scope = [
|
10 |
+
"https://www.googleapis.com/auth/drive.readonly"
|
11 |
+
]
|
12 |
+
credentials = Credentials.from_service_account_info(st.secrets["google"], scopes=scope)
|
13 |
+
file_id = st.secrets["drive"]["file_id"]
|
14 |
+
|
15 |
+
drive_service = build('drive', 'v3', credentials=credentials)
|
16 |
+
|
17 |
+
@st.cache_data(show_spinner=False)
|
18 |
+
def load_data():
|
19 |
+
request = drive_service.files().get_media(fileId=file_id)
|
20 |
+
|
21 |
+
file_buffer = io.BytesIO()
|
22 |
+
|
23 |
+
downloader = MediaIoBaseDownload(file_buffer, request)
|
24 |
+
done = False
|
25 |
+
|
26 |
+
progress_bar = st.sidebar.progress(0)
|
27 |
+
progress_text = st.sidebar.empty()
|
28 |
+
progress_text.text("๋ฐ์ดํฐ ๋ถ๋ฌ์ค๋ ์ค...")
|
29 |
+
|
30 |
+
while not done:
|
31 |
+
status, done = downloader.next_chunk()
|
32 |
+
progress = int(status.progress() * 100)
|
33 |
+
progress_bar.progress(progress)
|
34 |
+
progress_text.text(f"๋ฐ์ดํฐ ๋ถ๋ฌ์ค๋ ์ค...({progress}%)")
|
35 |
+
|
36 |
+
file_buffer.seek(0)
|
37 |
+
df = pd.read_csv(file_buffer)
|
38 |
+
|
39 |
+
df['ru_svc_lat_val'] = df['ru_svc_lat_val'].astype(float)
|
40 |
+
df['ru_svc_lng_val'] = df['ru_svc_lng_val'].astype(float)
|
41 |
+
|
42 |
+
df_map = df.drop_duplicates(subset=['ru_svc_lat_val', 'ru_svc_lng_val'])
|
43 |
+
|
44 |
+
progress_bar.empty()
|
45 |
+
progress_text.empty()
|
46 |
+
st.sidebar.success("๋ฐ์ดํฐ ๋ก๋ ์๋ฃ!")
|
47 |
+
|
48 |
+
return df, df_map
|
js.py
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from folium.map import Marker
|
2 |
+
from jinja2 import Template
|
3 |
+
|
4 |
+
def set_marker_click_template():
|
5 |
+
click_marker = """
|
6 |
+
{% macro script(this, kwargs) %}
|
7 |
+
|
8 |
+
function copyToClipboard(text) {
|
9 |
+
navigator.clipboard.writeText(text).then(function() {
|
10 |
+
console.log("ํด๋ฆฝ๋ณด๋์ ๋ณต์ฌ๋์์ต๋๋ค: ", text);
|
11 |
+
}, function(err) {
|
12 |
+
console.error("ํด๋ฆฝ๋ณด๋ ๋ณต์ฌ์ ์คํจํ์ต๋๋ค: ", err);
|
13 |
+
});
|
14 |
+
}
|
15 |
+
|
16 |
+
function showToast() {
|
17 |
+
var toast = document.getElementById("toast");
|
18 |
+
toast.style.visibility = "visible";
|
19 |
+
setTimeout(function() {
|
20 |
+
toast.style.visibility = "hidden";
|
21 |
+
}, 3000);
|
22 |
+
}
|
23 |
+
|
24 |
+
function onClick(e) {
|
25 |
+
var marker = e.target;
|
26 |
+
if (marker.getTooltip()) {
|
27 |
+
var cellID = marker.getTooltip().getElement().innerText.trim();
|
28 |
+
copyToClipboard(cellID);
|
29 |
+
}
|
30 |
+
}
|
31 |
+
|
32 |
+
var {{ this.get_name() }} = L.marker(
|
33 |
+
{{ this.location|tojson }},
|
34 |
+
{{ this.options|tojson }}
|
35 |
+
).addTo({{ this._parent.get_name() }}).on('click', onClick);
|
36 |
+
|
37 |
+
{% endmacro %}
|
38 |
+
"""
|
39 |
+
|
40 |
+
Marker._template = Template(click_marker)
|
41 |
+
|
map.py
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import folium
|
2 |
+
from folium import CustomIcon, DivIcon
|
3 |
+
|
4 |
+
def create_map(dataframe):
|
5 |
+
m = folium.Map(
|
6 |
+
location=[35.1796, 129.0756],
|
7 |
+
zoom_start=12,
|
8 |
+
control_scale=True,
|
9 |
+
tiles='CartoDB positron'
|
10 |
+
)
|
11 |
+
|
12 |
+
for idx, row in dataframe.iterrows():
|
13 |
+
cell_id = row['enbid_pci']
|
14 |
+
|
15 |
+
color = 'green'
|
16 |
+
custom_icon = DivIcon(
|
17 |
+
html=f"""
|
18 |
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" width="20" height="20">
|
19 |
+
<circle cx="10" cy="10" r="5.625" fill="{color}" stroke="#000000" stroke-width="1.25"/>
|
20 |
+
</svg>
|
21 |
+
""",
|
22 |
+
icon_size=(20, 20),
|
23 |
+
icon_anchor=(10, 10)
|
24 |
+
)
|
25 |
+
|
26 |
+
marker = folium.Marker(
|
27 |
+
# popup=f'Cell ID: {cell_id}',
|
28 |
+
location=(row['ru_svc_lat_val'], row['ru_svc_lng_val']),
|
29 |
+
icon=custom_icon,
|
30 |
+
tooltip=f'{cell_id}'
|
31 |
+
)
|
32 |
+
|
33 |
+
marker.add_to(m)
|
34 |
+
|
35 |
+
return m
|
map_recommend.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import folium
|
2 |
+
from folium import CustomIcon, DivIcon
|
3 |
+
|
4 |
+
def create_map(dataframe, recommendations):
|
5 |
+
m = folium.Map(
|
6 |
+
location=[35.1796, 129.0756],
|
7 |
+
zoom_start=12,
|
8 |
+
control_scale=True,
|
9 |
+
tiles='CartoDB positron'
|
10 |
+
)
|
11 |
+
|
12 |
+
for idx, row in dataframe.iterrows():
|
13 |
+
cell_id = row['enbid_pci']
|
14 |
+
|
15 |
+
recommended_cell_state = recommendations.get(cell_id, 'OFF')
|
16 |
+
|
17 |
+
if recommended_cell_state == 'ON':
|
18 |
+
color = 'blue'
|
19 |
+
else:
|
20 |
+
color = 'red'
|
21 |
+
|
22 |
+
custom_icon = DivIcon(
|
23 |
+
html=f"""
|
24 |
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" width="20" height="20">
|
25 |
+
<circle cx="10" cy="10" r="5.625" fill="{color}" stroke="#000000" stroke-width="1.25"/>
|
26 |
+
</svg>
|
27 |
+
""",
|
28 |
+
icon_size=(20, 20),
|
29 |
+
icon_anchor=(10, 10)
|
30 |
+
)
|
31 |
+
|
32 |
+
marker = folium.Marker(
|
33 |
+
location=(row['ru_svc_lat_val'], row['ru_svc_lng_val']),
|
34 |
+
icon=custom_icon,
|
35 |
+
tooltip=f'{cell_id} - {recommended_cell_state}'
|
36 |
+
)
|
37 |
+
|
38 |
+
marker.add_to(m)
|
39 |
+
|
40 |
+
return m
|
pages/About.py
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from streamlit.logger import get_logger
|
3 |
+
|
4 |
+
LOGGER = get_logger(__name__)
|
5 |
+
|
6 |
+
def run():
|
7 |
+
st.set_page_config(
|
8 |
+
page_title="About"
|
9 |
+
)
|
10 |
+
|
11 |
+
st.markdown(
|
12 |
+
"""
|
13 |
+
##### *Team ASAP์ ๋คํธ์ํฌ์ ์๋์ง ์๋น๋ฅผ ์ค์ด๊ณ ํ์ ๋ฐฐ์ถ์ ๊ฐ์์ํค๊ธฐ ์ํ AI ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ๋ฐํ๊ณ ์์ต๋๋ค. ์ฐ๋ฆฌ์ ๋ชฉํ๋ ๋ชจ๋ฐ์ผ ๋คํธ์ํฌ์์ ์๋์ง ํจ์จ์ฑ์ ๊ทน๋ํํ์ฌ ์ง์ ๊ฐ๋ฅํ ๋ฐ์ ์ ์ด๋ฃจ๋ ๊ฒ์
๋๋ค.*
|
14 |
+
|
15 |
+
##### Green AI์ ํ์์ฑ
|
16 |
+
- **ํจ์จ์ฑ**: AI ๊ธฐ๋ฐ์ ์๊ณ ๋ฆฌ์ฆ์ ๋คํธ์ํฌ์ ์๋์ง ์๋น ํจํด์ ๋ถ์ํ๊ณ ์ต์ ํํ์ฌ ๋ถํ์ํ ์๋น๋ฅผ ์ค์
๋๋ค.
|
17 |
+
- **๊ณ ๊ฐ ๊ฒฝํ**: ๊ณ ๊ฐ ๊ฒฝํ์ ์ํฅ์ ์ฃผ์ง ์์ผ๋ฉด์ ์๋์ง๋ฅผ ์ ์ฝํ ์ ์๋ ์๋ฃจ์
์ ๊ฐ๋ฐํฉ๋๋ค.
|
18 |
+
- **์ง์ ๊ฐ๋ฅ์ฑ**: ํ์ ๋ฐฐ์ถ์ ์ค์ด๊ณ ์ด์๋น์ฉ(OPEX)์ ์ ๊ฐํ์ฌ ํ๊ฒฝ๊ณผ ๊ฒฝ์ ์ ์ด์ต์ ๋์์ ์ถ๊ตฌํฉ๋๋ค.
|
19 |
+
|
20 |
+
##### ์ฃผ์ ๊ธฐ์
|
21 |
+
- **AI ๊ธฐ๋ฐ ์๋์ง ์ ์ฝ ์๊ณ ๋ฆฌ์ฆ**: ๋คํธ์ํฌ ํธ๋ํฝ ๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ์ผ๋ก ๋ถ์ํ์ฌ, ์๋์ง ์๋น๋ฅผ ์ต์ํํ๋ ๋ฐฉ๋ฒ์ ์ถ์ฒํฉ๋๋ค.
|
22 |
+
- **MLOps**: ์๋ํ๋ ๋ชจ๋ธ ํ์ต ๋ฐ ๋ฐฐํฌ ํ์ดํ๋ผ์ธ์ ํตํด AI ๋ชจ๋ธ์ ํจ์จ์ ์ธ ์ด์์ ์ง์ํฉ๋๋ค.
|
23 |
+
|
24 |
+
##### ํ๋ก์ ํธ์ ๊ฐ์น
|
25 |
+
- **์๋์ง ์ ๊ฐ**: ์๋์ง ์ ์ฝ ๊ธฐ๋ฅ์ ํตํด ์ ๊ธฐ ์๊ธ์ ์ ๊ฐํ๊ณ , ๊ณ ๊ฐ์๊ฒ ์ต์์ ์๋น์ค๋ฅผ ์ ๊ณตํฉ๋๋ค.
|
26 |
+
"""
|
27 |
+
)
|
28 |
+
|
29 |
+
if __name__ == "__main__":
|
30 |
+
run()
|
pages/Dashboard.py
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from streamlit_folium import folium_static
|
3 |
+
import pandas as pd
|
4 |
+
import data
|
5 |
+
import map
|
6 |
+
import js
|
7 |
+
import chart
|
8 |
+
|
9 |
+
st.set_page_config(page_title="Dashboard",
|
10 |
+
layout="wide",
|
11 |
+
page_icon="๐บ๏ธ")
|
12 |
+
|
13 |
+
if not st.session_state.get('authentication_status', False):
|
14 |
+
st.write("### ๐จ **์ ๊ทผ ๋ถ๊ฐ** ๐จ")
|
15 |
+
st.write("์ด ํ์ด์ง๋ฅผ ๋ณผ ์ ์๋ ๊ถํ์ด ์์ต๋๋ค.<br>๋ก๊ทธ์ธํด ์ฃผ์ธ์.", unsafe_allow_html=True)
|
16 |
+
st.stop()
|
17 |
+
|
18 |
+
df, df_map = data.load_data()
|
19 |
+
|
20 |
+
cell_map = map.create_map(df_map)
|
21 |
+
|
22 |
+
if 'selected_cell' not in st.session_state:
|
23 |
+
st.session_state['selected_cell'] = ""
|
24 |
+
|
25 |
+
if 'selected_rbs' not in st.session_state:
|
26 |
+
st.session_state['selected_rbs'] = ['RB_800', 'RB_1800', 'RB_2100', 'RB_2600_10', 'RB_2600_20']
|
27 |
+
|
28 |
+
def main():
|
29 |
+
st.markdown("# Dashboard")
|
30 |
+
|
31 |
+
show_map = st.sidebar.checkbox("์ง๋ ๋ณด๊ธฐ", True)
|
32 |
+
if show_map:
|
33 |
+
st.markdown("### ๐บ๏ธ ๋ถ์ฐ PoC ์
์ฌ์ดํธ")
|
34 |
+
|
35 |
+
folium_static(cell_map)
|
36 |
+
|
37 |
+
st.write("""
|
38 |
+
<style>
|
39 |
+
iframe {
|
40 |
+
max-width: 2000px;
|
41 |
+
width: 100%;
|
42 |
+
height: 600px;
|
43 |
+
border-radius: 10px;
|
44 |
+
border: 1px solid #d3d3d3;
|
45 |
+
}
|
46 |
+
</style>
|
47 |
+
""", unsafe_allow_html=True)
|
48 |
+
|
49 |
+
js.set_marker_click_template()
|
50 |
+
|
51 |
+
unique_cells = df['enbid_pci'].unique().tolist()
|
52 |
+
|
53 |
+
show_chart = st.sidebar.checkbox("์ฐจํธ ๋ณด๊ธฐ", True)
|
54 |
+
if show_chart:
|
55 |
+
selected_cell = st.selectbox("์กฐํํ ์
ID:", unique_cells, index=unique_cells.index(st.session_state['selected_cell']) if st.session_state['selected_cell'] in unique_cells else 0)
|
56 |
+
st.session_state['selected_cell'] = selected_cell
|
57 |
+
|
58 |
+
cell_data = df[df['enbid_pci'] == st.session_state['selected_cell']].copy()
|
59 |
+
|
60 |
+
if not cell_data.empty:
|
61 |
+
rb_options = []
|
62 |
+
if cell_data['Equip_800'].eq(1).any():
|
63 |
+
rb_options.append('RB_800')
|
64 |
+
if cell_data['Equip_1800'].eq(1).any():
|
65 |
+
rb_options.append('RB_1800')
|
66 |
+
if cell_data['Equip_2100'].eq(1).any():
|
67 |
+
rb_options.append('RB_2100')
|
68 |
+
if cell_data['Equip_2600_10'].eq(1).any():
|
69 |
+
rb_options.append('RB_2600_10')
|
70 |
+
if cell_data['Equip_2600_20'].eq(1).any():
|
71 |
+
rb_options.append('RB_2600_20')
|
72 |
+
|
73 |
+
selected_rbs = st.multiselect("RB ์ปฌ๋ผ:", rb_options, default=[rb for rb in st.session_state['selected_rbs'] if rb in rb_options])
|
74 |
+
st.session_state['selected_rbs'] = selected_rbs
|
75 |
+
|
76 |
+
cell_data['timestamp'] = pd.to_datetime(cell_data['timestamp'])
|
77 |
+
|
78 |
+
min_date = cell_data['timestamp'].min().to_pydatetime()
|
79 |
+
max_date = cell_data['timestamp'].max().to_pydatetime()
|
80 |
+
|
81 |
+
start_date, end_date = st.slider(
|
82 |
+
"๋ ์ง ๋ฒ์:",
|
83 |
+
min_value=min_date,
|
84 |
+
max_value=max_date,
|
85 |
+
value=(min_date, max_date),
|
86 |
+
format="MM/DD/YY"
|
87 |
+
)
|
88 |
+
|
89 |
+
filtered_data = cell_data[(cell_data['timestamp'] >= start_date) & (cell_data['timestamp'] <= end_date)]
|
90 |
+
|
91 |
+
filtered_data_long = pd.melt(
|
92 |
+
filtered_data,
|
93 |
+
id_vars=['timestamp'],
|
94 |
+
value_vars=st.session_state['selected_rbs'],
|
95 |
+
var_name='RB',
|
96 |
+
value_name='Value'
|
97 |
+
)
|
98 |
+
|
99 |
+
chart_obj = chart.create_area_chart(filtered_data_long, st.session_state['selected_cell'])
|
100 |
+
|
101 |
+
# ์ฐจํธ ํ์
|
102 |
+
st.altair_chart(chart_obj, use_container_width=True)
|
103 |
+
else:
|
104 |
+
st.write("์ ํํ ์
ID์ ๋ํ ๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค.")
|
105 |
+
|
106 |
+
if __name__ == "__main__":
|
107 |
+
main()
|
pages/Recommendation System.py
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import pandas as pd
|
3 |
+
import numpy as np
|
4 |
+
from datetime import datetime, time
|
5 |
+
import tensorflow as tf
|
6 |
+
from streamlit_folium import folium_static
|
7 |
+
import map_recommend
|
8 |
+
import data
|
9 |
+
|
10 |
+
st.set_page_config(page_title="Frequency Off Recommendation System",
|
11 |
+
layout="wide",
|
12 |
+
page_icon="๐ก")
|
13 |
+
|
14 |
+
if not st.session_state.get('authentication_status', False):
|
15 |
+
st.write("### ๐จ **์ ๊ทผ ๋ถ๊ฐ** ๐จ")
|
16 |
+
st.write("์ด ํ์ด์ง๋ฅผ ๋ณผ ์ ์๋ ๊ถํ์ด ์์ต๋๋ค.<br>๋ก๊ทธ์ธํด ์ฃผ์ธ์.", unsafe_allow_html=True)
|
17 |
+
st.stop()
|
18 |
+
|
19 |
+
st.title('Cell Off Recommendation System')
|
20 |
+
|
21 |
+
date_input = st.date_input('๋ ์ง ์ ํ:', datetime(2024, 8, 6))
|
22 |
+
time_input = st.time_input('์๊ฐ ์ ํ:', time(0, 0))
|
23 |
+
|
24 |
+
timestamp_input = datetime.combine(date_input, time_input)
|
25 |
+
|
26 |
+
model_options = ['๋ชจ๋ธ 1: Rule-based']
|
27 |
+
selected_model = st.selectbox('๋ชจ๋ธ ์ ํ:', model_options)
|
28 |
+
|
29 |
+
run_button = st.button('Run')
|
30 |
+
|
31 |
+
input_data = pd.DataFrame({
|
32 |
+
'hour': [timestamp_input.hour],
|
33 |
+
'is_weekend': [timestamp_input.weekday() >= 5]
|
34 |
+
})
|
35 |
+
|
36 |
+
def load_and_predict(model_name, input_data, df_map, progress_callback=None):
|
37 |
+
recommended_cell_states = {}
|
38 |
+
|
39 |
+
if progress_callback:
|
40 |
+
progress_callback(10)
|
41 |
+
|
42 |
+
if model_name == '๋ชจ๋ธ 1: Rule-based':
|
43 |
+
for idx, row in df_map.iterrows():
|
44 |
+
if timestamp_input.hour < 6 or timestamp_input.hour > 22:
|
45 |
+
recommended_cell_states[row['enbid_pci']] = 'OFF'
|
46 |
+
else:
|
47 |
+
recommended_cell_states[row['enbid_pci']] = 'ON'
|
48 |
+
if progress_callback:
|
49 |
+
progress_callback(10 + 80 * (idx + 1) // len(df_map))
|
50 |
+
|
51 |
+
return recommended_cell_states
|
52 |
+
|
53 |
+
if run_button:
|
54 |
+
|
55 |
+
# with st.sidebar:
|
56 |
+
# with st.spinner('๋ฐ์ดํฐ ๋ก๋ฉ ์ค...'):
|
57 |
+
# df, df_map = data.load_data()
|
58 |
+
# st.sidebar.success('๋ฐ์ดํฐ ๋ก๋ ์๋ฃ')
|
59 |
+
df, df_map = data.load_data()
|
60 |
+
|
61 |
+
progress_bar = st.sidebar.progress(0)
|
62 |
+
|
63 |
+
timestamp_input = pd.to_datetime(timestamp_input)
|
64 |
+
|
65 |
+
recommended_cell_states = load_and_predict(
|
66 |
+
selected_model,
|
67 |
+
input_data,
|
68 |
+
df_map,
|
69 |
+
progress_callback=progress_bar.progress
|
70 |
+
)
|
71 |
+
|
72 |
+
m = map_recommend.create_map(df_map, recommended_cell_states)
|
73 |
+
|
74 |
+
progress_bar.progress(100)
|
75 |
+
st.sidebar.success('๋ถ์ ์๋ฃ')
|
76 |
+
|
77 |
+
progress_bar.empty()
|
78 |
+
|
79 |
+
folium_static(m)
|
80 |
+
|
81 |
+
st.write("""
|
82 |
+
<style>
|
83 |
+
iframe {
|
84 |
+
max-width: 2000px;
|
85 |
+
width: 100%;
|
86 |
+
height: 600px;
|
87 |
+
border-radius: 10px;
|
88 |
+
border: 1px solid #d3d3d3;
|
89 |
+
}
|
90 |
+
</style>
|
91 |
+
""", unsafe_allow_html=True)
|
requirements.txt
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
extra-streamlit-components==0.1.71
|
2 |
+
Flask==3.0.3
|
3 |
+
Flask-Cors==4.0.1
|
4 |
+
Flask-SocketIO==5.3.6
|
5 |
+
flatbuffers==24.3.25
|
6 |
+
folium==0.17.0
|
7 |
+
google-api-core==2.19.1
|
8 |
+
google-api-python-client==2.139.0
|
9 |
+
google-auth==2.32.0
|
10 |
+
google-auth-httplib2==0.2.0
|
11 |
+
google-auth-oauthlib==1.2.1
|
12 |
+
google-pasta==0.2.0
|
13 |
+
googleapis-common-protos==1.63.2
|
14 |
+
gspread==5.12.4
|
15 |
+
gspread-dataframe==4.0.0
|
16 |
+
gspread-formatting==1.2.0
|
17 |
+
gspread-pandas==3.3.0
|
18 |
+
keras==3.4.1
|
19 |
+
matplotlib==3.9.1
|
20 |
+
matplotlib-inline==0.1.7
|
21 |
+
numpy==1.26.4
|
22 |
+
pandas==1.5.3
|
23 |
+
pip==24.2
|
24 |
+
scikit-learn==1.5.1
|
25 |
+
scipy==1.14.0
|
26 |
+
seaborn==0.13.2
|
27 |
+
streamlit==1.37.1
|
28 |
+
streamlit-authenticator==0.3.3
|
29 |
+
streamlit-cookies-controller==0.0.4
|
30 |
+
streamlit-cookies-manager==0.2.0
|
31 |
+
streamlit_folium==0.22.0
|
32 |
+
streamlit-javascript==0.1.5
|
33 |
+
tensorboard==2.17.0
|
34 |
+
tensorboard-data-server==0.7.2
|
35 |
+
tensorflow==2.17.0
|
36 |
+
tensorflow-io-gcs-filesystem==0.37.1
|
37 |
+
tqdm==4.66.5
|