<jupyter_start><jupyter_text>Objective  This notebook shows an example of how to:- **Use `Welly` to load two wells with Vp, Vs, and RHOB curves**- **Use `Pandas` to store the wells in individual DataFrames, clean-up data, then concatenate in a single DataFrame**- **Use `Backus` from `Bruges` to upscale all curves individually (well by well using `unique` values in the well name column)**  Import libraries__NB this notebook is tested in Python 3.6__<jupyter_code>import bruges as br
import numpy as np
import pandas as pd
from welly import Well
import matplotlib.pyplot as plt
from IPython.display import HTML<jupyter_output><empty_output><jupyter_text>Import wells<jupyter_code>R39 = Well.from_las('../data/R-39.las')
P129 = Well.from_las('../data/P-129_out.las')<jupyter_output><empty_output><jupyter_text>Data clean-up and manipulation - **Make well basis common to both wells**- **Make dataframes**- **Check for null values**- **Select columns of interest**- **Convert slowness to velocity**- **Add well name column**- **Concatenate dataframes** __Common basis__<jupyter_code>depth39_new = np.arange(2300,3350,1)
depth129_new = np.arange(300,1875,1)
R39.unify_basis(basis=depth39_new)
P129.unify_basis(basis=depth129_new)<jupyter_output><empty_output><jupyter_text>__Make dataframes__<jupyter_code>w39_df = R39.df()
w39_df = w39_df[['DT4P', 'DT4S', 'RHOB']]
w39_df.columns = ['DT', 'DTS', 'RHOB']
w39_df.describe(include = 'all')
w129_df = P129.df()
w129_df = w129_df[['DT', 'DTS', 'RHOB']]
w129_df.describe(include = 'all')<jupyter_output><empty_output><jupyter_text>__Checking well R-39 for null values__<jupyter_code>for x in w39_df.columns:
    print (x, w39_df[x].isnull().values.any())
    
print(w39_df.isnull().sum()) # finds how many missing points there are<jupyter_output>DT False
DTS False
RHOB False
DT      0
DTS     0
RHOB    0
dtype: int64<jupyter_text>There are no null values. Let's check P-129<jupyter_code>for x in w129_df.columns:
    print (x, w129_df[x].isnull().values.any())

print(w129_df.isnull().sum()) # finds how many missing points there are<jupyter_output>DT False
DTS False
RHOB False
DT      0
DTS     0
RHOB    0
dtype: int64<jupyter_text>__Convert slowness to velocity__ For well P-129: usec/ft >> m/s<jupyter_code>w129_df['Vp'] = 3.048e5 / w129_df['DT'] 
w129_df['Vs'] = 3.048e5 / w129_df['DTS'] 
w129_df.describe(include = 'all')<jupyter_output><empty_output><jupyter_text>For well R-39: usec/m >> m/s<jupyter_code>w39_df['Vp'] = 1.0e6 / w39_df['DT'] 
w39_df['Vs'] = 1.0e6 / w39_df['DTS'] 
w39_df.describe(include = 'all')<jupyter_output><empty_output><jupyter_text>__Add well name columns__<jupyter_code>w39_df['DEPTH'] = w39_df.index
w39_df['well'] = 'R-39'
w39_df = w39_df.reset_index(drop=True)
w39_df.describe(include = 'all')
w129_df['DEPTH'] = w129_df.index
w129_df['well'] = 'P-129'
w129_df = w129_df.reset_index(drop=True)
w129_df.describe(include = 'all')<jupyter_output><empty_output><jupyter_text>__Quick look at the top of the DataFrame to ensure everything looks right__<jupyter_code>w39_df.head()
w129_df.head()<jupyter_output><empty_output><jupyter_text>__Concatenate dataframes drop slownness columns, sort columns__<jupyter_code>wells = pd.DataFrame()

for i,df in enumerate([ w129_df, w39_df]):
    wells=wells.append(df)   

wells.drop(wells.columns[[0, 1]], inplace=True, axis=1) 
wells = wells[['DEPTH', 'Vp', 'Vs', 'RHOB', 'well']]    
wells.describe(include = 'all')<jupyter_output><empty_output><jupyter_text>__Remove negative values in Vs for R-39 as those will cause a square root of negative error with `Backus`.__ __I know about this ahead of time. This is how you check programmatically__<jupyter_code>(wells.loc[wells.well == 'R-39', 'Vs'] > 0).all()<jupyter_output><empty_output><jupyter_text>__Make utility function to remove low values__<jupyter_code>def remove_lows(c):
    '''Replace low values with nans then interpolates to fill. In place.'''
    c[[d <1500 if ~np.isnan(d) else False for d in c]] = np.nanmean(c) 
    return c.interpolate()<jupyter_output><empty_output><jupyter_text>__Plot, remove, plot again__<jupyter_code>fig = plt.figure(figsize=(6,10))

