Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Field alias - first try #146

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63,750 changes: 63,750 additions & 0 deletions tests/P-129_out_kb.LAS

Large diffs are not rendered by default.

105 changes: 68 additions & 37 deletions welly/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,52 +5,58 @@
:license: Apache 2.0
"""
from .crs import CRS
from .utils import lasio_get


las_sections = {'well', 'params'}
las_fields = {
'well': {
},
'header': {
'name': ('well', 'WELL'),
'field': ('well', 'FLD'),
'license': ('well', 'LIC'),
'uwi': ('well', 'UWI'),
'api': ('well', 'API'),
'company': ('well', 'COMP'),
'name': [{'section': 'well', "code": 'WELL'}],
'field': [{'section': 'well', "code": 'FLD'}],
'license': [{'section': 'well', "code": 'LIC'}],
'uwi': [{'section': 'well', "code": 'UWI'}],
'api': [{'section': 'well', "code": 'API'}],
'company': [{'section': 'well', "code": 'COMP'}],
},
'location': {
'location': ('well', 'LOC'),
'country': ('well', 'CTRY'),
'province': ('well', 'PROV'),
'state': ('well', 'STAT'),
'county': ('well', 'CNTY'),
'latitude': ('well', 'LATI'),
'longitude': ('well', 'LONG'),
'northing': ('well', 'NS'),
'easting': ('well', 'EW'),
'x': ('well', 'XCOORD'),
'y': ('well', 'YCOORD'),
'datum': ('well', 'GDAT'),
'section': ('well', 'SECT'),
'range': ('well', 'RANG'),
'township': ('well', 'TOWN'),
'api': ('well', 'API'),
'ekb': ('params', 'EKB'),
'egl': ('params', 'EGL'),
'kb': ('params', 'KB'),
'gl': ('params', 'GL'),
'td': ('params', 'TD'),
'tdd': ('params', 'TDD'),
'tdl': ('params', 'TDL'),
'location': [{'section': 'well', "code": 'LOC'}],
'country': [{'section': 'well', "code": 'CTRY'}],
'province': [{'section': 'well', "code": 'PROV'}],
'state': [{'section': 'well', "code": 'STAT'}],
'county': [{'section': 'well', "code": 'CNTY'}],
'latitude': [{'section': 'well', "code": 'LATI'}],
'longitude': [{'section': 'well', "code": 'LONG'}],
'northing': [{'section': 'well', "code": 'NS'},
{'section': 'well', "code": 'Y'}],
'easting': [{'section': 'well', "code": 'EW'},
{'section': 'well', "code": 'X'}],
'x': [{'section': 'well', "code": 'XCOORD'}],
'y': [{'section': 'well', "code": 'YCOORD'}],
'datum': [{'section': 'well', "code": 'GDAT'}],
'section': [{'section': 'well', "code": 'SECT'}],
'range': [{'section': 'well', "code": 'RANG'}],
'township': [{'section': 'well', "code": 'TOWN'}],
'api': [{'section': 'well', "code": 'API'}],
'kb': [{'section': 'params', "code": 'KB'},
{'section': 'params', "code": 'EKB'},
{'section': 'params', "code": 'EREF', "secondary_code": 'DREF', "secondary_desc": ["KB", "K.B.", "KELLY BUSHING"]}],
'gl': [{'section': 'params', "code": 'GL'},
{'section': 'params', "code": 'EGL'},
{'section': 'params', "code": 'EPD', "secondary_code": "PD", "secondary_desc": ["Ground Level", "G.L.", "GROUND LEVEL"]},
{'section': 'params', "code": 'Elevation', "secondary_code": "PermDatum", "secondary_desc": ["Ground Level", "G.L.", "GROUND LEVEL"]}],
'td': [{'section': 'params', "code": 'TD'}],
'tdd': [{'section': 'params', "code": 'TDD'}],
'tdl': [{'section': 'params', "code": 'TDL'}],
},
'data': {
'start': ('well', 'STRT'),
'stop': ('well', 'STOP'),
'step': ('well', 'STEP'),
'null': ('well', 'NULL'),
'run': ('params', 'RUN'),
'service_company': ('well', 'SRVC'),
'date': ('well', 'DATE')
'start': [{'section': 'well', "code": 'STRT'}],
'stop': [{'section': 'well', "code": 'STOP'}],
'step': [{'section': 'well', "code": 'STEP'}],
'null': [{'section': 'well', "code": 'NULL'}],
'run': [{'section': 'params', "code": 'RUN'}],
'service_company': [{'section': 'well', "code": 'SRVC'}],
'date': [{'section': 'well', "code": 'DATE'}],
}
}

Expand All @@ -61,3 +67,28 @@
'kb': (r"# WELL DATUM .+?: ([.0-9]+).+?", float),
'crs': (r"XYZ TRACE .+? \[\d+_(\d+)\] .+?", CRS.from_epsg),
}

def parse_fields(l, remap=None, funcs=None, initial_params=None,
field_alias=None, hdr_sect='header'):
params = {}
# print("parse_fields:", hdr_sect)
if initial_params is not None:
params = initial_params
fields = field_alias
if fields is None:
fields = las_fields[hdr_sect]
# print("____", fields)
for field, values in fields.items():
for val in values:
params[field] = lasio_get(l,
val,
# val['section'],
# val['code'],
# check=check,
remap=remap,
funcs=funcs)
# print("_______", val, field, params[field])
if params[field] is not None:
break

return params
10 changes: 2 additions & 8 deletions welly/header.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"""
import csv

