<jupyter_start><jupyter_text>Quick start This notebooks looks at the main `striplog` object. For the basic objects it depends on, see [Basic objects](./02_Basic_objects.ipynb).First, import anything we might need.<jupyter_code>import matplotlib.pyplot as plt
import numpy as np

import striplog
striplog.__version__<jupyter_output><empty_output><jupyter_text>Making a striplog from CSV dataSuppose we have CSV data like this:<jupyter_code>csv_string = """top, base, comp lithology, comp grainsize
  230.329,  233.269,  Grey sandstone, vf-f
  233.269,  234.700,  Anhydrite,
  234.700,  236.596,  Dolomite,
  236.596,  237.911,  Red siltstone,
  237.911,  238.723,  Anhydrite,
  238.723,  239.807,  Grey sandstone, vf-f
  239.807,  240.774,  Red siltstone,
  240.774,  241.122,  Dolomite,
  241.122,  241.702,  Grey siltstone,
  241.702,  243.095,  Dolomite,
"""<jupyter_output><empty_output><jupyter_text>Because the lithology column is named **comp lithology** (or **component lithology**), striplog will interpret this column as the lithology of a component. Likewise, the grainsize is pulled out as another property. However, the colour of the rock is not pulled out -- it remains combined with the lithology.<jupyter_code>from striplog import Striplog

strip = Striplog.from_csv(text=csv_string)
strip.plot(aspect=3)<jupyter_output><empty_output><jupyter_text>Later we'll see how to make this plot look nicer. Let's look at one **interval** of the striplog. We'll choose the first one, because it has the grainsize property. It looks like this:<jupyter_code>strip[0]<jupyter_output><empty_output><jupyter_text>Adding a lexicon Often, we don't have properties conveniently separated out into columns like the example above. Instead we have data like:    Light grey vf sandstoneWe can get `striplog` to pull these different properties apart for us, by using a `Lexicon`. This is a dictionary-like look-up table that tells Striplog what different words mean. For example, using the default lexicon, here are the things it understands to be 'lithologies':<jupyter_code>from striplog import Lexicon

lexicon = Lexicon.default()

lexicon.lithology<jupyter_output><empty_output><jupyter_text>And grainsize (these use regular expressions to capture variance in how grainsize might be expressed; all of them are case insensitive):<jupyter_code>lexicon.grainsize<jupyter_output><empty_output><jupyter_text>Now we can accept data in which the descriptions combine several properties:<jupyter_code>csv_string = """top, base, description
  200.000,  230.329,  Anhydrite                                       
  230.329,  233.269,  Grey vf-f sandstone
  233.269,  234.700,  Anhydrite                                       
  234.700,  236.596,  Dolomite                                        
  236.596,  237.911,  Red siltstone                                   
  237.911,  238.723,  Anhydrite                                       
  238.723,  239.807,  Grey vf-f sandstone                             
  239.807,  240.774,  Red siltstone                                   
  240.774,  241.122,  Dolomite                                        
  241.122,  241.702,  Grey siltstone                                  
  241.702,  243.095,  Dolomite                                        
  243.095,  246.654,  Grey vf-f sandstone                             
  246.654,  247.234,  Dolomite                                        
  247.234,  255.435,  Grey vf-f sandstone                             
  255.435,  258.723,  Grey siltstone                                  
  258.723,  259.729,  Dolomite                                        
  259.729,  260.967,  Grey siltstone                                  
  260.967,  261.354,  Dolomite                                        
  261.354,  267.041,  Grey siltstone                                  
  267.041,  267.350,  Dolomite                                        
  267.350,  274.004,  Grey siltstone                                  
  274.004,  274.313,  Dolomite                                        
  274.313,  294.816,  Grey siltstone                                  
  294.816,  295.397,  Dolomite                                        
  295.397,  296.286,  Limestone                                       
  296.286,  300.000,  Volcanic                                        
"""<jupyter_output><empty_output><jupyter_text>Let's see how the lexicon parses one of these 'descriptions':<jupyter_code>from striplog import Component

Component.from_text('Light grey vf-f sandstone', lexicon)<jupyter_output><empty_output><jupyter_text>Now we can pass in the CSV text and apply the lexicon to it, producing a striplog:<jupyter_code>strip2 = Striplog.from_csv(text=csv_string, lexicon=lexicon, )
strip2
strip2[1]<jupyter_output><empty_output><jupyter_text>Making a `striplog` from an imageWe originally made `striplog` for a specific use-case: we had a lot of images of striplogs, with tops and bottom depths. So striplog can read images and try to make striplog objects out of them: Here is one of the images we will convert into striplogs:<jupyter_code>imgfile = "M-MG-70_14.3_135.9.png"<jupyter_output><empty_output><jupyter_text>Striplog's `Legend` class maps 'components' (rocks, if you will) to display styles (colour, width, etc). We will eventually use a legend to control how striplogs are displayed, but a legend can also control how a striplog image is interpreted.<jupyter_code>from striplog import Legend

legend = Legend.builtin('NSDOE')
strip = Striplog.from_image(imgfile, 14.3, 135.9, legend=legend)
strip
strip.plot(legend, ladder=True, aspect=5)<jupyter_output><empty_output><jupyter_text>This thing might look like the image (because it uses the same legend), but it's data:<jupyter_code>strip[0]<jupyter_output><empty_output><jupyter_text>Representations of a `striplog` There are several ways to inspect a striplog:* **`print`** prints the contents of the striplog* **`unique`** shows us a list of the primary lithologies in the striplog, in order of cumulative thickness* **`histogram`** makes a histogram of the lithologies (and also returns the histogram data)* **`plot`** makes a plot of the striplog with coloured bars<jupyter_code>print(strip[:5])
strip.unique
_ = strip.histogram(legend=legend, rotation=45, ha='right')<jupyter_output><empty_output><jupyter_text>You have already seen some basic plotting. For more control, you can pass some parameters to the `Striplog.plot()` method, but all of them are optional.<jupyter_code>strip.plot(legend, ladder=True, aspect=5, ticks=5)
hashy_csv = """colour,width,hatch,component colour,component grainsize,component lithology
#dddddd,1,---,grey,,siltstone,
#dddddd,2,xxx,,,anhydrite,
#dddddd,3,...,grey,vf-f,sandstone,
#dddddd,4,+--,,,dolomite,
#dddddd,5,ooo,,,volcanic,
#dddddd,6,---,red,,siltstone,
#dddddd,7,,,,limestone,
"""
hashy = Legend.from_csv(text=hashy_csv)
strip.plot(hashy, ladder=True, aspect=6, lw=1)<jupyter_output><empty_output><jupyter_text>Manipulating a `striplog` Again, the object is indexable and iterable.<jupyter_code>print(strip[:3])
print(strip[-1].primary.summary())
for i in strip[:5]:
    print(i.summary())
import numpy as np

np.array([d.top.z for d in strip[5:13]])<jupyter_output><empty_output><jupyter_text>Slicing returns a new `striplog`:<jupyter_code>strip[1:3]<jupyter_output><empty_output><jupyter_text>You can even index into it with an iterable, like a list of indices. The result is a striplog.<jupyter_code>indices = [2,4,6]
strip[indices].plot(legend, aspect=5)<jupyter_output><empty_output><jupyter_text>You can add striplogs:<jupyter_code>strip[:5] + strip[-5:]<jupyter_output><empty_output><jupyter_text>Striplog from LAS dataSuppose we have LAS 3.0 data like this:<jupyter_code>las3 = """~Lithology_Parameter
LITH .                    : Lithology source          {S}
LITHD.   MD               : Lithology depth reference {S}

~Lithology_Definition
LITHT.M                   : Lithology top depth       {F}
LITHB.M                   : Lithology base depth      {F}
LITHN.                    : Lithology name            {S}

~Lithology_Data | Lithology_Definition
  200.000,  230.329,  Anhydrite                                       
  230.329,  233.269,  Grey vf-f sandstone                             
  233.269,  234.700,  Anhydrite                                       
  234.700,  236.596,  Dolomite                                        
  236.596,  237.911,  Red siltstone                                   
  237.911,  238.723,  Anhydrite                                       
  238.723,  239.807,  Grey vf-f sandstone                             
  239.807,  240.774,  Red siltstone                                   
  240.774,  241.122,  Dolomite                                        
  241.122,  241.702,  Grey siltstone                                  
  241.702,  243.095,  Dolomite                                        
  243.095,  246.654,  Grey vf-f sandstone                             
  246.654,  247.234,  Dolomite                                        
  247.234,  255.435,  Grey vf-f sandstone                             
  255.435,  258.723,  Grey siltstone                                  
  258.723,  259.729,  Dolomite                                        
  259.729,  260.967,  Grey siltstone                                  
  260.967,  261.354,  Dolomite                                        
  261.354,  267.041,  Grey siltstone                                  
  267.041,  267.350,  Dolomite                                        
  267.350,  274.004,  Grey siltstone                                  
  274.004,  274.313,  Dolomite                                        
  274.313,  294.816,  Grey siltstone                                  
  294.816,  295.397,  Dolomite                                        
  295.397,  296.286,  Limestone                                       
  296.286,  300.000,  Volcanic                                        
"""<jupyter_output><empty_output><jupyter_text>There is a method for this format:<jupyter_code>strip3 = Striplog.from_las3(las3, lexicon)
strip3
strip3.plot(aspect=3)<jupyter_output><empty_output><jupyter_text>We can also produce a file like this from a striplog:<jupyter_code>print(strip3.to_las3())<jupyter_output>~Lithology_Parameter
LITH .   Striplog         : Lithology source          {S}
LITHD.   MD               : Lithology depth reference {S}

~Lithology_Definition
LITHT.M                   : Lithology top depth       {F}
LITHB.M                   : Lithology base depth      {F}
LITHD.                    : Lithology description     {S}

~Lithology_Data | Lithology_Definition
200.0,230.329,Anhydrite
230.329,233.269,"Sandstone, vf-f, grey"
233.269,234.7,Anhydrite
234.7,236.596,Dolomite
236.596,237.911,"Siltstone, red"
237.911,238.723,Anhydrite
238.723,239.807,"Sandstone, vf-f, grey"
239.807,240.774,"Siltstone, red"
240.774,241.122,Dolomite
241.122,241.702,"Siltstone, grey"
241.702,243.095,Dolomite
243.095,246.654,"Sandstone, vf-f, grey"
246.654,247.234,Dolomite
247.234,255.435,"Sandstone, vf-f, grey"
255.435,258.723,"Siltstone, grey"
258.723,259.729,Dolomite
259.729,260.967,"Siltstone, grey"
260.967,261.354,Dolomite
261.354,267.041,"Siltstone, grey"
267.041,267.35,Dolomite[...]
{'fraction_non_alphanumeric': 0.09262041537781705, 'fraction_numerical': 0.09209014582412726, 'mean_word_length': 2.1573660714285716, 'pattern_counts': {'":': 0, '<': 84, '<?xml version=': 0, '>': 84, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '21', 'dir': 'jupyter-structured-clean-dedup', 'id': '367690', 'license': 'Apache-2.0', 'n_tokens_mistral': 4327, 'n_tokens_neox': 3579, 'n_words': 907, 'path': 'docs/tutorial/01_Basics.ipynb', 'repo_name': 'agilescientific/striplog', 'size': '11315'}