def test_project(): """ Test basic stuff. """ project = Project.from_las('tests/1.las') assert len(project) == 1 w = Well.from_las('tests/2.las') project += w assert w in project assert len(project) == 2 project += project assert project.uwis[0] == 1 s = "<table><tr><th>UWI</th><th>Data</th><th>Curves</th></tr><tr><td>1</td>" assert s in project._repr_html_() # Check __getitem__. assert project[1] == w assert len(project[:2]) == 2 l = [0, 1] assert len(project[l]) == 2 assert len(project.get_mnemonics(['DT'])) == 4 html = project.curve_table_html() assert "<table><tr><th>UWI</th><th>Data</th>" in html assert "<th>DPHI_SAN</th>" in html s = """<td style="background-color:#CCEECC; line-height:80%; padding:5px 4px 2px 4px;">DTS<div style="font-size:80%; float:right; padding:4px 0px 4px 6px; color:#CCCCCC;"></div><br /><span style="font-size:70%; color:#33AA33">us/ft</span></td>""" assert s in html
def test_project(): """ Test basic stuff. """ project = Project.from_las('tests/1.las') assert len(project) == 1 w = Well.from_las('tests/2.las') project += w assert w in project assert len(project) == 2 project += project assert project.uwis[0] == '1' s = "<table>" s += "<tr><th>Index</th><th>UWI</th><th>Data</th><th>Curves</th></tr>" s += "<tr><td>0</td><td><strong>1</strong></td>" assert s in project._repr_html_() # Check __getitem__. assert project[1] == w assert len(project[:2]) == 2 l = [0, 1] assert len(project[l]) == 2 assert len(project.get_mnemonics(['DT'])) == 4 html = project.curve_table_html() assert '<table><tr><th>Idx</th><th>UWI</th><th>Data</th><th>Passing</th>' in html assert "<th>DPHI_SAN</th>" in html s = """<td style="background-color:#CCEECC; line-height:80%; padding:5px 4px 2px 4px;">DTS""" assert s in html
def test_project(): """ Test basic stuff. """ project = Project.from_las('tests/1.las') assert len(project) == 1 w = Well.from_las('tests/2.las') project += w assert w in project assert len(project) == 2 project += project assert project.uwis[0] == 1 s = "<table><tr><th>UWI</th><th>Data</th><th>Curves</th></tr><tr><td>1</td>" assert s in project._repr_html_() # Check __getitem__. assert project[1] == w assert len(project[:2]) == 2 l = [0, 1] assert len(project[l]) == 2 assert len(project.get_mnemonics(['DT'])) == 4 html = project.curve_table_html() assert '<table><tr><th>Idx</th><th>UWI</th><th>Data</th><th>Quality</th>' in html assert "<th>DPHI_SAN</th>" in html s = """<td style="background-color:#CCEECC; line-height:80%; padding:5px 4px 2px 4px;">DTS""" assert s in html
def load_wells(): base_dir = "./data/McMurray_data" # # load well data """Need to add a method for the user to point to the directory or add additional las files later""" fpath = Path(base_dir+"/las/*.LAS") return Project.from_las(str(fpath))
def test_data_as_matrix(): alias = {'Sonic': ['DT', 'foo']} project = Project.from_las('tests/*.las') X_train, y_train = project.data_as_matrix(X_keys=['DEPT', 'HCAL', 'Sonic'], y_key='CALI', alias=alias, window_length=1, remove_zeros=True, ) assert X_train.shape[0] == y_train.size
def __init__(self, well_name: str = None): """ Class that wraps `welly` to read borehole data - las files and deviations, csv, excel - and converts it into a `subsurface.UnstructuredData` This class is only meant to be extended with all the necessary functionality to load borehole data. For extensive manipulations of the data it should be done in `welly` itself. We need a class because it is going to be quite difficult to make one single function that fits all A borehole has: - Datum (XYZ location) - Deviation - Lithology: For this we are going to need striplog - Logs Everything would be a LineSet with a bunch of properties Parameters ---------- well_name (Optional[str]): Name of the borehole Notes ----- TODO: I think welly can initialize a Well from a file. That would be something to consider later on """ # Init empty Project self.p = Project([]) self._well_names = set() # Init empty well self.well = Well(params={'header': {'name': well_name}}) self.well.location = Location(params={'kb': 100})
def test_data_as_matrix(): alias = {'Sonic': ['DT', 'foo']} project = Project.from_las('tests/*.las') X_train, y_train = project.data_as_matrix( X_keys=['DEPT', 'HCAL', 'Sonic'], y_key='CALI', alias=alias, window_length=1, remove_zeros=True, ) assert X_train.shape[0] == y_train.size
def make_well_project(laspath='data/las/', stripath='data/tops/'): """ Return a dictionary of wells and striplogs where the key is the base filename """ wells = {} lasfiles = glob(laspath + '*.LAS') stripfiles = glob(stripath + '*.csv') for fname, sname in zip(lasfiles, stripfiles): name = fname.split('/')[-1].split('.')[0] wells[name] = Well.from_las(fname) wells[name].data['tops'] = Striplog.from_csv(sname) proj = Project(list(wells.values())) return proj
def make_well_project(laspath='data/las/', stripath='data/tops/'): """ Return a dictionary of wells and striplogs where the key is the base filename This assumes that the las file and tops files have the same name """ wells = {} lasfiles = glob(laspath + '*.LAS') stripfiles = glob(stripath + '*.csv') for fname, sname in zip(lasfiles, stripfiles): name = Path(fname).stem wells[name] = Well.from_las(fname) wells[name].data['tops'] = Striplog.from_csv(sname) proj = Project(list(wells.values())) return proj
def test_data_as_matrix(): alias = {'Sonic': ['DT', 'foo']} project = Project.from_las('tests/*.las')
import json import numpy as np import pandas as pd from pathlib import Path import numpy as np import helper app = Dash(__name__) # Create server variable with Flask server object for use with gunicorn server = app.server # # load well data """Need to add a method for the user to point to the directory or add additional las files later""" #w = Well.from_las(str(Path("data/las/PoseidonNorth1Decim.LAS"))) #original example p = Project.from_las(str(Path("data/McMurray_data/las/*.LAS"))) well_uwi = [w.uwi for w in p ] ##gets the well uwi data for use in the well-selector tool df = p[0].df() ##gets data from the first well in the Welly Project curve_list = df.columns.tolist( ) ##gets the column names for later use in the curve-selector tool curve = curve_list[ 0] ##gets the first curve name to be used as the first curve displayed in the plotly figure ## Load well top data surface_picks_df = pd.read_table(Path('./data/McMurray_data/PICKS.TXT'), usecols=['UWI', 'PICK', 'MD']) #well dropdown selector well_dropdown_options = [{
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP]) # Create server variable with Flask server object for use with gunicorn server = app.server # Get las files path = 'data/Poseidon_data/las/' # direct link to specific data lasfiles = glob(path + '*.LAS') # Get striplog files path2 = 'data/Poseidon_data/tops/' # direct link to specific data stripfiles = glob(path2 + '*.csv') legend = Legend.from_csv(filename='data/Poseidon_data/tops_legend.csv' ) # direct link to specific data p = Project.from_las( 'data/Poseidon_data/las/*.LAS') # direct link to specific data well_uwi = [w.uwi for w in p ] ##gets the well uwi data for use in the well-selector tool # Add striplogs to Project # Striplog must have the same name as LAS file. # e.g. Torosa-1.LAS and Torosa-1.csv for w in p: name = Path(w.fname).stem strip = Striplog.from_csv( f'data/Poseidon_data/tops/{name}.csv') # direct link to specific data w.data['tops'] = strip well = p[0] ##gets data from the first well in the Welly Project curve_list = get_curves( p) ##gets the column names for later use in the curve-selector tool
from welly import Well, Project from glob import glob # # load well data """Need to add a method for the user to point to the directory or add additional las files later""" #w = Well.from_las(str(Path("well_picks/data/las/PoseidonNorth1Decim.LAS"))) #original example # Get las files path = 'las/' print('\n LAS PATH:', path, '\n') lasfiles = glob(path + '*.LAS') for fname in lasfiles: print(' ' * 5, fname) print('\n') # Get striplog files path2 = 'tops/' print('\n STRIP PATH:', path2, '\n') stripfiles = glob(path2 + '*.csv') for fname in stripfiles: print(' ' * 5, fname) print('\n') p = Project.from_las("las/*.LAS") well_uwi = [w.uwi for w in p ] ##gets the well uwi data for use in the well-selector tool print(p)
from welly import Project from alaska import Alias, get_data_path path = str(get_data_path("testcase1.las")) # initialize aliaser a = Alias() # the parameters can also be customized as such: # a = Alias(dictionary=True, keyword_extractor=True, # model=True, prob_cutoff=.5) # the parse function returns two dictionaries, one for parsed # and another one for mnemonics not found using the aliaser parsed, not_found = a.parse(path) # print aliased mnemonics to screen print("*" * 10, "Aliased dictionary", "*" * 10) for i in parsed: print("{}: {}".format(i, parsed[i])) print("Not parsed with Aliaser:", not_found) # feed parsed dictionary into welly, and leave the not aliased # ones alone p = Project.from_las(path) data = p.df(keys=list(parsed.keys()), alias=parsed) print(data) # print the heatmap of the aliased mnemonics to visualize results a.heatmap()
for fname in lasfiles: print(' '*5, fname) print('\n') # Get striplog files path2 = 'data/Poseidon_data/tops/' print('\n STRIP PATH:', path2, '\n') stripfiles = glob(path2 + '*.csv') for fname in stripfiles: print(' '*5, fname) print('\n') tops_legend = Legend.from_csv(filename='data/Poseidon_data/tops_legend.csv') p = Project.from_las('data/Poseidon_data/las/*.LAS') well_uwi = [w.uwi for w in p] ##gets the well uwi data for use in the well-selector tool # Add striplogs to Project # Striplog must have the same name as LAS file. # e.g. Torosa-1.LAS and Torosa-1.csv for w in p: name = Path(w.fname).name.split('.')[0] new_path = f'data/Poseidon_data/tops/{name}.csv' print(name, new_path) strip = Striplog.from_csv(f'data/Poseidon_data/tops/{name}.csv') w.data['tops'] = strip # Make the well correlation panel def encode_xsection(p):
import json import numpy as np import pandas as pd from pathlib import Path import helper app = Dash(__name__) # Create server variable with Flask server object for use with gunicorn server = app.server # # load well data """Need to add a method for the user to point to the directory or add additional las files later""" #w = Well.from_las(str(Path("well_picks/data/las/PoseidonNorth1Decim.LAS"))) #original example p = Project.from_las(str(Path("well_picks/data/las/*.LAS"))) well_uwi = [w.uwi for w in p] ##gets the well uwi data for use in the well-selector tool df = p[0].df() ##gets data from the first well in the Welly Project curve_list = df.columns.tolist() ##gets the column names for later use in the curve-selector tool curve = curve_list[0] ##gets the first curve name to be used as the first curve displayed in the plotly figure ## Load well top data """sample pick data, this will eventually need to load data from file or other source into the current dict""" surface_picks = {"Sea Bed": 520.4, "Montara Formation": 4620, "Plover Formation (Top Volcanics)": 4703.2, "Plover Formation (Top Reservoir)": 4798.4, "Nome Formation": 5079} #well dropdown selector well_dropdown_options = [{'label': k, 'value': k} for k in well_uwi] ##list of wells to the dropdown #tops dropdown options
from welly import Project from alaska import Alias, get_data_path PATH = str(get_data_path("722436A.las")) # initialize aliaser a = Alias() # the parameters can also be customized as such: # a = Alias(dictionary=True, keyword_extractor=True, # model=True, prob_cutoff=.5) # the parse function returns two dictionaries, one for parsed # and another one for mnemonics not found using the aliaser parsed, not_found = a.parse(PATH) # print aliased mnemonics to screen print("*" * 10, "Aliased dictionary", "*" * 10) for i in parsed: print("{}: {}".format(i, parsed[i])) print("Not parsed with Aliaser:", not_found) # feed parsed dictionary into welly, and leave the not aliased # ones alone p = Project.from_las(PATH) data = p.df(keys=list(parsed.keys()), alias=parsed) print(data) # print the heatmap of the aliased mnemonics to visualize results a.heatmap()
import streamlit as st import json import random import pandas as pd import plotly.graph_objects as go from welly import Project from pathlib import Path import helper2 base_dir = "./data/McMurray_data" fpath = Path(base_dir+"/las/*.LAS") p = Project.from_las(str(fpath)) #get the first well. this need to be updated with the well list df = p[0].df() def app(): st.title('Correlation Panel') st.write('well logs displayed below') # first argument takes the titleof the selectionbox # second argument takes options f = open('/home/user/github_repo/t21-hack-SwellCorr/log_dict.json',) log_inp = json.load(f)
class WellyToSubsurface: def __init__(self, well_name: str = None): """ Class that wraps `welly` to read borehole data - las files and deviations, csv, excel - and converts it into a `subsurface.UnstructuredData` This class is only meant to be extended with all the necessary functionality to load borehole data. For extensive manipulations of the data it should be done in `welly` itself. We need a class because it is going to be quite difficult to make one single function that fits all A borehole has: - Datum (XYZ location) - Deviation - Lithology: For this we are going to need striplog - Logs Everything would be a LineSet with a bunch of properties Parameters ---------- well_name (Optional[str]): Name of the borehole Notes ----- TODO: I think welly can initialize a Well from a file. That would be something to consider later on """ # Init empty Project self.p = Project([]) self._well_names = set() # Init empty well self.well = Well(params={'header': {'name': well_name}}) self.well.location = Location(params={'kb': 100}) def __repr__(self): return self.p.__repr__() def add_wells(self, well_names: Iterable): new_boreholes = self._well_names.symmetric_difference(well_names) self._well_names = self._well_names.union(well_names) for b in new_boreholes: # TODO: Name and uwi should be different w = Well(params={'header': {'name': b, 'uwi': b}}) w.location = Location(params={'kb': 100}) self.p += w return self.p def add_datum(self, data: pd.DataFrame): unique_borehole = np.unique(data.index) self.add_wells(unique_borehole) for b in unique_borehole: w = self.p.get_well(b) assert data.loc[[b]].shape[1] == 3, 'datum must be XYZ coord' w.position = data.loc[[b]].values return self.p def add_collar(self, *args, **kwargs): """Alias for add_datum""" return self.add_datum(*args, **kwargs) def add_striplog(self, data: pd.DataFrame): unique_borehole = np.unique(data.index) self.add_wells(unique_borehole) for b in unique_borehole: w = self.p.get_well(b) data_dict = data.loc[b].to_dict('list') s = Striplog.from_dict(data_dict, points=True) start, stop, step_size = self._calculate_basis_parameters(w, w.location.md.shape[0]) s_log, basis, table = s.to_log(step_size, start, stop, return_meta=True) w.data['lith'] = s w.data['lith_log'] = Curve(s_log, basis) return self.p def add_assays(self, data: pd.DataFrame, basis: Union[str, Iterable]): unique_borehole = np.unique(data.index) self.add_wells(unique_borehole) assay_attributes = data.columns if type(basis) == str: assay_attributes = assay_attributes.drop(basis) basis = data[basis] elif type(basis) == Iterable: pass else: raise AttributeError('basis must be either a string with the column name' 'or a array like object') for b in unique_borehole: for a in assay_attributes: w = self.p.get_well(b) w.data[a] = Curve(data[a], basis) return self.p @staticmethod def _calculate_basis_parameters(well, n_points): max_ = well.location.md.max() min_ = well.location.md.min() step_size = (max_ - min_) / n_points return min_ + step_size / 2, max_ - step_size / 2, step_size + 1e-12 def add_deviation(self, deviations: pd.DataFrame, td=None, method='mc', update_deviation=True, azimuth_datum=0): """ Add a deviation survey to this instance, and try to compute a position log from it. Args: deviations (pd.DataFrame): td method update_deviation azimuth_datum """ unique_borehole = np.unique(deviations.index) self.add_wells(unique_borehole) for b in unique_borehole: w = self.p.get_well(b) w.location.add_deviation(deviations.loc[b, ['md', 'inc', 'azi']], td=td, method=method, update_deviation=update_deviation, azimuth_datum=azimuth_datum) return self.p def trajectory(self, datum=None, elev=True, points=1000, **kwargs): """ Get regularly sampled well trajectory. Assumes there is a position log already, e.g. resulting from calling `add_deviation()` on a deviation survey. Args: datum (array-like): A 3-element array with adjustments to (x, y, z). For example, the x-position, y-position, and KB of the tophole location. This is also known as collar of the borehole. elev (bool): In general the (x, y, z) array of positions will have z as TVD, which is positive down. If `elev` is True, positive will be upwards. points (int): The number of points in the trajectory. kwargs: Will be passed to `scipy.interpolate.splprep()`. Returns: ndarray. An array with shape (`points` x 3) representing the well trajectory. Columns are (x, y, z). """ return self.well.location.trajectory(datum=datum, elev=elev, points=points, **kwargs) def to_subsurface(self, elev=True, n_points=1000, return_element=False, convert_lith=True, **kwargs): """Method to convert well data to `subsurface.UnstructuredData` Args: elev (bool): In general the (x, y, z) array of positions will have z as TVD, which is positive down. If `elev` is True, positive will be upwards. n_points (int): Number of vertex used to describe the geometry of the well. return_element (bool): if True return a `subsurface.LineSet` instead convert_lith (bool): if True convert lith from stiplog to curve **kwargs: `Well.location.trajectory` kwargs Returns: """ vertex = np.zeros((0, 3)) cells = np.zeros((0, 2), dtype=np.int_) last_index = 0 for w in self.p.get_wells(): if w.location.position is None: raise AttributeError('At least one of the wells do not have' 'assigned a survey.') xyz = w.location.trajectory(None, elev, n_points, **kwargs) # Make sure deviation is there a = np.arange(0 + last_index, xyz.shape[0] - 1 + last_index, dtype=np.int_) b = np.arange(1 + last_index, xyz.shape[0] + last_index, dtype=np.int_) last_index += xyz.shape[0] cells_b = np.vstack([a, b]).T vertex = np.vstack((vertex, xyz)) cells = np.vstack((cells, cells_b)) # Change curve basis start, stop, step_size = self._calculate_basis_parameters(w, n_points) basis = np.arange(start, stop, step_size) w.unify_basis(keys=None, basis=basis) # Convert striplog into Curve if convert_lith is True: try: start, stop, step_size = self._calculate_basis_parameters(w, n_points - 1) s_log, basis, table = w.data['lith'].to_log(step_size, start, stop, return_meta=True) w.data['lith_log'] = Curve(s_log, basis) except KeyError: warnings.warn(f'No lith curve in this borehole {w.name}. Setting values' 'to 0') w.data['lith_log'] = Curve(np.zeros(n_points - 1)) try: df = self.p.df().loc['foo'] except KeyError: df = self.p.df() df = self.p.df() unstructured_data = UnstructuredData( vertex, cells, df ) if return_element is True: return LineSet(unstructured_data) else: return unstructured_data