Spaces:
Sleeping
Sleeping
Ver 1.0, Plot by Projecting SEDs on 3D TOP surface
Browse files- app.py +61 -0
- header.py +9 -0
- home.py +28 -0
- load_css.py +7 -0
- plotting.py +71 -0
- raw_data.py +18 -0
- read_kvl_file.py +48 -0
- style.css +15 -0
app.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
st.set_page_config(layout="wide", page_title='Rock physics template v.0.1')
|
| 3 |
+
|
| 4 |
+
from load_css import local_css
|
| 5 |
+
# import pandas as pd
|
| 6 |
+
# Local Imports
|
| 7 |
+
import home
|
| 8 |
+
# import raw_data
|
| 9 |
+
import plotting
|
| 10 |
+
import header
|
| 11 |
+
import read_kvl_file as kvl
|
| 12 |
+
# import plotly.express as px
|
| 13 |
+
|
| 14 |
+
# from io import StringIO
|
| 15 |
+
|
| 16 |
+
local_css("style.css")
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
@st.cache_data
|
| 20 |
+
def load_data(uploaded_file):
|
| 21 |
+
if uploaded_file is not None:
|
| 22 |
+
try:
|
| 23 |
+
data=kvl.read_kvl_file(uploaded_file)
|
| 24 |
+
|
| 25 |
+
except UnicodeDecodeError as e:
|
| 26 |
+
st.error(f"error loading log.kvl: {e}")
|
| 27 |
+
else:
|
| 28 |
+
data=None
|
| 29 |
+
|
| 30 |
+
return data
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
# Sidebar Options & File Uplaod
|
| 34 |
+
kvl_file=None
|
| 35 |
+
st.sidebar.write('# KVL Data Visualisation')
|
| 36 |
+
st.sidebar.write('To begin using the app, load your KVL file using the file upload option below.')
|
| 37 |
+
|
| 38 |
+
path = st.sidebar.file_uploader('Choose a kvl files', accept_multiple_files=True, type=['.kvl'])
|
| 39 |
+
for uploadfile in path:
|
| 40 |
+
#uploadedfile =
|
| 41 |
+
kvl_file = load_data(uploadfile)
|
| 42 |
+
|
| 43 |
+
if kvl_file:
|
| 44 |
+
st.sidebar.success('File Uploaded Successfully')
|
| 45 |
+
st.sidebar.write(f'<b>Keys Name</b>: {kvl_file.keys()}',unsafe_allow_html=True)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
# Sidebar Navigation
|
| 49 |
+
st.sidebar.title('Navigation')
|
| 50 |
+
options = st.sidebar.radio('Select a page:',
|
| 51 |
+
['Home', 'Keys Information', 'Data Visualisation',
|
| 52 |
+
])
|
| 53 |
+
|
| 54 |
+
if options == 'Home':
|
| 55 |
+
home.home()
|
| 56 |
+
elif options == 'Keys Information':
|
| 57 |
+
header.header(kvl_file)
|
| 58 |
+
# elif options == 'Data Information':
|
| 59 |
+
# raw_data.raw_data(kvl_file)
|
| 60 |
+
elif options == 'Data Visualisation':
|
| 61 |
+
plotting.plot(kvl_file)
|
header.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
|
| 3 |
+
def header(kvl_file):
|
| 4 |
+
st.title('KVL File Keys Info')
|
| 5 |
+
if not kvl_file:
|
| 6 |
+
st.warning('No file has been uploaded')
|
| 7 |
+
else:
|
| 8 |
+
for keys in kvl_file:
|
| 9 |
+
st.write(keys)
|
home.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
|
| 3 |
+
def home():
|
| 4 |
+
#pweb = """<a href='http://andymcdonald.scot' target="_blank">http://andymcdonald.scot</a>"""
|
| 5 |
+
#sm_li = """<a href='https://www.linkedin.com/in/andymcdonaldgeo/' target="_blank"><img src='https://cdn.exclaimer.com/Handbook%20Images/linkedin-icon_32x32.png'></a>"""
|
| 6 |
+
#sm_tw = """<a href='https://twitter.com/geoandymcd' target="_blank"><img src='https://cdn.exclaimer.com/Handbook%20Images/twitter-icon_32x32.png'></a>"""
|
| 7 |
+
#sm_med = """<a href='https://medium.com/@andymcdonaldgeo/' target="_blank"><img src='https://cdn.exclaimer.com/Handbook%20Images/Medium_32.png'></a>"""
|
| 8 |
+
email = """ <a href="mailto:phongnt@vpi.pvn.vn"> phongnt@vpi.pvn.vn </a> """
|
| 9 |
+
st.title('KVL Data Visualisation')
|
| 10 |
+
st.write('## Welcome to the KVL Visualisation Tool')
|
| 11 |
+
st.write('### Created by N. T. Phong')
|
| 12 |
+
st.write('''KVL Visualisation is a tool designed using Python and Streamlit to help you view and gain an understanding the data in your KVL file.''')
|
| 13 |
+
st.write('To begin using the app, load your KVL file using the file upload option on the sidebar. Once you have done this, you can navigate to the relevant tools using the Navigation menu.')
|
| 14 |
+
st.write('\n')
|
| 15 |
+
st.write('## Sections')
|
| 16 |
+
st.write('**Keys Info:** Information from the KVL file header/keys.')
|
| 17 |
+
st.write('**Data Visualisation:** Visualisation tools to view las file data on a log plot, crossplot and histogram.')
|
| 18 |
+
|
| 19 |
+
st.write('## Get in Touch')
|
| 20 |
+
#st.write(f'\nIf you want to get in touch, you can find me on Social Media at the links below or visit my website at: {pweb}.', unsafe_allow_html=True)
|
| 21 |
+
st.write(f'\nIf you want to get in touch, you can find me on the following email:')
|
| 22 |
+
st.write(f'{email}', unsafe_allow_html=True)
|
| 23 |
+
|
| 24 |
+
#st.write(f'{sm_li} {sm_med} {sm_tw}', unsafe_allow_html=True)
|
| 25 |
+
|
| 26 |
+
#st.write('## Source Code, Bugs, Feature Requests')
|
| 27 |
+
#githublink = """<a href='https://github.com/andymcdgeo/las_explorer' target="_blank">https://github.com/andymcdgeo/las_explorer</a>"""
|
| 28 |
+
#st.write(f'\n\nCheck out the GitHub Repo at: {githublink}. If you find any bugs or have suggestions, please open a new issue and I will look into it.', unsafe_allow_html=True)
|
load_css.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# https://discuss.streamlit.io/t/colored-boxes-around-sections-of-a-sentence/3201/2
|
| 2 |
+
|
| 3 |
+
import streamlit as st
|
| 4 |
+
|
| 5 |
+
def local_css(file_name):
|
| 6 |
+
with open(file_name) as f:
|
| 7 |
+
st.markdown('<style>{}</style>'.format(f.read()), unsafe_allow_html=True)
|
plotting.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
import plotly.graph_objects as go
|
| 3 |
+
import numpy as np
|
| 4 |
+
|
| 5 |
+
def plot(kvl_file):
|
| 6 |
+
st.title('KVL Data Visualisation')
|
| 7 |
+
nt = 0
|
| 8 |
+
sampleno = 0
|
| 9 |
+
|
| 10 |
+
if not kvl_file:
|
| 11 |
+
st.warning('No file has been uploaded')
|
| 12 |
+
else:
|
| 13 |
+
if 'TIME' in kvl_file:
|
| 14 |
+
nt = len(kvl_file['TIME'])
|
| 15 |
+
dt = int(kvl_file['TIME'][1]) - int(kvl_file['TIME'][0])
|
| 16 |
+
t_iter = list(kvl_file['TIME'])
|
| 17 |
+
keys = list(kvl_file.keys())
|
| 18 |
+
|
| 19 |
+
curves = st.multiselect('Select TOP Key to Visualize surface, SED keys to project', keys)
|
| 20 |
+
inst = st.select_slider('Select Time Instance', t_iter)
|
| 21 |
+
gridno=st.checkbox('Grid on')
|
| 22 |
+
time = int(inst) / dt
|
| 23 |
+
sampleno = len(kvl_file['TOP']) / nt
|
| 24 |
+
start_index = int(time * sampleno)
|
| 25 |
+
end_index = start_index + int(sampleno)
|
| 26 |
+
|
| 27 |
+
# Get the data for the current instance
|
| 28 |
+
for curve in curves:
|
| 29 |
+
height_data = kvl_file['TOP'][start_index:end_index]
|
| 30 |
+
intensity_data= kvl_file[curve][start_index:end_index]
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
# Create the surface plot for the 'TOP' key
|
| 34 |
+
z_data = np.array(height_data)
|
| 35 |
+
x_data = np.arange(z_data.shape[1])
|
| 36 |
+
y_data = np.arange(z_data.shape[0])
|
| 37 |
+
|
| 38 |
+
# Create meshgrid for surface
|
| 39 |
+
xGrid, yGrid = np.meshgrid(x_data, y_data)
|
| 40 |
+
xRev, yRev = np.meshgrid(y_data, x_data)
|
| 41 |
+
|
| 42 |
+
# Create figure
|
| 43 |
+
fig = go.Figure(data=[go.Surface(x=x_data, y=y_data, z=z_data,surfacecolor=intensity_data,colorscale='Rainbow')])
|
| 44 |
+
if gridno: #grid on
|
| 45 |
+
for i,j,k in zip(xGrid,yGrid,z_data):
|
| 46 |
+
fig.add_trace(go.Scatter3d(x=i,y=j,z=k, mode='lines', line=dict(color='black', width=1,)))
|
| 47 |
+
for i,j,k in zip(xRev,yRev,z_data.T):
|
| 48 |
+
fig.add_trace(go.Scatter3d(x=j,y=i,z=k, mode='lines', line=dict(color='black', width=1,)))
|
| 49 |
+
|
| 50 |
+
# Update the layout of the figure
|
| 51 |
+
fig.update_layout(
|
| 52 |
+
height=700,
|
| 53 |
+
showlegend=False,
|
| 54 |
+
title='KVL Data Visualisation of '+curve,
|
| 55 |
+
scene=dict(
|
| 56 |
+
xaxis_title='X',
|
| 57 |
+
yaxis_title='Y',
|
| 58 |
+
zaxis_title='Z',
|
| 59 |
+
aspectmode='manual',
|
| 60 |
+
aspectratio=dict(x=1.5, y=1.5, z=1),
|
| 61 |
+
camera=dict(
|
| 62 |
+
eye=dict(x=2.2, y=-1, z=0.6)
|
| 63 |
+
),
|
| 64 |
+
)
|
| 65 |
+
)
|
| 66 |
+
|
| 67 |
+
# Display the figure
|
| 68 |
+
st.plotly_chart(fig, theme=None, use_container_width=True)
|
| 69 |
+
|
| 70 |
+
else:
|
| 71 |
+
st.warning('No time data found')
|
raw_data.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
# import pandas as pd
|
| 3 |
+
|
| 4 |
+
def raw_data(las_file, well_data):
|
| 5 |
+
st.title('KVL File Data Info')
|
| 6 |
+
if not las_file:
|
| 7 |
+
st.warning('No file has been uploaded')
|
| 8 |
+
else:
|
| 9 |
+
st.write('**Curve Information**')
|
| 10 |
+
for count, curve in enumerate(las_file.curves):
|
| 11 |
+
# st.write(f"<b>Curve:</b> {curve.mnemonic}, <b>Units: </b>{curve.unit}, <b>Description:</b> {curve.descr}", unsafe_allow_html=True)
|
| 12 |
+
st.write(f" {curve.mnemonic} ({curve.unit}): {curve.descr}", unsafe_allow_html=True)
|
| 13 |
+
st.write(f"<b>There are a total of: {count+1} curves present within this file</b>", unsafe_allow_html=True)
|
| 14 |
+
|
| 15 |
+
st.write('<b>Curve Statistics</b>', unsafe_allow_html=True)
|
| 16 |
+
st.write(well_data.describe())
|
| 17 |
+
st.write('<b>Raw Data Values</b>', unsafe_allow_html=True)
|
| 18 |
+
st.dataframe(data=well_data)
|
read_kvl_file.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
def read_kvl_file(file):
|
| 2 |
+
data = {}
|
| 3 |
+
current_key = None
|
| 4 |
+
|
| 5 |
+
for line in file:
|
| 6 |
+
line = line.decode().strip() # Convert bytes to string and strip whitespace
|
| 7 |
+
if not line: # Skip empty lines
|
| 8 |
+
continue
|
| 9 |
+
if '=' in line:
|
| 10 |
+
key, value = line.split('=')
|
| 11 |
+
key = key.strip()
|
| 12 |
+
value = value.strip()
|
| 13 |
+
if value: # Non-empty value, treat as vector data
|
| 14 |
+
if key not in data:
|
| 15 |
+
data[key] = []
|
| 16 |
+
try:
|
| 17 |
+
data[key].append(float(value))
|
| 18 |
+
except ValueError:
|
| 19 |
+
data[key].append(value)
|
| 20 |
+
else: # Empty value, treat as matrix data
|
| 21 |
+
current_key = key
|
| 22 |
+
if current_key not in data:
|
| 23 |
+
data[current_key] = [] # Initialize list to store matrices
|
| 24 |
+
elif current_key:
|
| 25 |
+
row_values = line.split()
|
| 26 |
+
if row_values:
|
| 27 |
+
data[current_key].append([float(value) for value in row_values])
|
| 28 |
+
|
| 29 |
+
return data
|
| 30 |
+
|
| 31 |
+
# def write_data_to_file(file_path, data):
|
| 32 |
+
# with open(file_path, 'w') as file:
|
| 33 |
+
# for key, values in data.items():
|
| 34 |
+
# file.write(key + ':\n')
|
| 35 |
+
# if isinstance(values[0], list): # Matrix data
|
| 36 |
+
# for row in values:
|
| 37 |
+
# file.write(' '.join(row) + '\n')
|
| 38 |
+
# else: # Vector data
|
| 39 |
+
# for value in values:
|
| 40 |
+
# file.write(value + '\n')
|
| 41 |
+
|
| 42 |
+
# # Example usage
|
| 43 |
+
# input_file_path = 'd:\Git\KVL_visualize\Turbidites_out.kvl'
|
| 44 |
+
# output_file_path = 'd:\Git\KVL_visualize\Test.txt'
|
| 45 |
+
|
| 46 |
+
# kvl_data = read_kvl_file(input_file_path)
|
| 47 |
+
|
| 48 |
+
# write_data_to_file(output_file_path, kvl_data)
|
style.css
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.green_text {
|
| 2 |
+
color: green;
|
| 3 |
+
}
|
| 4 |
+
|
| 5 |
+
.bold_text {
|
| 6 |
+
font-weight: bold;
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
.load_successful_text{
|
| 10 |
+
background-color: green;
|
| 11 |
+
color:white;
|
| 12 |
+
border-radius: 0.4em;
|
| 13 |
+
padding: 0.5rem;
|
| 14 |
+
font-weight: bold;
|
| 15 |
+
}
|