from .fields import las_fields
from .fields import las_fields, parse_fields
from . import utils


Expand Down Expand Up @@ -51,13 +51,7 @@ def from_lasio(cls, l, remap=None, funcs=None):
implementing a transform before loading. Can be a lambda.

"""
params = {}
for field, (sect, code) in las_fields['header'].items():
params[field] = utils.lasio_get(l,
sect,
code,
remap=remap,
funcs=funcs)
params = parse_fields(l, remap, funcs)
return cls(params)

@classmethod
Expand Down
19 changes: 8 additions & 11 deletions welly/location.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import io

from . import utils
from .fields import las_fields
from .fields import las_fields, parse_fields, parse_fields
from .fields import dev_fields
from .crs import CRS
from .tools import compute_position_log
Expand Down Expand Up @@ -65,7 +65,7 @@ def __init__(self, params=None):
m = "The position log could not be computed. Consider "
m += "trying another setting for the 'method' argument."
warnings.warn(m)
dev_new, pos, dog = deviation, None, None
dev_new, pos, dog = self.deviation, None, None

self.position = pos
self.dogleg = dog
Expand Down Expand Up @@ -102,7 +102,7 @@ def crs_from_string(self, string):
return

@classmethod
def from_lasio(cls, l, remap=None, funcs=None):
def from_lasio(cls, l, remap=None, funcs=None, field_alias=None):
"""
Make a Location object from a lasio object. Assumes we're starting
with a lasio object, l.
Expand All @@ -112,19 +112,16 @@ def from_lasio(cls, l, remap=None, funcs=None):
remap (dict): Optional. A dict of 'old': 'new' LAS field names.
funcs (dict): Optional. A dict of 'las field': function() for
implementing a transform before loading. Can be a lambda.
field_alias ?????

Returns:
Location. An instance of this class.
"""
params = {}
funcs = funcs or {}
funcs['location'] = str
for field, (sect, code) in las_fields['location'].items():
params[field] = utils.lasio_get(l,
sect,
code,
remap=remap,
funcs=funcs)

params = parse_fields(l, remap, funcs, field_alias=field_alias,
hdr_sect='location')
return cls(params)

@classmethod
Expand Down Expand Up @@ -336,7 +333,7 @@ def trajectory(self, datum=None, elev=True, points=1000, **kwargs):

Returns:
ndarray. An array with shape (`points` x 3) representing the well
trajectory. Columns are (x, y, z).
trajectory. Columns are (x, y, z).
"""
pos = self.position.copy()

Expand Down
25 changes: 19 additions & 6 deletions welly/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def bbox(points):
def aspect(points):
"""
Aspect like 2:1 is shape like |___ (twice as wide as high).

This function returns the WIDTH per unit height.
"""
(minx, miny), (maxx, maxy) = bbox(points)
Expand Down Expand Up @@ -208,9 +208,10 @@ def list_and_add(a, b):


