Skip to content

Commit

Permalink
Merge pull request #81 from jonnymaserati/enhancement/node_properties
Browse files Browse the repository at this point in the history
Add node module and interpolate method
  • Loading branch information
jonnymaserati authored Aug 2, 2021
2 parents d3c319e + e80e922 commit 860b78d
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 96 deletions.
7 changes: 5 additions & 2 deletions examples/connect_two_random_points.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@
azi2=azi2,
degrees=True,
min_tangent=0.,
dls_design=2.0,
# delta_radius=10.,
dls_design=1.0,
delta_dls=0.1,
max_iterations=1_000
)

# Print some pertinent calculation data
Expand All @@ -111,6 +111,9 @@
# Create a survey object of the section with interpolated points and coords
survey = section.survey(radius=5, step=30)

# test interpolate_md function
node = survey.interpolate_md(123).properties()

# As a QAQC step, check that the wellpath hits the defined turn points
start_points = np.array([section.pos1])
end_points = np.array([section.pos_target])
Expand Down
1 change: 1 addition & 0 deletions welleng/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
import welleng.target
import welleng.connector
import welleng.fluid
import welleng.node
74 changes: 1 addition & 73 deletions welleng/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,79 +13,7 @@
NEV_to_HLA, dls_from_radius
)
from .survey import Survey, SurveyHeader


class Node:
def __init__(
self,
pos=None,
vec=None,
md=None,
inc=None,
azi=None,
unit='meters',
degrees=True,
nev=True,
):
self.check_angle_inputs(inc, azi, vec, nev, degrees)
self.get_pos(pos, nev)
self.md = md
self.unit = unit

def check_angle_inputs(self, inc, azi, vec, nev, degrees):
if all(v is None for v in [inc, azi, vec]):
self.vec_xyz = None
self.vec_nev = None
self.inc_rad = None
self.inc_deg = None
self.azi_rad = None
self.azi_rad = None
return
elif vec is None:
assert inc is not None and azi is not None, (
"vec or (inc, azi) must not be None"
)
self.vec_xyz = get_vec(inc, azi, deg=degrees).reshape(3)
self.vec_nev = get_nev(self.vec_xyz).reshape(3)
else:
if nev:
self.vec_nev = get_unit_vec(vec).reshape(3)
self.vec_xyz = get_xyz(self.vec_nev).reshape(3)
else:
self.vec_xyz = get_unit_vec(vec).reshape(3)
self.vec_nev = get_nev(self.vec_xyz).reshape(3)
self.inc_rad, self.azi_rad = (
get_angles(self.vec_xyz).T
).reshape(2)
self.inc_deg, self.azi_deg = (
np.degrees(np.array([self.inc_rad, self.azi_rad]))
).reshape(2)

def get_pos(self, pos, nev):
if pos is None:
self.pos_xyz = None
self.pos_nev = None
return
if nev:
self.pos_nev = np.array(pos).reshape(3)
self.pos_xyz = get_xyz(pos).reshape(3)
else:
self.pos_xyz = np.array(pos).reshape(3)
self.pos_nev = get_nev(pos).reshape(3)

@staticmethod
def get_unit_vec(vec):
vec = vec / np.linalg.norm(vec)

return vec


def get_node_params(node):
pos = node.pos_nev
vec = node.vec_nev
md = node.md

return pos, vec, md
from .node import Node, get_node_params


class Connector:
Expand Down
83 changes: 83 additions & 0 deletions welleng/node.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import numpy as np
from .utils import (
get_unit_vec, get_vec, get_angles, get_nev, get_xyz,
)


class Node:
def __init__(
self,
pos=None,
vec=None,
md=None,
inc=None,
azi=None,
unit='meters',
degrees=True,
nev=True,
**kwargs
):
self.check_angle_inputs(inc, azi, vec, nev, degrees)
self.get_pos(pos, nev)
self.md = md
self.unit = unit
for k, v in kwargs.items():
setattr(self, k, v)

def check_angle_inputs(self, inc, azi, vec, nev, degrees):
if all(v is None for v in [inc, azi, vec]):
self.vec_xyz = None
self.vec_nev = None
self.inc_rad = None
self.inc_deg = None
self.azi_rad = None
self.azi_rad = None
return
elif vec is None:
assert inc is not None and azi is not None, (
"vec or (inc, azi) must not be None"
)
self.vec_xyz = get_vec(inc, azi, deg=degrees).reshape(3).tolist()
self.vec_nev = get_nev(self.vec_xyz).reshape(3).tolist()
else:
if nev:
self.vec_nev = get_unit_vec(vec).reshape(3).tolist()
self.vec_xyz = get_xyz(self.vec_nev).reshape(3).tolist()
else:
self.vec_xyz = get_unit_vec(vec).reshape(3).tolist()
self.vec_nev = get_nev(self.vec_xyz).reshape(3).tolist()
self.inc_rad, self.azi_rad = (
get_angles(self.vec_xyz).T
).reshape(2)
self.inc_deg, self.azi_deg = (
np.degrees(np.array([self.inc_rad, self.azi_rad]))
).reshape(2)

