AmrGharieb commited on
Commit
1a9ac32
1 Parent(s): eb77f93

Upload 6 files

Browse files
Files changed (6) hide show
  1. DecisionTree.pkl +3 -0
  2. app.py +226 -0
  3. functions.py +246 -0
  4. max_min.txt +3 -0
  5. requirements.txt +0 -0
  6. uh-primary.png +0 -0
DecisionTree.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3b8f324bde5f91a95920ae53fb4a13fcd13e37861f0a34282a4fd02ac5f32354
3
+ size 651272
app.py ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ import streamlit as st
3
+ from functions import *
4
+
5
+
6
+ # Initialize session state
7
+ if 'pumping_file' not in st.session_state:
8
+ st.session_state.pumping_file = None
9
+ if 'pumping_df' not in st.session_state:
10
+ st.session_state.pumping_df = None
11
+ if 'cwt_df' not in st.session_state:
12
+ st.session_state.cwt_df = None
13
+ if 'ms_df' not in st.session_state:
14
+ st.session_state.ms_df = None
15
+ if 'mc_events_predicted_df' not in st.session_state:
16
+ st.session_state.mc_events_predicted_df = None
17
+ if 'date_col' not in st.session_state:
18
+ st.session_state.date_col = None
19
+ if 'pressure_col' not in st.session_state:
20
+ st.session_state.pressure_col = None
21
+ if 'rate_col' not in st.session_state:
22
+ st.session_state.rate_col = None
23
+ if 'start_date' not in st.session_state:
24
+ st.session_state.start_date = None
25
+ if 'start_time' not in st.session_state:
26
+ st.session_state.start_time = None
27
+ if 'end_date' not in st.session_state:
28
+ st.session_state.end_date = None
29
+ if 'end_time' not in st.session_state:
30
+ st.session_state.end_time = None
31
+ if 'east' not in st.session_state:
32
+ st.session_state.east = None
33
+ if 'north' not in st.session_state:
34
+ st.session_state.north = None
35
+ if 'depth' not in st.session_state:
36
+ st.session_state.depth = None
37
+
38
+ if 'start_datetime_selector' not in st.session_state:
39
+ st.session_state.start_datetime_selector = False
40
+ if 'end_datetime_selector' not in st.session_state:
41
+ st.session_state.end_datetime_selector = False
42
+
43
+ x_names = [str(i) for i in range(1,257)]
44
+ y_names=['delta_east', 'delta_north', 'delta_depth']
45
+
46
+
47
+ #Main decoration
48
+ st.set_page_config(page_title='Microseismic Prediction',
49
+ layout="wide",page_icon='📈')
50
+ st.title('Microseismic Prediction')
51
+ st.markdown('Predict Microseismic Events (X, Y, Z)')
52
+ image_path = Path('uh-primary.png')
53
+ st.sidebar.image(str(image_path))
54
+
55
+
56
+
57
+ click_event_container = st.empty()
58
+
59
+
60
+ # Define tab titles
61
+ tab_titles = ["Pumping pressure table", "Pumping pressure chart", "Adjusted chart" , "Predicted Microseismic Events","Quality Check"]
62
+
63
+ # Create tabs using st.tabs
64
+ tabs = st.tabs(tab_titles)
65
+
66
+ uploaded_pumping_file = st.sidebar.\
67
+ file_uploader("Please upload pumping XLSX file", type=["xlsx"])
68
+
69
+
70
+
71
+ # Add content to each tab
72
+ with tabs[0]:
73
+ st.header("Table of pumping data")
74
+ pumping_data_frame_container = st.empty()
75
+ if uploaded_pumping_file:
76
+ #create a pumping dataframe
77
+ pumping_data_frame_container.\
78
+ dataframe(st.session_state.pumping_df, use_container_width=True)
79
+
80
+ with tabs[1]:
81
+ st.header("Pumping pressure and rate chart")
82
+ with st.container():
83
+ #check box with date selector
84
+
85
+ option = st.radio("Which date you want to select?", ("Start date", "End date"),captions=("Select start date and time", "Select end date and time"))
86
+ if option == "Start date":
87
+ st.session_state.start_datetime_selector = True
88
+ st.session_state.end_datetime_selector = False
89
+ elif option == "End date":
90
+ st.session_state.start_datetime_selector = False
91
+ st.session_state.end_datetime_selector = True
92
+
93
+
94
+ with st.form(key='pumping_chart_form'):
95
+
96
+ if st.session_state.pumping_df is not None:
97
+ fig = plot_pumping_data(st.session_state.pumping_df, \
98
+ st.session_state.date_col, st.session_state.pressure_col,\
99
+ st.session_state.rate_col)
100
+ st.empty()
101
+ selected_events = plotly_events(fig)
102
+ if selected_events:
103
+ click_event = selected_events[0]
104
+ x_value = click_event['x']
105
+
106
+ if st.session_state.start_datetime_selector:
107
+ #convert x_value to datetime
108
+ x_value = pd.to_datetime(x_value)
109
+ #extract date and time then assign to start_date and start_time
110
+ st.session_state.start_date = x_value.date()
111
+ st.session_state.start_time = x_value.time()
112
+
113
+ st.write(f"Start date: {st.session_state.start_date}")
114
+ st.write(f"Start time: {st.session_state.start_time}")
115
+
116
+ if st.session_state.end_datetime_selector:
117
+ #convert x_value to datetime
118
+ x_value = pd.to_datetime(x_value)
119
+ #extract date and time then assign to end_date and end_time
120
+ st.session_state.end_date = x_value.date()
121
+ st.session_state.end_time = x_value.time()
122
+
123
+ st.write(f"End date: {st.session_state.end_date}")
124
+ st.write(f"End time: {st.session_state.end_time}")
125
+
126
+ #open tab 3
127
+
128
+
129
+ st.form_submit_button(label = "Transfer new chart")
130
+
131
+
132
+ with tabs[2]:
133
+ if st.session_state.pumping_df is not None:
134
+
135
+ fig = plot_pumping_data(st.session_state.pumping_df, \
136
+ st.session_state.date_col, st.session_state.pressure_col,st.session_state.rate_col)
137
+
138
+ st.plotly_chart(fig, use_container_width=True)
139
+
140
+ with st.form(key='adjusted_chart_form'):
141
+ st.empty()
142
+ st.write("Please provide the x, y, z for mid perforation")
143
+ col1, col2, col3 = st.columns(3)
144
+ with col1:
145
+ st.session_state.east = st.number_input("East", value=0.0)
146
+ with col2:
147
+ st.session_state.north = st.number_input("North", value=0.0)
148
+ with col3:
149
+ st.session_state.depth = st.number_input("Depth", value=0.0)
150
+
151
+ calc_cwt = st.form_submit_button(label = "Predict Microseismic Events")
152
+ if calc_cwt:
153
+ st.session_state.cwt_df = calculate_cwt(st.session_state.pumping_df, st.session_state.date_col, st.session_state.pressure_col)
154
+ st.write("CWT calculated")
155
+
156
+ with st.expander("CWT Data"):
157
+ st.dataframe(st.session_state.cwt_df)
158
+
159
+
160
+ with tabs[3]:
161
+ if st.session_state.cwt_df is not None:
162
+ with st.container():
163
+ st.session_state.mc_events_predicted_df = predict_microseismic_events(\
164
+ st.session_state.cwt_df,x_names, y_names,\
165
+ st.session_state.east, st.session_state.north, st.session_state.depth)
166
+
167
+ with st.expander("Microseismic Events"):
168
+ st.dataframe( st.session_state.mc_events_predicted_df)
169
+
170
+ fig = plot_microseismic_events( st.session_state.mc_events_predicted_df)
171
+ st.plotly_chart(fig, use_container_width=True)
172
+
173
+ else:
174
+ st.write("Please calculate CWT first")
175
+
176
+
177
+ with tabs[4]:
178
+ #upload file
179
+
180
+
181
+ with st.container():
182
+ actual_ms_uploaded_file = \
183
+ st.file_uploader("Please upload actual Micro Seismic events XLSX file", type=["xlsx"])
184
+
185
+ if actual_ms_uploaded_file:
186
+ st.session_state.ms_df = convert_ms_to_df(actual_ms_uploaded_file)
187
+
188
+ col1, col2, col3,col4 = st.columns(4)
189
+ ms_east_col = col1.selectbox("Select the east column", st.session_state.ms_df.columns)
190
+ ms_north_col = col2.selectbox("Select the north column", st.session_state.ms_df.columns)
191
+ ms_depth_col = col3.selectbox("Select the depth column", st.session_state.ms_df.columns)
192
+ depth_shift = col4.number_input("Depth shift", value=0.0)
193
+
194
+
195
+ with st.form('compare_form'):
196
+ if st.session_state.mc_events_predicted_df is not None:
197
+ fig = compare_microseismic_events(st.session_state.mc_events_predicted_df,\
198
+ st.session_state.ms_df,\
199
+ ms_east_col,ms_north_col,ms_depth_col,depth_shift)
200
+
201
+ compare_btn = st.form_submit_button(label = "Compare")
202
+ if compare_btn:
203
+ st.plotly_chart(fig, use_container_width=True)
204
+
205
+
206
+
207
+
208
+ if uploaded_pumping_file:
209
+
210
+ st.session_state.pumping_file = uploaded_pumping_file
211
+ st.session_state.pumping_df = convert_pumping_data_to_df(st.session_state.pumping_file)
212
+ st.session_state.date_col = st.sidebar.selectbox("Select the date column", st.session_state.pumping_df.columns)
213
+ st.session_state.pressure_col = st.sidebar.selectbox("Select the pressure column", st.session_state.pumping_df.columns)
214
+ st.session_state.rate_col = st.sidebar.selectbox("Select the rate column", st.session_state.pumping_df.columns)
215
+
216
+ #view pumping data via clicking the button
217
+ view_pumping_data_btn = st.sidebar.button("View pumping Data")
218
+ if view_pumping_data_btn:
219
+ try:
220
+ #create a pumping dataframe
221
+ pumping_data_frame_container.\
222
+ dataframe(st.session_state.pumping_df, use_container_width=True)
223
+ except:
224
+ pass
225
+
226
+
functions.py ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pickle
2
+ from pathlib import Path
3
+ import streamlit as st
4
+ import pandas as pd
5
+ import plotly.graph_objects as go
6
+ from plotly.subplots import make_subplots
7
+ from streamlit_plotly_events import plotly_events
8
+ import streamlit as st
9
+ import pandas as pd
10
+ import numpy as np
11
+ from sklearn import preprocessing
12
+ import pywt
13
+
14
+
15
+ def convert_pumping_data_to_df(uploaded_file):
16
+
17
+ df = pd.read_excel(uploaded_file)
18
+ # convert the date column to datatime
19
+ try:
20
+ #convert the first column to datetime
21
+ df.iloc[:,0] = pd.to_datetime(df.iloc[:,0])
22
+
23
+ except Exception as e:
24
+ st.warning(f"An error occurred while converting the date column to datetime: {e}")
25
+
26
+ return df
27
+
28
+ def convert_ms_to_df(uploaded_file):
29
+
30
+ df = pd.read_excel(uploaded_file)
31
+ # convert the date column to datatime
32
+ try:
33
+ #convert the first column to datetime
34
+ df.iloc[:,0] = pd.to_datetime(df.iloc[:,0])
35
+
36
+ except Exception as e:
37
+ st.warning(f"An error occurred while converting the date column to datetime: {e}")
38
+
39
+ return df
40
+
41
+ def plot_pumping_data(df, date_col, pressure_col, rate_col):
42
+ fig = make_subplots(specs=[[{"secondary_y": True}]])
43
+ fig.add_trace(go.Scatter(x=df[date_col], y=df[pressure_col], mode='lines', name='Pressure', line=dict(color='blue')), secondary_y=False)
44
+ fig.add_trace(go.Scatter(x=df[date_col], y=df[rate_col], mode='lines', name='Rate', line=dict(color='red')), secondary_y=True)
45
+ fig.update_layout(title_text="Pumping Data")
46
+ fig.update_xaxes(title_text="Date")
47
+ fig.update_yaxes(title_text="Pressure", secondary_y=False)
48
+ fig.update_yaxes(title_text="Rate", secondary_y=True)
49
+ #update the legend to be horizonal at the top
50
+ fig.update_layout(legend=dict(
51
+ orientation="h",
52
+ yanchor="bottom",
53
+ y=1.02,
54
+ xanchor="right",
55
+ x=1
56
+ ))
57
+
58
+ #remove secondary axis gridlines
59
+ fig.update_yaxes(showgrid=False, secondary_y=True)
60
+ #click event on the chart to get the x axis value
61
+ # Attempt to capture click events using streamlit-plotly-events (install required)
62
+
63
+
64
+ return fig
65
+
66
+
67
+ def calculate_cwt(df,time_col,pressure_col):
68
+
69
+
70
+ #convert first column in both data frame pumping and microseismic to datetime
71
+ df[time_col] = pd.to_datetime(df[time_col])
72
+
73
+ norm_coef2_a,period,time_data,scales_a,coef_a, freqs_a,pressure_data = continous_wavelet_transformer(df[pressure_col],df[time_col])
74
+ #transpose norm_coef2_a
75
+ norm_coef2_a = norm_coef2_a.T
76
+ #merge the norm_coef2_a with time_data as date time and pressure data and QC_LOC_X,Y,Z and remove the nulls in time_data
77
+ norm_coef2_a = pd.DataFrame(norm_coef2_a,columns=scales_a)
78
+
79
+ norm_coef2_a['t'] = df[time_col]
80
+ norm_coef2_a['p'] = df[pressure_col]
81
+ norm_coef2_a = norm_coef2_a.dropna(subset=['t'])
82
+
83
+ return norm_coef2_a
84
+
85
+
86
+ def continous_wavelet_transformer(pressure_data,time_data):
87
+ scales_a = np.linspace(1, 256, 256)
88
+ coef_a, freqs_a = pywt.cwt(pressure_data, scales_a, "cmor1.5-1.0")
89
+
90
+ energy = np.sqrt(coef_a.real**2 + coef_a.imag**2)
91
+ coef2_a = np.log2(energy)
92
+ period = 1.0 / freqs_a
93
+ scaler=preprocessing.MinMaxScaler(feature_range=(0,1)).fit(coef2_a)
94
+ norm_coef2_a=scaler.transform(coef2_a)
95
+
96
+ return norm_coef2_a,period,time_data,scales_a,coef_a, freqs_a,pressure_data
97
+
98
+ def reload_DT_model():
99
+ # Load the model from the file
100
+ with open(Path('DecisionTree.pkl'), 'rb') as file:
101
+ model = pickle.load(file)
102
+ return model
103
+
104
+ def import_min_max():
105
+ #import min max from txt file
106
+ with open(Path('max_min.txt'),'r') as f:
107
+
108
+ min_max = f.readlines()
109
+ min_max = [x.strip() for x in min_max]
110
+ min_max = [x.split(',') for x in min_max]
111
+ min_max = [[float(y) for y in x] for x in min_max]
112
+ min_max = np.array(min_max)
113
+ return min_max
114
+
115
+ def predict_microseismic_events(df,x_names,y_names,east_perf,north_perf,depth_perf):
116
+
117
+ model = reload_DT_model()
118
+ #predict the microseismic events
119
+
120
+ df.reset_index(drop=True, inplace=True)
121
+ df.rename(columns=dict(zip(df.columns[:256], x_names)), inplace=True)
122
+
123
+ ds_test = df[x_names]
124
+
125
+
126
+ # Convert example_data to a DataFrame with column names (cont_names)
127
+
128
+ example_data_df = pd.DataFrame(ds_test, columns=x_names)
129
+
130
+ # Make predictions on the example data
131
+
132
+ predictions = model.predict(example_data_df)
133
+
134
+ # convert the predictions to dataframe
135
+
136
+ predictions_df = pd.DataFrame(predictions, columns=y_names)
137
+
138
+ # trail the column names with _pred
139
+
140
+ predictions_df.columns = [
141
+ str(col) + '_pred' for col in predictions_df.columns]
142
+
143
+ final_df = predictions_df.reset_index(drop=True)
144
+
145
+ # denormalize the pred columns using min max
146
+
147
+ min_max = import_min_max()
148
+
149
+ final_df['delta_east_pred_denormalized'] = final_df['delta_east_pred'] * \
150
+ (min_max[0][1] - min_max[0][0]) + min_max[0][0]
151
+
152
+ final_df['delta_north_pred_denormalized'] = (
153
+ final_df['delta_north_pred'] * (min_max[1][1] - min_max[1][0]) + min_max[1][0])
154
+
155
+ final_df['delta_depth_pred_denormalized'] = final_df['delta_depth_pred'] * \
156
+ (min_max[2][1] - min_max[2][0]) + min_max[2][0]
157
+
158
+ final_df['east_pred'] = final_df['delta_east_pred_denormalized'] + east_perf
159
+
160
+ final_df['north_pred'] = final_df['delta_north_pred_denormalized'] + north_perf
161
+
162
+ final_df['depth_pred'] = final_df['delta_depth_pred_denormalized'] + depth_perf
163
+
164
+ final = pd.concat([df, final_df], axis=1)
165
+
166
+ return final
167
+
168
+ def plot_microseismic_events(final):
169
+
170
+ fig = go.Figure(data=[go.Scatter3d(
171
+ x=final['east_pred'],
172
+ y=final['north_pred'],
173
+ z=final['depth_pred'],
174
+ mode='markers',
175
+ marker=dict(
176
+ size=3,
177
+ opacity=1,
178
+ color='red'
179
+ ),
180
+ name='Predicted'
181
+ )])
182
+ # #add the predicted
183
+ # fig.add_trace(go.Scatter3d(
184
+ # x=final['east_pred'],
185
+ # y=final['north_pred'],
186
+ # z=final['depth_pred'],
187
+ # mode='markers',
188
+ # marker=dict(
189
+ # size=2,
190
+ # opacity=0.2,
191
+ # color='red'
192
+ # ),
193
+ # name='predicted'
194
+ # ))
195
+ fig.update_layout(title=f"Predicted Micro Seismic Events", xaxis_title="east", yaxis_title="north",height=800)
196
+ return fig
197
+
198
+ def compare_microseismic_events(final,actual,east,north,depth,depth_shift):
199
+ # #convert first column in final to datetime64[ns]
200
+ # final['t'] = pd.to_datetime(final['t'])
201
+
202
+ # st.write(actual[time_col])
203
+ # st.write(final.t)
204
+
205
+
206
+
207
+ # #write the type of final.t column and actual[time_col] column
208
+ # st.write(f"actual[time_col] column type: {actual[time_col].dtype}")
209
+ # st.write(f"final.t column type: {final.t.dtype}")
210
+
211
+ # #join the final and actual depending on column zero
212
+
213
+ # # joined_df = pd.merge(final, actual, left_on='t', right_on=time_col, how='outer')
214
+
215
+ # st.write(joined_df)
216
+
217
+ actual[depth] = depth_shift - actual[depth]
218
+
219
+
220
+ fig = go.Figure(data=[go.Scatter3d(
221
+ x=final['east_pred'],
222
+ y=final['north_pred'],
223
+ z=final['depth_pred'],
224
+ mode='markers',
225
+ marker=dict(
226
+ size=2,
227
+ opacity=0.3,
228
+ color='red'
229
+ ),
230
+ name='Predicted'
231
+ )])
232
+ #add the actual
233
+ fig.add_trace(go.Scatter3d(
234
+ x=actual[east],
235
+ y=actual[north],
236
+ z=actual[depth],
237
+ mode='markers',
238
+ marker=dict(
239
+ size=3,
240
+ opacity=1,
241
+ color='navy'
242
+ ),
243
+ name='Actual'
244
+ ))
245
+ fig.update_layout(title=f"Predicted Micro Seismic Events", xaxis_title="east", yaxis_title="north",height=800)
246
+ return fig
max_min.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ -3310.3351891629864,2156.3472485230304
2
+ -2622.2025576928863,3026.023548964993
3
+ -433.7171200566636,428.34999036096906
requirements.txt ADDED
Binary file (5.18 kB). View file
 
uh-primary.png ADDED