def lasio_get(l,
section,
# section,
item,
attrib='value',
# check=None,
default=None,
remap=None,
funcs=None):
Expand All @@ -231,18 +232,30 @@ def lasio_get(l,
The transformed item.
"""
remap = remap or {}
item_to_fetch = remap.get(item, item)
item_to_fetch = remap.get(item['code'], item['code'])
if item_to_fetch is None:
return None

try:
obj = getattr(l, section)
result = getattr(obj, item_to_fetch)[attrib]
obj = getattr(l, item['section'])
if 'secondary_code' in item:
result = default
for val in item['secondary_desc']:
# print(' ', val, val== getattr(obj, item['secondary_code'])[attrib])
if val == getattr(obj, item['secondary_code'])[attrib]:
# print("sdjnvkfjvbafkjvnafjlsvn lsajfv asfvasfv", item_to_fetch)
# print(getattr(obj, item_to_fetch)[attrib])
result = getattr(obj, item_to_fetch)[attrib]
# print("___******", result)
break
else:
result = getattr(obj, item_to_fetch)[attrib]

except:
return default

if funcs is not None:
f = funcs.get(item, null)
f = funcs.get(item['code'], null)
result = f(result)

return result
Expand Down
49 changes: 20 additions & 29 deletions welly/well.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

from . import utils
from .fields import las_fields as LAS_FIELDS
from .fields import parse_fields
from .curve import Curve
from .header import Header
from .location import Location
Expand Down Expand Up @@ -142,7 +143,7 @@ def _get_curve_mnemonics(self, keys=None, curves_only=True):
keys_ = []
else:
keys_ = utils.flatten_list(keys)

if curves_only:
keys = [k for k in keys_ if isinstance(self.data.get(k), Curve)]
else:
Expand All @@ -155,6 +156,7 @@ def from_lasio(cls,
l,
remap=None,
funcs=None,
field_alias=None,
data=True,
req=None,
alias=None,
Expand All @@ -170,6 +172,7 @@ def from_lasio(cls,
remap (dict): Optional. A dict of 'old': 'new' LAS field names.
funcs (dict): Optional. A dict of 'las field': function() for
implementing a transform before loading. Can be a lambda.
field_alias (dict): Optional. A dict of LAS param header mappings.
data (bool): Whether to load curves or not.
req (list): An alias list, giving all required curves.
alias (dict): An alias dictionary.
Expand Down Expand Up @@ -211,13 +214,7 @@ def from_lasio(cls,
l_index = getattr(l, index_attr)

# Build a dict of curves.
curve_params = {}
for field, (sect, code) in LAS_FIELDS['data'].items():
curve_params[field] = utils.lasio_get(l,
sect,
code,
remap=remap,
funcs=funcs)
curve_params = parse_fields(l, remap, funcs, hdr_sect='data')

# This is annoying, but I need the whole depth array to
# deal with edge cases, eg non-uniform sampling.
Expand Down Expand Up @@ -265,23 +262,20 @@ def from_lasio(cls,
# Build a dict of the other well data.
params = {'las': l,
'header': Header.from_lasio(l, remap=remap, funcs=funcs),
'location': Location.from_lasio(l, remap=remap, funcs=funcs),
'location': Location.from_lasio(l, field_alias=field_alias, remap=remap, funcs=funcs),
'data': curves,
'fname': fname}

for field, (sect, code) in LAS_FIELDS['well'].items():
params[field] = utils.lasio_get(l,
sect,
code,
remap=remap,
funcs=funcs)
params = parse_fields(l, remap, funcs, initial_params=params,
hdr_sect='well')
return cls(params)

@classmethod
def from_las(cls,
fname,
remap=None,
funcs=None,
field_alias=None,
data=True,
req=None,
alias=None,
Expand All @@ -298,6 +292,7 @@ def from_las(cls,
remap (dict): Optional. A dict of 'old': 'new' LAS field names.
funcs (dict): Optional. A dict of 'las field': function() for
implementing a transform before loading. Can be a lambda.
field_alias (dict): Optional. A dict of LAS param header mappings.
data (bool): Whether to load the data or only the header.
req (list): An alias list, giving all required curves.
alias (dict): An alias dictionary.
Expand Down Expand Up @@ -329,6 +324,7 @@ def from_las(cls,
return cls.from_lasio(las,
remap=remap,
funcs=funcs,
field_alias=field_alias,
data=data,
req=req,
alias=alias,
Expand Down Expand Up @@ -425,13 +421,14 @@ def to_lasio(self, keys=None, basis=None, null_value=-999.25):
for obj, dic in LAS_FIELDS.items():
if obj == 'data':
continue
for attr, (sect, item) in dic.items():
value = getattr(getattr(self, obj), attr, None)
try:
getattr(l, sect)[item].value = value
except:
h = lasio.HeaderItem(item, "", value, "")
getattr(l, sect)[item] = h
for attr, values in dic.items():
for val in values:
value = getattr(getattr(self, obj), attr, None)
try:
getattr(l, val['section'])[val['code']].value = value
except:
h = lasio.HeaderItem(val['code'], "", value, "")
getattr(l, val['section'])[val['code']] = h

# Clear curves from header portion.
l.header['Curves'] = []
Expand Down Expand Up @@ -547,13 +544,7 @@ def add_curves_from_lasio(self, l, remap=None, funcs=None):
Returns:
None. Works in place.
"""
params = {}
for field, (sect, code) in LAS_FIELDS['data'].items():
params[field] = utils.lasio_get(l,
sect,
code,
remap=remap,
funcs=funcs)
params = parse_fields(l, remap, funcs, hdr_sect='data')

curves = {c.mnemonic: Curve.from_lasio_curve(c, **params)
for c in l.curves}
Expand Down