Spaces:
Sleeping
Sleeping
Upload 44 files
Browse files- packages.txt +2 -0
- .gitattributes +3 -0
- Antuns/__pycache__/p1_import_csv.cpython-39.pyc +0 -0
- Antuns/__pycache__/page_setting.cpython-39.pyc +0 -0
- Antuns/__pycache__/prediction_LGBM.cpython-39.pyc +0 -0
- Antuns/page_setting.py +14 -0
- Antuns/prediction_LGBM.py +21 -0
- app.py +62 -0
- backup/081222/Antuns/p1_import_csv.py +13 -0
- backup/081222/Antuns/page_setting.py +14 -0
- backup/081222/Antuns/prediction_LGBM.py +21 -0
- backup/081222/Homepage.py +10 -0
- backup/081222/models/LGBM_20221125.json +3 -0
- backup/081222/models/LightGBM_0.45.pbz2 +3 -0
- backup/model.json +0 -0
- data/LogoVPI.png +0 -0
- data/all_file_merged_updated_with_All_geometry.csv +3 -0
- data/merged/Training_data.csv +0 -0
- data/merged/merged_df.csv +0 -0
- mLogsFunctions/__init__.py +31 -0
- mLogsFunctions/__pycache__/__init__.cpython-39.pyc +0 -0
- mLogsFunctions/__pycache__/dataloading.cpython-39.pyc +0 -0
- mLogsFunctions/__pycache__/dataprocessing.cpython-39.pyc +0 -0
- mLogsFunctions/__pycache__/fx.cpython-39.pyc +0 -0
- mLogsFunctions/__pycache__/lightGBMPred.cpython-39.pyc +0 -0
- mLogsFunctions/__pycache__/rmOutliers.cpython-39.pyc +0 -0
- mLogsFunctions/__pycache__/viewCurves.cpython-39.pyc +0 -0
- mLogsFunctions/dataloading.py +32 -0
- mLogsFunctions/dataprocessing.py +14 -0
- mLogsFunctions/fx.py +360 -0
- mLogsFunctions/lightGBMPred.py +21 -0
- mLogsFunctions/rmOutliers.py +135 -0
- mLogsFunctions/viewCurves.py +102 -0
- models/05_13_2023_11_50_38_model_LGBM.json +0 -0
- pages/1_LAS_Exploratory.py +289 -0
- pages/2_Exploratory_Data_Analysis.py +92 -0
- pages/3_Fracture_Training_Models.py +388 -0
- pages/4_Fracture_Prediction.py +190 -0
- requirements.txt +13 -0
- ui/PageComponents.py +176 -0
- ui/UIConfigs.py +41 -0
- ui/__init__.py +18 -0
- ui/__pycache__/PageComponents.cpython-39.pyc +0 -0
- ui/__pycache__/UIConfigs.cpython-39.pyc +0 -0
- ui/__pycache__/__init__.cpython-39.pyc +0 -0
packages.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
freeglut3-dev
|
| 2 |
+
libgtk2.0-dev
|
.gitattributes
CHANGED
|
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
backup/081222/models/LGBM_20221125.json filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
backup/081222/models/LightGBM_0.45.pbz2 filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
data/all_file_merged_updated_with_All_geometry.csv filter=lfs diff=lfs merge=lfs -text
|
Antuns/__pycache__/p1_import_csv.cpython-39.pyc
ADDED
|
Binary file (616 Bytes). View file
|
|
|
Antuns/__pycache__/page_setting.cpython-39.pyc
ADDED
|
Binary file (726 Bytes). View file
|
|
|
Antuns/__pycache__/prediction_LGBM.cpython-39.pyc
ADDED
|
Binary file (678 Bytes). View file
|
|
|
Antuns/page_setting.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
from PIL import Image
|
| 3 |
+
img = Image.open("/work/2022_VPIMLogs_WebApp/data/LogoVPI.png")
|
| 4 |
+
def page_intro():
|
| 5 |
+
st.set_page_config(# Alternate names: setup_page, page, layout
|
| 6 |
+
layout="wide", # Can be "centered" or "wide". In the future also "dashboard", etc.
|
| 7 |
+
initial_sidebar_state="auto", # Can be "auto", "expanded", "collapsed"
|
| 8 |
+
page_title="VPI-MLogs", # String or None. Strings get appended with "• Streamlit".
|
| 9 |
+
page_icon=img, # String, anything supported by st.image, or None.
|
| 10 |
+
)
|
| 11 |
+
col_1, col_2, col_3, col_4, col_5, = st.columns(5)
|
| 12 |
+
with col_3:
|
| 13 |
+
st.image("https://i.ibb.co/Yd42K98/LogoVPI.png", width=250)
|
| 14 |
+
st.header("Welcome to VPI-MLOGS!")
|
Antuns/prediction_LGBM.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
|
| 3 |
+
def Prediction_LGBM(trained_models:list=None, data:pd.DataFrame=None, feature_names:list=None):
|
| 4 |
+
"""
|
| 5 |
+
mode: "predict", "predict_proba"
|
| 6 |
+
"""
|
| 7 |
+
data_copy = data.copy()
|
| 8 |
+
# if mode == "predict":
|
| 9 |
+
# for i, model in enumerate(trained_models):
|
| 10 |
+
# y_preds = model.predict(data_copy[feature_names])
|
| 11 |
+
# data_copy[f"model_{i}"] = y_preds
|
| 12 |
+
#
|
| 13 |
+
# else:
|
| 14 |
+
for i, model in enumerate(trained_models):
|
| 15 |
+
y_preds = model.predict(data_copy[feature_names])
|
| 16 |
+
data_copy[f"model_{i}"] = y_preds
|
| 17 |
+
|
| 18 |
+
return data_copy
|
| 19 |
+
|
| 20 |
+
if __name__ == '__main__':
|
| 21 |
+
Prediction_LGBM()
|
app.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
from ui.UIConfigs import *
|
| 3 |
+
|
| 4 |
+
#Streamlit dashboard------------------------------------------------------------------------------------------
|
| 5 |
+
set_page_config(page='home', logo_size=200)
|
| 6 |
+
hide_menu_button()
|
| 7 |
+
condense_layout()
|
| 8 |
+
|
| 9 |
+
st.sidebar.success("")
|
| 10 |
+
st.markdown("""
|
| 11 |
+
<style>
|
| 12 |
+
h2 {
|
| 13 |
+
text-align: left;
|
| 14 |
+
}
|
| 15 |
+
</style>
|
| 16 |
+
""", unsafe_allow_html=True)
|
| 17 |
+
# st.markdown("""
|
| 18 |
+
# <center><h2>VPI-MLOGs Web App</h2></center>
|
| 19 |
+
# <b>VPI-MLOGs</b> is a web app designed for log data analysis and visualization. It provides various functions to help users process, analyze, and visualize log data.<br>
|
| 20 |
+
# <h4>1. Read LAS Files and Convert to CSV Files</h4>
|
| 21 |
+
|
| 22 |
+
# <b>VPI-MLOGs</b> allows users to upload LAS files and convert them to CSV format. This feature makes it easy to work with log data in other programs, such as Excel or Python.
|
| 23 |
+
|
| 24 |
+
# <h4>2. Explore Data Analysis with Multiple Charts</h4>
|
| 25 |
+
|
| 26 |
+
# <b>VPI-MLOGs</b> provides several exploratory data analysis (EDA) functions, such as detecting missing data, generating histograms, and visualizing distribution. These functions help users understand the structure and characteristics of the log data.<br>
|
| 27 |
+
|
| 28 |
+
# <h4>3. Training LGBM Model</h4>
|
| 29 |
+
|
| 30 |
+
# <b>VPI-MLOGs</b> provides a machine learning feature that allows users to train a LGBM (Light Gradient Boosting Machine) model using their log data.
|
| 31 |
+
|
| 32 |
+
# <h4>4. Prediction</h4>
|
| 33 |
+
|
| 34 |
+
# <b>VPI-MLOGs</b> Users can also make predictions using the trained model.
|
| 35 |
+
# """
|
| 36 |
+
st.markdown("""
|
| 37 |
+
<center><h2>VPI-MLOGs Web App</h2></center>
|
| 38 |
+
|
| 39 |
+
**Read LAS Files and Convert to CSV Files**
|
| 40 |
+
|
| 41 |
+
VPI-MLOGs enables the reading of LAS files, a commonly used format for storing log data. Once uploaded, VPI-MLOGs can convert LAS files to the CSV format, which is more widely compatible with other programs like Excel or Python.
|
| 42 |
+
|
| 43 |
+
**Explore Data Analysis with Multiple Charts**
|
| 44 |
+
|
| 45 |
+
VPI-MLOGs offers various exploratory data analysis (EDA) functions to better understand the characteristics of log data. These EDA functions include:
|
| 46 |
+
|
| 47 |
+
- **Missing Data Detection**: Identifies any missing data points in the log data.
|
| 48 |
+
- **Histogram Generation**: Creates graphical representations of data value distributions.
|
| 49 |
+
- **Distribution Visualization**: Creates graphical representations showcasing the spread of data values.
|
| 50 |
+
- **Outliers Removal**: Identifies any data points that are significantly different from the rest of the data.
|
| 51 |
+
|
| 52 |
+
**Training LGBM Model**
|
| 53 |
+
|
| 54 |
+
VPI-MLOGs provides a machine learning feature that enables users to train a LGBM (Light Gradient Boosting Machine) model using their log data. LGBM is a versatile machine learning algorithm suitable for various tasks like classification and regression. Once trained, the LGBM model can be used to make predictions on new data.
|
| 55 |
+
|
| 56 |
+
**Prediction**
|
| 57 |
+
|
| 58 |
+
VPI-MLOGs allows users to make predictions using the trained model. These predictions can be applied to new data not present in the training set. This functionality proves beneficial for tasks like identifying potential drilling targets or predicting rock formation properties.
|
| 59 |
+
|
| 60 |
+
In summary, VPI-MLOGs is a powerful tool for processing, analyzing, and visualizing log data. It offers a diverse range of functions that aid users in gaining a deeper understanding of their data, enabling them to make more informed decisions.
|
| 61 |
+
"""
|
| 62 |
+
,unsafe_allow_html=True)
|
backup/081222/Antuns/p1_import_csv.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
import pandas as pd
|
| 3 |
+
|
| 4 |
+
def upload_csv():
|
| 5 |
+
df = None
|
| 6 |
+
uploaded_file = st.file_uploader(label='Upload *csv file from your drive! Choose a file:', type='csv')
|
| 7 |
+
if uploaded_file is not None:
|
| 8 |
+
df = pd.read_csv(uploaded_file, na_values=-9999)
|
| 9 |
+
st.success("Loading finished!")
|
| 10 |
+
st.dataframe(df, width=1400, height=300)
|
| 11 |
+
st.write('---')
|
| 12 |
+
return df
|
| 13 |
+
|
backup/081222/Antuns/page_setting.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
from PIL import Image
|
| 3 |
+
img = Image.open("data/LogoVPI.png")
|
| 4 |
+
def page_intro():
|
| 5 |
+
st.set_page_config(# Alternate names: setup_page, page, layout
|
| 6 |
+
layout="wide", # Can be "centered" or "wide". In the future also "dashboard", etc.
|
| 7 |
+
initial_sidebar_state="auto", # Can be "auto", "expanded", "collapsed"
|
| 8 |
+
page_title="VPI-MLogs", # String or None. Strings get appended with "• Streamlit".
|
| 9 |
+
page_icon=img, # String, anything supported by st.image, or None.
|
| 10 |
+
)
|
| 11 |
+
col_1, col_2, col_3, col_4, col_5, = st.columns(5)
|
| 12 |
+
with col_3:
|
| 13 |
+
st.image("https://i.ibb.co/Yd42K98/LogoVPI.png", width=250)
|
| 14 |
+
st.header("Welcome to VPI-MLOGS!")
|
backup/081222/Antuns/prediction_LGBM.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
|
| 3 |
+
def Prediction_LGBM(trained_models:list=None, data:pd.DataFrame=None, feature_names:list=None):
|
| 4 |
+
"""
|
| 5 |
+
mode: "predict", "predict_proba"
|
| 6 |
+
"""
|
| 7 |
+
data_copy = data.copy()
|
| 8 |
+
# if mode == "predict":
|
| 9 |
+
# for i, model in enumerate(trained_models):
|
| 10 |
+
# y_preds = model.predict(data_copy[feature_names])
|
| 11 |
+
# data_copy[f"model_{i}"] = y_preds
|
| 12 |
+
#
|
| 13 |
+
# else:
|
| 14 |
+
for i, model in enumerate(trained_models):
|
| 15 |
+
y_preds = model.predict(data_copy[feature_names])
|
| 16 |
+
data_copy[f"model_{i}"] = y_preds
|
| 17 |
+
|
| 18 |
+
return data_copy
|
| 19 |
+
|
| 20 |
+
if __name__ == '__main__':
|
| 21 |
+
Prediction_LGBM()
|
backup/081222/Homepage.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
from Antuns.page_setting import page_intro
|
| 3 |
+
|
| 4 |
+
#Streamlit dashboard------------------------------------------------------------------------------------------
|
| 5 |
+
page_intro()
|
| 6 |
+
st.sidebar.success("")
|
| 7 |
+
st.markdown("""
|
| 8 |
+
:flag-vn:
|
| 9 |
+
"""
|
| 10 |
+
,unsafe_allow_html=False)
|
backup/081222/models/LGBM_20221125.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:02b0cb118e7b9a39b3003abb0701c7be91f1acb1b0df30635a93a149a4968049
|
| 3 |
+
size 14032845
|
backup/081222/models/LightGBM_0.45.pbz2
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e960d2e933f4884dc0df6a55c33819807ae4beb86a35489685dd209a7699aeab
|
| 3 |
+
size 1936897
|
backup/model.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
data/LogoVPI.png
ADDED
|
data/all_file_merged_updated_with_All_geometry.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:58c41e72f17af5c6235cbd79ec9700d539c96303d998b0f33018bfaaad4402b1
|
| 3 |
+
size 12897889
|
data/merged/Training_data.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
data/merged/merged_df.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
mLogsFunctions/__init__.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .dataloading import *
|
| 2 |
+
from .dataprocessing import *
|
| 3 |
+
from .viewCurves import *
|
| 4 |
+
from .rmOutliers import *
|
| 5 |
+
from .lightGBMPred import *
|
| 6 |
+
|
| 7 |
+
__all__ = ['csv_uploader',
|
| 8 |
+
'tweak_data',
|
| 9 |
+
'columns_list',
|
| 10 |
+
'well_filter',
|
| 11 |
+
'view_curves',
|
| 12 |
+
'rmOutliers',
|
| 13 |
+
'Prediction_LGBM',
|
| 14 |
+
|
| 15 |
+
#FX
|
| 16 |
+
'upload_csv',
|
| 17 |
+
'selection_info',
|
| 18 |
+
'interval_define',
|
| 19 |
+
'make_selection',
|
| 20 |
+
'bar_plot',
|
| 21 |
+
'curve_plot',
|
| 22 |
+
'missing_bar',
|
| 23 |
+
'missing_box',
|
| 24 |
+
'hist_line_plot',
|
| 25 |
+
'crossplot',
|
| 26 |
+
'pairplot',
|
| 27 |
+
'heatmap',
|
| 28 |
+
'plotly_3d',
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
]
|
mLogsFunctions/__pycache__/__init__.cpython-39.pyc
ADDED
|
Binary file (541 Bytes). View file
|
|
|
mLogsFunctions/__pycache__/dataloading.cpython-39.pyc
ADDED
|
Binary file (1.2 kB). View file
|
|
|
mLogsFunctions/__pycache__/dataprocessing.cpython-39.pyc
ADDED
|
Binary file (647 Bytes). View file
|
|
|
mLogsFunctions/__pycache__/fx.cpython-39.pyc
ADDED
|
Binary file (7.84 kB). View file
|
|
|
mLogsFunctions/__pycache__/lightGBMPred.cpython-39.pyc
ADDED
|
Binary file (571 Bytes). View file
|
|
|
mLogsFunctions/__pycache__/rmOutliers.cpython-39.pyc
ADDED
|
Binary file (4.17 kB). View file
|
|
|
mLogsFunctions/__pycache__/viewCurves.cpython-39.pyc
ADDED
|
Binary file (11.3 kB). View file
|
|
|
mLogsFunctions/dataloading.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import streamlit as st
|
| 3 |
+
|
| 4 |
+
def csv_uploader(label:str='', type:str='csv'):
|
| 5 |
+
uploaded_file = st.file_uploader(label=label, type=type)
|
| 6 |
+
loading_data = None
|
| 7 |
+
if uploaded_file is not None:
|
| 8 |
+
if type == 'csv':
|
| 9 |
+
loading_data = pd.read_csv(uploaded_file, na_values=-9999)
|
| 10 |
+
return loading_data
|
| 11 |
+
|
| 12 |
+
@st.cache_data
|
| 13 |
+
def tweak_data(data, reindex:bool=True, resample:bool=False, max_number:int=5000):
|
| 14 |
+
if data is not None:
|
| 15 |
+
data = data.rename(str.upper, axis='columns')
|
| 16 |
+
if len(data) > max_number and resample:
|
| 17 |
+
data = data.sample(max_number, random_state=42)
|
| 18 |
+
if set(["DEPTH", 'WELL']).issubset(data.columns.unique()):
|
| 19 |
+
data.assign(
|
| 20 |
+
DEPTH=data.DEPTH.astype('float64'),
|
| 21 |
+
WELL=data.WELL.astype("string"),
|
| 22 |
+
)
|
| 23 |
+
if "FRACTURE_ZONE" in data.columns.unique():
|
| 24 |
+
data = data.rename(columns={'FRACTURE_ZONE':'FRACTUREZONE'})
|
| 25 |
+
if "FRACTURE INTENSITY" in data.columns.unique():
|
| 26 |
+
data = data.rename(columns={'FRACTURE INTENSITY':'FRACTURE_INTENSITY'})
|
| 27 |
+
# if "FRACTUREZONE" in data.columns.unique():
|
| 28 |
+
# data = data.reset_index(drop=True).drop(["FRACTUREZONE"], axis=1)
|
| 29 |
+
if reindex:
|
| 30 |
+
data = data.reindex(sorted(data.columns), axis=1) #Reindex and sort columns name
|
| 31 |
+
return data
|
| 32 |
+
|
mLogsFunctions/dataprocessing.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import streamlit as st
|
| 3 |
+
|
| 4 |
+
def columns_list(data:pd.DataFrame, no_depth:bool=None, no_well:bool=None):
|
| 5 |
+
columns_list = list(data.columns.unique())
|
| 6 |
+
columns_list.sort()
|
| 7 |
+
if "DEPTH" in columns_list and no_depth == True:
|
| 8 |
+
columns_list.remove("DEPTH")
|
| 9 |
+
if "WELL" in columns_list and no_well == True:
|
| 10 |
+
columns_list.remove("WELL")
|
| 11 |
+
return columns_list
|
| 12 |
+
|
| 13 |
+
def well_filter(df, well_name):
|
| 14 |
+
return df[df.WELL == well_name]
|
mLogsFunctions/fx.py
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import numpy as np
|
| 3 |
+
|
| 4 |
+
# import matplotlib.pyplot as plt
|
| 5 |
+
import seaborn as sns
|
| 6 |
+
import plotly.express as px
|
| 7 |
+
|
| 8 |
+
import altair as alt
|
| 9 |
+
|
| 10 |
+
import streamlit as st
|
| 11 |
+
import streamlit_nested_layout
|
| 12 |
+
from streamlit_vega_lite import altair_component
|
| 13 |
+
|
| 14 |
+
from mLogsFunctions import *
|
| 15 |
+
|
| 16 |
+
#LOADING DATA------------------------------------------------------------------------------------------
|
| 17 |
+
def upload_csv():
|
| 18 |
+
df = None
|
| 19 |
+
uploaded_file = st.file_uploader(label='Upload *csv file from your drive! Choose a file:', type='csv')
|
| 20 |
+
if uploaded_file is not None:
|
| 21 |
+
df = pd.read_csv(uploaded_file, na_values=-9999)
|
| 22 |
+
st.success("Loading finished!")
|
| 23 |
+
st.write('---')
|
| 24 |
+
return df
|
| 25 |
+
|
| 26 |
+
#PLOTTING------------------------------------------------------------------------------------------
|
| 27 |
+
# Store the initial value of widgets in session state
|
| 28 |
+
def selection_info(df, method, option_w, option_x, option_y, option_c):
|
| 29 |
+
if "method" not in st.session_state:
|
| 30 |
+
st.session_state.method:str = "Single Well"
|
| 31 |
+
st.session_state.option_w:str = "15-1-SNN-3P"
|
| 32 |
+
st.session_state.option_x:str = "RHOB"
|
| 33 |
+
st.session_state.option_y:str = "DTC"
|
| 34 |
+
st.session_state.option_c:str = "WELL"
|
| 35 |
+
well_names = np.sort(df.WELL.unique())
|
| 36 |
+
st.radio("",
|
| 37 |
+
key=method,
|
| 38 |
+
options=["All Wells", "Single Well"],)
|
| 39 |
+
st.radio(
|
| 40 |
+
"WELL",
|
| 41 |
+
key=option_w,
|
| 42 |
+
options=well_names,)
|
| 43 |
+
st.selectbox(
|
| 44 |
+
"X Axis",
|
| 45 |
+
key=option_x,
|
| 46 |
+
options=(df.columns.sort_values().str.upper().drop(["WELL", "DEPTH"])),)
|
| 47 |
+
st.selectbox(
|
| 48 |
+
"Y Axis",
|
| 49 |
+
key=option_y,
|
| 50 |
+
options=(df.columns.sort_values().str.upper().drop(["WELL", "DEPTH"])),)
|
| 51 |
+
st.selectbox(
|
| 52 |
+
"Color Axis",
|
| 53 |
+
key=option_c,
|
| 54 |
+
options=df.columns.sort_values().str.upper())
|
| 55 |
+
return st.session_state
|
| 56 |
+
|
| 57 |
+
#Interactive Charts-----------------------------------------------------------------------
|
| 58 |
+
@st.cache_resource
|
| 59 |
+
def interval_define():
|
| 60 |
+
return alt.selection_interval()
|
| 61 |
+
|
| 62 |
+
@st.cache_resource
|
| 63 |
+
def make_selection(df, _interval, option_x, option_y, option_c):
|
| 64 |
+
def c_(df, _interval, option_x, option_y, x_log:str="linear", y_log:str="linear"):
|
| 65 |
+
return alt.Chart(df,
|
| 66 |
+
title="Crossplot "+option_x+" vs "+option_y+"",
|
| 67 |
+
).mark_point().encode(
|
| 68 |
+
x = alt.X(option_x.upper(),
|
| 69 |
+
axis=alt.Axis(title=option_x),
|
| 70 |
+
scale= alt.Scale(zero=False, type=x_log
|
| 71 |
+
)
|
| 72 |
+
),
|
| 73 |
+
y = alt.Y(option_y.upper(),
|
| 74 |
+
axis=alt.Axis(title=option_y),
|
| 75 |
+
scale=alt.Scale(zero=False,type=y_log
|
| 76 |
+
)
|
| 77 |
+
),
|
| 78 |
+
color=alt.condition(_interval, option_c, alt.value('lightgray')),
|
| 79 |
+
).properties(
|
| 80 |
+
selection=_interval,
|
| 81 |
+
height=570,
|
| 82 |
+
width=600)#.transform_regression(option_x.upper(), option_y.upper()).mark_line()
|
| 83 |
+
|
| 84 |
+
if option_x in ["LLD", "LLS"]:
|
| 85 |
+
x_log = "log"
|
| 86 |
+
else:
|
| 87 |
+
x_log = "linear"
|
| 88 |
+
|
| 89 |
+
if option_y in ["LLD", "LLS"]:
|
| 90 |
+
y_log = "log"
|
| 91 |
+
else:
|
| 92 |
+
y_log = "linear"
|
| 93 |
+
return c_(df, _interval, option_x, option_y, x_log, y_log)
|
| 94 |
+
|
| 95 |
+
#Histogram-----------------------------------------------------------------------
|
| 96 |
+
def bar_plot(data, option_x):
|
| 97 |
+
def c_(data, option_x, _log):
|
| 98 |
+
return alt.Chart(title="Histogram of "+option_x+"",
|
| 99 |
+
data=data
|
| 100 |
+
).mark_bar().encode(
|
| 101 |
+
x = alt.X(option_x.upper(),
|
| 102 |
+
bin=alt.Bin(maxbins=30),
|
| 103 |
+
axis=alt.Axis(title=option_x),
|
| 104 |
+
scale=alt.Scale(zero=False)
|
| 105 |
+
),
|
| 106 |
+
y = alt.Y('count()',
|
| 107 |
+
axis=alt.Axis(title='Number of Values'),
|
| 108 |
+
scale=alt.Scale(zero=False, type=_log),
|
| 109 |
+
),
|
| 110 |
+
color = alt.Color('WELL', legend=None
|
| 111 |
+
)
|
| 112 |
+
).properties(
|
| 113 |
+
height=250,
|
| 114 |
+
width=250
|
| 115 |
+
)
|
| 116 |
+
if option_x in ["LLD", "LLS"]:
|
| 117 |
+
return c_(data, option_x, "symlog")
|
| 118 |
+
else:
|
| 119 |
+
return c_(data, option_x, "linear")
|
| 120 |
+
|
| 121 |
+
#Curve View-----------------------------------------------------------------------
|
| 122 |
+
def curve_plot(data,filted_data, x_column):
|
| 123 |
+
def c_(data,filted_data, x_column, _log):
|
| 124 |
+
color_codes = {"GR":"lime",
|
| 125 |
+
"LLD":"red",
|
| 126 |
+
"LLS":"dodgerblue",
|
| 127 |
+
"NPHI":"blue",
|
| 128 |
+
"RHOB":"red",
|
| 129 |
+
"DTC":"red",
|
| 130 |
+
"DTS":"magenta",
|
| 131 |
+
"FRACTURE_ZONE":"lightcoral",
|
| 132 |
+
"FRACTURE_ZONE_PRED":"lightgreen"
|
| 133 |
+
}
|
| 134 |
+
if x_column in color_codes.keys():
|
| 135 |
+
color_ = color_codes[x_column]
|
| 136 |
+
else:
|
| 137 |
+
color_ = "blue"
|
| 138 |
+
return alt.Chart(data
|
| 139 |
+
).mark_line(size=1,
|
| 140 |
+
orient='horizontal',
|
| 141 |
+
color=color_,
|
| 142 |
+
point=alt.OverlayMarkDef(color="", size=1) #Show raw points
|
| 143 |
+
).encode(
|
| 144 |
+
x=alt.X(x_column.upper(),
|
| 145 |
+
scale=alt.Scale(zero=False, type=_log),
|
| 146 |
+
axis=alt.Axis(title=x_column.upper(),
|
| 147 |
+
titleAnchor='middle',
|
| 148 |
+
orient='top',
|
| 149 |
+
labelAngle=0,
|
| 150 |
+
titleColor=color_,
|
| 151 |
+
labelColor=color_,
|
| 152 |
+
tickColor=color_,
|
| 153 |
+
)
|
| 154 |
+
),
|
| 155 |
+
y=alt.Y('DEPTH',
|
| 156 |
+
scale=alt.Scale(zero=False,
|
| 157 |
+
reverse=True,
|
| 158 |
+
),
|
| 159 |
+
axis=alt.Axis(title=None,
|
| 160 |
+
labelColor=color_,
|
| 161 |
+
tickColor=color_,
|
| 162 |
+
)
|
| 163 |
+
)
|
| 164 |
+
).properties(height=500,
|
| 165 |
+
width=129
|
| 166 |
+
)
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
if x_column in ["LLD", "LLS"]:
|
| 170 |
+
curve = c_(data,filted_data, x_column, "log")
|
| 171 |
+
else:
|
| 172 |
+
curve = c_(data,filted_data, x_column, "linear")
|
| 173 |
+
|
| 174 |
+
if filted_data is not None:
|
| 175 |
+
point_plot = alt.Chart(filted_data).mark_circle(size=20,
|
| 176 |
+
color='red',
|
| 177 |
+
opacity=1
|
| 178 |
+
).encode(
|
| 179 |
+
x=x_column,
|
| 180 |
+
y='DEPTH'
|
| 181 |
+
)
|
| 182 |
+
return curve + point_plot
|
| 183 |
+
else:
|
| 184 |
+
return curve
|
| 185 |
+
# import altair as alt
|
| 186 |
+
# def curve_plot(data, filted_data, x_column):
|
| 187 |
+
# def c_(data, filted_data, x_column, _log):
|
| 188 |
+
# color_codes = {
|
| 189 |
+
# "GR": "lime",
|
| 190 |
+
# "LLD": "red",
|
| 191 |
+
# "LLS": "dodgerblue",
|
| 192 |
+
# "NPHI": "blue",
|
| 193 |
+
# "RHOB": "red",
|
| 194 |
+
# "DTC": "red",
|
| 195 |
+
# "DTS": "magenta",
|
| 196 |
+
# "FRACTURE_ZONE": "lightcoral",
|
| 197 |
+
# "FRACTURE_ZONE_PRED": "lightgreen"
|
| 198 |
+
# }
|
| 199 |
+
# if x_column in color_codes.keys():
|
| 200 |
+
# color_ = color_codes[x_column]
|
| 201 |
+
# else:
|
| 202 |
+
# color_ = "blue"
|
| 203 |
+
# return alt.Chart(data).mark_line(size=1, orient='horizontal', color=color_, point=alt.OverlayMarkDef(color="", size=1)).encode(
|
| 204 |
+
# y=alt.X(x_column.upper(),
|
| 205 |
+
# scale=alt.Scale(zero=False, type=_log),
|
| 206 |
+
# axis=alt.Axis(title=x_column.upper(),
|
| 207 |
+
# titleAnchor='middle',
|
| 208 |
+
# orient='top',
|
| 209 |
+
# labelAngle=0,
|
| 210 |
+
# titleColor=color_,
|
| 211 |
+
# labelColor=color_,
|
| 212 |
+
# tickColor=color_,
|
| 213 |
+
# )
|
| 214 |
+
# ),
|
| 215 |
+
# x=alt.Y('DEPTH',
|
| 216 |
+
# scale=alt.Scale(zero=False, reverse=True),
|
| 217 |
+
# axis=alt.Axis(title=None, labelColor=color_, tickColor=color_))
|
| 218 |
+
# ).properties(
|
| 219 |
+
# height=500,
|
| 220 |
+
# width=700
|
| 221 |
+
# )
|
| 222 |
+
|
| 223 |
+
# if x_column in ["LLD", "LLS"]:
|
| 224 |
+
# curve = c_(data, filted_data, x_column, "log")
|
| 225 |
+
# else:
|
| 226 |
+
# curve = c_(data, filted_data, x_column, "linear")
|
| 227 |
+
|
| 228 |
+
# if filted_data is not None:
|
| 229 |
+
# point_plot = alt.Chart(filted_data).mark_circle(size=20, color='red', opacity=1).encode(
|
| 230 |
+
# y=alt.X(x_column, scale=alt.Scale(zero=False)),
|
| 231 |
+
# x=alt.Y('DEPTH', scale=alt.Scale(zero=False, reverse=True))
|
| 232 |
+
# )
|
| 233 |
+
# return (curve + point_plot).resolve_scale(y='shared')
|
| 234 |
+
# else:
|
| 235 |
+
# return curve
|
| 236 |
+
|
| 237 |
+
|
| 238 |
+
#MissingBar-----------------------------------------------------------------------
|
| 239 |
+
def missing_bar(data, x_title):
|
| 240 |
+
return alt.Chart(data).mark_bar().encode(
|
| 241 |
+
x=alt.X('Columns', sort='-y', title=x_title),
|
| 242 |
+
y='Count missing (%)',
|
| 243 |
+
color=alt.condition(
|
| 244 |
+
alt.datum['Count missing (%)'] >10, # If count missing is > 10%, returns True,
|
| 245 |
+
alt.value('orange'), # which sets the bar orange.
|
| 246 |
+
alt.value('steelblue') # And if it's not true it sets the bar steelblue.
|
| 247 |
+
)
|
| 248 |
+
).properties(
|
| 249 |
+
width=500,
|
| 250 |
+
height=250
|
| 251 |
+
).configure_axis(
|
| 252 |
+
grid=False
|
| 253 |
+
)
|
| 254 |
+
#BoxPLot-----------------------------------------------------------------------
|
| 255 |
+
def missing_box(data, curve):
|
| 256 |
+
if curve in ["LLD", "LLS"]:
|
| 257 |
+
return alt.Chart(data).mark_boxplot(extent='min-max').encode(
|
| 258 |
+
x=alt.X('WELL:O', title=None,
|
| 259 |
+
),
|
| 260 |
+
y=alt.Y(f'{curve}:Q', title=curve,scale=alt.Scale(zero=False, type="log")
|
| 261 |
+
),
|
| 262 |
+
color='WELL:N'
|
| 263 |
+
).properties(
|
| 264 |
+
width=500,
|
| 265 |
+
height=300
|
| 266 |
+
)
|
| 267 |
+
else:
|
| 268 |
+
return alt.Chart(data).mark_boxplot(extent='min-max').encode(
|
| 269 |
+
x=alt.X('WELL:O', title=None
|
| 270 |
+
),
|
| 271 |
+
y=alt.Y(f'{curve}:Q', title=curve,scale=alt.Scale(zero=False)
|
| 272 |
+
),
|
| 273 |
+
color='WELL:N'
|
| 274 |
+
).properties(
|
| 275 |
+
width=500,
|
| 276 |
+
height=300
|
| 277 |
+
)
|
| 278 |
+
#Histogram Line-----------------------------------------------------------------------
|
| 279 |
+
def hist_line_plot(data, curve):
|
| 280 |
+
st.caption(f"Histogram of {curve}")
|
| 281 |
+
if curve in ["LLD", "LLS"]:
|
| 282 |
+
fig = sns.displot(data, x=curve, hue="WELL", kind="kde", height=5,aspect=1.2, log_scale=True)
|
| 283 |
+
fig.set(ylabel="Values")
|
| 284 |
+
st.pyplot(fig)
|
| 285 |
+
else:
|
| 286 |
+
fig = sns.displot(data, x=curve, hue="WELL", kind="kde", height=5,aspect=1.2)
|
| 287 |
+
fig.set(ylabel="Values")
|
| 288 |
+
st.pyplot(fig)
|
| 289 |
+
#CrossPlot-----------------------------------------------------------------------
|
| 290 |
+
def crossplot(data, x_curve, y_curve):
|
| 291 |
+
fig = sns.jointplot(data=data, x=x_curve, y=y_curve, hue="WELL")
|
| 292 |
+
if x_curve in ["LLD", "LLS"]:
|
| 293 |
+
fig.ax_joint.set_xscale('log')
|
| 294 |
+
fig.ax_marg_x.set_xscale('log')
|
| 295 |
+
if y_curve in ["LLD", "LLS"]:
|
| 296 |
+
fig.ax_joint.set_yscale('log')
|
| 297 |
+
fig.ax_marg_y.set_yscale('log')
|
| 298 |
+
st.pyplot(fig)
|
| 299 |
+
#PairPlot-----------------------------------------------------------------------
|
| 300 |
+
def pairplot(data, rows, cols,color_):
|
| 301 |
+
return alt.Chart(data).mark_circle().encode(
|
| 302 |
+
alt.X(alt.repeat("column"), type='quantitative', scale=alt.Scale(zero=False)),
|
| 303 |
+
alt.Y(alt.repeat("row"), type='quantitative', scale=alt.Scale(zero=False)),
|
| 304 |
+
color=color_
|
| 305 |
+
).properties(
|
| 306 |
+
width=100,
|
| 307 |
+
height=100
|
| 308 |
+
).repeat(
|
| 309 |
+
row = rows,
|
| 310 |
+
column = cols
|
| 311 |
+
).configure_axis(
|
| 312 |
+
grid=False
|
| 313 |
+
)
|
| 314 |
+
#Heatmap----------------------------------------------------------------
|
| 315 |
+
def heatmap(df):
|
| 316 |
+
fig = sns.heatmap(df, annot=True)
|
| 317 |
+
st.pyplot(fig)
|
| 318 |
+
#Heatmap----------------------------------------------------------------
|
| 319 |
+
def plotly_3d(data, x, y, z, color, size, symbol, log_x, log_y, log_z):
|
| 320 |
+
#Data slicer
|
| 321 |
+
curvs_ = columns_list(data, no_well=True)
|
| 322 |
+
def slicer_(data, sli_key, val_key,):
|
| 323 |
+
slicer1_, slicer2_ = st.columns([4, 6])
|
| 324 |
+
# sli=curvs_[0]
|
| 325 |
+
with slicer1_:
|
| 326 |
+
sli = st.selectbox("Data slicer", key=sli_key, options=curvs_)
|
| 327 |
+
with slicer2_:
|
| 328 |
+
values = st.slider('Select a range of values',
|
| 329 |
+
min_value = float(data[sli].min()),
|
| 330 |
+
max_value = float(data[sli].max()),
|
| 331 |
+
value=(float(data[sli].min()), float(data[sli].max())),
|
| 332 |
+
key=val_key,
|
| 333 |
+
)
|
| 334 |
+
data = data.query(f"{sli} >= {values[0]} and {sli} <= {values[1]}")
|
| 335 |
+
return data
|
| 336 |
+
c1, c2, c3 = st.columns(3)
|
| 337 |
+
with c1:
|
| 338 |
+
data = slicer_(data, "slicer_1", "sli1_value")
|
| 339 |
+
with c2:
|
| 340 |
+
data = slicer_(data, "slicer_2", "sli2_value")
|
| 341 |
+
with c3:
|
| 342 |
+
data = slicer_(data, "slicer_3", "sli3_value")
|
| 343 |
+
|
| 344 |
+
fig = px.scatter_3d(data, x=x,
|
| 345 |
+
y=y,
|
| 346 |
+
z=z,
|
| 347 |
+
color=color,
|
| 348 |
+
size=size,
|
| 349 |
+
size_max=18,
|
| 350 |
+
symbol=symbol,
|
| 351 |
+
opacity=0.7,
|
| 352 |
+
log_x=log_x,
|
| 353 |
+
log_y=log_y,
|
| 354 |
+
log_z = log_z,
|
| 355 |
+
width=1000, height=700,
|
| 356 |
+
color_continuous_scale="blugrn")
|
| 357 |
+
fig.update_layout(margin=dict(l=0, r=0, b=0, t=0), #tight layout
|
| 358 |
+
# paper_bgcolor="LightSteelBlue"
|
| 359 |
+
template="none")
|
| 360 |
+
st.plotly_chart(fig)
|
mLogsFunctions/lightGBMPred.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
|
| 3 |
+
def Prediction_LGBM(trained_models:list=None, data:pd.DataFrame=None, feature_names:list=None):
|
| 4 |
+
"""
|
| 5 |
+
mode: "predict", "predict_proba"
|
| 6 |
+
"""
|
| 7 |
+
data_copy = data.copy()
|
| 8 |
+
# if mode == "predict":
|
| 9 |
+
# for i, model in enumerate(trained_models):
|
| 10 |
+
# y_preds = model.predict(data_copy[feature_names])
|
| 11 |
+
# data_copy[f"model_{i}"] = y_preds
|
| 12 |
+
#
|
| 13 |
+
# else:
|
| 14 |
+
for i, model in enumerate(trained_models):
|
| 15 |
+
y_preds = model.predict(data_copy[feature_names])
|
| 16 |
+
data_copy[f"model_{i}"] = y_preds
|
| 17 |
+
|
| 18 |
+
return data_copy
|
| 19 |
+
|
| 20 |
+
if __name__ == '__main__':
|
| 21 |
+
Prediction_LGBM()
|
mLogsFunctions/rmOutliers.py
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import streamlit as st
|
| 4 |
+
import altair as alt
|
| 5 |
+
from streamlit_vega_lite import altair_component
|
| 6 |
+
|
| 7 |
+
from .fx import *
|
| 8 |
+
from mLogsFunctions import *
|
| 9 |
+
|
| 10 |
+
def rmOutliers(df):
|
| 11 |
+
_o1, _o2 = st.columns([1,8])
|
| 12 |
+
with _o1:
|
| 13 |
+
st.session_state = selection_info(df,"method", "option_w", "option_x", "option_y", "option_c")
|
| 14 |
+
|
| 15 |
+
#Crossplot and bar plot-----------------------------------------------------------------------
|
| 16 |
+
with _o2:
|
| 17 |
+
def rm_outliers(data):
|
| 18 |
+
interval = interval_define()
|
| 19 |
+
col21, col22 = st.columns(2)
|
| 20 |
+
with col21:
|
| 21 |
+
selected_points = altair_component(make_selection(data,
|
| 22 |
+
interval,
|
| 23 |
+
st.session_state.option_x,
|
| 24 |
+
st.session_state.option_y,
|
| 25 |
+
st.session_state.option_c,
|
| 26 |
+
)
|
| 27 |
+
)
|
| 28 |
+
if len(selected_points) > 0:
|
| 29 |
+
del[selected_points['name']]
|
| 30 |
+
|
| 31 |
+
with col22:
|
| 32 |
+
selected_df = None
|
| 33 |
+
if len(selected_points) != 0:
|
| 34 |
+
query = ' & '.join(
|
| 35 |
+
f'{crange[0]} <= `{col}` <= {crange[1]}'
|
| 36 |
+
for col, crange in selected_points.items())
|
| 37 |
+
selected_df = data.query(query)
|
| 38 |
+
st.write(f"Total selected points: {len(selected_df)}")
|
| 39 |
+
st.dataframe(selected_df, width=800, height=260,use_container_width=False)
|
| 40 |
+
else:
|
| 41 |
+
st.write("No Selection")
|
| 42 |
+
|
| 43 |
+
if selected_df is not None:
|
| 44 |
+
st.write("Histogram of selected data:")
|
| 45 |
+
histogram_x = bar_plot(selected_df, st.session_state.option_x)
|
| 46 |
+
histogram_y = bar_plot(selected_df, st.session_state.option_y)
|
| 47 |
+
st.write(alt.hconcat(histogram_x,histogram_y))
|
| 48 |
+
else:
|
| 49 |
+
st.write("Histogram of entire data:")
|
| 50 |
+
histogram_x = bar_plot(data, st.session_state.option_x)
|
| 51 |
+
histogram_y = bar_plot(data, st.session_state.option_y)
|
| 52 |
+
st.write(alt.hconcat(histogram_x,histogram_y))
|
| 53 |
+
|
| 54 |
+
#Outlier Removal-----------------------------------------------------------------------
|
| 55 |
+
st.write('---')
|
| 56 |
+
df_nomarlized = data.copy()
|
| 57 |
+
curve_editting = st.selectbox("Select curve to edit:",
|
| 58 |
+
key="selected_curve",
|
| 59 |
+
options=columns_list(data, no_depth=True, no_well=True),
|
| 60 |
+
)
|
| 61 |
+
n_value = int(st.text_input("Number of rows for Mean calculation ", "5"))
|
| 62 |
+
|
| 63 |
+
def normalize_outlier(df_nomarlized, selected_df, curve, n_value):
|
| 64 |
+
n=n_value//2
|
| 65 |
+
for i in selected_df.index:
|
| 66 |
+
df_nomarlized.loc[[i],curve.upper()] = df_nomarlized.loc[i-n:i+n,curve.upper()].mean()
|
| 67 |
+
return df_nomarlized
|
| 68 |
+
def remove_data_point(df_nomarlized, selected_df, curve):
|
| 69 |
+
for i in selected_df.index:
|
| 70 |
+
df_nomarlized[i, curve] = 0 #ERROR ALARM!!!!
|
| 71 |
+
# df_nomarlized = df_nomarlized.drop(index=i) #ERROR ALARM!!!!
|
| 72 |
+
return df_nomarlized
|
| 73 |
+
|
| 74 |
+
if st.button("Outliers Processing"):
|
| 75 |
+
st.session_state.fdata = normalize_outlier(df_nomarlized, selected_df, curve_editting, n_value)
|
| 76 |
+
_well = "".join((st.session_state.fdata.WELL.unique()).tolist())
|
| 77 |
+
st.session_state.loc_data = pd.concat([df[(df["WELL"] != _well)],st.session_state.fdata], axis=0)
|
| 78 |
+
selected_df = None
|
| 79 |
+
if st.button("Remove"):
|
| 80 |
+
st.session_state.fdata = remove_data_point(df_nomarlized, selected_df, curve_editting)
|
| 81 |
+
_well = "".join((st.session_state.fdata.WELL.unique()).tolist())
|
| 82 |
+
st.write(_well)
|
| 83 |
+
st.write(type(_well))
|
| 84 |
+
st.session_state.loc_data = pd.concat([df[(df["WELL"] != _well)],st.session_state.fdata], axis=0)
|
| 85 |
+
selected_df = None
|
| 86 |
+
|
| 87 |
+
#Curve View-----------------------------------------------------------------------
|
| 88 |
+
def plt_curs(data, option_w):
|
| 89 |
+
data_plt = data[data["WELL"] == option_w]
|
| 90 |
+
if plotting_curves != []:
|
| 91 |
+
for i, c in enumerate(plotting_curves):
|
| 92 |
+
charts_dict[i] = curve_plot(data=data_plt,filted_data=selected_df, x_column=c)
|
| 93 |
+
|
| 94 |
+
# with col2:
|
| 95 |
+
charts_dict={}
|
| 96 |
+
plotting_curves = st.multiselect("Select curves to plot:", key="curvs_plt", options=columns_list(data, no_depth=True, no_well=True))
|
| 97 |
+
|
| 98 |
+
if st.session_state.option_w is not None:
|
| 99 |
+
if 'loc_data' not in st.session_state:
|
| 100 |
+
plt_curs(df_nomarlized, st.session_state.option_w)
|
| 101 |
+
else:
|
| 102 |
+
plt_curs(st.session_state.loc_data, st.session_state.option_w)
|
| 103 |
+
|
| 104 |
+
#Show Curve-----------------------------------------------------------------------
|
| 105 |
+
st.write(alt.concat(*charts_dict.values()).configure(autosize='fit'))#.configure_concat(spacing=0))
|
| 106 |
+
|
| 107 |
+
#------------------------
|
| 108 |
+
def check_method(df):
|
| 109 |
+
if st.session_state.method == "Single Well":
|
| 110 |
+
data = df[df.WELL == st.session_state.option_w]
|
| 111 |
+
data = data.sort_values(by=['DEPTH'])
|
| 112 |
+
data = data.reset_index().drop(["index"], axis=1)
|
| 113 |
+
else:
|
| 114 |
+
data = df
|
| 115 |
+
return data
|
| 116 |
+
#------------------------
|
| 117 |
+
|
| 118 |
+
if 'loc_data' not in st.session_state:
|
| 119 |
+
data = check_method(df)
|
| 120 |
+
else:
|
| 121 |
+
data = check_method(st.session_state.loc_data)
|
| 122 |
+
|
| 123 |
+
rm_outliers(data)
|
| 124 |
+
|
| 125 |
+
# # Download --------------------------------------------------------------
|
| 126 |
+
st.write('---')
|
| 127 |
+
st.write("Download final result to csv file")
|
| 128 |
+
if "loc_data" not in st.session_state:
|
| 129 |
+
saving_df = df
|
| 130 |
+
else:
|
| 131 |
+
saving_df = st.session_state.loc_data
|
| 132 |
+
st.download_button(label='Download',
|
| 133 |
+
data = saving_df.to_csv(),
|
| 134 |
+
file_name='Query_data.csv',
|
| 135 |
+
mime='text/csv')
|
mLogsFunctions/viewCurves.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import streamlit as st
|
| 3 |
+
import plotly.graph_objects as go
|
| 4 |
+
from plotly.subplots import make_subplots
|
| 5 |
+
import json
|
| 6 |
+
#Curve View--------------------------------------------------------------------------------------------------------------
|
| 7 |
+
#OPERATIONS--------------------------------------------------------------------------------------------------------------
|
| 8 |
+
#Make subplots layout
|
| 9 |
+
def view_curves(data:pd.DataFrame=None, curves:list=[], log:list=[],
|
| 10 |
+
depth_col:str='DEPTH', new_color:dict={}, new_unit:dict={},
|
| 11 |
+
):
|
| 12 |
+
#FUNCTIONS DESIGNING-------------------------------------------------------------------------------------------------
|
| 13 |
+
#Function of Plotting single curve
|
| 14 |
+
def add_trace(curv:str=None, color:str='#38a2e8', xaxis:str='x1', unit:str=None, id_subplt:int=1, log:list=None):
|
| 15 |
+
fig.add_trace(go.Scattergl(y=data[depth_col], x=data[curv], name=curv, mode="lines", line=dict(color=color, width=1.), xaxis=xaxis),1 ,id_subplt)\
|
| 16 |
+
.update_xaxes(title_text=f'{curv} ({unit})', row=1, col=id_subplt, color=color,
|
| 17 |
+
tickcolor=color, minor=dict(tickcolor=color), tickfont=dict(color=color))
|
| 18 |
+
if curv in log:
|
| 19 |
+
fig.update_xaxes(type='log', row=1, col=id_subplt)
|
| 20 |
+
|
| 21 |
+
#Function to update X-Axis parameters
|
| 22 |
+
def update_xaxes(type:str=None):
|
| 23 |
+
fig.update_xaxes(
|
| 24 |
+
title_font=dict(size=16, family='Arial'),
|
| 25 |
+
title_standoff = 0, side='top', nticks=5, fixedrange=True,
|
| 26 |
+
ticks="inside", tickwidth=1, ticklen=8, ticklabelstep=1,
|
| 27 |
+
tickfont=dict(family="Arial", size=12),
|
| 28 |
+
minor_ticks="inside", minor=dict(ticklen=4, showgrid=True),
|
| 29 |
+
showline=True, linewidth=1, linecolor='black', mirror=True,
|
| 30 |
+
showgrid=True, gridwidth=1, gridcolor='#d9d9d9',
|
| 31 |
+
showspikes=True, spikecolor="#8d9199", spikesnap="hovered data", spikemode="across", spikethickness=1, spikedash='solid',
|
| 32 |
+
)
|
| 33 |
+
if type is not None:
|
| 34 |
+
fig.update_xaxes(type=type)
|
| 35 |
+
|
| 36 |
+
#Function to update Y-Axis parameters
|
| 37 |
+
def update_yaxes(type:str=None):
|
| 38 |
+
fig.update_yaxes(
|
| 39 |
+
# title_font=dict(size=18, family='Arial', color='#393533'),
|
| 40 |
+
# matches='y'
|
| 41 |
+
title_standoff = 0,
|
| 42 |
+
autorange="reversed",
|
| 43 |
+
nticks=10,
|
| 44 |
+
ticks="outside", tickwidth=1, tickcolor='black', ticklen=8, ticklabelstep=1,
|
| 45 |
+
tickfont=dict(family="Arial", color='black', size=12),
|
| 46 |
+
minor_ticks="outside", minor=dict(ticklen=4, tickcolor="black", showgrid=False),
|
| 47 |
+
showline=True, linewidth=1, linecolor='black', mirror=True,
|
| 48 |
+
showgrid=True, gridwidth=1, gridcolor='#d9d9d9',
|
| 49 |
+
rangemode='nonnegative', #(normal or tozero or nonnegative)
|
| 50 |
+
showspikes=True, spikecolor="#8d9199", spikesnap="cursor", spikemode="across", spikethickness=1, spikedash='solid',
|
| 51 |
+
)
|
| 52 |
+
if type is not None:
|
| 53 |
+
fig.update_yaxes(type=type)
|
| 54 |
+
|
| 55 |
+
#Function to update FIGURE LAYOUT parameters
|
| 56 |
+
def update_layout(_size:list=[400,800]):
|
| 57 |
+
fig.update_layout(
|
| 58 |
+
width=_size[0], height=_size[1],
|
| 59 |
+
showlegend=False,
|
| 60 |
+
plot_bgcolor="white",
|
| 61 |
+
margin=dict(t=10,l=10,b=10,r=10),
|
| 62 |
+
hovermode="y", #"y unified", "y", "x", "closest"
|
| 63 |
+
)
|
| 64 |
+
|
| 65 |
+
#VARIABLES DEFINITION------------------------------------------------------------------------------------------------
|
| 66 |
+
#Sort dataframe by DEPTH
|
| 67 |
+
data = data.sort_values(by=depth_col)
|
| 68 |
+
|
| 69 |
+
#Default color codes
|
| 70 |
+
meta_info = '{"Unit":{"HCAL":"in","CALI":"in","CALS":"in","C1":"in","C2":"in","RHOB":"g\\/c3","RHO8":"g\\/c3","RHO8_filte":"g\\/c3","RHOZ":"g\\/c3","ZDEN":"g\\/c3","ZDNC":"g\\/c3","HDRA":"g\\/c3","DRHO":"g\\/c3","DSOZ":"g\\/c3","ECD_ARC":"g\\/c3","NPHI":"v\\/v","TNPH":"v\\/v","TNPH_CH":"v\\/v","HNPO":"v\\/v","HNPO_filte":"v\\/v","CNCF":"% (pu)","NPOR":"v\\/v","CH_NPHI":"v\\/v","CH_NPHIds":"v\\/v","CFTC":"Hz","CNTC":"Hz","DTC":"us\\/f","DTCO":"us\\/f","DT":"us\\/f","DT4P":"us\\/f","DT5":"us\\/f","DT_SPL":"us\\/f","DTS":"us\\/f","DTSM":"us\\/f","DT2":"us\\/f","DTSO":"us\\/f","DT4S":"us\\/f","GR":"GAPI","GR1":"GAPI","GR_ARC":"GAPI","CGR":"GAPI","EHGR":"GAPI","ECGR":"GAPI","SGR":"GAPI","GR_SPULSE_BHC":"GAPI","GR_IMP":"GAPI","GRM1":"GAPI","MWD_GR_BHC":"GAPI","GRAM":"GAPI","GR_SPL":"GAPI","GR_CDR":"GAPI","ARC_GR_RT":"GAPI","GR_LWD":"GAPI","POTA":"%","THOR":"ppm","URAN":"ppm","TPRA":"v\\/v","TURA":"v\\/v","UPRA":"v\\/v","LLD":"Ohmm","LLS":"Ohmm","DIL":"Ohmm","ILD":"Ohmm","ILM":"Ohmm","RILD":"Ohmm","RILM":"Ohmm","HRI":"Ohmm","RIDPH":"Ohmm","RIMPH":"Ohmm","RSFL":"Ohmm","HDRS":"Ohmm","HMRS":"Ohmm","LL3":"Ohmm","RIPD":"Ohmm","RIPM":"Ohmm","AT10":"Ohmm","AT20":"Ohmm","AT30":"Ohmm","AT60":"Ohmm","AT90":"Ohmm","AO10":"Ohmm","AO20":"Ohmm","AO30":"Ohmm","AO60":"Ohmm","AO90":"Ohmm","AF10":"Ohmm","AF20":"Ohmm","AF30":"Ohmm","AF60":"Ohmm","AF90":"Ohmm","AHO10":"Ohmm","AHO20":"Ohmm","AHO30":"Ohmm","AHO60":"Ohmm","AHO90":"Ohmm","M2RX":"Ohmm","M2R9":"Ohmm","M2R6":"Ohmm","M2R3":"Ohmm","M2R1":"Ohmm","P16H_UNC":"Ohmm","P22H_UNC":"Ohmm","P28H_UNC":"Ohmm","P34H_UNC":"Ohmm","P40H_UNC":"Ohmm","A28H_UNC":"Ohmm","A34H_UNC":"Ohmm","A40H_UNC":"Ohmm","P16L_UNC":"Ohmm","P22L_UNC":"Ohmm","P28L_UNC":"Ohmm","P34L_UNC":"Ohmm","P40L_UNC":"Ohmm","P22H_UNC_RT":"Ohmm","P40H_UNC_RT":"Ohmm","P40H_UNC_R":"Ohmm","P22H_UNC_R":"Ohmm","HLLD":"Ohmm","HLLS":"Ohmm","RES_DEEP":"Ohmm","RES_SHAL":"Ohmm","Rdeep":"Ohmm","Rshallow":"Ohmm","P33H_UNC":"Ohmm","P33L_UNC":"Ohmm","A33H_UNC":"Ohmm","A33L_UNC":"Ohmm","RACHM":"Ohmm","RACLM":"Ohmm","RPCHM":"Ohmm","RPCLM":"Ohmm","RPCSHM":"Ohmm","RPCSLM":"Ohmm","RACSHM":"Ohmm","RACSLM":"Ohmm","RAC1HM":"Ohmm","RAC1LM":"Ohmm","RPC1HM":"Ohmm","RPC1LM":"Ohmm","RAC2HM":"Ohmm","RAC2LM":"Ohmm","RPC2HM":"Ohmm","RPC2LM":"Ohmm","RAC3HM":"Ohmm","RAC3LM":"Ohmm","RPC3HM":"Ohmm","RPC3LM":"Ohmm","RAC4HM":"Ohmm","RAC4LM":"Ohmm","RPC4HM":"Ohmm","RPC4LM":"Ohmm","MSFL":"Ohmm","RXO8":"Ohmm","ATR":"Ohmm","PSR":"Ohmm","RT":"Ohmm","TAB_CDR_RES":"hr","TAB_ARC_RES":"s","TAB_RES":"s","PEF":"_","PEF8":"_","PERF":"_","PEFZ":"_","ROP5_RM":"m\\/hr","ROP":"m\\/hr","ROP5":"m\\/hr","ROPS":"m\\/hr","RXOZ":"Ohmm","RSOZ":"Ohmm","ITT":"s","TENS":"lbf","TTEN":"lbf","HTEN":"lbf","CDF":"lbf","ATMP":"degC","TEMP_MCR":"_","TVDE":"m","SP":"mV","VPVS":"v\\/v","LSN":"cps","SSN":"cps","APRS_ARC":"psi","ARTM":"_","AGTK":"_","ARTK":"_","Temp":"degC","TEMP_LWD":"degC","WTBH":"degC","WTBH1":"degC","TEMP_DNI_RT":"degC","HSTEMP":"degC","TCDM":"degC","RPTHM":"mins","CHT":"lbf","DPHI":"v\\/v","SPHI":"v\\/v","PHIE":"v\\/v","PR":"_","ICV":"m3","IHV":"m3","GTEM":"degC","DHTEMP":"degC","TTEM_CDR":"degC","SVEL":"m\\/s","TTSL":"us","TT":"us","CBSL":"mV","CBL":"mV","WF2":"_","WF1":"_","CBLF":"mV","CCL":"_","BS":"_","TGAS":"ppm","Oilshow":"_"},"Color":{"HCAL":"#bf2273","CALI":"#bf2273","CALS":"#bf2273","C1":"#bf2273","C2":"#bf2273","RHOB":"#f20a0a","RHO8":"#f20a0a","RHO8_filte":"#f20a0a","RHOZ":"#f20a0a","ZDEN":"#f20a0a","ZDNC":"#f20a0a","HDRA":"#f20a0a","DRHO":"#f20a0a","DSOZ":"#f20a0a","ECD_ARC":"#f20a0a","NPHI":"#0a44f2","TNPH":"#0a44f2","TNPH_CH":"#0a44f2","HNPO":"#0a44f2","HNPO_filte":"#0a44f2","CNCF":"#0a44f2","NPOR":"#0a44f2","CH_NPHI":"#0a44f2","CH_NPHIds":"#0a44f2","CFTC":"#0a44f2","CNTC":"#0a44f2","DTC":"#ea0af2","DTCO":"#ea0af3","DT":"#ea0af4","DT4P":"#ea0af5","DT5":"#ea0af6","DT_SPL":"#ea0af7","DTS":"#630af2","DTSM":"#630af3","DT2":"#630af4","DTSO":"#630af6","DT4S":"#630af7","GR":"#40f20a","GR1":"#40f20a","GR_ARC":"#40f20a","CGR":"#40f20a","EHGR":"#40f20a","ECGR":"#40f20a","SGR":"#40f20a","GR_SPULSE_BHC":"#40f20a","GR_IMP":"#40f20a","GRM1":"#40f20a","MWD_GR_BHC":"#40f20a","GRAM":"#40f20a","GR_SPL":"#40f20a","GR_CDR":"#40f20a","ARC_GR_RT":"#40f20a","GR_LWD":"#40f20a","POTA":"#0a0a0a","THOR":"#0a0a0a","URAN":"#0a0a0a","TPRA":"#0a0a0a","TURA":"#0a0a0a","UPRA":"#0a0a0a","LLD":"#f20a0a","LLS":"#0a44f2","DIL":"#0a44f2","ILD":"#f20a0a","ILM":"#0a44f2","RILD":"#f20a0a","RILM":"#0a44f2","HRI":"#f20a0a","RIDPH":"#0a44f2","RIMPH":"#eb0edc","RSFL":"#f20a0a","HDRS":"#0a44f2","HMRS":"#eb0edc","LL3":"#f20a0a","RIPD":"#0a44f2","RIPM":"#eb0edc","AT10":"#f20a0a","AT20":"#f20a0a","AT30":"#f20a0a","AT60":"#0a44f2","AT90":"#0a44f2","AO10":"#f20a0a","AO20":"#f20a0a","AO30":"#f20a0a","AO60":"#0a44f2","AO90":"#0a44f2","AF10":"#f20a0a","AF20":"#f20a0a","AF30":"#f20a0a","AF60":"#0a44f2","AF90":"#0a44f2","AHO10":"#f20a0a","AHO20":"#f20a0a","AHO30":"#f20a0a","AHO60":"#0a44f2","AHO90":"#0a44f2","M2RX":"#0a44f2","M2R9":"#0a44f2","M2R6":"#0a44f2","M2R3":"#f20a0a","M2R1":"#f20a0a","P16H_UNC":"#f20a0a","P22H_UNC":"#f20a0a","P28H_UNC":"#f20a0a","P34H_UNC":"#0a44f2","P40H_UNC":"#0a44f2","A28H_UNC":"#f20a0a","A34H_UNC":"#0a44f2","A40H_UNC":"#0a44f2","P16L_UNC":"#f20a0a","P22L_UNC":"#f20a0a","P28L_UNC":"#f20a0a","P34L_UNC":"#0a44f2","P40L_UNC":"#0a44f2","P22H_UNC_RT":"#f20a0a","P40H_UNC_RT":"#0a44f2","P40H_UNC_R":"#0a44f2","P22H_UNC_R":"#f20a0a","HLLD":"#f20a0a","HLLS":"#0a44f2","RES_DEEP":"#f20a0a","RES_SHAL":"#0a44f2","Rdeep":"#f20a0a","Rshallow":"#0a44f2","P33H_UNC":"#0a44f2","P33L_UNC":"#f20a0a","A33H_UNC":"#0a44f2","A33L_UNC":"#f20a0a","RACHM":"#0a44f2","RACLM":"#f20a0a","RPCHM":"#0a44f2","RPCLM":"#f20a0a","RPCSHM":"#0a44f2","RPCSLM":"#f20a0a","RACSHM":"#0a44f2","RACSLM":"#f20a0a","RAC1HM":"#0a44f2","RAC1LM":"#f20a0a","RPC1HM":"#0a44f2","RPC1LM":"#f20a0a","RAC2HM":"#0a44f2","RAC2LM":"#f20a0a","RPC2HM":"#0a44f2","RPC2LM":"#f20a0a","RAC3HM":"#0a44f2","RAC3LM":"#f20a0a","RPC3HM":"#0a44f2","RPC3LM":"#f20a0a","RAC4HM":"#0a44f2","RAC4LM":"#f20a0a","RPC4HM":"#0a44f2","RPC4LM":"#f20a0a","MSFL":"#0a44f2","RXO8":"#f20a0a","ATR":"#0a44f2","PSR":"#f20a0a","RT":"#f20a0a","TAB_CDR_RES":"#f20a0a","TAB_ARC_RES":"#f20a0a","TAB_RES":"#f20a0a","PEF":"#f70ad0","PEF8":"#f70ad1","PERF":"#f70ad2","PEFZ":"#f70ad3","ROP5_RM":"#f20a0a","ROP":"#f20a0a","ROP5":"#f20a0a","ROPS":"#f20a0a","RXOZ":"#0e33eb","RSOZ":"#0e33eb","ITT":"#2291f2","TENS":"#11f2f2","TTEN":"#11f2f3","HTEN":"#11f2f4","CDF":"#11f2f5","ATMP":"#fa0202","TEMP_MCR":"#fa0203","TVDE":"#0f1d29","SP":"#fa4402","VPVS":"#e102fa","LSN":"#ed0510","SSN":"#0533ed","APRS_ARC":"#ed0510","ARTM":"#f20a0a","AGTK":"#40f20a","ARTK":"#f20a0a","Temp":"#fa0202","TEMP_LWD":"#fa0203","WTBH":"#fa0204","WTBH1":"#fa0205","TEMP_DNI_RT":"#fa0206","HSTEMP":"#fa0207","TCDM":"#fa0208","RPTHM":"#454141","CHT":"#34fa02","DPHI":"#fa4402","SPHI":"#fa02e9","PHIE":"#fa0249","PR":"#fa02f6","ICV":"#9c959b","IHV":"#9c959b","GTEM":"#fa0202","DHTEMP":"#fa0203","TTEM_CDR":"#fa0205","SVEL":"#dd02fa","TTSL":"#dd02fa","TT":"#dd02fa","CBSL":"#fa0202","CBL":"#fa0203","WF2":"#630af2","WF1":"#630af2","CBLF":"#9c959b","CCL":"#9c959b","BS":"#9c959b","TGAS":"#fa0202","Oilshow":"#078238"}}'
|
| 71 |
+
curve_info = json.loads(meta_info)
|
| 72 |
+
curve_info['Unit'].update(new_unit) if len(new_unit) != 0 else curve_info['Unit']
|
| 73 |
+
curve_info['Color'].update(new_color) if len(new_color) != 0 else curve_info['Color']
|
| 74 |
+
log_type = ['LLD', 'LLS', 'DIL', 'ILD', 'ILM', 'RILD', 'RILM', 'HRI', 'RIDPH', 'RIMPH', 'RSFL', 'HDRS', 'HMRS', 'LL3', 'RIPD', 'RIPM', 'AT10', 'AT20', 'AT30', 'AT60', 'AT90', 'AO10', 'AO20', 'AO30', 'AO60', 'AO90', 'AF10', 'AF20', 'AF30', 'AF60', 'AF90', 'AHO10', 'AHO20', 'AHO30', 'AHO60', 'AHO90', 'M2RX', 'M2R9', 'M2R6', 'M2R3', 'M2R1', 'P16H_UNC', 'P22H_UNC', 'P28H_UNC', 'P34H_UNC', 'P40H_UNC', 'A28H_UNC', 'A34H_UNC', 'A40H_UNC', 'P16L_UNC', 'P22L_UNC', 'P28L_UNC', 'P34L_UNC', 'P40L_UNC', 'P22H_UNC_RT', 'P40H_UNC_RT', 'P40H_UNC_R', 'P22H_UNC_R', 'HLLD', 'HLLS', 'RES_DEEP', 'RES_SHAL', 'Rdeep', 'Rshallow', 'P33H_UNC', 'P33L_UNC', 'A33H_UNC', 'A33L_UNC', 'RACHM', 'RACLM', 'RPCHM', 'RPCLM', 'RPCSHM', 'RPCSLM', 'RACSHM', 'RACSLM', 'RAC1HM', 'RAC1LM', 'RPC1HM', 'RPC1LM', 'RAC2HM', 'RAC2LM', 'RPC2HM', 'RPC2LM', 'RAC3HM', 'RAC3LM', 'RPC3HM', 'RPC3LM', 'RAC4HM', 'RAC4LM', 'RPC4HM', 'RPC4LM', 'MSFL', 'RXO8', 'ATR', 'PSR', 'RT', 'RXOZ', 'RSOZ']
|
| 75 |
+
log_type_update = list(set(log_type + log))
|
| 76 |
+
|
| 77 |
+
#Define curves in columns list
|
| 78 |
+
if len(curves) != 0:
|
| 79 |
+
curves_list = curves
|
| 80 |
+
else:
|
| 81 |
+
curves_list = data.select_dtypes(include=['float64']).columns.drop(depth_col)
|
| 82 |
+
|
| 83 |
+
#Calculate numbers of plotting columns and size of whole figure
|
| 84 |
+
cols = len(curves_list); height= 800;
|
| 85 |
+
width = cols * 150 if cols*150 < 1300 else 1300
|
| 86 |
+
#Make subplots layout
|
| 87 |
+
fig = go.Figure()
|
| 88 |
+
fig = make_subplots(rows=1, cols=cols, shared_yaxes=True, horizontal_spacing=0.01)
|
| 89 |
+
|
| 90 |
+
#Check selected curves for plotting
|
| 91 |
+
for i, curve in enumerate(curves_list):
|
| 92 |
+
#Assign color code for single curve
|
| 93 |
+
color = curve_info['Color'][curve] if curve in curve_info['Color'].keys() else '#38a2e8'
|
| 94 |
+
unit = curve_info['Unit'][curve] if curve in curve_info['Unit'].keys() else '_'
|
| 95 |
+
#Add trace to subplots
|
| 96 |
+
add_trace(curv=curve, color=color, xaxis=f'x{i+1}', unit=unit, id_subplt=i+1, log=log_type_update)
|
| 97 |
+
|
| 98 |
+
#Setup the Axes and Layout parameters
|
| 99 |
+
update_xaxes(); update_yaxes(); update_layout([width, height])
|
| 100 |
+
#Show the main figure
|
| 101 |
+
# fig.show(config=dict(displayModeBar=True))
|
| 102 |
+
st.plotly_chart(fig)
|
models/05_13_2023_11_50_38_model_LGBM.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
pages/1_LAS_Exploratory.py
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import matplotlib.pyplot as plt
|
| 3 |
+
import lasio, os
|
| 4 |
+
import numpy as np
|
| 5 |
+
import os
|
| 6 |
+
import streamlit as st
|
| 7 |
+
|
| 8 |
+
import altair as alt
|
| 9 |
+
from streamlit_vega_lite import altair_component
|
| 10 |
+
|
| 11 |
+
from io import StringIO
|
| 12 |
+
|
| 13 |
+
from ui import *
|
| 14 |
+
from Antuns.page_setting import page_intro
|
| 15 |
+
from mLogsFunctions import *
|
| 16 |
+
from mLogsFunctions.fx import *
|
| 17 |
+
#-----------------------------------------------------------------------------
|
| 18 |
+
page_intro()
|
| 19 |
+
|
| 20 |
+
#1_LOADINGDATA-----------------------------------------------------------------
|
| 21 |
+
st.write("Log ASCII standard (LAS) is a standard file format common in the oil-and-gas and water well industries to store well log information. Well logging is used to investigate and characterize the subsurface stratigraphy in a well.")
|
| 22 |
+
# pagetile = """<center><h1>LAS EXPLORATORY</h1></center>"""
|
| 23 |
+
# st.markdown(pagetile, unsafe_allow_html=True)
|
| 24 |
+
st.subheader('To begin using the app, load your LAS file using the file upload option below.')
|
| 25 |
+
st.subheader("1. LAS File Loading:")
|
| 26 |
+
#------------------------------------------------------------------------------
|
| 27 |
+
#Streamlit Dashboard------------------------------------------------------------------------------------------
|
| 28 |
+
|
| 29 |
+
# set_page_config(page='custom')
|
| 30 |
+
hide_menu_button()
|
| 31 |
+
condense_layout()
|
| 32 |
+
#-----------------------------------------------------------------------------
|
| 33 |
+
@st.cache_data() #allow_output_mutation=True, suppress_st_warning=True
|
| 34 |
+
def upload_las(uploaded_files):
|
| 35 |
+
dataframes = {}
|
| 36 |
+
las_data_list = []
|
| 37 |
+
las_data = []
|
| 38 |
+
if uploaded_files is not None:
|
| 39 |
+
for file in uploaded_files:
|
| 40 |
+
try:
|
| 41 |
+
bytes_data = file.read()
|
| 42 |
+
str_io = StringIO(bytes_data.decode('Windows-1252'))
|
| 43 |
+
las_data = lasio.read(str_io)
|
| 44 |
+
well_data = las_data.df()
|
| 45 |
+
well_data['WELL'] = las_data.well.WELL.value
|
| 46 |
+
if well_data.index.name == 'DEPT':
|
| 47 |
+
well_data.reset_index('DEPT', inplace=True) # Set 'DEPT' as the new index
|
| 48 |
+
well_data.index.name = 'DEPT'
|
| 49 |
+
if len(well_data) > 0: # Kiểm tra xem dataframe có dữ liệu không
|
| 50 |
+
dataframes[file.name] = well_data
|
| 51 |
+
las_data_list.append(las_data)
|
| 52 |
+
else:
|
| 53 |
+
st.warning(f"No data in file {file.name}")
|
| 54 |
+
else:
|
| 55 |
+
well_data.index.name == 'DEPTH'
|
| 56 |
+
well_data.reset_index('DEPTH', inplace=True) # Set 'DEPTH' as the new index
|
| 57 |
+
well_data.index.name = 'DEPTH'
|
| 58 |
+
if len(well_data) > 0: # Kiểm tra xem dataframe có dữ liệu không
|
| 59 |
+
dataframes[file.name] = well_data
|
| 60 |
+
las_data_list.append(las_data)
|
| 61 |
+
except Exception as e:
|
| 62 |
+
st.error(f"Error loading {file.name}: {e}")
|
| 63 |
+
return dataframes, las_data_list, las_data
|
| 64 |
+
|
| 65 |
+
# Sidebar Options & File Upload
|
| 66 |
+
uploaded_files = st.file_uploader(label='Upload LAS files:', accept_multiple_files=True, type='las')
|
| 67 |
+
|
| 68 |
+
dataframes, las_data_list, las_data = upload_las(uploaded_files)
|
| 69 |
+
# print("print las data", las_data_list)
|
| 70 |
+
well_names = {}
|
| 71 |
+
if dataframes:
|
| 72 |
+
merged_df = []
|
| 73 |
+
for file_name, df in dataframes.items():
|
| 74 |
+
well_name = file_name.split(".")[0]
|
| 75 |
+
# Lấy danh sách các tên giếng
|
| 76 |
+
well_names = list(dataframes.keys())
|
| 77 |
+
|
| 78 |
+
# Cho phép người dùng chọn giếng và hiển thị DataFrame tương ứng
|
| 79 |
+
selected_well = st.selectbox("Select Well", well_names, key = "selected_well_1")
|
| 80 |
+
|
| 81 |
+
# st.write(f"Data for {selected_well}:")
|
| 82 |
+
st.write(dataframes[selected_well])
|
| 83 |
+
# Tạo một danh sách các DataFrame
|
| 84 |
+
dfs = [df for _, df in dataframes.items()]
|
| 85 |
+
merged_df = pd.concat([df for df in dfs])
|
| 86 |
+
# Hiển thị DataFrame tổng thể
|
| 87 |
+
st.write("Merged DataFrame:")
|
| 88 |
+
st.write(merged_df)
|
| 89 |
+
else:
|
| 90 |
+
print ("Please select LAS files for uploading ")
|
| 91 |
+
st.warning('No valid LAS files were uploaded.')
|
| 92 |
+
|
| 93 |
+
curves = []
|
| 94 |
+
wellname = []
|
| 95 |
+
las = las_data
|
| 96 |
+
list_well = []
|
| 97 |
+
if las:
|
| 98 |
+
|
| 99 |
+
for las_data in las_data_list:
|
| 100 |
+
well_name = las_data.well['WELL'].value
|
| 101 |
+
list_well.append(well_name)
|
| 102 |
+
# print(list_well)
|
| 103 |
+
|
| 104 |
+
st.success('File Uploaded Successfully')
|
| 105 |
+
st.write(f'<b>Well Name</b>: {list_well}', unsafe_allow_html=True)
|
| 106 |
+
# 2_CURVES_INFOMATION-----------------------------------------------------------------
|
| 107 |
+
if las:
|
| 108 |
+
|
| 109 |
+
st.subheader("2. Curve logs details:")
|
| 110 |
+
selected_well = st.selectbox("Select Well", well_names, key = "selected_well_2")
|
| 111 |
+
st.caption("All curve logs in data:")
|
| 112 |
+
|
| 113 |
+
curves = []
|
| 114 |
+
|
| 115 |
+
for well, las_file in zip(well_names, las_data_list):
|
| 116 |
+
if well == selected_well:
|
| 117 |
+
las = las_file
|
| 118 |
+
break
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
# print("in ra las:", las)
|
| 122 |
+
for curve in las.curves:
|
| 123 |
+
st.write(curve.mnemonic)
|
| 124 |
+
curves.append(curve.mnemonic)
|
| 125 |
+
|
| 126 |
+
for count, curve in enumerate(las.curves):
|
| 127 |
+
st.write("---")
|
| 128 |
+
st.write(f"Curve: {curve.mnemonic}, \t Units: {curve.unit}, \t Description: {curve.descr}")
|
| 129 |
+
st.write(f"There are a total of: {count+1} curves present within this file")
|
| 130 |
+
|
| 131 |
+
#3_DATAFRAME-----------------------------------------------------------------
|
| 132 |
+
if "selected_well" not in st.session_state:
|
| 133 |
+
st.session_state.selected_well = None
|
| 134 |
+
st.session_state.selected_well_multi = None
|
| 135 |
+
st.subheader("3. Converting LAS to DataFrame:")
|
| 136 |
+
st.caption("3.1 Preview of all Dataframe")
|
| 137 |
+
|
| 138 |
+
selected_well = st.selectbox("Select Well", well_names, key = "selected_well_5")
|
| 139 |
+
# print("Well_name", well_names)
|
| 140 |
+
# print("las_data_list", las_data_list)
|
| 141 |
+
for well, las_file in zip(well_names, las_data_list):
|
| 142 |
+
if well == selected_well:
|
| 143 |
+
las = las_file
|
| 144 |
+
break
|
| 145 |
+
# break
|
| 146 |
+
well = las.df()
|
| 147 |
+
well['WELL'] = las.well.WELL.value
|
| 148 |
+
well['DEPTH'] = well.index
|
| 149 |
+
well = well.reset_index(drop=True)
|
| 150 |
+
well = well.reindex(columns=['DEPTH'] + [col for col in well.columns if col != 'DEPTH'])
|
| 151 |
+
st.write(well.head())
|
| 152 |
+
st.caption("3.2 Well curves Statistics")
|
| 153 |
+
st.write(well.describe())
|
| 154 |
+
# print("in ra danh sách giếng", list_well)
|
| 155 |
+
# create a selectbox to choose the well
|
| 156 |
+
|
| 157 |
+
selected_well_multi = st.multiselect(" 3.3 Select well for download", list_well)
|
| 158 |
+
st.session_state.changename = st.button("Create", key="create_curve")
|
| 159 |
+
if st.session_state.changename:
|
| 160 |
+
dataframes_df = pd.concat(dataframes.values(), ignore_index=True)
|
| 161 |
+
st.session_state.selected_well_multi = dataframes_df.loc[dataframes_df['WELL'].isin(selected_well_multi)].reset_index(drop=True)
|
| 162 |
+
st.dataframe(st.session_state.selected_well_multi)
|
| 163 |
+
st.write(" Download DataFrame")
|
| 164 |
+
st.download_button(label='Download CSV File',
|
| 165 |
+
data = st.session_state.selected_well_multi.to_csv(),
|
| 166 |
+
file_name=f"{selected_well_multi}.csv",
|
| 167 |
+
mime='text/csv')
|
| 168 |
+
|
| 169 |
+
#4_Data Preprocessing-----------------------------------------------------------------
|
| 170 |
+
st.subheader("4. Data Preprocessing:")
|
| 171 |
+
st.session_state.old_name:str
|
| 172 |
+
st.session_state.new_name:str
|
| 173 |
+
st.session_state.changename:bool
|
| 174 |
+
st.session_state.well = None
|
| 175 |
+
|
| 176 |
+
st.write("4.1 Rename curves")
|
| 177 |
+
|
| 178 |
+
st.session_state.selected_well_rename = None
|
| 179 |
+
selected_well_rename = st.selectbox("Select Well", list_well, key="well_selectbox")
|
| 180 |
+
|
| 181 |
+
well_to_las = {}
|
| 182 |
+
well = []
|
| 183 |
+
data_rename_1 =[]
|
| 184 |
+
df_all_full = pd.DataFrame()
|
| 185 |
+
st.session_state.selected_well_rename = None
|
| 186 |
+
for i in range(len(well_names)):
|
| 187 |
+
well_to_las[well_names[i]] = las_data_list[i]
|
| 188 |
+
# print("key: ",well_names[i][:len(selected_well_rename)], " value: ",las_data_list[i])
|
| 189 |
+
if selected_well_rename == well_names[i][:len(selected_well_rename)]:
|
| 190 |
+
las = las_data_list[i]
|
| 191 |
+
break
|
| 192 |
+
# print("In ra las:", las)
|
| 193 |
+
well = las.df()
|
| 194 |
+
well['WELL'] = las.well.WELL.value
|
| 195 |
+
# print("In ra well2:", well)
|
| 196 |
+
curves = well.columns.tolist()
|
| 197 |
+
# print ("print ra cuvers:", curves) # save the number of curves for the selected well in session state
|
| 198 |
+
st.session_state.num_curves = len(curves)
|
| 199 |
+
df_rename = pd.DataFrame()
|
| 200 |
+
st.session_state.selected_well_rename = df_rename
|
| 201 |
+
st.session_state.selected_well_rename = well
|
| 202 |
+
|
| 203 |
+
import pandas as pd
|
| 204 |
+
|
| 205 |
+
# Khởi tạo DataFrame từ dữ liệu có sẵn
|
| 206 |
+
# Khởi tạo thuộc tính selected_well_rename trong st.session_state
|
| 207 |
+
st.session_state.setdefault('selected_well_rename', 'Default value')
|
| 208 |
+
# Truy cập thuộc tính selected_well_rename
|
| 209 |
+
|
| 210 |
+
data = st.session_state.selected_well_rename
|
| 211 |
+
if 'columns' in data:
|
| 212 |
+
n_cols = 4
|
| 213 |
+
n_rows = -(-len(data.columns) // n_cols) # Round up division
|
| 214 |
+
for i in range(n_rows):
|
| 215 |
+
cols = st.columns(n_cols)
|
| 216 |
+
for j in range(n_cols):
|
| 217 |
+
idx = i * n_cols + (j-1)
|
| 218 |
+
if idx < len(data.columns):
|
| 219 |
+
col = data.columns[idx]
|
| 220 |
+
# Lưu trữ tên cũ trong biến old_col
|
| 221 |
+
old_col = col
|
| 222 |
+
# new_col == well_names[i][:len(col)]
|
| 223 |
+
new_col = cols[j-1].text_input(f"Enter new name for '{col}'", key=f"input_{cols}")
|
| 224 |
+
# Kiểm tra nếu người dùng không nhập tên mới
|
| 225 |
+
if not new_col:
|
| 226 |
+
# Sử dụng tên cũ thay thế
|
| 227 |
+
new_col = old_col
|
| 228 |
+
data = data.rename(columns={col: new_col})
|
| 229 |
+
data["DEPTH"] = well.index
|
| 230 |
+
data.insert(0, 'DEPTH', data.pop('DEPTH'))
|
| 231 |
+
data = data.reset_index(drop=True)
|
| 232 |
+
st.dataframe(data)
|
| 233 |
+
else:
|
| 234 |
+
print ("Please select LAS files for input data")
|
| 235 |
+
# Hiển thị lại bảng
|
| 236 |
+
|
| 237 |
+
def my_function(data):
|
| 238 |
+
# Lưu trữ DataFrame khi người dùng nhấn vào nút "L��u"
|
| 239 |
+
if st.button("Lưu", key="saved_rename"):
|
| 240 |
+
# Tạo tên file CSV dựa trên biến selected_well_rename
|
| 241 |
+
file_name = f"/work/2022_VPIMLogs_WebApp/data/change_name_logs/{selected_well_rename}.csv"
|
| 242 |
+
# Lưu trữ DataFrame vào tệp CSV với tên file tương ứng
|
| 243 |
+
data.to_csv(file_name, index=False)
|
| 244 |
+
# Trả về giá trị của biến result
|
| 245 |
+
return data
|
| 246 |
+
result = my_function(data)
|
| 247 |
+
|
| 248 |
+
# for name in selected_well_multi:
|
| 249 |
+
# # dataframe_merged_df = pd.DataFrame()
|
| 250 |
+
# merged_df = pd.read_csv("data/change_name_logs/merged_df.csv")
|
| 251 |
+
# dataframe_merged_df.append(merged_df[merged_df.WELL==name])
|
| 252 |
+
# dataframe_merged_df.to_csv("data/change_name_logs/merged_df.csv")
|
| 253 |
+
# st.dataframe(dataframe_merged_df, width=1400)
|
| 254 |
+
|
| 255 |
+
|
| 256 |
+
selected_well_multi= st.multiselect(" 4.3 Select well for download", list_well, key = 'selected_well_multi_lasts')
|
| 257 |
+
# dowload_dataframes_df = pd.DataFrame()
|
| 258 |
+
st.session_state.changename_download = st.button("Create", key="selected_well_multi_rename_curve_111")
|
| 259 |
+
# Đường dẫn đến thư mục chứa các file csv
|
| 260 |
+
dir_path = '/work/2022_VPIMLogs_WebApp/data/change_name_logs/'
|
| 261 |
+
if st.session_state.changename_download:
|
| 262 |
+
# Tạo một DataFrame rỗng để chứa dữ liệu
|
| 263 |
+
merged_df = pd.DataFrame()
|
| 264 |
+
dataframe_merged_df = pd.DataFrame()
|
| 265 |
+
# Duyệt qua tất cả các file trong thư mục và gộp chúng vào DataFrame
|
| 266 |
+
for filename in os.listdir(dir_path):
|
| 267 |
+
if filename.endswith('.csv'):
|
| 268 |
+
filepath = os.path.join(dir_path, filename)
|
| 269 |
+
df = pd.read_csv(filepath)
|
| 270 |
+
merged_df = pd.concat([merged_df, df], ignore_index=True).reset_index(drop=True)
|
| 271 |
+
merged_df.to_csv(f"/work/2022_VPIMLogs_WebApp/data/merged/{selected_well_multi}_merged_df.csv")
|
| 272 |
+
dataframes_df = pd.read_csv(f"/work/2022_VPIMLogs_WebApp/data/merged/{selected_well_multi}_merged_df.csv")
|
| 273 |
+
st.session_state.selected_well_multi = dataframes_df.loc[dataframes_df['WELL'].isin(selected_well_multi)].reset_index(drop=True).drop('Unnamed: 0', axis = 1)
|
| 274 |
+
|
| 275 |
+
st.dataframe(st.session_state.selected_well_multi , width=1400)
|
| 276 |
+
# 4.3_DOWNLOAD-----------------------------------------------------------------
|
| 277 |
+
st.write("4.3 Download well curves with renamed names")
|
| 278 |
+
st.download_button(label='Download CSV File',
|
| 279 |
+
data = st.session_state.selected_well_multi.to_csv(),
|
| 280 |
+
file_name=f"{selected_well_multi}.csv",
|
| 281 |
+
mime='text/csv')
|
| 282 |
+
for filename in os.listdir(dir_path):
|
| 283 |
+
if filename.endswith('.csv'):
|
| 284 |
+
os.remove(os.path.join(dir_path, filename))
|
| 285 |
+
#'''Adding the ‘download’ tag attribute as shown below allows you to provide a file name and extension.
|
| 286 |
+
#f'<a href="data:file/csv;base64,{b64}" download="myfilename.csv">Download csv file</a>'''
|
| 287 |
+
|
| 288 |
+
hide_menu_button()
|
| 289 |
+
condense_layout()
|
pages/2_Exploratory_Data_Analysis.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import streamlit as st
|
| 3 |
+
import pandas as pd
|
| 4 |
+
import os
|
| 5 |
+
from ui import *
|
| 6 |
+
from mLogsFunctions import *
|
| 7 |
+
|
| 8 |
+
#Streamlit Dashboard------------------------------------------------------------------------------------------
|
| 9 |
+
pagetile = """<center><h1>EXPLORATORY DATA ANALYSIS</h1></center>"""
|
| 10 |
+
set_page_config(page='custom')
|
| 11 |
+
hide_menu_button()
|
| 12 |
+
condense_layout()
|
| 13 |
+
|
| 14 |
+
logo_site, info_site = st.columns([1.5, 8.5])
|
| 15 |
+
with logo_site:
|
| 16 |
+
st.image("https://i.ibb.co/Yd42K98/LogoVPI.png", use_column_width='auto')
|
| 17 |
+
with info_site:
|
| 18 |
+
# st.set_option('deprecation.showfileUploaderEncoding', False)
|
| 19 |
+
# st.set_option('maxUploadSize', 200*1024) # 200 MB
|
| 20 |
+
st.markdown(pagetile, unsafe_allow_html=True)
|
| 21 |
+
# Option 1: CSV File Loading
|
| 22 |
+
st.write('You can load your csv file using the file upload or selection from LAS Exploration option below.')
|
| 23 |
+
st.subheader("1. CSV File Loading")
|
| 24 |
+
df = csv_uploader()
|
| 25 |
+
df = tweak_data(df,resample=False, reindex=True)
|
| 26 |
+
|
| 27 |
+
# Option 2: CSV from LAS Exploration
|
| 28 |
+
st.subheader("2. CSV from LAS Exploration")
|
| 29 |
+
dir_path = '/work/2022_VPIMLogs_WebApp/data/merged/'
|
| 30 |
+
csv_files = [filename for filename in os.listdir(dir_path) if filename.endswith('.csv')]
|
| 31 |
+
selected_csv_file= st.multiselect('Select a CSV file', csv_files, key = 'st.session_state.selected_well_multi')
|
| 32 |
+
|
| 33 |
+
# # Đọc file csv được chọn vào DataFrame
|
| 34 |
+
if selected_csv_file: # Nếu người dùng đã chọn file CSV
|
| 35 |
+
# Đọc file csv được chọn vào DataFrame
|
| 36 |
+
file_path = '/work/2022_VPIMLogs_WebApp/data/merged/'
|
| 37 |
+
merged_data = pd.concat([pd.read_csv(file_path + f) for f in selected_csv_file])
|
| 38 |
+
df = tweak_data(merged_data, resample=False, reindex=True)
|
| 39 |
+
else: # Nếu người dùng không chọn file CSV
|
| 40 |
+
merged_data = df
|
| 41 |
+
df = tweak_data(merged_data, resample=False, reindex=True)
|
| 42 |
+
#|CHECK DATA EXISTENCE-----------------------------------------------------------------------------------------
|
| 43 |
+
if df is not None:
|
| 44 |
+
curves = columns_list(df, no_depth=True, no_well=True)
|
| 45 |
+
well_names = np.sort(df.WELL.unique())
|
| 46 |
+
#|TABS-ESTABLISHING-----------------------------------------------------------------------------------------
|
| 47 |
+
tab1, tab2, tab3, tab4, tab5 = st.tabs(['DataFrame',
|
| 48 |
+
'DataStatistics',
|
| 49 |
+
'3D Scatter Points',
|
| 50 |
+
'CurvesView',
|
| 51 |
+
'OutliersRemoval'
|
| 52 |
+
])
|
| 53 |
+
#|TABS-1-----------------------------------------------------------------------------------------
|
| 54 |
+
st.write('---')
|
| 55 |
+
with tab1:
|
| 56 |
+
st.dataframe(df, width=1400, height=500)
|
| 57 |
+
|
| 58 |
+
#|TABS-2-----------------------------------------------------------------------------------------
|
| 59 |
+
with tab2:
|
| 60 |
+
st.radio('DataVisualizationMethod',
|
| 61 |
+
key='displayTab2',
|
| 62 |
+
options=['DataStatistics',
|
| 63 |
+
'Missing Statistic',
|
| 64 |
+
'Curve Distribution',
|
| 65 |
+
'Histogram Overlay',
|
| 66 |
+
'Cross-Plot',
|
| 67 |
+
'PairPlot'],
|
| 68 |
+
horizontal=True)
|
| 69 |
+
if st.session_state.displayTab2 == 'DataStatistics':
|
| 70 |
+
subtab21(df, well_names)
|
| 71 |
+
elif st.session_state.displayTab2 == 'Missing Statistic':
|
| 72 |
+
subtab22(df)
|
| 73 |
+
elif st.session_state.displayTab2 == 'Curve Distribution':
|
| 74 |
+
subtab23(df, curves)
|
| 75 |
+
elif st.session_state.displayTab2 == 'Histogram Overlay':
|
| 76 |
+
subtab24(df, curves)
|
| 77 |
+
elif st.session_state.displayTab2 == 'Cross-Plot':
|
| 78 |
+
subtab25(df, curves)
|
| 79 |
+
elif st.session_state.displayTab2 == 'PairPlot':
|
| 80 |
+
subtab26(df, curves)
|
| 81 |
+
else:
|
| 82 |
+
subtab21(df, well_names)
|
| 83 |
+
|
| 84 |
+
#|TABS-3-----------------------------------------------------------------------------------------
|
| 85 |
+
with tab3:
|
| 86 |
+
scatterPoint3D(df)
|
| 87 |
+
#|TABS-4-----------------------------------------------------------------------------------------
|
| 88 |
+
with tab4:
|
| 89 |
+
stViewCurves(df)
|
| 90 |
+
#|TABS-5-----------------------------------------------------------------------------------------
|
| 91 |
+
with tab5:
|
| 92 |
+
rmOutliers(df)
|
pages/3_Fracture_Training_Models.py
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import pandas as pd
|
| 3 |
+
|
| 4 |
+
import altair as alt
|
| 5 |
+
import lightgbm as lgb
|
| 6 |
+
import matplotlib.pyplot as plt
|
| 7 |
+
import pickle, os, datetime
|
| 8 |
+
import bz2file as bz2
|
| 9 |
+
|
| 10 |
+
from sklearn.model_selection import train_test_split, StratifiedShuffleSplit
|
| 11 |
+
from sklearn.metrics import roc_auc_score, balanced_accuracy_score, f1_score, recall_score, precision_score
|
| 12 |
+
from sklearn.metrics import roc_curve, precision_recall_curve, auc
|
| 13 |
+
|
| 14 |
+
import streamlit as st
|
| 15 |
+
|
| 16 |
+
from ui import *
|
| 17 |
+
from mLogsFunctions import *
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
#------------------------------------------------------------------------------------------
|
| 21 |
+
# processing pipeline
|
| 22 |
+
def remove_negative_val(df, col):
|
| 23 |
+
return df.drop(index=df[df[col] < 0].index)
|
| 24 |
+
def rel_depth(df):
|
| 25 |
+
dfx = []
|
| 26 |
+
for well in df.WELL.unique():
|
| 27 |
+
df_ = df[df.WELL==well].sort_values(by="DEPTH", ascending=True)
|
| 28 |
+
dfx.append(df_.assign(rel_depth=df_.DEPTH / df_.DEPTH.values[0]))
|
| 29 |
+
return pd.concat(dfx).reset_index(drop=True)
|
| 30 |
+
|
| 31 |
+
def tweak_data_S(df):
|
| 32 |
+
return (
|
| 33 |
+
df.assign(
|
| 34 |
+
FRACTURE_ZONE=df.FRACTURE_ZONE.replace({-9999: 0, np.nan: 0}).astype('int8'),
|
| 35 |
+
GR=df.GR.replace({-9999.:0.}).astype('float32'),
|
| 36 |
+
DCALI_FINAL=df.DCALI_FINAL.replace({-9999.:0.}).astype('float32'),
|
| 37 |
+
LLD=df.LLD.replace({-9999.:0.}).astype('float32'),
|
| 38 |
+
LLS=df.LLS.replace({-9999.:0.}).astype('float32'),
|
| 39 |
+
NPHI=df.NPHI.replace({-9999.:0.}).astype('float32'),
|
| 40 |
+
RHOB=df.RHOB.replace({-9999.:0.}).astype('float32'),
|
| 41 |
+
DTC=df.DTC.replace({-9999.:0.}).astype('float32'),
|
| 42 |
+
DTS=df.DTS.replace({-9999.:0.}).astype('float32'),
|
| 43 |
+
DEPTH=df.DEPTH.astype('float32')
|
| 44 |
+
)
|
| 45 |
+
.pipe(remove_negative_val, "RHOB")
|
| 46 |
+
.pipe(remove_negative_val, "DTC")
|
| 47 |
+
.pipe(remove_negative_val, "DTS")
|
| 48 |
+
.pipe(remove_negative_val, "GR")
|
| 49 |
+
.pipe(remove_negative_val, "LLD")
|
| 50 |
+
).pipe(rel_depth)
|
| 51 |
+
|
| 52 |
+
#Streamlit Dashboard------------------------------------------------------------------------------------------
|
| 53 |
+
pagetile = """<center><h1>TRAINING SITE</h1></center>"""
|
| 54 |
+
set_page_config(page='custom')
|
| 55 |
+
hide_menu_button()
|
| 56 |
+
condense_layout()
|
| 57 |
+
|
| 58 |
+
logo_site, info_site = st.columns([1.5, 8.5])
|
| 59 |
+
with logo_site:
|
| 60 |
+
st.image("https://i.ibb.co/Yd42K98/LogoVPI.png", use_column_width='auto')
|
| 61 |
+
with info_site:
|
| 62 |
+
st.set_option('deprecation.showfileUploaderEncoding', False)
|
| 63 |
+
# st.set_option('maxUploadSize', 200*1024) # 200 MB
|
| 64 |
+
st.markdown(pagetile, unsafe_allow_html=True)
|
| 65 |
+
# Option 1: CSV File Loading
|
| 66 |
+
st.write('You can load your csv file using the file upload or selection from LAS Exploration option below.')
|
| 67 |
+
|
| 68 |
+
st.subheader("1. CSV File Loading")
|
| 69 |
+
df = csv_uploader()
|
| 70 |
+
# df = tweak_data(df,resample=False, reindex=True)
|
| 71 |
+
|
| 72 |
+
# Option 2: CSV from LAS Exploration
|
| 73 |
+
st.subheader("2. CSV from LAS Exploration")
|
| 74 |
+
dir_path = '/work/2022_VPIMLogs_WebApp/data/merged/'
|
| 75 |
+
csv_files = [filename for filename in os.listdir(dir_path) if filename.endswith('.csv')]
|
| 76 |
+
selected_csv_file= st.multiselect('Select a CSV file', csv_files, key = 'st.session_state.selected_well_multi')
|
| 77 |
+
|
| 78 |
+
# # Đọc file csv được chọn vào DataFrame
|
| 79 |
+
if selected_csv_file: # Nếu người dùng đã chọn file CSV
|
| 80 |
+
# Đọc file csv được chọn vào DataFrame
|
| 81 |
+
file_path = '/work/2022_VPIMLogs_WebApp/data/merged/'
|
| 82 |
+
merged_data = pd.concat([pd.read_csv(file_path + f) for f in selected_csv_file])
|
| 83 |
+
# df = tweak_data_S(merged_data, resample=False, reindex=True)
|
| 84 |
+
df = merged_data
|
| 85 |
+
else: # Nếu người dùng không chọn file CSV
|
| 86 |
+
merged_data = df
|
| 87 |
+
|
| 88 |
+
# df = tweak_data(merged_data, resample=False, reindex=True)
|
| 89 |
+
#------------------------------------------------------------------------------------------
|
| 90 |
+
if df is not None:
|
| 91 |
+
st.caption("Data Preparation")
|
| 92 |
+
# Processing data
|
| 93 |
+
# df = tweak_data_S(df)
|
| 94 |
+
try:
|
| 95 |
+
df = tweak_data_S(df)
|
| 96 |
+
except AttributeError as e:
|
| 97 |
+
print(" ")
|
| 98 |
+
st.info("Tweak Data")
|
| 99 |
+
i1, i2 = st.columns(2)
|
| 100 |
+
for i, v in enumerate(["FRACTURE_ZONE", "GR", "DCAL", "LLD", "LLS", "NPHI", "RHOB", "DTC", "DTS", "DEPTH"]):
|
| 101 |
+
if i%2==0:
|
| 102 |
+
with i1:
|
| 103 |
+
st.success(f"{v}: Replaced nan values by 0")
|
| 104 |
+
if i%2==1:
|
| 105 |
+
with i2:
|
| 106 |
+
st.success(f"{v}: Replaced nan values by 0")
|
| 107 |
+
st.info(" Negative values removal in RHOB, DTC, DTS, GR, LLD: Done!")
|
| 108 |
+
st.write("---")
|
| 109 |
+
|
| 110 |
+
#--------------------------------------------------------------------------------------
|
| 111 |
+
# define training/testing data
|
| 112 |
+
st.write("Please to slectect Curves input for Traning Model")
|
| 113 |
+
feature_names_dict = [col for col in df.columns if col not in ["WELL",
|
| 114 |
+
"DEPTH",
|
| 115 |
+
# "Fracture Intensity",
|
| 116 |
+
# "FRACTURE_ZONE",
|
| 117 |
+
]]
|
| 118 |
+
feature_names = st.multiselect('Select curves', feature_names_dict, key = 'st.session_state.selected_well_multi_curves')
|
| 119 |
+
feature_names_label = [col for col in df.columns if col not in ["WELL",
|
| 120 |
+
"DEPTH",
|
| 121 |
+
# "Fracture Intensity",
|
| 122 |
+
# "FRACTURE_ZONE",
|
| 123 |
+
]]
|
| 124 |
+
st.write("Please to slectect a Label input for Traning Model")
|
| 125 |
+
feature_names_label = st.selectbox('Select a curves', feature_names_label, key = 'st.session_state.selected_well_multi_label')
|
| 126 |
+
|
| 127 |
+
label_name = feature_names_label
|
| 128 |
+
st.caption("Features Selection")
|
| 129 |
+
st.info(f"Label names: {label_name}")
|
| 130 |
+
st.info(f"Feature names: {feature_names}")
|
| 131 |
+
st.write("---")
|
| 132 |
+
#--------------------------------------------------------------------------------------
|
| 133 |
+
st.caption("Split Data")
|
| 134 |
+
|
| 135 |
+
## split data
|
| 136 |
+
### some data for test model after deploy
|
| 137 |
+
ss = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42)
|
| 138 |
+
|
| 139 |
+
for _train_inx, _test_inx in ss.split(df, df["WELL"]):
|
| 140 |
+
train_df, test_df = df.loc[_train_inx, :], df.loc[_test_inx, :]
|
| 141 |
+
|
| 142 |
+
X_train, X_test, y_train, y_test = train_test_split(
|
| 143 |
+
train_df[feature_names],
|
| 144 |
+
train_df[label_name],
|
| 145 |
+
stratify=train_df[label_name],
|
| 146 |
+
train_size=0.9,
|
| 147 |
+
random_state=42,
|
| 148 |
+
)
|
| 149 |
+
|
| 150 |
+
### create lgb dataset
|
| 151 |
+
train_set = lgb.Dataset(X_train,
|
| 152 |
+
label=y_train,
|
| 153 |
+
feature_name=feature_names,
|
| 154 |
+
)
|
| 155 |
+
valid_set = lgb.Dataset(X_test,
|
| 156 |
+
label=y_test,
|
| 157 |
+
reference=train_set,
|
| 158 |
+
feature_name=feature_names,
|
| 159 |
+
)
|
| 160 |
+
|
| 161 |
+
st.info(f"Size of FULL Dataset: {len(df)}")
|
| 162 |
+
st.info(f"Size of TRAINING set: {train_set.construct().num_data()}")
|
| 163 |
+
st.info(f"Size of VALIDATION set: {valid_set.construct().num_data()}")
|
| 164 |
+
st.info(f"Size of TESTING set: {len(test_df)}")
|
| 165 |
+
st.write("---")
|
| 166 |
+
#Traning model--------------------------------------------------------------------------------------
|
| 167 |
+
if st.button("Start Train"):
|
| 168 |
+
# Modeling
|
| 169 |
+
## custom metric
|
| 170 |
+
st.caption("Training")
|
| 171 |
+
from sklearn.metrics import recall_score, precision_score, accuracy_score, f1_score, roc_auc_score, precision_recall_curve
|
| 172 |
+
model = lgb.train(
|
| 173 |
+
params={"boosting_type": "gbdt",
|
| 174 |
+
"objective": "cross_entropy",
|
| 175 |
+
"metric": ["rmse","recall"],
|
| 176 |
+
"is_unbalance": True,
|
| 177 |
+
},
|
| 178 |
+
train_set=lgb.Dataset(data=X_train, label=y_train,
|
| 179 |
+
feature_name=feature_names),
|
| 180 |
+
num_boost_round=2000,
|
| 181 |
+
valid_sets=lgb.Dataset(data=X_test, label=y_test,
|
| 182 |
+
feature_name=feature_names),
|
| 183 |
+
early_stopping_rounds=5,
|
| 184 |
+
verbose_eval=0,
|
| 185 |
+
)
|
| 186 |
+
st.success("Finished Training!")
|
| 187 |
+
st.success("Saved Model!")
|
| 188 |
+
st.write("---")
|
| 189 |
+
|
| 190 |
+
now = datetime.datetime.now()
|
| 191 |
+
current_time = now.strftime("%m_%d_%Y_%H_%M_%S")
|
| 192 |
+
link= f"/work/2022_VPIMLogs_WebApp/models/{current_time}_model_LGBM.json"
|
| 193 |
+
model.save_model(filename= link)
|
| 194 |
+
|
| 195 |
+
with open(link, 'r') as f:
|
| 196 |
+
file_content = f.read()
|
| 197 |
+
if st.download_button(label='Download JSON File',
|
| 198 |
+
data=file_content,
|
| 199 |
+
file_name=link,
|
| 200 |
+
mime='application/json'):
|
| 201 |
+
pass
|
| 202 |
+
else:
|
| 203 |
+
st.text(" ")
|
| 204 |
+
#Scores--------------------------------------------------------------------------------------
|
| 205 |
+
## using model to make prediction
|
| 206 |
+
st.caption("Modeling Scores")
|
| 207 |
+
|
| 208 |
+
threshold = 0.5
|
| 209 |
+
#Make label Prediction
|
| 210 |
+
predictions = (model.predict(df[feature_names])> threshold).astype(int)
|
| 211 |
+
df['FRACTURE_ZONE_PRED'] = predictions
|
| 212 |
+
test_preds = model.predict(test_df[feature_names])
|
| 213 |
+
train_preds = model.predict(X_train)
|
| 214 |
+
valid_preds = model.predict(X_test)
|
| 215 |
+
|
| 216 |
+
valid_recall = recall_score(y_test, valid_preds >= threshold, average = 'weighted')
|
| 217 |
+
valid_precision = precision_score(y_test, valid_preds >= threshold, average = 'weighted')
|
| 218 |
+
valid_acc = accuracy_score(y_test, valid_preds >= threshold)
|
| 219 |
+
valid_f1 = f1_score(y_test, valid_preds >= threshold, average = 'weighted')
|
| 220 |
+
valid_aoc = roc_auc_score(y_test, valid_preds >= threshold)
|
| 221 |
+
|
| 222 |
+
train_recall = recall_score(y_train, train_preds >= threshold, average = 'weighted')
|
| 223 |
+
train_precision = precision_score(y_train, train_preds >= threshold, average = 'weighted')
|
| 224 |
+
train_acc = accuracy_score(y_train, train_preds >= threshold)
|
| 225 |
+
train_aoc = roc_auc_score(y_train, train_preds >= threshold)
|
| 226 |
+
train_f1 = f1_score(y_train, train_preds >= threshold, average = 'weighted')
|
| 227 |
+
|
| 228 |
+
test_recall = recall_score(test_df[label_name], test_preds >= threshold, average = 'weighted')
|
| 229 |
+
test_precision = precision_score(test_df[label_name], test_preds >= threshold, average = 'weighted')
|
| 230 |
+
test_acc = accuracy_score(test_df[label_name], test_preds >= threshold)
|
| 231 |
+
test_aoc = roc_auc_score(test_df[label_name], test_preds >= threshold)
|
| 232 |
+
test_f1 = f1_score(test_df[label_name], test_preds >= threshold, average = 'weighted')
|
| 233 |
+
|
| 234 |
+
sc1, sc2, sc3 = st.columns(3)
|
| 235 |
+
with sc1:
|
| 236 |
+
st.info(f"Training score (RECALL): {train_recall}")
|
| 237 |
+
st.info(f"Training score (PRECISION): {train_precision}")
|
| 238 |
+
st.info(f"Training score (ACC): {train_acc}")
|
| 239 |
+
st.info(f"Training score (F1): {train_f1}")
|
| 240 |
+
st.info(f"Training score (AOC): {train_aoc}")
|
| 241 |
+
|
| 242 |
+
with sc2:
|
| 243 |
+
st.info(f"Validation score (RECALL): {valid_recall}")
|
| 244 |
+
st.info(f"Validation score (PRECISION): {valid_precision}")
|
| 245 |
+
st.info(f"Validation score (ACC): {valid_acc}")
|
| 246 |
+
st.info(f"Validation score (F1): {valid_f1}")
|
| 247 |
+
st.info(f"Validation score (AOC): {valid_aoc}")
|
| 248 |
+
|
| 249 |
+
with sc3:
|
| 250 |
+
st.info(f"Testing score (RECALL): {test_recall}")
|
| 251 |
+
st.info(f"Testing score (PRECISION): {test_precision}")
|
| 252 |
+
st.info(f"Testing score (ACC): {test_acc}")
|
| 253 |
+
st.info(f"Testing score (F1): {test_f1}")
|
| 254 |
+
st.info(f"Testing score (AOC): {test_aoc}")
|
| 255 |
+
st.write("---")
|
| 256 |
+
#Measure Scores--------------------------------------------------------------------------------------
|
| 257 |
+
st.caption("Scores plotting charts")
|
| 258 |
+
|
| 259 |
+
## roc valid
|
| 260 |
+
fpr_valid, tpr_valid, threshold_valid = roc_curve(y_test, valid_preds)
|
| 261 |
+
roc_auc_valid = auc(fpr_valid, tpr_valid)
|
| 262 |
+
## precision recall valid
|
| 263 |
+
pr_valid, rc_valid, threshold_valid= precision_recall_curve(y_test, valid_preds)
|
| 264 |
+
## roc training
|
| 265 |
+
tfpr_train, ttpr_train, tthreshold_train = roc_curve(y_train, train_preds)
|
| 266 |
+
troc_auc_train = auc(tfpr_train, ttpr_train)
|
| 267 |
+
## precision recall training
|
| 268 |
+
tpr_train, trc_train, tthreshold_train = precision_recall_curve(y_train, train_preds)
|
| 269 |
+
## roc test
|
| 270 |
+
tfpr_test, ttpr_test, tthreshold = roc_curve(test_df[label_name], test_preds)
|
| 271 |
+
troc_auc_test = auc(tfpr_test, ttpr_test)
|
| 272 |
+
## precision recall testing
|
| 273 |
+
tpr_test, trc_test, tthreshold_test = precision_recall_curve(test_df[label_name], test_preds)
|
| 274 |
+
|
| 275 |
+
#Plot Scores--------------------------------------------------------------------------------------
|
| 276 |
+
fig, ax = plt.subplots(figsize=(40,40))
|
| 277 |
+
ax1 = plt.subplot2grid((7,7), (0,0), rowspan=1, colspan = 1)
|
| 278 |
+
ax2 = plt.subplot2grid((7,7), (0,1), rowspan=1, colspan = 1)
|
| 279 |
+
ax3 = plt.subplot2grid((7,7), (0,2), rowspan=1, colspan = 1)
|
| 280 |
+
ax4 = plt.subplot2grid((7,7), (1,0), rowspan=1, colspan = 1)
|
| 281 |
+
ax5 = plt.subplot2grid((7,7), (1,1), rowspan=1, colspan = 1)
|
| 282 |
+
ax6 = plt.subplot2grid((7,7), (1,2), rowspan=1, colspan = 1)
|
| 283 |
+
|
| 284 |
+
def set_ax(ax,
|
| 285 |
+
x, y, color, label, legend,
|
| 286 |
+
line:bool=False,
|
| 287 |
+
title:str=None,
|
| 288 |
+
x_label:str=None,
|
| 289 |
+
y_label:str=None,
|
| 290 |
+
):
|
| 291 |
+
ax.plot(x, y, color, label=label)
|
| 292 |
+
ax.set_title(title)
|
| 293 |
+
ax.legend(loc = legend)
|
| 294 |
+
if line == True:
|
| 295 |
+
ax.plot([0, 1], [0, 1],'r--')
|
| 296 |
+
ax.set_xlim([0, 1])
|
| 297 |
+
ax.set_ylim([0, 1])
|
| 298 |
+
ax.set_ylabel(y_label)
|
| 299 |
+
ax.set_xlabel(x_label)
|
| 300 |
+
p1, p2, p3 = st.columns([1,14,1])
|
| 301 |
+
with p2:
|
| 302 |
+
## roc valid
|
| 303 |
+
set_ax(ax2, fpr_valid, tpr_valid, 'b',
|
| 304 |
+
label = 'AUC = %0.2f' % roc_auc_valid,
|
| 305 |
+
legend='lower right',
|
| 306 |
+
title='Receiver Operating Characteristic - Validation',
|
| 307 |
+
line=True,
|
| 308 |
+
x_label='False Positive Rate',
|
| 309 |
+
y_label='True Positive Rate',
|
| 310 |
+
)
|
| 311 |
+
|
| 312 |
+
## precision recall valid
|
| 313 |
+
set_ax(ax5, pr_valid, rc_valid, 'orange',
|
| 314 |
+
label = 'PR Curve',
|
| 315 |
+
legend='lower right',
|
| 316 |
+
title='Precision Recall Curve - Validation',
|
| 317 |
+
line=True,
|
| 318 |
+
x_label='Recall',
|
| 319 |
+
y_label='Precision',
|
| 320 |
+
)
|
| 321 |
+
|
| 322 |
+
## roc training
|
| 323 |
+
set_ax(ax1, tfpr_train, ttpr_train, 'b',
|
| 324 |
+
label = 'AUC = %0.2f' % troc_auc_train,
|
| 325 |
+
legend='lower right',
|
| 326 |
+
title='Receiver Operating Characteristic - Training',
|
| 327 |
+
line=True,
|
| 328 |
+
x_label='False Positive Rate',
|
| 329 |
+
y_label='True Positive Rate',
|
| 330 |
+
)
|
| 331 |
+
|
| 332 |
+
## precision recall training
|
| 333 |
+
set_ax(ax4, tpr_train, trc_train, 'orange',
|
| 334 |
+
label = 'PR Curve',
|
| 335 |
+
legend='lower right',
|
| 336 |
+
title='Precision Recall Curve - Training',
|
| 337 |
+
line=True,
|
| 338 |
+
x_label='Recall',
|
| 339 |
+
y_label='Precision',
|
| 340 |
+
)
|
| 341 |
+
|
| 342 |
+
## roc test
|
| 343 |
+
set_ax(ax3, tfpr_test, ttpr_test, 'b',
|
| 344 |
+
label = 'AUC = %0.2f' % troc_auc_test,
|
| 345 |
+
legend='lower right',
|
| 346 |
+
title='Receiver Operating Characteristic - Blind test',
|
| 347 |
+
line=True,
|
| 348 |
+
x_label='False Positive Rate',
|
| 349 |
+
y_label='True Positive Rate',
|
| 350 |
+
)
|
| 351 |
+
|
| 352 |
+
## precision recall testing
|
| 353 |
+
set_ax(ax6, tpr_test, trc_test, 'orange',
|
| 354 |
+
label = 'PR Curve',
|
| 355 |
+
legend='lower right',
|
| 356 |
+
title='Precision Recall Curve - Blind test',
|
| 357 |
+
line=True,
|
| 358 |
+
x_label='Recall',
|
| 359 |
+
y_label='Precision',
|
| 360 |
+
)
|
| 361 |
+
|
| 362 |
+
st.pyplot(fig)
|
| 363 |
+
|
| 364 |
+
#Plot Data------------------------------------------------------------------
|
| 365 |
+
plotting_curves = [c for c in df.columns.unique() if c not in ["DEPTH", "WELL", "TVD", "DCALI_FINAL", "INCL", "AZIM_TN", "rel_depth"]]
|
| 366 |
+
plotting_curves.sort()
|
| 367 |
+
if "FRACTURE_ZONE_PRED" in df.columns.unique():
|
| 368 |
+
plotting_curves.append("FRACTURE_ZONE_PRED")
|
| 369 |
+
for well in df.WELL.unique():
|
| 370 |
+
st.write('---')
|
| 371 |
+
st.write(f"{well} Logs: \n")
|
| 372 |
+
well_plot = df[df.WELL == well]
|
| 373 |
+
charts_dict={}
|
| 374 |
+
for i, c in enumerate(plotting_curves):
|
| 375 |
+
charts_dict[i] = curve_plot(data=well_plot,filted_data=None, x_column=c)
|
| 376 |
+
#Show Curve-----------------------------------------------------------------------
|
| 377 |
+
st.write(alt.concat(*charts_dict.values(), columns = 12).configure(autosize='fit'))
|
| 378 |
+
# st.snow()
|
| 379 |
+
#DOWNLOAD-----------------------------------------------------------------
|
| 380 |
+
# Define the download button
|
| 381 |
+
|
| 382 |
+
# if st.download_button('Download Modeling (with format JSON)'):
|
| 383 |
+
# with open(filename, 'r') as f:
|
| 384 |
+
# data = json.load(f)
|
| 385 |
+
# href = f"data:text/json;charset=utf-8,{json.dumps(data, indent=2)}"
|
| 386 |
+
# st.markdown(f'<a href="{href}" download="{filename}">Download Modeling (with format JSON)</a>')
|
| 387 |
+
hide_menu_button()
|
| 388 |
+
condense_layout()
|
pages/4_Fracture_Prediction.py
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import lightgbm as lgb
|
| 3 |
+
|
| 4 |
+
import pickle, os
|
| 5 |
+
import bz2file as bz2
|
| 6 |
+
|
| 7 |
+
import altair as alt
|
| 8 |
+
|
| 9 |
+
import streamlit as st
|
| 10 |
+
|
| 11 |
+
from ui import *
|
| 12 |
+
from mLogsFunctions import *
|
| 13 |
+
from mLogsFunctions.fx import *
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
#ignore version warnings
|
| 17 |
+
import warnings
|
| 18 |
+
warnings.filterwarnings("ignore")
|
| 19 |
+
|
| 20 |
+
#Global variables
|
| 21 |
+
THRESHOLD_GLOBAL = 0.5
|
| 22 |
+
|
| 23 |
+
#All wells to be trained
|
| 24 |
+
wells_name = ["01-97-HXS-1X", "15-1-SN-1X", "15-1-SN-2X", "15-1-SN-3XST", "15-1-SN-4X", "15-1-SNN-1P",
|
| 25 |
+
"15-1-SNN-2P", "15-1-SNN-3P", "15-1-SNN-4P", "15-1-SNS-1P", "15-1-SNS-2P", "15-1-SNS-4P"]
|
| 26 |
+
#Obtain data and label of wells
|
| 27 |
+
name_features = ["GR", "LLD", "LLS", "NPHI", "RHOB", "DTC", "DTS"]
|
| 28 |
+
label = "FRACTURE_ZONE"
|
| 29 |
+
#-----------------------------------------------------------------
|
| 30 |
+
# processing pipeline
|
| 31 |
+
def remove_negative_val(df, col):
|
| 32 |
+
return df.drop(index=df[df[col] < 0].index)
|
| 33 |
+
def rel_depth(df):
|
| 34 |
+
dfx = []
|
| 35 |
+
for well in df.WELL.unique():
|
| 36 |
+
df_ = df[df.WELL==well].sort_values(by="DEPTH", ascending=True)
|
| 37 |
+
dfx.append(df_.assign(rel_depth=df_.DEPTH / df_.DEPTH.values[0]))
|
| 38 |
+
return pd.concat(dfx).reset_index(drop=True)
|
| 39 |
+
|
| 40 |
+
def tweak_data_S(df):
|
| 41 |
+
return (
|
| 42 |
+
df.assign(
|
| 43 |
+
# FRACTURE_ZONE=df.FRACTURE_ZONE.replace({-9999: 0, np.nan: 0}).astype('int8'),
|
| 44 |
+
GR=df.GR.replace({-9999.:0.}).astype('float32'),
|
| 45 |
+
DCALI_FINAL=df.DCALI_FINAL.replace({-9999.:0.}).astype('float32'),
|
| 46 |
+
LLD=df.LLD.replace({-9999.:0.}).astype('float32'),
|
| 47 |
+
LLS=df.LLS.replace({-9999.:0.}).astype('float32'),
|
| 48 |
+
NPHI=df.NPHI.replace({-9999.:0.}).astype('float32'),
|
| 49 |
+
RHOB=df.RHOB.replace({-9999.:0.}).astype('float32'),
|
| 50 |
+
DTC=df.DTC.replace({-9999.:0.}).astype('float32'),
|
| 51 |
+
DTS=df.DTS.replace({-9999.:0.}).astype('float32'),
|
| 52 |
+
DEPTH=df.DEPTH.astype('float32')
|
| 53 |
+
)
|
| 54 |
+
.pipe(remove_negative_val, "RHOB")
|
| 55 |
+
.pipe(remove_negative_val, "DTC")
|
| 56 |
+
.pipe(remove_negative_val, "DTS")
|
| 57 |
+
.pipe(remove_negative_val, "GR")
|
| 58 |
+
.pipe(remove_negative_val, "LLD")
|
| 59 |
+
).pipe(rel_depth)
|
| 60 |
+
# Calculate the confusion matrix of applying model on dataframe (including features and label) df with threshold
|
| 61 |
+
def calculate_confusion_matrix (model = None, df= None, threshold=None):
|
| 62 |
+
model_prediction = [model]
|
| 63 |
+
# Apply model on dataframe
|
| 64 |
+
proba = Prediction_LGBM(trained_models=model_prediction, data = df, feature_names=name_features)
|
| 65 |
+
proba_well = proba.loc[:, "model_0"]
|
| 66 |
+
# Apply threshold
|
| 67 |
+
if threshold==None: threshold = 0.5
|
| 68 |
+
# Get label from dataframe df
|
| 69 |
+
well_proba = proba_well.apply(lambda x: 1 if x >= threshold else 0)
|
| 70 |
+
return well_proba
|
| 71 |
+
|
| 72 |
+
#------------------------------------------------------------------
|
| 73 |
+
# Load any compressed pickle file
|
| 74 |
+
file = "/work/2022_VPIMLogs_WebApp/models/LightGBM_0.45.pbz2"
|
| 75 |
+
def decompress_pickle(file):
|
| 76 |
+
data = bz2.BZ2File(file, 'rb')
|
| 77 |
+
data = pickle.load(data)
|
| 78 |
+
return data
|
| 79 |
+
# model_best = decompress_pickle(file)
|
| 80 |
+
|
| 81 |
+
# Loading Modeling
|
| 82 |
+
# model_best = lgb.Booster(model_file="/work/2022_VPIMLogs_WebApp/models/LGBM_20221125.json")
|
| 83 |
+
|
| 84 |
+
#Loading data from browser:----------------------------------------
|
| 85 |
+
#Streamlit Dashboard------------------------------------------------------------------------------------------
|
| 86 |
+
pagetile = """<center><h1>PREDICTION SITE</h1></center>"""
|
| 87 |
+
st.markdown(pagetile, unsafe_allow_html=True)
|
| 88 |
+
# set_page_config(page='custom')
|
| 89 |
+
|
| 90 |
+
hide_menu_button()
|
| 91 |
+
condense_layout()
|
| 92 |
+
|
| 93 |
+
logo_site, info_site = st.columns([1.5, 8.5])
|
| 94 |
+
with logo_site:
|
| 95 |
+
st.image("https://i.ibb.co/Yd42K98/LogoVPI.png", use_column_width='auto')
|
| 96 |
+
with info_site:
|
| 97 |
+
# Option 1: CSV File Loading
|
| 98 |
+
st.write('You can load your csv file using the file upload or selection from LAS Exploration option below.')
|
| 99 |
+
st.subheader("1. CSV File Loading")
|
| 100 |
+
st.caption('## 1.1. CSV from Uploader')
|
| 101 |
+
df = csv_uploader()
|
| 102 |
+
|
| 103 |
+
# Option 2: CSV from LAS Exploration
|
| 104 |
+
st.caption('## 1.2. CSV from LAS Exploration')
|
| 105 |
+
dir_path = '/work/2022_VPIMLogs_WebApp/data/merged/'
|
| 106 |
+
csv_files = [filename for filename in os.listdir(dir_path) if filename.endswith('.csv')]
|
| 107 |
+
selected_csv_file= st.multiselect('Select a CSV file', csv_files, key = 'st.session_state.selected_well_multi')
|
| 108 |
+
if selected_csv_file: # Nếu người dùng đã chọn file CSV
|
| 109 |
+
# Đọc file csv được chọn vào DataFrame
|
| 110 |
+
file_path = '/work/2022_VPIMLogs_WebApp/data/merged/'
|
| 111 |
+
wells_df_predict = pd.concat([pd.read_csv(file_path + f) for f in selected_csv_file])
|
| 112 |
+
# wells_df_predict = tweak_data_S(wells_df_predict)
|
| 113 |
+
else: # Nếu người dùng không chọn file CSV
|
| 114 |
+
wells_df_predict = df
|
| 115 |
+
# wells_df_predict = tweak_data_S(wells_df_predict)
|
| 116 |
+
|
| 117 |
+
st.write('You can load your json file using the file upload or selection from TRAINING SECTION below.')
|
| 118 |
+
|
| 119 |
+
st.subheader("2. JSON File Loading")
|
| 120 |
+
st.caption('## 2.1. JSON from Uploader')
|
| 121 |
+
model_best_uploader = None
|
| 122 |
+
uploaded_file = st.file_uploader("Choose a JSON file", type="json")
|
| 123 |
+
# Kiểm tra xem có file được upload hay không
|
| 124 |
+
if uploaded_file is not None:
|
| 125 |
+
# Lưu file JSON tạm thời
|
| 126 |
+
with open("temp.json", "w") as f:
|
| 127 |
+
f.write(uploaded_file.read().decode("utf-8"))
|
| 128 |
+
# Đường dẫn tới file JSON tạm thời
|
| 129 |
+
temp_file_path = os.path.abspath("temp.json")
|
| 130 |
+
# Tạo Booster từ file JSON
|
| 131 |
+
model_best_uploader = lgb.Booster(model_file=temp_file_path)
|
| 132 |
+
|
| 133 |
+
# Xóa file tạm sau khi sử dụng
|
| 134 |
+
os.remove(temp_file_path)
|
| 135 |
+
# Option 2: JSON from TRAINING SECTION
|
| 136 |
+
st.caption('## 2.2. JSON from TRANING SECTION')
|
| 137 |
+
dir_path = '/work/2022_VPIMLogs_WebApp/models/'
|
| 138 |
+
json_files = [filename for filename in os.listdir(dir_path) if filename.endswith('.json')]
|
| 139 |
+
selected_json_file= st.multiselect('Select a JSON file', json_files, key = 'st.session_state.selected_well_multi_JSON')
|
| 140 |
+
if selected_json_file: # Nếu người dùng đã chọn file json
|
| 141 |
+
# Đọc file json được chọn vào Booster
|
| 142 |
+
file_path = '/work/2022_VPIMLogs_WebApp/models/'
|
| 143 |
+
model_files = "/work/2022_VPIMLogs_WebApp/models/05_13_2023_11_50_38_model_LGBM.json"
|
| 144 |
+
model_best = lgb.Booster(model_file=model_files)
|
| 145 |
+
else: # Nếu người dùng không chọn file json
|
| 146 |
+
model_best = model_best_uploader
|
| 147 |
+
|
| 148 |
+
if wells_df_predict is not None:
|
| 149 |
+
wells_df_predict = tweak_data_S(wells_df_predict)
|
| 150 |
+
wells_df_predict = wells_df_predict.replace({-9999: np.nan}).dropna(how='any', subset = "FRACTURE_ZONE")
|
| 151 |
+
st.write("Data Input:")
|
| 152 |
+
st.dataframe(wells_df_predict.sort_index(), width=1400, height=300)
|
| 153 |
+
st.write('---')
|
| 154 |
+
st.write("Selected Prediction Model:")
|
| 155 |
+
st.write(model_best)
|
| 156 |
+
#------------------------------------------------------------------
|
| 157 |
+
feature_names = [col for col in wells_df_predict.columns if col not in ["WELL", "DEPTH","FRACTURE_ZONE"]]
|
| 158 |
+
# Full data for export data
|
| 159 |
+
st.session_state.pred = st.button("Predict Fracture Zone")
|
| 160 |
+
if st.session_state.pred:
|
| 161 |
+
threshold = 0.5
|
| 162 |
+
#Make label Prediction
|
| 163 |
+
predictions = (model_best.predict(wells_df_predict[feature_names])> threshold).astype(int)
|
| 164 |
+
wells_df_predict['FRACTURE_ZONE_PRED'] = predictions
|
| 165 |
+
st.dataframe(wells_df_predict, width=1400, height=300)
|
| 166 |
+
#Plot Data------------------------------------------------------------------
|
| 167 |
+
plotting_curves = [c for c in wells_df_predict.columns.unique() if c not in ["DEPTH", "WELL", "TVD", "FRACTURE_ZONE", "FRACTURE_ZONE_PRED", "DCALI_FINAL", "INCL", "AZIM_TN", "rel_depth"]]
|
| 168 |
+
plotting_curves.sort()
|
| 169 |
+
if "FRACTURE_ZONE_PRED" in wells_df_predict.columns.unique():
|
| 170 |
+
plotting_curves.append("FRACTURE_ZONE_PRED")
|
| 171 |
+
for well in wells_df_predict.WELL.unique():
|
| 172 |
+
st.write('---')
|
| 173 |
+
st.write(f"{well} Logs: \n")
|
| 174 |
+
well_plot = wells_df_predict[wells_df_predict.WELL == well]
|
| 175 |
+
charts_dict={}
|
| 176 |
+
for i, c in enumerate(plotting_curves):
|
| 177 |
+
charts_dict[i] = curve_plot(data=well_plot,filted_data=None, x_column=c)
|
| 178 |
+
#Show Curve-----------------------------------------------------------------------
|
| 179 |
+
st.write(alt.concat(*charts_dict.values(), columns = 12).configure(autosize='fit'))
|
| 180 |
+
# Download --------------------------------------------------------------
|
| 181 |
+
st.write('---')
|
| 182 |
+
st.write("Download final result to csv file")
|
| 183 |
+
|
| 184 |
+
st.download_button(label='Download All Wells',
|
| 185 |
+
data = wells_df_predict.to_csv(),
|
| 186 |
+
file_name='FracturePredictionALL.csv',
|
| 187 |
+
mime='text/csv')
|
| 188 |
+
|
| 189 |
+
hide_menu_button()
|
| 190 |
+
condense_layout()
|
requirements.txt
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
altair==4.2.0
|
| 2 |
+
bz2file==0.98
|
| 3 |
+
lasio==0.30
|
| 4 |
+
matplotlib==3.4.3
|
| 5 |
+
numpy==1.21.6
|
| 6 |
+
pandas==1.4.3
|
| 7 |
+
seaborn==0.11.2
|
| 8 |
+
streamlit==1.22.0
|
| 9 |
+
streamlit_vega_lite==0.1.0
|
| 10 |
+
streamlit-nested-layout==0.1.1
|
| 11 |
+
lightgbm==3.3.2
|
| 12 |
+
plotly==5.10.0
|
| 13 |
+
scikit-learn==1.1.2
|
ui/PageComponents.py
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import streamlit as st
|
| 3 |
+
from mLogsFunctions.fx import *
|
| 4 |
+
from mLogsFunctions import *
|
| 5 |
+
|
| 6 |
+
def subtab21(df, well_names):
|
| 7 |
+
col1, col2 = st.columns([1,8])
|
| 8 |
+
if "method_eda" not in st.session_state:
|
| 9 |
+
st.session_state.method_eda:str = "Single Well"
|
| 10 |
+
st.session_state.well_eda:str = well_names[0]
|
| 11 |
+
with col1:
|
| 12 |
+
st.radio("",
|
| 13 |
+
key="method_eda",
|
| 14 |
+
options=["All Wells", "Single Well"])
|
| 15 |
+
st.radio("WELL",
|
| 16 |
+
key="well_eda",
|
| 17 |
+
options=well_names)
|
| 18 |
+
with col2:
|
| 19 |
+
st.write('Data Description:')
|
| 20 |
+
if st.session_state.method_eda == "All Wells":
|
| 21 |
+
st.dataframe(df.describe(),width=1400, height=300)
|
| 22 |
+
elif st.session_state.method_eda == "Single Well":
|
| 23 |
+
df_single_w = df[df.WELL == st.session_state.well_eda]
|
| 24 |
+
st.dataframe(df_single_w.describe(),width=1400, height=300)
|
| 25 |
+
else:
|
| 26 |
+
pass
|
| 27 |
+
|
| 28 |
+
def subtab22(df,):
|
| 29 |
+
def missing_count(df):
|
| 30 |
+
missing = df.isnull().sum()*100/df.isnull().sum().sum()
|
| 31 |
+
missing = missing[missing >= 0].reset_index()
|
| 32 |
+
missing.columns = ['Columns', 'Count missing (%)']
|
| 33 |
+
return missing
|
| 34 |
+
|
| 35 |
+
mt1, mt2, mt3 = st.columns(3)
|
| 36 |
+
|
| 37 |
+
with mt1:
|
| 38 |
+
st.caption("Missing data rate of whole wells")
|
| 39 |
+
st.write(missing_bar(missing_count(df), "ALL WELLS"))
|
| 40 |
+
for i, w in enumerate(df.WELL.unique()):
|
| 41 |
+
if i%3 == 0:
|
| 42 |
+
st.caption(f"Missing data rate of {w}")
|
| 43 |
+
st.write(missing_bar(missing_count(well_filter(df, w)), f"WELL {w}"))
|
| 44 |
+
with mt2:
|
| 45 |
+
for i, w in enumerate(df.WELL.unique()):
|
| 46 |
+
if i%3 == 1:
|
| 47 |
+
st.caption(f"Missing data rate of {w}")
|
| 48 |
+
st.write(missing_bar(missing_count(well_filter(df, w)), f"WELL {w}"))
|
| 49 |
+
with mt3:
|
| 50 |
+
for i, w in enumerate(df.WELL.unique()):
|
| 51 |
+
if i%3 == 2:
|
| 52 |
+
st.caption(f"Missing data rate of {w}")
|
| 53 |
+
st.write(missing_bar(missing_count(well_filter(df, w)), f"WELL {w}"))
|
| 54 |
+
|
| 55 |
+
def subtab23(df, curves):
|
| 56 |
+
mb1, mb2, mb3 = st.columns(3)
|
| 57 |
+
for i, c in enumerate(curves):
|
| 58 |
+
if i%3 == 0:
|
| 59 |
+
with mb1:
|
| 60 |
+
st.caption(f"Distribution of {c}")
|
| 61 |
+
st.write(missing_box(df, c))
|
| 62 |
+
if i%3 == 1:
|
| 63 |
+
with mb2:
|
| 64 |
+
st.caption(f"Distribution of {c}")
|
| 65 |
+
st.write(missing_box(df, c))
|
| 66 |
+
if i%3 == 2:
|
| 67 |
+
with mb3:
|
| 68 |
+
st.caption(f"Distribution of {c}")
|
| 69 |
+
st.write(missing_box(df, c))
|
| 70 |
+
|
| 71 |
+
def subtab24(df, curves):
|
| 72 |
+
#Histogram Line----------------------------------------------------------------
|
| 73 |
+
h1, h2, h3 = st.columns(3)
|
| 74 |
+
for i, c in enumerate(curves):
|
| 75 |
+
if i%3 == 0:
|
| 76 |
+
with h1:
|
| 77 |
+
hist_line_plot(df,c)
|
| 78 |
+
if i%3 == 1:
|
| 79 |
+
with h2:
|
| 80 |
+
hist_line_plot(df,c)
|
| 81 |
+
if i%3 == 2:
|
| 82 |
+
with h3:
|
| 83 |
+
hist_line_plot(df,c)
|
| 84 |
+
|
| 85 |
+
def subtab25(df, curves):
|
| 86 |
+
#CrossPlot----------------------------------------------------------------
|
| 87 |
+
pair_curv = [(a, b) for idx, a in enumerate(curves) for b in curves[idx + 1:]]
|
| 88 |
+
cp0, cp1, cp2, cp3, cp4 = st.columns(5)
|
| 89 |
+
for i, c in enumerate(pair_curv):
|
| 90 |
+
if i%5 == 0:
|
| 91 |
+
with cp0:
|
| 92 |
+
crossplot(df, pair_curv[i][0], pair_curv[i][1])
|
| 93 |
+
if i%5 == 1:
|
| 94 |
+
with cp1:
|
| 95 |
+
crossplot(df, pair_curv[i][0], pair_curv[i][1])
|
| 96 |
+
if i%5 == 2:
|
| 97 |
+
with cp2:
|
| 98 |
+
crossplot(df, pair_curv[i][0], pair_curv[i][1])
|
| 99 |
+
if i%5 == 3:
|
| 100 |
+
with cp3:
|
| 101 |
+
crossplot(df, pair_curv[i][0], pair_curv[i][1])
|
| 102 |
+
if i%5 == 4:
|
| 103 |
+
with cp4:
|
| 104 |
+
crossplot(df, pair_curv[i][0], pair_curv[i][1])
|
| 105 |
+
|
| 106 |
+
def subtab26(df, curves):
|
| 107 |
+
#Pairpot----------------------------------------------------------------
|
| 108 |
+
_p1, _p2, _p3 = st.columns([2,2,2])
|
| 109 |
+
if "pair_opt" not in st.session_state:
|
| 110 |
+
st.session_state.pair_opt:str = "ALL WELLS"
|
| 111 |
+
st.session_state.color_pair:str = "WELL"
|
| 112 |
+
st.session_state.well_pair:str = list(df.WELL.unique())[0]
|
| 113 |
+
with _p1:
|
| 114 |
+
pair_opt_ = st.radio("Displayed objects", key="pair_opt", options=["ALL WELLS", "SINGLE WELL"], horizontal=True)
|
| 115 |
+
with _p2:
|
| 116 |
+
well_pair_ = st.selectbox("WELL", key="well_pair", options=list(df.WELL.unique()))
|
| 117 |
+
with _p3:
|
| 118 |
+
colorp_ = st.selectbox("COLOR", key="color_pair", options=columns_list(df))
|
| 119 |
+
if pair_opt_ == "ALL WELLS":
|
| 120 |
+
st.write(pairplot(df, curves, curves, colorp_))
|
| 121 |
+
elif pair_opt_ == "SINGLE WELL":
|
| 122 |
+
st.write(pairplot(df[df["WELL"]==well_pair_], curves, curves, colorp_))
|
| 123 |
+
else:
|
| 124 |
+
st.write("Undefined Error!")
|
| 125 |
+
|
| 126 |
+
def scatterPoint3D(df,):
|
| 127 |
+
#3D Plotly----------------------------------------------------------------
|
| 128 |
+
wells_ = list(df.WELL.unique())
|
| 129 |
+
curvs_ = columns_list(df, no_well=True)
|
| 130 |
+
colors_ = columns_list(df)
|
| 131 |
+
sizes_ = ["WELL", "FRACTURE_INTENSITY", "DEPTH", None]
|
| 132 |
+
symbols_ = ["WELL", "FRACTURE_INTENSITY", None]
|
| 133 |
+
|
| 134 |
+
if "well_3d" not in st.session_state:
|
| 135 |
+
st.session_state.w_opt:str = "ALL WELLS"
|
| 136 |
+
st.session_state.well_3d:str = wells_[0]
|
| 137 |
+
st.session_state.x_3d:str = curvs_[0]
|
| 138 |
+
st.session_state.y_3d:str = curvs_[0]
|
| 139 |
+
st.session_state.z_3d:str = curvs_[0]
|
| 140 |
+
st.session_state.color_3d:str = "WELL"
|
| 141 |
+
st.session_state.size_3d:str = "DEPTH"
|
| 142 |
+
st.session_state.symbol_3d:str = "WELL"
|
| 143 |
+
|
| 144 |
+
p1_, p2_ = st.columns([1,7])
|
| 145 |
+
with p1_:
|
| 146 |
+
w_opt = st.radio("DisplayType", key="w_opt", options=["ALL WELLS", "SINGLE WELL"])
|
| 147 |
+
well_ = st.selectbox("WELL", key="well_3d", options=wells_)
|
| 148 |
+
x_ = st.selectbox("X", key="x_3d", options=curvs_)
|
| 149 |
+
y_ = st.selectbox("Y", key="y_3d", options=curvs_)
|
| 150 |
+
z_ = st.selectbox("Z", key="z_3d", options=curvs_)
|
| 151 |
+
color_ = st.selectbox("COLOR", key="color_3d", options=colors_)
|
| 152 |
+
size_ = st.selectbox("SIZE", key="size_3d", options=sizes_)
|
| 153 |
+
symbol_ = st.selectbox("SYMBOL", key="symbol_3d", options=symbols_)
|
| 154 |
+
with p2_:
|
| 155 |
+
log_x, log_y, log_z = [False, False, False]
|
| 156 |
+
if x_ in ["LLD", "LLS"]:
|
| 157 |
+
log_x = True
|
| 158 |
+
if y_ in ["LLD", "LLS"]:
|
| 159 |
+
log_y = True
|
| 160 |
+
if z_ in ["LLD", "LLS"]:
|
| 161 |
+
log_z = True
|
| 162 |
+
if w_opt == "ALL WELLS":
|
| 163 |
+
plotly_3d(df, x_, y_, z_, color_, size_, symbol_, log_x, log_y, log_z)
|
| 164 |
+
else:
|
| 165 |
+
df_3d_plt = df[df["WELL"]==well_]
|
| 166 |
+
plotly_3d(df_3d_plt, x_, y_, z_, color_, size_, symbol_, log_x, log_y, log_z)
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
def stViewCurves(df):
|
| 170 |
+
_w = st.selectbox(label='Select WELL', options=list(df.WELL.unique()), key='w_plot')
|
| 171 |
+
if st.session_state.w_plot is not None:
|
| 172 |
+
df_plot = df[df['WELL']== _w]
|
| 173 |
+
_c = st.multiselect("Select curves for plotting:", key="curv_plt", options=columns_list(df, no_depth=True, no_well=True))
|
| 174 |
+
if len(_c) != 0:
|
| 175 |
+
view_curves(df_plot, curves=_c)
|
| 176 |
+
|
ui/UIConfigs.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
from PIL import Image
|
| 3 |
+
|
| 4 |
+
def hide_menu_button():
|
| 5 |
+
st.markdown(""" <style>
|
| 6 |
+
#MainMenu {visibility: hidden;}
|
| 7 |
+
footer {visibility: hidden;}
|
| 8 |
+
</style> """, unsafe_allow_html=True
|
| 9 |
+
)
|
| 10 |
+
|
| 11 |
+
def condense_layout():
|
| 12 |
+
padding = 0
|
| 13 |
+
st.markdown(f""" <style>
|
| 14 |
+
.reportview-container .main .block-container{{
|
| 15 |
+
padding-top: {padding}rem;
|
| 16 |
+
padding-right: {padding}rem;
|
| 17 |
+
padding-left: {padding}rem;
|
| 18 |
+
padding-bottom: {padding}rem;
|
| 19 |
+
}} </style> """, unsafe_allow_html=True
|
| 20 |
+
)
|
| 21 |
+
|
| 22 |
+
def set_page_config(page:str='home', logo_size:str=200, pagetile:str=None):
|
| 23 |
+
img = Image.open("/work/LogoVPI.png")
|
| 24 |
+
st.set_page_config(# Alternate names: setup_page, page, layout
|
| 25 |
+
layout="wide", # Can be "centered" or "wide". In the future also "dashboard", etc.
|
| 26 |
+
initial_sidebar_state="auto", # Can be "auto", "expanded", "collapsed"
|
| 27 |
+
page_title="VPI-MLogs", # String or None. Strings get appended with "• Streamlit".
|
| 28 |
+
page_icon=img, # String, anything supported by st.image, or None.
|
| 29 |
+
)
|
| 30 |
+
if page == 'home':
|
| 31 |
+
col_1, col_2, col_3, col_4, col_5, = st.columns(5)
|
| 32 |
+
with col_3:
|
| 33 |
+
st.image("https://i.ibb.co/Yd42K98/LogoVPI.png", width=logo_size)
|
| 34 |
+
elif page == 'sub':
|
| 35 |
+
logo, info = st.columns([3, 7])
|
| 36 |
+
with logo:
|
| 37 |
+
st.image("https://i.ibb.co/Yd42K98/LogoVPI.png", width=logo_size)
|
| 38 |
+
with info:
|
| 39 |
+
st.markdown(pagetile, unsafe_allow_html=True)
|
| 40 |
+
|
| 41 |
+
|
ui/__init__.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .UIConfigs import *
|
| 2 |
+
from .PageComponents import *
|
| 3 |
+
|
| 4 |
+
__all__ = ['hide_menu_button',
|
| 5 |
+
'condense_layout',
|
| 6 |
+
'set_page_config',
|
| 7 |
+
|
| 8 |
+
'subtab21',
|
| 9 |
+
'subtab22',
|
| 10 |
+
'subtab23',
|
| 11 |
+
'subtab24',
|
| 12 |
+
'subtab25',
|
| 13 |
+
'subtab26',
|
| 14 |
+
|
| 15 |
+
'scatterPoint3D',
|
| 16 |
+
'stViewCurves',
|
| 17 |
+
|
| 18 |
+
]
|
ui/__pycache__/PageComponents.cpython-39.pyc
ADDED
|
Binary file (6 kB). View file
|
|
|
ui/__pycache__/UIConfigs.cpython-39.pyc
ADDED
|
Binary file (1.67 kB). View file
|
|
|
ui/__pycache__/__init__.cpython-39.pyc
ADDED
|
Binary file (347 Bytes). View file
|
|
|