ax0 = fig.add_subplot(121)
ax0.plot(wells.loc[wells.well == 'R-39', 'Vp'], 
         wells.loc[wells.well == 'R-39', 'DEPTH'],
                                 'black', alpha=0.8, linewidth = 1, label='Vp')

ax0.legend( loc='upper left')
ax0.set_title('R-39 Vp')
ax0.set_ylabel(r'depth [m]', size=12)
ax0.invert_yaxis()
ax0.set_xlabel(r'Vp [m/s]', size=12)

ax1 = fig.add_subplot(122)
ax1.plot(wells.loc[wells.well == 'R-39', 'Vs'], 
         wells.loc[wells.well == 'R-39', 'DEPTH'],
         'blue', alpha=0.8, linewidth = 1, label='Vs')

ax1.legend( loc='upper left')
ax1.set_title('R-39 Vs')
ax1.set_ylabel(r'depth [m]', size=12)
ax1.invert_yaxis()
ax1.set_xlabel(r'Vs [m/s]', size=12)

plt.tight_layout();
wells.loc[wells.well == 'R-39', 'Vs'] = remove_lows(wells.loc[wells.well == 'R-39', 'Vs'])
fig = plt.figure(figsize=(6,10))

ax0 = fig.add_subplot(121)
ax0.plot(wells.loc[wells.well == 'R-39', 'Vp'], 
         wells.loc[wells.well == 'R-39', 'DEPTH'],
                                 'black', alpha=0.8, linewidth = 1, label='Vp')

ax0.legend( loc='upper left')
ax0.set_title('R-39 Vp')
ax0.set_ylabel(r'depth [m]', size=12)
ax0.invert_yaxis()
ax0.set_xlabel(r'Vp [m/s]', size=12)

ax1 = fig.add_subplot(122)
ax1.plot(wells.loc[wells.well == 'R-39', 'Vs'], 
         wells.loc[wells.well == 'R-39', 'DEPTH'],
         'blue', alpha=0.8, linewidth = 1, label='Vs')

ax1.legend( loc='upper left')
ax1.set_title('Despiked R-39 Vs')
ax1.set_ylabel(r'depth [m]', size=12)
ax1.invert_yaxis()
ax1.set_xlabel(r'Vs [m/s]', size=12)

plt.tight_layout();<jupyter_output><empty_output><jupyter_text>Upscale Vp, Vs, and RHOB with Backus  __Define Backus length and sampling interval__In real-world the former would be defined by modeling or estimated from seismic dominant frequency around the zone of interest at the well location (I recommend the latter for comparing logs to seismic inversion-derived properties).<jupyter_code>lb = 40
dz = 1.0<jupyter_output><empty_output><jupyter_text>__Upscale and plot comparison__<jupyter_code>wells_bk = pd.DataFrame()

grouped = wells['well'].unique()

for well in grouped:    
    new_df = pd.DataFrame() 
    Vp = np.array(wells.loc[wells['well'] == well, 'Vp'])
    Vs = np.array(wells.loc[wells['well'] == well, 'Vs'])
    rhob = np.array(wells.loc[wells['well'] == well, 'RHOB']) 
    Vp_bks, Vs_bks, rhob_bks = br.rockphysics.backus(Vp, Vs, rhob, lb, dz)   
    
    new_df['Vp_bk'] = Vp_bks
    new_df['Vs_bk'] = Vs_bks
    new_df['rhob_bk'] = rhob_bks
    
    wells_bk = pd.concat([wells_bk, new_df])
wells_final = (np.concatenate((wells.values, wells_bk.values), axis=1))
cols = list(wells) + list(wells_bk)
wells_final_df = pd.DataFrame(wells_final, columns=cols)
fig = plt.figure(figsize=(12,10))

ax0 = fig.add_subplot(141)
ax0.plot(wells_final_df.loc[wells_final_df.well == 'P-129', 'Vp'], 
         wells_final_df.loc[wells_final_df.well == 'P-129', 'DEPTH'],
                                 'black', alpha=0.8, linewidth = 1, label='Vp')
ax0.legend( loc='best')
ax0.set_title('P-129 Vp')
ax0.set_ylabel(r'depth [m]', size=12)
ax0.invert_yaxis()
ax0.set_xlabel(r'Vp [m/s]', size=12)

