import numpy as np
%matplotlib inline
bruges
welly
bruges
¶The idea is that you have UTM coordinates of three unique inline, crossline locations in a seismic survey (e.g. three cornerpoints). Once you have provided these, you can look up the (x,y) location of any (inline, xline) location, or vice versa.
import bruges
Define the cornerpoints:
# UTM coords of 3 unique inline, crossline locations.
corners_xy = np.array([[600938.125, 6073394.5],
[631226.3125, 6074241.0],
[630720.25, 6092358.5]])
# The inline, crossline locations you just provided.
corners_ix = np.array([[99, 104],
[99, 1316],
[824,1316]])
The CoordTransform
class provides a function, which we'll call transform
.
transform = bruges.transform.CoordTransform(corners_ix, corners_xy)
transform([440, 763]) # Or, equivalently, transform.forward([440, 763])
# Should be [617167, 6082379]
array([ 617168.67831747, 6082376.23932798])
We can also go back, from (x, y) to (inline, crossline).
transform.reverse([617167, 6082379])
array([440, 763])
(If you only wanted the reverse function, you could also just have passed the coordinate arrays in to the instantiation in reverse order.)
To get the seismic sample belonging to a particular depth, we need a velocity model.
If you already have an average velocity model in depth, then you can just look up the velocity and convert it directly.
But let's assume you only have a sonic well log for velocity information...
from welly import Well
w = Well.from_las("data/F03-04.las")
w.data
{'CALI': Curve([ nan, nan, nan, ..., nan, nan, nan]), 'DRHO': Curve([ nan, nan, nan, ..., nan, nan, nan]), 'DT': Curve([ nan, nan, nan, ..., nan, nan, nan]), 'GR': Curve([ nan, nan, nan, ..., nan, nan, nan]), 'ILD': Curve([ nan, nan, nan, ..., nan, nan, nan]), 'LLD': Curve([ nan, nan, nan, ..., nan, nan, nan]), 'LLS': Curve([ nan, nan, nan, ..., nan, nan, nan]), 'MSFL': Curve([ nan, nan, nan, ..., nan, nan, nan]), 'NPHI': Curve([ nan, nan, nan, ..., nan, nan, nan]), 'RHOB': Curve([ nan, nan, nan, ..., nan, nan, nan]), 'SN': Curve([ nan, nan, nan, ..., nan, nan, nan]), 'SP': Curve([ nan, nan, nan, ..., nan, nan, nan])}
dt = w.data['DT']
dt.plot()
dt.units
'US/F'
dt
DT [US/F] | |
---|---|
38.0000 : 3156.8660 : 0.1524 | |
description | 3 BHC |
run | None |
service_company | |
code | |
null | -999.25 |
date | |
Stats | |
samples (NaNs) | 20465 (2933) |
min mean max | 54.36 119.321 203.60 |
Depth | Value |
38.0000 | nan |
38.1524 | nan |
38.3048 | nan |
⋮ | ⋮ |
3156.4088 | nan |
3156.5612 | nan |
3156.7136 | nan |
# Correct for feet and microseconds.
vp = 0.3048 * 1e6 / dt
vp.start
38.0
vp.interpolate()
DT [US/F] | |
---|---|
38.0000 : 3156.8660 : 0.1524 | |
run | None |
service_company | |
code | |
null | -999.25 |
date | |
Stats | |
samples (NaNs) | 20465 (0) |
min mean max | 1497.04 2702.927 5607.01 |
Depth | Value |
38.0000 | 4107.1049 |
38.1524 | 4107.1049 |
38.3048 | 4107.1049 |
⋮ | ⋮ |
3156.4088 | 2178.1177 |
3156.5612 | 2178.1177 |
3156.7136 | 2178.1177 |
vp = vp.to_basis(start=0).extrapolate()
vp = vp.despike().smooth(20)
vp.plot()
vp
DT [US/F] | |
---|---|
0.0000 : 3156.9660 : 0.1524 | |
run | None |
service_company | |
code | |
null | -999.25 |
date | |
Stats | |
samples (NaNs) | 20715 (0) |
min mean max | 1551.33 2719.812 5007.77 |
Depth | Value |
0.0000 | 4107.1049 |
0.1524 | 4107.1049 |
0.3048 | 4107.1049 |
⋮ | ⋮ |
3156.5088 | 2178.1177 |
3156.6612 | 2178.1177 |
3156.8136 | 2178.1177 |
Get Vp log in time:
import bruges
dt = 0.004 # seconds seismic sample interval
vp_t = bruges.transform.depth_to_time(vp, vmodel=vp, dt=dt, dz=vp.step, mode='linear')
vp_t.shape
(581,)
It's too short (must match seismic trace), so pad it:
vp_t = np.pad(vp_t, pad_width=[0, 1000-vp_t.size], mode='edge')
Make a random trace and use time-based model to convert it to depth:
tr = np.random.randn(1000)
dz = 0.5 # Depth sample interval
tr_z = bruges.transform.time_to_depth(tr, vmodel=vp_t, dt=dt, dz=dz, mode="linear")
Make a basis for the seismic in depth:
basis = np.linspace(0, tr_z.size*dz, tr_z.size+1)
basis
array([ 0.00000000e+00, 5.00000000e-01, 1.00000000e+00, ..., 4.57450000e+03, 4.57500000e+03, 4.57550000e+03])
This basis gives the depths in 0.5 m intervals. To get the seismic sample at a particluar depth, get it from tr_z, which is the seismic amplitude in depth (i.e. the same basis).