#### Seismic Facies Identification Challenge

# [Explainer] Just a simple Video-Notebook - Starter Pack

Video version of Just a Simple Notebook

## Just a Simple Video-Notebook

Hi all! This is Santiago from Argentina again.

I have created a video version of my notebook "Just a Simple Notebook" (https://colab.research.google.com/drive/1935VS3tMKoJ1FbgR1AOkoAC2z0IO9HWr?usp=sharing). This is my submission as part of the second Community challenge. I hope that you find it interesting and insightful by being able to listen to a human voice going through, mainly, how seismic attributes are created, their meaning, their usefulness in each case and then finally through a quick overview on my solution and some of the things you could implement in your future solution addressing this kind of challenge.

Thanks as always to the SEAM and AICrowd team for such an amazing Challenge!

LINK: Click Here

# **Just a simple notebook**¶

Hi there! I am a recently graduated geophysicist from Argentina. I got into Data Science and Machine Learning just a few months ago, so I'm certainly an inexperienced little tiny deep learning practitioner as you may well guess. Here are some questions you may ask yourselves...

*What did you do?*¶

The last few hours I've tried to put together a simple notebook that goes from showing some simple seismic attributes, to implementing a deep learning model.

*How did you do it?*¶

I started by using my seismic attributes knowledge, then I tried to think of a way of implementing different kinds of information, and finally, I used the keras-image-segmentation package that you can find here: https://github.com/divamgupta/image-segmentation-keras to produce a model, train it, and test it.

*Well, but I could have done that on my own!...*¶

Well, of course you could! But beware that I also try to give an insight on some facts over using this seismic dataset and how you may improve your results by taking this into account. Maybe it will help you!

*I don't really know about these seismic facies and stuff...*¶

Well, maybe you just like to watch at some random guys' notebook and you'll probably like those nice images!

Hope you find it useful, funny and maybe consider giving it a thumbs up on the discourse!

**Loading packages**¶

This notebook uses keras_segmentation package to take advantage of other pre-trained models used in image segmentation.

It also uses:

- NumPy (duh..)
- matplotlib (duh..x2)
- cv2 (dux..x3)
- tensorflow (kind of duh..)
- scipy (wait... why?)

```
# Installing image_segmentation_keras
!pip install git+https://github.com/santiactis/image-segmentation-keras
# For data preprocessing & manipulation
import numpy as np
# FOr data visualisations & image processing
import matplotlib.pyplot as plt
import cv2
import scipy
# utilities
from tqdm.notebook import tqdm
import datetime
# For Deep learning
import tensorflow as tf
from tensorflow import keras
from keras_segmentation.models.unet import vgg_unet, resnet50_unet
from keras_segmentation.models.model_utils import get_segmentation_model
```

**Loading the data**¶

We download the datasets for the competition using !wget and their corresponding URLs

```
# Downloading training data
!wget https://datasets.aicrowd.com/default/aicrowd-public-datasets/seamai-facies-challenge/v0.1/public/data_train.npz
# Downloading training data
!wget https://datasets.aicrowd.com/default/aicrowd-public-datasets/seamai-facies-challenge/v0.1/public/labels_train.npz
# Downloading testing data
!wget https://datasets.aicrowd.com/default/aicrowd-public-datasets/seamai-facies-challenge/v0.1/public/data_test_1.npz
```

Don't look in here.......

```
#@title
import matplotlib.colors as mcolors
# Helpful functions
def hex_to_rgb(value):
'''
Converts hex to rgb colours
value: string of 6 characters representing a hex colour.
Returns: list length 3 of RGB values'''
value = value.strip("#") # removes hash symbol if present
lv = len(value)
return tuple(int(value[i:i + lv // 3], 16) for i in range(0, lv, lv // 3))
def rgb_to_dec(value):
'''
Converts rgb to decimal colours (i.e. divides each value by 256)
value: list (length 3) of RGB values
Returns: list (length 3) of decimal values'''
return [v/256 for v in value]
def get_continuous_cmap(hex_list, float_list=None):
''' creates and returns a color map that can be used in heat map figures.
If float_list is not provided, colour map graduates linearly between each color in hex_list.
If float_list is provided, each color in hex_list is mapped to the respective location in float_list.
Parameters
----------
hex_list: list of hex code strings
float_list: list of floats between 0 and 1, same length as hex_list. Must start with 0 and end with 1.
Returns
----------
colour map'''
rgb_list = [rgb_to_dec(hex_to_rgb(i)) for i in hex_list]
if float_list:
pass
else:
float_list = list(np.linspace(0,1,len(rgb_list)))
cdict = dict()
for num, col in enumerate(['red', 'green', 'blue']):
col_list = [[float_list[i], rgb_list[i][num], rgb_list[i][num]] for i in range(len(float_list))]
cdict[col] = col_list
cmp = mcolors.LinearSegmentedColormap('my_cmp', segmentdata=cdict, N=256)
return cmp
```

*We've got to talk about Seismic (Attributes)*¶

*We've got to talk about Seismic (Attributes)*

We are going to make a gentle and very visual introduction to seismic attributes. These are widely used in the Oil&Gas industry to aid Geophysicists and Geologist to find new prospects fast and easy. Of course that afterwards, each potential prospect is further analyzed to confirm if it is just an anomaly in the seismic image or in fact, a potential prospect.

### Visualizing the seismic slice over Y=380¶

We are going to visualize one of our seismic sections over which we are going to calculate differente seismic attributes.

```
# Taking a seismic slice for calculating seismic attributes
data_seis = np.load('/content/data_train.npz',
allow_pickle=True, mmap_mode = 'r')['data'][:,:,380]
```

```
# Setting figure size
plt.rcParams["figure.figsize"] = (20, 10)
# We plot the slice
plt.imshow(data_seis, cmap='binary')
```

*Instantaneous Attributes*¶

*Instantaneous Attributes*

They are defined by taking the analytic trace in consideration. This trace is obtained by taking the Hilbert transform over the real trace, and thus, obtaining the complex part of the analytic trace. By doing this, the seismic trace is composed by a real part (the real trace) and a complex part (its Hilbert transform.

This trace now allows us to calculate the so called 'Instantaneous Attributes'. These seismic attributes were of the first ever used when looking for DHI (Direct Hydrocarbon Indicators), generally by looking at the Envelope searching for amplitude anomalies.

The analytic trace $u(t)$ is defined as: $u(t) = x(t) + i y(t)$ , where $x(t)$ is the real trace and $y(t)$ is the Hilbert transform of $x(t)$ ( $H[x(t)]$ )

```
# We calculate the Hilbert transform for every trace in the slice to obtain the analytic traces
def calc_hil(data):
H = []
for i in range(data.shape[1]):
H.append(np.imag(scipy.signal.hilbert(data[:,i])))
H = np.asarray(H)
H = np.swapaxes(H, 0,1)
return H
H = calc_hil(data_seis)
```

```
# We plot the slice
plt.imshow(H, cmap='binary')
```

Ok, so at first glance this might seem the same thing... So let's go a little further

*Envelope*¶

This seismic attribute contributes information about the strength of a reflection, therefore giving information about "how different" are two geologic formations on the subsurface. The envelope is defined as: $E(t)=\sqrt{x^2 + y^2}$

```
# We calculate the Envelope
def calc_env(data):
env = data.copy()*0.0
for i in range(data.shape[1]):
for j in range(data.shape[0]):
env[j,i] = np.sqrt((data[j,i])**2 + (H[j,i])**2)
return env
env = calc_env(data_seis)
# We plot the slice
plt.imshow(env, cmap='jet')
```

Well... This looks a little bit more promising now, doesn't it? I can already assure you that some geophysicist or geologist are looking into those bright anomalies next to that main fault drooling over the potential fields... This could be enhanced visually by changing the middle values of the palette. Let's keep going...

*Instantaneous Phase*¶

This one is kind of a trickier one. It generally helps to define the edges of the reflectors and also helps on defining discontinuities. Its meaning it's a little difficult to define, some say that it has to do with the wave front, thus, the values that have a certain continuity correspond to the same wave front, and since we are looking at reflections, well, we could be seeing the same reflector if we follow a certain pattern. It is defined as: $ \theta = atan\left (\frac{x(t)}{y(t)} \right)$ . This generates some troubles over certain values, therefore it's useful to take the Cosine of that function, which is what I will do here.

```
# We calculate the Cosine of the Instantaneous Phase
def cos_ph(data):
ph = data.copy()*0.0
for i in range(data.shape[1]):
for j in range(data.shape[0]):
ph[j,i] = np.cos((data[j,i])/(H[j,i]))
return ph
ph = cos_ph(data_seis)
# We plot the slice
hex_list = ['#000000', '#ffffff', '#000000']
plt.imshow(ph, cmap=get_continuous_cmap(hex_list))
```