Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,398 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from streamlit_option_menu import option_menu
|
3 |
+
import pandas as pd
|
4 |
+
import seaborn as sns
|
5 |
+
import matplotlib.pyplot as plt
|
6 |
+
import pickle
|
7 |
+
import numpy as np
|
8 |
+
import base64
|
9 |
+
from streamlit_shap import st_shap
|
10 |
+
from streamlit_echarts import st_echarts
|
11 |
+
import shap
|
12 |
+
from sklearn.model_selection import train_test_split
|
13 |
+
import xgboost
|
14 |
+
import plotly.express as px
|
15 |
+
|
16 |
+
|
17 |
+
|
18 |
+
# Load the dataset
|
19 |
+
data = pd.read_csv('concrete.csv')
|
20 |
+
|
21 |
+
# Display the column names for inspection
|
22 |
+
# st.write("Column names in the dataset:")
|
23 |
+
# st.write(data.columns)
|
24 |
+
|
25 |
+
# Load the saved regression model
|
26 |
+
with open('concrete.pkl', 'rb') as f:
|
27 |
+
regressor = pickle.load(f)
|
28 |
+
|
29 |
+
|
30 |
+
# Sidebar
|
31 |
+
st.sidebar.image('logo.png',width=250)
|
32 |
+
with st.sidebar:
|
33 |
+
selected = option_menu(
|
34 |
+
"Menu",
|
35 |
+
['Home', 'Dashboard', 'Analytics', 'Visualization', 'Machine Learning'],
|
36 |
+
icons=['house', 'speedometer2', 'boxes', 'graph-up-arrow', 'easel2'],
|
37 |
+
menu_icon="list",
|
38 |
+
default_index=0,
|
39 |
+
styles={
|
40 |
+
"container": {"padding": "5px", "background-color": "transparent", "font-weight": "bold"},
|
41 |
+
"icon": {"font-size": "17px"},
|
42 |
+
"nav-link": {"font-size": "15px", "text-align": "left", "margin": "5px", "padding": "10px", "--hover-color": "#9A9DA0"},
|
43 |
+
"nav-link-selected": {"background-color": "#B28E52"},
|
44 |
+
}
|
45 |
+
)
|
46 |
+
|
47 |
+
# Page content based on the selected option
|
48 |
+
page = selected
|
49 |
+
|
50 |
+
|
51 |
+
|
52 |
+
if page == 'Home':
|
53 |
+
# st.markdown("Welcome to the Home page")
|
54 |
+
st.markdown("<h1 style='text-align:center;color: #B28E52; '> Welcome to Concrete Test Analysis </h1>",unsafe_allow_html=True)
|
55 |
+
st.markdown("<h3 style='text-align:center;color: white; '> Your Online calculator of cement strengh</h3>",unsafe_allow_html=True)
|
56 |
+
st.markdown("<br>", unsafe_allow_html=True)
|
57 |
+
|
58 |
+
|
59 |
+
|
60 |
+
|
61 |
+
|
62 |
+
|
63 |
+
|
64 |
+
# Home page
|
65 |
+
if page == "Home":
|
66 |
+
st.markdown("<h3> Introduction </h3>", unsafe_allow_html=True)
|
67 |
+
st.markdown("<br>", unsafe_allow_html=True) # Add space between the title and content
|
68 |
+
|
69 |
+
col1, _, col2 = st.columns([3, 0.3, 3])
|
70 |
+
with col1:
|
71 |
+
st.write("""
|
72 |
+
This tool allows you to explore and analyze cement slump test data, and apply a machine learning model to predict compressive strength based on your input data.
|
73 |
+
- **Home:** Overview of the project.
|
74 |
+
- **Dashboard:** Graphs of the project.
|
75 |
+
- **Analytics and Visualization:** Explore and visualize the dataset.
|
76 |
+
- **Machine Learning:** Make predictions using a pre-trained model.
|
77 |
+
""")
|
78 |
+
with col2:
|
79 |
+
st.image("image.png", width=200, use_column_width=True)
|
80 |
+
|
81 |
+
st.markdown("<hr>", unsafe_allow_html=True)
|
82 |
+
|
83 |
+
st.markdown("<h4> Overview </h4>", unsafe_allow_html=True)
|
84 |
+
col3, _, col4 = st.columns([3, 0.3, 3])
|
85 |
+
with col3:
|
86 |
+
st.write("""
|
87 |
+
The cement slump test is used to measure the consistency and workability of fresh concrete before it sets. It is a simple and widely-used test that provides a quick assessment of the quality of the concrete mix.
|
88 |
+
|
89 |
+
The main components measured in the test are:
|
90 |
+
- **Cement**: The primary binding material.
|
91 |
+
- **Slag**: A byproduct of steel production that can enhance concrete durability.
|
92 |
+
- **Ash**: A byproduct of coal combustion that can improve concrete workability.
|
93 |
+
- **Water**: Essential for the hydration process.
|
94 |
+
- **Superplasticizer**: Used to improve the workability without adding more water.
|
95 |
+
""")
|
96 |
+
with col4:
|
97 |
+
st.image("3.jpg", width=200, use_column_width=True)
|
98 |
+
|
99 |
+
|
100 |
+
|
101 |
+
st.markdown("<hr>", unsafe_allow_html=True)
|
102 |
+
|
103 |
+
st.markdown("<h4> Project Goals </h4>", unsafe_allow_html=True)
|
104 |
+
st.write("""
|
105 |
+
This project aims to:
|
106 |
+
1. **Analyze** the cement slump test dataset to understand the relationships between different components.
|
107 |
+
2. **Visualize** the data through various charts and plots for better insights.
|
108 |
+
3. **Predict** the compressive strength of cement using a machine learning model trained on the dataset.
|
109 |
+
""")
|
110 |
+
|
111 |
+
st.markdown("<hr>", unsafe_allow_html=True)
|
112 |
+
|
113 |
+
st.markdown("<h4> Key Features </h4>", unsafe_allow_html=True)
|
114 |
+
st.write("""
|
115 |
+
- **Interactive Visualizations**: Explore the dataset through various plots and charts.
|
116 |
+
- **Machine Learning Predictions**: Input your data and get predictions for the compressive strength.
|
117 |
+
- **Detailed Analytics**: Gain insights into the dataset with detailed analytics and summary statistics.
|
118 |
+
""")
|
119 |
+
|
120 |
+
st.markdown("<hr>", unsafe_allow_html=True)
|
121 |
+
|
122 |
+
st.markdown("<h4> About Us </h4>", unsafe_allow_html=True)
|
123 |
+
st.write("""
|
124 |
+
This application is developed by Hadama Oceane, aiming to provide an easy-to-use interface for cement slump test data analysis and prediction.
|
125 |
+
Feel free to reach out to us for any queries or feedback.
|
126 |
+
""")
|
127 |
+
|
128 |
+
st.markdown("<br>", unsafe_allow_html=True)
|
129 |
+
st.write("Contact us: oceanehadama@gmail.com")
|
130 |
+
|
131 |
+
st.markdown("<hr>", unsafe_allow_html=True)
|
132 |
+
|
133 |
+
# # Image Gallery
|
134 |
+
# st.markdown("<h4> Image Gallery of elements we needs</h4>", unsafe_allow_html=True)
|
135 |
+
|
136 |
+
# col1, col2, col3 = st.columns(3)
|
137 |
+
# with col1:
|
138 |
+
# st.image("3.jpg", caption="Cement", use_column_width=True)
|
139 |
+
# st.image("2.jpg", caption="Slag", use_column_width=True)
|
140 |
+
# with col2:
|
141 |
+
# st.image("image.png", caption="Fly Ash", use_column_width=True)
|
142 |
+
# st.image("2.jpg", caption="Water", use_column_width=True)
|
143 |
+
# with col3:
|
144 |
+
# st.image("3.jpg", caption="Superplasticizer", use_column_width=True)
|
145 |
+
# st.image("1.png", caption="Coarse Aggregate", use_column_width=True)
|
146 |
+
|
147 |
+
# st.markdown("<br>", unsafe_allow_html=True)
|
148 |
+
|
149 |
+
|
150 |
+
|
151 |
+
# Dashboard page
|
152 |
+
if page == "Dashboard":
|
153 |
+
st.markdown("<h1 style='text-align: center;'>Dashboard</h1>", unsafe_allow_html=True)
|
154 |
+
st.markdown("<br>", unsafe_allow_html=True) # Add space between the title and content
|
155 |
+
|
156 |
+
# Function to load the dataset
|
157 |
+
@st.cache_data
|
158 |
+
def load_data():
|
159 |
+
data = pd.read_csv('concrete.csv')
|
160 |
+
return data
|
161 |
+
|
162 |
+
# Load dataset
|
163 |
+
data = load_data()
|
164 |
+
|
165 |
+
# Metrics row
|
166 |
+
col4, space1, col5, space2, col6 = st.columns([3, 0.5, 3, 0.5, 3])
|
167 |
+
with col4:
|
168 |
+
st.metric(label="Total lines", value=1032)
|
169 |
+
with col5:
|
170 |
+
st.metric(label="Total Colunms", value=9)
|
171 |
+
with col6:
|
172 |
+
st.metric(label="Total parameters", value=8)
|
173 |
+
|
174 |
+
st.markdown("<hr>", unsafe_allow_html=True)
|
175 |
+
|
176 |
+
|
177 |
+
# Function to train the model
|
178 |
+
@st.cache_data
|
179 |
+
def load_model(X, y):
|
180 |
+
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=7)
|
181 |
+
d_train = xgboost.DMatrix(X_train, label=y_train)
|
182 |
+
d_test = xgboost.DMatrix(X_test, label=y_test)
|
183 |
+
params = {
|
184 |
+
"eta": 0.01,
|
185 |
+
"objective": "reg:squarederror",
|
186 |
+
"subsample": 0.5,
|
187 |
+
"base_score": np.mean(y_train),
|
188 |
+
"eval_metric": "rmse",
|
189 |
+
"n_jobs": -1,
|
190 |
+
}
|
191 |
+
model = xgboost.train(params, d_train, 100, evals=[(d_test, "test")], verbose_eval=10, early_stopping_rounds=20)
|
192 |
+
return model, X_test, y_test
|
193 |
+
|
194 |
+
# Define features and target
|
195 |
+
X = data.drop(columns=['strength'])
|
196 |
+
y = data['strength']
|
197 |
+
|
198 |
+
|
199 |
+
# Train the model
|
200 |
+
model, X_test, y_test = load_model(X, y)
|
201 |
+
|
202 |
+
# Compute SHAP values
|
203 |
+
explainer = shap.Explainer(model, X_test)
|
204 |
+
shap_values = explainer(X_test)
|
205 |
+
|
206 |
+
# Create two columns for plots
|
207 |
+
col7, col8 = st.columns(2)
|
208 |
+
|
209 |
+
with col7:
|
210 |
+
# SHAP summary plot
|
211 |
+
st.subheader("SHAP Summary Plot")
|
212 |
+
fig_summary, ax_summary = plt.subplots()
|
213 |
+
shap.summary_plot(shap_values, X_test, show=False)
|
214 |
+
st.pyplot(fig_summary)
|
215 |
+
|
216 |
+
with col8:
|
217 |
+
with col8:
|
218 |
+
# Pie chart
|
219 |
+
st.subheader("Component Distribution Pie Chart")
|
220 |
+
fig_pie, ax_pie = plt.subplots()
|
221 |
+
labels = X.columns.tolist()
|
222 |
+
sizes = [data[label].sum() for label in labels if label in data.columns]
|
223 |
+
|
224 |
+
def autopct(pct):
|
225 |
+
total = sum(sizes)
|
226 |
+
val = int(round(pct*total/100.0))
|
227 |
+
return f'{pct:.1f}%\n({val:d})'
|
228 |
+
|
229 |
+
wedges, texts, autotexts = ax_pie.pie(sizes, labels=labels, autopct=autopct, startangle=140, colors=plt.cm.Paired.colors)
|
230 |
+
for text in texts:
|
231 |
+
text.set_color('grey')
|
232 |
+
for autotext in autotexts:
|
233 |
+
autotext.set_color('white')
|
234 |
+
ax_pie.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle.
|
235 |
+
fig_pie.patch.set_facecolor('none') # Remove background
|
236 |
+
st.pyplot(fig_pie)
|
237 |
+
|
238 |
+
st.markdown("<hr>", unsafe_allow_html=True)
|
239 |
+
|
240 |
+
st.subheader("Concrete Data Distribution")
|
241 |
+
|
242 |
+
fig, ax = plt.subplots()
|
243 |
+
sns.histplot(data['cement'], bins=20, kde=True, color='blue', ax=ax)
|
244 |
+
ax.set_title('Distribution of Cement Data')
|
245 |
+
st.pyplot(fig)
|
246 |
+
|
247 |
+
|
248 |
+
|
249 |
+
# Analytics page
|
250 |
+
elif page == "Analytics":
|
251 |
+
st.title("Cement Data Analytics")
|
252 |
+
|
253 |
+
# Display dataset
|
254 |
+
st.subheader("Dataset")
|
255 |
+
st.write(data.head())
|
256 |
+
|
257 |
+
st.sidebar.markdown("## Customize Analytics")
|
258 |
+
plot_type = st.sidebar.radio("Select display", ["Summary", "Correlation Heatmap"])
|
259 |
+
|
260 |
+
if plot_type == 'Summary':
|
261 |
+
st.subheader('Cement Sumary')
|
262 |
+
st.dataframe(data.describe())
|
263 |
+
|
264 |
+
|
265 |
+
if plot_type == "Correlation Heatmap":
|
266 |
+
# Display correlation heatmap
|
267 |
+
st.subheader("Correlation Heatmap")
|
268 |
+
fig, ax = plt.subplots()
|
269 |
+
sns.heatmap(data.corr(), annot=True, cmap='coolwarm', ax=ax)
|
270 |
+
st.pyplot(fig)
|
271 |
+
|
272 |
+
# Visualization page
|
273 |
+
|
274 |
+
elif page == "Visualization":
|
275 |
+
st.title("Cement Data Analytics")
|
276 |
+
|
277 |
+
# Display dataset
|
278 |
+
st.subheader("Dataset")
|
279 |
+
st.write(data.head())
|
280 |
+
|
281 |
+
st.sidebar.markdown("## Customize Visualizations")
|
282 |
+
plot_type = st.sidebar.radio("Select Plot Type", ["Regplot","Scatterplot", "lineplot","Barplot","Pairplot"])
|
283 |
+
|
284 |
+
if plot_type == "Pairplot":
|
285 |
+
st.subheader("Pairplot")
|
286 |
+
fig = sns.pairplot(data)
|
287 |
+
st.pyplot(fig)
|
288 |
+
|
289 |
+
elif plot_type == "Regplot":
|
290 |
+
# Regplot Tab
|
291 |
+
st.subheader('Cement Data Regplot')
|
292 |
+
fig = plt.figure(figsize=(15, 5))
|
293 |
+
sns.regplot(data=data, x='water', y='cement')
|
294 |
+
st.pyplot(fig)
|
295 |
+
|
296 |
+
elif plot_type == "Scatterplot":
|
297 |
+
st.subheader('cement Data scatterplot')
|
298 |
+
fig = plt.figure(figsize=(15, 5))
|
299 |
+
sns.scatterplot(data=data, x='water', y='cement')
|
300 |
+
st.pyplot(fig)
|
301 |
+
|
302 |
+
elif plot_type == "lineplot":
|
303 |
+
st.subheader('cement Data lineplot')
|
304 |
+
fig = plt.figure(figsize=(15, 5))
|
305 |
+
sns.lineplot(data=data, x='water', y='cement')
|
306 |
+
st.pyplot(fig)
|
307 |
+
|
308 |
+
elif plot_type == "Barplot":
|
309 |
+
st.subheader('cement Data Barplot')
|
310 |
+
fig = plt.figure(figsize=(15, 5))
|
311 |
+
sns.barplot(data=data, x='water', y='cement')
|
312 |
+
st.pyplot(fig)
|
313 |
+
|
314 |
+
|
315 |
+
# Machine Learning page
|
316 |
+
elif page == "Machine Learning":
|
317 |
+
|
318 |
+
st.markdown("<h1 style='text-align:center;color: #B28E52; '> Cement Strength Prediction </h1>", unsafe_allow_html=True)
|
319 |
+
|
320 |
+
st.write("Use the form below to input features and get a prediction of the compressive strength.")
|
321 |
+
|
322 |
+
# Option du menu de navigation
|
323 |
+
|
324 |
+
selection = option_menu(
|
325 |
+
menu_title=None,
|
326 |
+
options=['User input', 'Upload csv'],
|
327 |
+
icons=['card-text', 'cloud-upload'],
|
328 |
+
default_index=0,
|
329 |
+
orientation='horizontal',
|
330 |
+
styles={
|
331 |
+
"container": {"padding": "5px", "background-color": "#333333", "font-weight": "bold"},
|
332 |
+
"icon": {"font-size": "17px"},
|
333 |
+
"nav-link": {"font-size": "15px", "text-align": "left", "margin": "5px", "padding": "10px", "--hover-color": "#9A9DA0"},
|
334 |
+
"nav-link-selected": {"background-color": "#B28E52"},
|
335 |
+
}
|
336 |
+
)
|
337 |
+
|
338 |
+
|
339 |
+
if selection == 'User input':
|
340 |
+
cement = st.number_input("Cement", min_value=0.0, max_value=1000.0, value=100.0)
|
341 |
+
slag = st.number_input("Slag", min_value=0.0, max_value=1000.0, value=100.0)
|
342 |
+
ash = st.number_input("Ash", min_value=0.0, max_value=1000.0, value=100.0)
|
343 |
+
water = st.number_input("Water", min_value=0.0, max_value=1000.0, value=100.0)
|
344 |
+
superplastic = st.number_input("Superplastic", min_value=0.0, max_value=1000.0, value=10.0)
|
345 |
+
coarseagg = st.number_input("Coarseaggr.", min_value=0.0, max_value=1000.0, value=100.0)
|
346 |
+
fineagg = st.number_input("Fineaggr.", min_value=0.0, max_value=1000.0, value=100.0)
|
347 |
+
age = st.number_input("age", min_value=0.0, max_value=100.0, value=10.0)
|
348 |
+
|
349 |
+
# Make prediction
|
350 |
+
if st.button("Predict"):
|
351 |
+
features = np.array([[cement, slag, ash, water, superplastic, coarseagg, fineagg , age]])
|
352 |
+
prediction = regressor.predict(features)
|
353 |
+
st.write(f"Predicted Strength: {prediction[0]:.2f}")
|
354 |
+
|
355 |
+
|
356 |
+
# Function to load data from an uploaded file
|
357 |
+
def load_data(file):
|
358 |
+
data = pd.read_csv(file)
|
359 |
+
return data
|
360 |
+
|
361 |
+
# Function to generate download link for a DataFrame
|
362 |
+
def filedownload(df):
|
363 |
+
csv = df.to_csv(index=False)
|
364 |
+
b64 = base64.b64encode(csv.encode()).decode() # B64 encoding
|
365 |
+
href = f'<a href="data:file/csv;base64,{b64}" download="predictions.csv">Download CSV File</a>'
|
366 |
+
return href
|
367 |
+
|
368 |
+
|
369 |
+
|
370 |
+
# Upload CSV section
|
371 |
+
if selection == "Upload csv":
|
372 |
+
st.write("### Upload your input CSV file")
|
373 |
+
uploaded_file = st.file_uploader('Choose a CSV file', type=["csv"])
|
374 |
+
|
375 |
+
if uploaded_file:
|
376 |
+
data = load_data(uploaded_file)
|
377 |
+
if st.checkbox('Load dataset'):
|
378 |
+
st.subheader('Loaded Dataset')
|
379 |
+
st.write(data)
|
380 |
+
|
381 |
+
|
382 |
+
if st.checkbox('Prediction'):
|
383 |
+
if 'strength' in data.columns:
|
384 |
+
data = data.drop(columns=['strength'])
|
385 |
+
|
386 |
+
model = pickle.load(open('concrete.pkl', 'rb'))
|
387 |
+
prediction = model.predict(data)
|
388 |
+
pp = pd.DataFrame(prediction, columns=['Prediction'])
|
389 |
+
ndf = pd.concat([data, pp], axis=1)
|
390 |
+
st.write(ndf)
|
391 |
+
|
392 |
+
if st.button("Download"):
|
393 |
+
st.markdown(filedownload(ndf), unsafe_allow_html=True)
|
394 |
+
|
395 |
+
|
396 |
+
st.sidebar.markdown( '''
|
397 |
+
---
|
398 |
+
Created by Oceane 😊 ''')
|