Skip to content

Commit

Permalink
Merge pull request #15 from AlexanderJuestel/dev_pybore
Browse files Browse the repository at this point in the history
Dev pybore
  • Loading branch information
AlexanderJuestel authored Dec 4, 2023
2 parents a3b7a2c + 12ee1fb commit 3d286c8
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 40 deletions.
3 changes: 3 additions & 0 deletions environment_dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ dependencies:
- pip
- pip:
- matplotlib
- sphinx_book_theme==0.3.3
- sphinx_copybutton
- nbsphinx

243 changes: 206 additions & 37 deletions pyborehole/borehole.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,21 @@ def create_df(self):
df : pd.DataFrame
DataFrame containing the Borehole Metadata.
Examples
________
>>> borehole.create_df()
>>> borehole.df
Value
Name RWE EB1
Address Am Kraftwerk 17, 52249 Eschweiler, Germany
Location POINT (6.313031 50.835676)
X 6.313031
Y 50.835676
Coordinate Reference System EPSG:4326
Coordinate Reference System PyProj EPSG:4326
Altitude above sea level 136
Altitude above KB None
"""
# Create dict from attributes
df_dict = {'Name': self.name,
Expand Down Expand Up @@ -133,9 +148,12 @@ def update_df(self, data_dict: dict):
df])

def add_deviation(self,
path: str,
delimiter: str,
step: float):
path: Union[str, pd.DataFrame],
delimiter: str = '',
step: float = 1,
md_column: str = 'MD',
dip_column: str = 'DIP',
azimuth_column: str = 'AZI'):
"""Add deviation to the Borehole Object.
Parameters
Expand All @@ -150,15 +168,19 @@ def add_deviation(self,
"""
# Create deviation
self.deviation = Deviation(path=path,
self.deviation = Deviation(self,
path=path,
delimiter=delimiter,
step=step)
step=step,
md_column=md_column,
dip_column=dip_column,
azimuth_column=azimuth_column)

# Updating DataFrame
self.update_df(self.deviation.data_dict)

def add_well_logs(self,
path):
path: str):
"""Add Well Logs to the Borehole Object.
Parameters
Expand All @@ -167,13 +189,29 @@ def add_well_logs(self,
Path to the well log file
"""
# Creating well logs
self.logs = Logs(path=path)
self.logs = Logs(self,
path=path)

def add_well_tops(self,
path: str,
delimiter: str = ','):
"""Add Well Tops to the Borehole Object.
Parameters
__________
path : str
Path to the well top file
delimiter : str
"""
# Creating well tops
self.well_tops = WellTops(path=path,
delimiter=delimiter)

# def read_boreholeml(self):
# def write_boreholeml(self):


class Deviation():
class Deviation(Borehole):
"""Class to initiate a Deviation object.
Parameters
Expand All @@ -186,10 +224,15 @@ class Deviation():
Step for resampling the deviation data, e.g. ``step=5``.
"""

def __init__(self,
path: str,
borehole,
path: Union[str, pd.DataFrame],
delimiter: str,
step: float = 5):
step: float = 5,
md_column: str = 'MD',
dip_column: str = 'DIP',
azimuth_column: str = 'AZI'):

# Importing wellpathpy
try:
Expand All @@ -198,8 +241,16 @@ def __init__(self,
ModuleNotFoundError('wellpathpy package not installed')

# Opening deviation file
md, inc, azi = wp.read_csv(fname=path,
delimiter=delimiter)
if isinstance(path, str):
md, inc, azi = wp.read_csv(fname=path,
delimiter=delimiter)

# Opening Pandas DataFrame
if isinstance(path, pd.DataFrame):
md = path[md_column].values
inc = path[dip_column].values
azi = path[azimuth_column].values


# Creating deviation
dev = wp.deviation(
Expand Down Expand Up @@ -253,10 +304,14 @@ def __init__(self,
orient='columns',
)

self.x = borehole.x
self.y = borehole.y
self.z = borehole.altitude_above_sea_level

def add_origin_to_desurveying(self,
x: float =0,
y: float =0,
z: float =0):
x: float = None,
y: float = None,
z: float = None):
"""Add origin to desurveying.
Parameters
Expand All @@ -269,6 +324,14 @@ def add_origin_to_desurveying(self,
Altitude of the origin, e.g. ``z=200``.
"""

if not x:
x = self.x
if not y:
y = self.y
if not z:
z = self.z

# Adding the X coordinate
self.desurveyed_df['Northing'] = self.desurveyed_df['Northing_rel'] + y

Expand Down Expand Up @@ -390,12 +453,28 @@ def lines_from_points(points):
tube = spline.tube(radius=radius)

# Assigning depth values
tube['TVD'] = tube.points[:,2]
tube['TVD'] = tube.points[:, 2]

return tube


class Logs:
class WellTops(Borehole):
"""Class to initiate Well Tops.
Parameters
__________
path : str
Path to the well tops, e.g. ``path='Well_Tops.csv'``.
"""

def __init__(self,
path: str,
delimiter: str = ','):
self.df = pd.read_csv(path, delimiter=delimiter)


class Logs(Borehole):
"""Class to initiate a Well Log Object.
Parameters
Expand All @@ -404,7 +483,10 @@ class Logs:
Path to the well logs, e.g. ``path='logs.las'``.
"""
def __init__(self, path: str):

def __init__(self,
borehole,
path: str):

# Importing lasio
try:
Expand Down Expand Up @@ -448,31 +530,118 @@ def __init__(self, path: str):
'value',
'descr'])

self.well_tops = borehole.well_tops

def plot_well_logs(self,
tracks: Union[str, list]):
tracks: Union[str, list],
depth_column: str = 'MD',
colors: Union[str, list] = None,
add_well_tops: bool = False,
fill_between: int = None):
"""Plot well logs
Parameters
__________
tracks : Union[str, list]
Name/s of the logs to be plotted
Name/s of the logs to be plotted, e.g. ``tracks='SGR'`` or ``tracks=['SGR', 'K'].
depth_column : str
Name of the column holding the depths, e.g. ``depth_column='MD'``.
colors : Union[str, list]
Colors of the logs, e.g. ``colors='black'`` or ``colors=['black', 'blue'].
add_well_tops : bool, default = False
Boolean to add well tops to the plot.
"""
# Selecting tracks
df = self.df[tracks].reset_index()

# Creating plot
fig, ax = plt.subplots(1, len(tracks), figsize=(len(tracks) * 2, 8))

# Plotting tracks
for i in range(len(tracks)):
ax[i].plot(df[tracks[i]], df['MD'])
ax[i].grid()
ax[i].invert_yaxis()
buffer = (max(df['MD']) - min(df['MD'])) / 20
ax[i].set_ylim(max(df['MD']) + buffer, min(df['MD']) - buffer)

return fig, ax
if isinstance(tracks, str):
# Creating plot
fig, ax = plt.subplots(1, 1, figsize=(1 * 2, 8))

ax.plot(df[tracks], df[depth_column], color=colors)
ax.grid()
ax.invert_yaxis()
buffer = (max(df[depth_column]) - min(df[depth_column])) / 20
ax.set_ylim(max(df[depth_column]) + buffer, min(df[depth_column]) - buffer)
ax.tick_params(top=True, labeltop=True, bottom=False, labelbottom=False)
ax.xaxis.set_label_position('top')
ax.set_xlabel(tracks + ' [%s]' %
self.curves[self.curves['original_mnemonic'] == tracks].reset_index(drop=True)['unit'].iloc[
0], color='black')
ax.set_ylabel(depth_column + ' [m]')

if fill_between:
left_col_value = np.min(df[tracks].dropna().values)
right_col_value = np.max(df[tracks].dropna().values)
span = abs(left_col_value - right_col_value)
cmap = plt.get_cmap('hot_r')
color_index = np.arange(left_col_value, right_col_value, span / 100)
# loop through each value in the color_index
for index in sorted(color_index):
index_value = (index - left_col_value) / span
color = cmap(index_value) # obtain color for color index value
ax.fill_betweenx(df[depth_column], df[tracks], left_col_value, where=df[tracks] >= index,
color=color)

return fig, ax

elif isinstance(tracks, list):

if add_well_tops:
j = 1
else:
j = 0

if not colors:
colors = [None] * len(tracks)

# Creating plot
fig, ax = plt.subplots(1,
len(tracks) + j,
figsize=(len(tracks) * 1.8, 8),
sharey=True)

# Helping variable for adding well tops
if add_well_tops:
for index, row in self.well_tops.df.iterrows():
ax[0].axhline(row[self.well_tops.df.columns[1]], 0, 1, color='black')
ax[0].text(0.05, row[self.well_tops.df.columns[1]] - 1, s=row[self.well_tops.df.columns[0]],
fontsize=6)
ax[0].grid()
ax[0].axes.get_xaxis().set_ticks([])

# Plotting tracks
for i in range(len(tracks)):
ax[i + j].plot(df[tracks[i]], df[depth_column], color=colors[i])
ax[i + j].grid()
ax[i + j].invert_yaxis()
buffer = (max(df[depth_column]) - min(df[depth_column])) / 20
ax[i + j].set_ylim(max(df[depth_column]) + buffer, min(df[depth_column]) - buffer)
ax[i + j].tick_params(top=True, labeltop=True, bottom=False, labelbottom=False)
ax[i + j].xaxis.set_label_position('top')
ax[i + j].set_xlabel(tracks[i] + ' [%s]' %
self.curves[self.curves['original_mnemonic'] == tracks[i]].reset_index(drop=True)[
'unit'].iloc[0],
color='black' if isinstance(colors[i], type(None)) else colors[i])
ax[0].set_ylabel(depth_column + ' [m]')

if fill_between is not None:
left_col_value = np.min(df[tracks[fill_between]].dropna().values)
right_col_value = np.max(df[tracks[fill_between]].dropna().values)
span = abs(left_col_value - right_col_value)
cmap = plt.get_cmap('hot_r')
color_index = np.arange(left_col_value, right_col_value, span / 100)
# loop through each value in the color_index
for index in sorted(color_index):
index_value = (index - left_col_value) / span
color = cmap(index_value) # obtain color for color index value
ax[fill_between+j].fill_betweenx(df[depth_column], df[tracks[fill_between]], left_col_value, where=df[tracks[fill_between]] >= index,
color=color)

plt.tight_layout()

return fig, ax

def plot_well_log_along_path(self,
log: str,
Expand Down Expand Up @@ -688,10 +857,10 @@ def resample_log(line: Union[gpd.GeoDataFrame, LineString],

gdf_resampled = pd.concat([pd.DataFrame.from_dict(
{'geometry': Point(x[0], y[0]), 'X': [x[0]], 'Y': [y[0]]}, orient='columns'),
gdf_resampled,
pd.DataFrame.from_dict(
{'geometry': Point(x[-1], y[-1]), 'X': [x[-1]], 'Y': [y[-1]]},
orient='columns')
], ignore_index=True)
gdf_resampled,
pd.DataFrame.from_dict(
{'geometry': Point(x[-1], y[-1]), 'X': [x[-1]], 'Y': [y[-1]]},
orient='columns')
], ignore_index=True)

return gdf_resampled
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,6 @@ version_scheme = "post-release"
# (so there isn't a + in the version)
local_scheme = "no-local-version"
# This _version_generated.py file is a file that you'll never want to add to version control - so you'll want to add it to your gitignore file. but when you build your package, setuptools_Scm creates it. and it contains version information that you will pull into your package below.
write_to = "pyheatdemand/_version_generated.py"
write_to = "pyborehole/_version_generated.py"
write_to_template = '__version__ = "v{version}"'

20 changes: 18 additions & 2 deletions test/test_borehole.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,25 @@ def test_borehole_class():
assert isinstance(borehole.crs_pyproj, pyproj.crs.crs.CRS)
assert borehole.altitude_above_sea_level == 136
assert isinstance(borehole.altitude_above_sea_level, float)
assert borehole.deviation == None
assert borehole.logs == None
assert borehole.deviation is None
assert borehole.logs is None
assert isinstance(borehole.df, pd.DataFrame)
assert borehole.__str__() == 'Weisweiler R1'

borehole.update_df({'newname': 'Weisweiler R2'})
assert borehole.df.T['newname'].iloc[0] == 'Weisweiler R2'

data = {'MD': [0, 50, 100],
'DIP': [2, 2, 2],
'AZI': [5, 5, 5]}

df_dev = pd.DataFrame.from_dict(data)

borehole.add_deviation(path=df_dev,
step=25,
md_column='MD',
dip_column='DIP',
azimuth_column='AZI')


def test_borehole_class_error():
Expand Down

0 comments on commit 3d286c8

Please sign in to comment.