ax1 = fig.add_subplot(142)
ax1.plot(wells_final_df.loc[wells_final_df.well == 'P-129', 'Vp_bk'], 
         wells_final_df.loc[wells_final_df.well == 'P-129', 'DEPTH'],
                                 'black', alpha=0.8, linewidth = 1, label='Vp')
ax1.legend( loc='best')
ax1.set_title('Upscaled P-129 Vp')
ax1.set_ylabel(r'depth [m]', size=12)
ax1.invert_yaxis()
ax1.set_xlabel(r'Vp [m/s]', size=12)

ax2 = fig.add_subplot(143)
ax2.plot(wells_final_df.loc[wells_final_df.well == 'P-129', 'Vs'], 
         wells_final_df.loc[wells_final_df.well == 'P-129', 'DEPTH'],
         'blue', alpha=0.8, linewidth = 1, label='Vs')
ax2.legend( loc='best')
ax2.set_title('P-129 Vs')
ax2.set_ylabel(r'depth [m]', size=12)
ax2.invert_yaxis()
ax2.set_xlabel(r'Vs [m/s]', size=12)

ax3 = fig.add_subplot(144)
ax3.plot(wells_final_df.loc[wells_final_df.well == 'P-129', 'Vs_bk'], 
         wells_final_df.loc[wells_final_df.well == 'P-129', 'DEPTH'],
         'blue', alpha=0.8, linewidth = 1, label='Vs')
ax3.legend( loc='best')
ax3.set_title('Upscaled P-129 Vs')
ax3.set_ylabel(r'depth [m]', size=12)
ax3.invert_yaxis()
ax3.set_xlabel(r'Vs [m/s]', size=12)

plt.tight_layout();
fig = plt.figure(figsize=(12,10))

ax0 = fig.add_subplot(141)
ax0.plot(wells_final_df.loc[wells_final_df.well == 'R-39', 'Vp'], 
         wells_final_df.loc[wells_final_df.well == 'R-39', 'DEPTH'],
                                 'black', alpha=0.8, linewidth = 1, label='Vp')
ax0.legend( loc='best')
ax0.set_title('R-39 Vp')
ax0.set_ylabel(r'depth [m]', size=12)
ax0.set_xlabel(r'Vp [m/s]', size=12)

ax1 = fig.add_subplot(142)
ax1.plot(wells_final_df.loc[wells_final_df.well == 'R-39', 'Vp_bk'], 
         wells_final_df.loc[wells_final_df.well == 'R-39', 'DEPTH'],
                                 'black', alpha=0.8, linewidth = 1, label='Vp')
ax0.invert_yaxis()

ax1.legend( loc='best')
ax1.set_title('Upscaled R-39 Vp')
ax1.set_ylabel(r'depth [m]', size=12)
ax1.invert_yaxis()
ax1.set_xlabel(r'Vp [m/s]', size=12)

ax2 = fig.add_subplot(143)
ax2.plot(wells_final_df.loc[wells_final_df.well == 'R-39', 'Vs'], 
         wells_final_df.loc[wells_final_df.well == 'R-39', 'DEPTH'],
         'blue', alpha=0.8, linewidth = 1, label='Vs')
ax2.legend( loc='best')
ax2.set_title('R-39 Vs')
ax2.set_ylabel(r'depth [m]', size=12)
ax2.invert_yaxis()
ax2.set_xlabel(r'Vs [m/s]', size=12)


ax3 = fig.add_subplot(144)
ax3.plot(wells_final_df.loc[wells_final_df.well == 'R-39', 'Vs_bk'], 
         wells_final_df.loc[wells_final_df.well == 'R-39', 'DEPTH'],
         'blue', alpha=0.8, linewidth = 1, label='Vs')
ax3.legend( loc='best')
ax3.set_title('Upscaled R-39 Vs')
ax3.set_ylabel(r'depth [m]', size=12)
ax3.invert_yaxis()
ax3.set_xlabel(r'Vs [m/s]', size=12)

plt.tight_layout();<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1716046927818652, 'fraction_numerical': 0.0514018691588785, 'mean_word_length': 4.774397244546498, 'pattern_counts': {'":': 0, '<': 64, '<?xml version=': 0, '>': 68, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '16', 'dir': 'jupyter-structured-clean-dedup', 'id': '535401', 'license': 'Apache-2.0', 'n_tokens_mistral': 4589, 'n_tokens_neox': 4233, 'n_words': 782, 'path': 'notebooks/Backus_from_dataframe.ipynb', 'repo_name': 'mycarta/in-bruges', 'size': '10058'}