In [48]:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
In [49]:
from IPython.display import Image
Image('./merging.png')
Out[49]:
Other possibility is using the deepest or shallowest base rather than top.
In [50]:
csv = """Top,Base,Comp Time,Comp Depth
100,200,2,a
110,120,1,b
150,325,3,c
210,225,1,d
300,400,2,e
350,375,3,f
"""
leg_csv = """Colour,Comp Depth
red,a
orange,b
limegreen,c
cyan,d
blue,e
magenta,f
"""
In [51]:
from striplog import Striplog, Legend
s = Striplog.from_csv(text=csv)
legend = Legend.from_csv(text=leg_csv)
In [52]:
s.plot(legend=legend,lw=1, aspect=3)
In [53]:
s[0]
Out[53]:
Strategy:
table
of the tops and bases we encounter, starting at the top. We will need to know 3 things: whether it's a top or a base, the depth it's at, and which interval in the striplog it corresponds to.First, the table:
In [54]:
def _get_table(s):
"""
Make a 'table of the tops and bases we encounter, starting at the top.
We will need to know 3 things: whether it's a top or a base, the depth
it's at, and which interval in the striplog it corresponds to.
Args
s (Striplog): A Striplog instance.
Returns
list. The table as a list of tuples.
"""
table = []
for i, interval in enumerate(s):
table.append(('T', interval.top.middle, i))
table.append(('B', interval.base.middle, i))
table = sorted(table, key = lambda x: x[1])
return table
_get_table(s)
Out[54]:
In [55]:
import operator
def _merge_table(s, attr, reverse=False):
"""
Do the merge operation on a table, and return a new table with
no nesting / overlaps.
Args
s (Striplog): A striplog instance.
attr (str): The attribute of the components you want to use.
reverse (bool): Whether to reverse the condition.
Returns
list: The merged table
"""
merged, stack = [], []
op = operator.le if reverse else operator.ge
for interface in _get_table(s):
print(stack)
tb, depth, idx = interface
if stack:
# 'this' is the top or base we're on in this loop iteration.
try:
this = getattr(s[idx], attr)
except AttributeError:
this = getattr(s[idx].primary, attr)
# 'current' is the highest priority unit in the stack.
try:
current = getattr(s[stack[-1]], attr)
except AttributeError:
current = getattr(s[stack[-1]].primary, attr)
# Compare 'this' to 'current' to decide what to do.
merge = op(this, current)
else:
merge = True
if tb == 'T':
# If this one meets the condition, merge it.
if merge:
# End the current unit, if any.
if stack:
merged.append(('B', depth, stack[-1]))
# Start the new top.
merged.append(interface)
# Insert this unit into stack and re-sort.
# (This is easier than trying to insert in the right place.)
stack.append(idx)
try:
stack = sorted(stack, key=lambda i: getattr(s[i], attr), reverse=reverse)
except AttributeError:
stack = sorted(stack, key=lambda i: getattr(s[i].primary, attr), reverse=reverse)
elif tb == 'B':
have_merged = False
# If this is the current unit's base, append it to the merge.
if idx == stack[-1]:
merged.append(interface)
have_merged = True
# End this unit in the stack.
stack.remove(idx)
# Add a top for the new current unit, if any, but only if we did a merge.
if stack and have_merged:
merged.append(('T', depth, stack[-1]))
return merged
Now we can make the merge table:
In [56]:
m = _merge_table(s, "top")
m
Out[56]:
Now we need to be able to make a new Striplog
instance from the merge table:
In [11]:
def _striplog_from_merge_table(s, table):
"""
Make a merge table into a Striplog instance.
Args
s (Striplog): the original Striplog.
table (list): the list of tuples from _merge_table().
Returns
Striplog. A new Striplog instance.
"""
m = []
for top, bot in zip(table[::2], table[1::2]):
# If zero thickness, discard.
if top[1] == bot[1]:
continue
i = s[top[2]].copy()
i.top = top[1]
i.base = bot[1]
m.append(i)
return Striplog(m)
In [12]:
m = _merge_table(s, 'top')
sm = _striplog_from_merge_table(s, m)
sm.plot(legend=legend, lw=1, aspect=5)
In [13]:
_merge_table(s, 'top', reverse=True)
Out[13]:
In [14]:
m = _merge_table(s, 'top', reverse=True)
sm = _striplog_from_merge_table(s, m)
sm.plot(legend=legend, lw=1, aspect=5)
This looks correct.
In [15]:
m = _merge_table(s, 'thickness')
sm = _striplog_from_merge_table(s, m)
sm.plot(legend=legend, lw=1, aspect=5)
In [16]:
m = _merge_table(s, 'thickness', reverse=True)
sm = _striplog_from_merge_table(s, m)
sm.plot(legend=legend, lw=1, aspect=5)
In [17]:
m = _merge_table(s, 'time')
sm = _striplog_from_merge_table(s, m)
sm.plot(legend=legend, lw=1, aspect=5)
In [18]:
m = _merge_table(s, 'time', reverse=True)
sm = _striplog_from_merge_table(s, m)
sm.plot(legend=legend, lw=1, aspect=5)
In [ ]:
In [19]:
from striplog import Striplog
remap = {'bottom':'base','type':'comp type'}
s = Striplog.from_csv("og815.csv", remap=remap)
In [21]:
from datetime import datetime
for iv in s:
iv.primary.date = datetime.fromisoformat(iv.data['date'])
In [22]:
s[1]
Out[22]:
Make a table of interfaces:
s
Then sort the table by depth.
In [28]:
m = _merge_table(s, 'top')
sm = _striplog_from_merge_table(s, m)
In [29]:
leg = """colour,comp type
limegreen,perforation
red,squeeze"""
In [31]:
from striplog import Legend
legend = Legend.from_csv(text=leg)
sm.plot(legend, lw=1, aspect=5)
In [33]:
sm.find_overlaps()
In [26]:
s_merge = []
for top, bot in zip(merged[::2], merged[1::2]):
# If zero thickness, discard.
if top[1] == bot[1]:
continue
i = s[top[2]].copy()
i.top = top[1]
i.base = bot[1]
s_merge.append(i)
m = Striplog(s_merge)
There aren't any! Good — this striplog should be 'flat'.
In [34]:
print(sm.to_csv())
This isn't quite right for Petrel.
Let's make another format.
In [39]:
def _to_petrel_csv(strip, attr, null):
"""
Make Petrel-ready CSV text for a striplog
"""
csv = ""
gap_top = 0
for iv in strip.merge_neighbours():
if iv.top.middle != gap_top:
csv += f"{gap_top},{null}\n"
csv += f"{iv.top.middle},{getattr(iv.primary, attr)}\n"
gap_top = iv.base.middle
csv += f"{iv.base.middle},{null}\n"
return csv
def to_petrel(fname, strip, attr, null=None):
"""
Make a Petrel-ready CSV file.
Args
fname (str): the filename, including extension
strip (Striplog): the striplog
null (str): what to use for nulls
Returns
None (writes file as side effect)
"""
if null is None:
null = "-999.25"
with open(fname, 'w') as f:
f.write(_to_petrel_csv(strip, attr, null))
return
In [40]:
print(_to_petrel_csv(sm, attr='type', null=-999.25))
In [43]:
to_petrel("well_for_petrel.csv", sm, attr='type')
In [ ]: