Tutorials Rob Leckenby

# #First a quick tour of the jupyter notebook

• Shortcuts
• Getting help
• Cell types
• Executing cells

### #Formatted text

We can write formated text in Markdown cells (Esc + m) and there are plenty of resources available:

Unordered list

• item 1
• item 2
• sub-item a
• sub-item b
• item 3

Ordered list

1. first
2. second
3. third

italic, bold, underline (not strictly markdown but works in the notebook)

quoted text

SyntaxDescription
ParagraphText

### #Equations

Mathematical expressions in notebooks use LaTeX: overleaf.com/learn/latex/Mathematical_expressions

Inline Gardner's equation $\rho = \alpha {V_P}^{\beta}$

Centered equation Darcy'y Law

$q = -\frac{k}{\mu L} \Delta p$
(1)#

### #Code

in-line code

and multiline formatted code:

# Some formatted python code

def say_hi():
"""Just print hello!"""
print('Hello!')
return None

### #Code output

print('Hello Transfrom 2022!')

### #Images # #A gentle introduction to python

### #mathematical operators

# Live coding of basic mathematical operators


# Press shift+enter to execute a cell
2 + 3
2 + 3.5
15.5 - 76
45 * 0.4
23 / 2
# Long division
23 // 2
# Remainder of long division: the "modulo operator"
23 % 2
2**3

### #logical operators

# Live coding of logical operators


23 > 4
534 < 100
100 <= 100
200 >= 199
13 == 15
43 != 49
# Combining them
11 % 2 == 0
(4 > 2) and (50 <= 10)
(4 > 2) or (50 <= 10)

### #Assignment

x = 10
# no output!
x

## #Stepping sideways out of your comfort zone

Words and collections in python (i.e. str, list, dict)

### #str

word = 'python'
type(word)
word
# single vs double quotes


double_quotes = "same thing"
double_quotes
len(word)
# str methods


word.upper()
word

### #list

word_list = ['python', 'geology', 'programming', 'code', 'outcrop']
# again, no output, assignment is silent
# exploring lists


type(word_list)
len(word_list)
word_list
'geology' in word_list
word_list.append('mineral')
# no output
word_list

## #Indexing and slicing

We can reach into these collections, there are two main things to remember:

1. python starts counting at 0
2. we use square brackets []

### #Indexing and slicing str

len(word)
word
word
word
# half-open interval
word[0:3]

### #Indexing and slicing list

# same thing with list
word_list
word_list
word_list[-1]
word_list[4:]

### #dict

container = {'words': word_list, 'word': word, 'transform': 2022}
container
# Exploring python dict


container.keys()
container.values()
container.get('word')

#### #Importing more functions

Sometimes we need to reach for some part of python that isn't loaded by default, there are three major ways to import packages:

• import package -> imports everything. Access things using package.function().
• import package as pkg -> imports everything with an alias. Accessing things using pkg.function().
• from package import function1, function2 -> import only function1 and function2. Accessed as function1() and function2().

Here we use the third method to import the datetime object from the datetime library:

from datetime import datetime

And we can now update the dict with a new value, for example today's date using the datetime object we just imported:

# using datetime to add today's date to the dict


# Build this up
container.update({'Location': 'Global', 'date': datetime.now().date().isoformat()})
container
container['date']

### #Keying into a dict

container.keys()
container.get('word')
container['word']

## #Controlling the flow

• if ... else

We often want to make decision in our code based on conditions, so first we need a bool-ean condition:

x < 5
word == 'python'
42 % 2 == 0
'Global' in container.values()
container['words'] == 'geology'

Now we can use these in the basic if statement:

if word == 'python':
print('Code!')

Let's look at container.values() again:

container.values()

And we can check for membership of this container.values():

'Global' in container.values()

So now we can use this in our conditional statement:

if 'python' in container.values():
print('Code!')
else:
print('No code.')

What does this look like with a geological example?

porosity = 0.23

if porosity >= 0.3:
reservoir = 'Good'
elif 0.15 < porosity < 0.3:
reservoir = 'Medium'
else:
reservoir = 'Poor'

reservoir

## #Say that again?

• loops in python (for, list comprehensions)

One of the main advantages of computers is the ability to repeat tedious tasks efficiently. Let us first load some data, we will use numpy for this:

import numpy as np
data = np.load('./data/GR-NPHI-RHOB-DT.npy')
print(data.shape)
nphi = data[:,1]
print(nphi.shape)
nphi
for porosity in nphi[:5]: # !! we only use the first 5 porosities to test our code (using a slice)
print(porosity)
import matplotlib.pyplot as plt
plt.plot(nphi)
plt.hlines(0.24, 0, 70, color='r')
plt.hlines(0.22, 0, 70, color='r')
plt.ylabel('NPHI')
plt.xlabel('Sample number')
plt.grid(alpha=0.4)
porosity = 0.23

if porosity >= 0.24:
reservoir = 'Good'
elif 0.22 < porosity < 0.24:
reservoir = 'Medium'
else:
reservoir = 'Poor'

reservoir
for porosity in nphi[:5]:
if porosity >= 0.24:
reservoir = 'Good'
elif 0.22 < porosity < 0.24:
reservoir = 'Medium'
else:
reservoir = 'Poor'
print(reservoir)
good_reservoir_count = 0

for porosity in nphi[:10]:
if porosity >= 0.24:
good_reservoir_count += 1

good_reservoir_count
good_reservoir_count = 0

for porosity in nphi:
if porosity >= 0.24:
good_reservoir_count += 1

good_reservoir_count
# IGNORE this if it's too much of a stretch!
good_resevoir_lc = sum([1 for poro in nphi if poro > 0.24])
good_resevoir_lc

## #An image speaks a thousand words

The python-visualization-landscape is vast and can be intimidating, no doubt you'll see many great examples during Transform 2022, but the place to start is usually matplotlib, you can reach the docs directly from with the jupyter notebook: import matplotlib.pyplot as plt
plt.plot(nphi)
plt.plot(nphi, 'o-', c='g')
fig, ax = plt.subplots()

ax.plot(nphi, 'o-', c='g', lw=0.4, markersize=2)
ax.set_ylabel('NPHI')
ax.set_xlabel('Sample number')
ax.set_title('Simple Porosity plot')
ax.grid(alpha=0.4)

Now we have created a plot, let's pull all of this together a single cell and save the figure:

import numpy as np
import matplotlib.pyplot as plt

nphi = data[:,1]

fig, ax = plt.subplots()

ax.plot(nphi, 'o-', c='g', lw=0.4, markersize=2)
ax.set_ylabel('NPHI')
ax.set_xlabel('Sample number')
ax.set_title('Simple Porosity plot')
ax.grid(alpha=0.4)

plt.savefig('./images/NPHI_plot.png')

plt.show()

### #Interactive plots

It is possible to add interactivity to plots in the Jupyter notebook using ipywidgets, without going through a full tutorial, here is a simple demo extending the plot we've been working with:

from ipywidgets import interact
import ipywidgets as widgets

@interact(high=widgets.FloatSlider(value=0.24, min=0.22, max=0.28, step=0.001, continuous_update=False),
low=widgets.FloatSlider(value=0.22, min=0.18, max=0.22, step=0.001, continuous_update=False)
)
def poro_high_low(high, low):
"""Create an interactive plot with ipywidgets."""
fig, ax = plt.subplots(figsize=(14, 6))
ax.plot(nphi, c='k', lw=1, markersize=6)
ax.plot(np.where(nphi > high, nphi, None), '^', c='r', lw=0.4, markersize=10)
ax.plot(np.where((nphi < high) & (nphi > low), nphi, None), 'o', c='g', lw=0.4, markersize=8)
ax.plot(np.where(nphi < low, nphi, None), 'v', c='b', lw=0.4, markersize=8)
ax.fill_between(np.arange(nphi.size), low, high, color='g', alpha=0.1)
ax.set_ylabel('NPHI')
ax.set_xlabel('Sample number')
ax.set_title('Simple Porosity plot')
ax.axhline(high, ls='--' ,c='r', label='high')
ax.axhline(low, ls='-.', c='b', label='low')
ax.legend()
ax.grid(alpha=0.4)

return None

## #Wrap it up and do it again

Part of the beauty of code is its reusabilty, we've used functions already:

type(print)
sum([1, 2, 3])
# using plt.scatter


xs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x2 = [x**2 for x in xs]
plt.scatter(xs, x2, c='r')
# writing our own simple function


def my_adder(a, b):
return a + b
my_adder?
my_adder(45, 98)

### #Writing actual equations in python

Remember this equation?

$\rho = \alpha {V_P}^{\beta}$
(2)#

Let's turn it into a python function:

def gardner(vp, alpha=310, beta=0.25):
"""Evaluate gardner's relation.
Args:
vp (float): P-wave velocity
alpha (float-like): alpha scalar
beta (float-like): beta exponent
Returns:
rho (float): density
Source: https://subsurfwiki.org/wiki/Gardner%27s_equation
"""
return alpha * vp**beta
gardner(2766)

## #Where to next? 