def get_pos(self, pos, nev):
if pos is None:
self.pos_xyz = None
self.pos_nev = None
return
if nev:
self.pos_nev = np.array(pos).reshape(3).tolist()
self.pos_xyz = get_xyz(pos).reshape(3).tolist()
else:
self.pos_xyz = np.array(pos).reshape(3).tolist()
self.pos_nev = get_nev(pos).reshape(3).tolist()

@staticmethod
def get_unit_vec(vec):
vec = vec / np.linalg.norm(vec)

return vec

def properties(self):
return vars(self)


def get_node_params(node):
pos = node.pos_nev
vec = node.vec_nev
md = node.md

return pos, vec, md
82 changes: 62 additions & 20 deletions welleng/survey.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
get_xyz
)
from .error import ErrorModel, ERROR_MODELS
# from .exchange.wbp import TurnPoint
# from .exchange.csv import export_csv
from .node import Node


AZI_REF = ["true", "magnetic", "grid"]
Expand All @@ -44,7 +43,7 @@ def __init__(
deg=True,
depth_unit='meters',
surface_unit='meters',
mag_defaults = {
mag_defaults={
'b_total': 50_000.,
'dip': 70.,
'declination': 0.,
Expand Down Expand Up @@ -471,7 +470,7 @@ def _get_nev(self):
]).T,
start_xyz=self.start_xyz,
start_nev=self.start_nev
).T
).reshape(-1, 3).T

def _make_angles(self, inc, azi, deg=True):
"""
Expand Down Expand Up @@ -624,6 +623,60 @@ def save(self, filename):
"""
export_csv(self, filename)

def interpolate_md(self, md):
"""
Method to interpolate a position based on measured depth and return
a node.
Parameters
----------
md: float
The measured depth of the point of interest.
Returns
-------
node: we.node.Node object
A node with attributes describing the point at the provided
measured depth.
Examples
--------
>>> import welleng as we
>>> survey = we.connector.interpolate_survey(
... survey=we.survey.Survey(
... md=[0, 500, 1000, 2000, 3000],
... inc=[0, 0, 30, 90, 90],
... azi=[0, 0, 45, 135, 180],
... ),
... step=30
... )
>>> node = survey.interpolate_md(1234)
>>> node.properties()
{
'vec_nev': [0.07584209568113438, 0.5840332282889957, 0.8081789187902809],
'vec_xyz': [0.5840332282889957, 0.07584209568113438, 0.8081789187902809],
'inc_rad': 0.6297429542197106,
'azi_rad': 1.4416597719915565,
'inc_deg': 36.081613454889634,
'azi_deg': 82.60102042890875,
'pos_nev': [141.27728744087796, 201.41424652428694, 1175.5823295305202],
'pos_xyz': [201.41424652428694, 141.27728744087796, 1175.5823295305202],
'md': 1234.0,
'unit': 'meters',
'interpolated': True
}
"""
s = interpolate_md(self, md)
node = Node(
pos=[s.n[-1], s.e[-1], s.tvd[-1]],
vec=s.vec_nev[-1].tolist(),
md=s.md[-1],
unit=s.unit,
nev=True,
interpolated=s.interpolated[-1]
)
return node


class TurnPoint:
def __init__(
Expand Down Expand Up @@ -732,7 +785,8 @@ def interpolate_survey(survey, x=0, index=0):
header=sh,
deg=False,
)
# s._min_curve(vec=None)
interpolated = False if x == 0 else True
s.interpolated = [False, interpolated]

return s

Expand Down Expand Up @@ -1017,21 +1071,9 @@ def get_sections(survey, rtol=1e-1, atol=1e-1, dls_cont=False, **targets):
starts = np.concatenate((
np.array([0]),
np.where(continuous == False)[0] + 1,
# np.array([len(continuous) - 1]),
np.array([len(survey.md) - 1])
))

# ends = np.concatenate(
# (
# starts[1:],
# np.array([len(continuous) - 1])
# )
# )

# starts = np.concatenate((
# starts, np.array([len(continuous) - 1])
# ))

actions = ["hold"]
actions.extend([
"hold" if d == 0.0 else "curve"
Expand Down Expand Up @@ -1189,8 +1231,8 @@ def export_csv(
):
"""
Function to export a minimalist (only the control points - i.e. the
begining and end points of hold and/or turn sections) survey to input into third
party trajectory planning software.
begining and end points of hold and/or turn sections) survey to input into
third party trajectory planning software.
Parameters
----------
Expand Down Expand Up @@ -1252,7 +1294,7 @@ def export_csv(
comments.extend([
f"{k}, {v}\n" for k, v in vars(survey.header).items()
])
comments += f"\n"
comments += "\n"
comments = ''.join(comments)

np.savetxt(
Expand Down
3 changes: 3 additions & 0 deletions welleng/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ def get_nev(
Returns:
An (n,3) array of [n, e, tvd] coordinates.
"""
# e, n, v = (
# np.array([pos]).reshape(-1,3) - np.array([start_xyz])
# ).T
e, n, v = (
np.array([pos]).reshape(-1,3) - np.array([start_xyz])
).T
Expand Down
2 changes: 1 addition & 1 deletion welleng/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.3.1'
__version__ = '0.3.2'

0 comments on commit 860b78d

Please sign in to comment.