<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 How to work with binary logs
We will invent a binary log -- maybe you can load it from an LAS file with welly.
Step1:  Make a striplog
A Striplog is a sequence of Interval objects (representing a layer). Each Interval must contain a Component (representing the layer, perhaps a rock).
Step2:  Each Interval in the striplog looks like
Step3:  Plot the intervals
To plot we need a legend, but we can generate a random one. This maps each Component to a colour (and a width and hatch, if you want).
We can generate a random legend
Step5:  Or we can make one with a bit more control
Step6:  Remove thin things
We can remove thin intervals
Step7:  Now we can anneal the gaps
Step8:  Then merge the adjacent intervals that are alike...
Step9:  We could have chained these commands
Step10:  Dilate and erode
This would be a binary thing, at least for now. I made an issue for this
Step11:  Some statistics
We can get the unique components and their thicknesses
Step12:  We can get at the thickest (and thinnest, with .thinnest()) intervals
Step13:  These functions optionally take an integer argument n specifying how many of the thickest or thinnest intervals you want to see. If n is greater than 1, a Striplog object is returned so you can see the positions of those items
Step14:  Bar plots and histograms
We can make a bar plot of the layers
Step15:  More interesting is to sort the thicknesses
Step16:  Finally, we can make a thickness histogram of the various types of component present in the log.
<ASSISTANT_TASK:>
Python Code:
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
fake_depth = np.linspace(100, 150, 101)
fake_log = np.array([np.random.choice([0, 1]) for _ in fake_depth])
plt.figure(figsize=(15, 1))
plt.plot(fake_depth, fake_log, 'o-')
Explanation: How to work with binary logs
We will invent a binary log -- maybe you can load it from an LAS file with welly.
End of explanation
from striplog import Striplog, Component
comps = [
    Component({'pay': True}),
    Component({'pay': False})
]
s = Striplog.from_log(fake_log, cutoff=0.5, components=comps, basis=fake_depth)
s[-1].base.middle = 150.5 # Adjust the bottom thickness... not sure if this is a bug.
Explanation: Make a striplog
A Striplog is a sequence of Interval objects (representing a layer). Each Interval must contain a Component (representing the layer, perhaps a rock).
End of explanation
s[0]
Explanation: Each Interval in the striplog looks like:
End of explanation
from striplog import Legend
legend = Legend.random(comps)
legend.get_decor(comps[-1]).width = 0.2
legend.plot()
Explanation: Plot the intervals
To plot we need a legend, but we can generate a random one. This maps each Component to a colour (and a width and hatch, if you want).
We can generate a random legend:
End of explanation
legend_csv = colour,hatch,width,component pay
#48cc0e,None,1,True
#5779e2,None,0.2,False
legend = Legend.from_csv(text=legend_csv)
legend.plot()
s.plot(legend=legend, aspect=5)
Explanation: Or we can make one with a bit more control:
End of explanation
pruned = s.prune(limit=1.0, keep_ends=True)
Explanation: Remove thin things
We can remove thin intervals:
End of explanation
annealed = pruned.anneal()
Explanation: Now we can anneal the gaps:
End of explanation
merged = annealed.merge_neighbours()  # Anneal works on a copy
Explanation: Then merge the adjacent intervals that are alike...
End of explanation
fig, axs = plt.subplots(ncols=4, figsize=(6, 10))
axs[0] = s.plot(legend=legend, ax=axs[0], lw=1, aspect=5)
axs[0].set_title('Original')
axs[1] = pruned.plot(legend=legend, ax=axs[1], lw=1, aspect=5)
axs[1].set_yticklabels([])
axs[1].set_title('Pruned')
axs[2] = annealed.plot(legend=legend, ax=axs[2], lw=1, aspect=5)
axs[2].set_yticklabels([])
axs[2].set_title('Annealed')
axs[3] = merged.plot(legend=legend, ax=axs[3], lw=1, aspect=5)
axs[3].set_yticklabels([])
axs[3].set_title('Merged')
plt.show()
Explanation: We could have chained these commands:
merged = s.prune(limit=1.0, keep_ends=True).anneal().merge_neighbours()
Let's plot all these steps, just for illustration:
End of explanation
fig, axs = plt.subplots(ncols=4, figsize=(6, 10))
opening = s.binary_morphology('pay', 'opening', step=0.1, p=7)
closing = s.binary_morphology('pay', 'closing', step=0.1, p=7)
axs[0] = s.plot(legend=legend, ax=axs[0], lw=1, aspect=5)
ntg = s.net_to_gross('pay')
axs[0].set_title(f'Original\n{ntg:.2f}')
axs[1] = merged.plot(legend=legend, ax=axs[1], lw=1, aspect=5)
axs[1].set_yticklabels([])
ntg = merged.net_to_gross('pay')
axs[1].set_title(f'PAM\n{ntg:.2f}')  # Prune-anneal-merge
axs[2] = opening.plot(legend=legend, ax=axs[2], lw=1, aspect=5)
axs[2].set_yticklabels([])
ntg = opening.net_to_gross('pay')
axs[2].set_title(f'Opening\n{ntg:.2f}')
axs[3] = closing.plot(legend=legend, ax=axs[3], lw=1, aspect=5)
axs[3].set_yticklabels([])
ntg = closing.net_to_gross('pay')
axs[3].set_title(f'Closing\n{ntg:.2f}')
plt.show()
Explanation: Dilate and erode
This would be a binary thing, at least for now. I made an issue for this: https://github.com/agile-geoscience/striplog/issues/95
You need to be on striplog v 0.8.1 at least for this to work.
End of explanation
s.unique
Explanation: Some statistics
We can get the unique components and their thicknesses:
End of explanation
s.thickest()
Explanation: We can get at the thickest (and thinnest, with .thinnest()) intervals:
End of explanation
s.thickest(5).plot(legend=legend, lw=1, aspect=5)
Explanation: These functions optionally take an integer argument n specifying how many of the thickest or thinnest intervals you want to see. If n is greater than 1, a Striplog object is returned so you can see the positions of those items:
End of explanation
s.bar(legend=legend)
Explanation: Bar plots and histograms
We can make a bar plot of the layers:
End of explanation
s.bar(legend=legend, sort=True)
Explanation: More interesting is to sort the thicknesses:
End of explanation
n, ents, ax = s.hist(legend=legend)
s
legend
data = [c[1] for c in s.unique]
colors = [c['_colour'] for c in legend.table]
fig, axs = plt.subplots(ncols=2,
                        gridspec_kw={'width_ratios': [1, 3]})
axs[0] = s.plot(ax=axs[0], legend=legend)
axs[0].set_title("Striplog")
axs[1].pie(data, colors=colors)
axs[1].set_title("Pay proportions")
plt.show()
Explanation: Finally, we can make a thickness histogram of the various types of component present in the log.
End of explanation
<END_TASK>