Exemple #1
0
    def test_intercept(self):
        """
        Should test if the intercept calculation returns the same result when using 'along_wiggle' as for single layer
        :return:
        """
        rho = RpTestCase.w.block['Logs'].logs['den'].data
        vp = cnvrt(RpTestCase.w.block['Logs'].logs['ac'].data, 'us/ft', 'm/s')
        incept2 = rp.intercept(vp, None, rho, None, along_wiggle=True)
        i = np.nanargmax(incept2)
        incept1 = rp.intercept(vp[i], vp[i + 1], rho[i], rho[i + 1])
        incept1_2 = rp.intercept(vp[i + 1], vp[i + 2], rho[i + 1], rho[i + 2])

        with self.subTest():
            print('Layer based intercept at i {}: {}'.format(i, incept1))
            print('Layer based intercept at i {}: {}'.format(i + 1, incept1_2))
            print('Wiggle based intercept at i {}: {}'.format(
                i, incept2[i:i + 2]))
            self.assertTrue(True)
Exemple #2
0
    def test_step(self):
        i = 5
        theta = 10.  # degrees
        x1 = np.linspace(1, 10, 10)
        x2 = np.linspace(2, 11, 10)
        x3 = np.linspace(3, 12, 10)
        d1 = rp.step(x1[i], x1[i + 1])
        d2 = rp.step(x1, None, along_wiggle=True)
        incept1 = rp.intercept(x1[i], x1[i + 1], x3[i], x3[i + 1])
        incept2 = rp.intercept(x1, None, x3, None, along_wiggle=True)
        grad1 = rp.gradient(x1[i], x1[i + 1], x2[i], x2[i + 1], x3[i],
                            x3[i + 1])
        grad2 = rp.gradient(x1, None, x2, None, x3, None, along_wiggle=True)
        func1 = rp.reflectivity(x1[i], x1[i + 1], x2[i], x2[i + 1], x3[i],
                                x3[i + 1])
        func2 = rp.reflectivity(x1,
                                None,
                                x2,
                                None,
                                x3,
                                None,
                                along_wiggle=True)

        with self.subTest():
            print('Layer based step at i {}: {}'.format(i, d1))
            print('Wiggle based step at i {}: {}'.format(i, d2[i]))
            print('Layer based intercept at i {}: {}'.format(i, incept1))
            print('Wiggle based intercept at i {}: {}'.format(i, incept2[i]))
            print('Layer based gradient at i {}: {}'.format(i, grad1))
            print('Wiggle based gradient at i {}: {}'.format(i, grad2[i]))
            print('Layer based refl. coeff. at i {} at {} deg.: {}'.format(
                i, theta, func1(theta)))
            print('Wiggle based refl. coeff. at i {} at {} deg.: {}'.format(
                i, theta,
                func2(theta)[i]))
            self.assertTrue(True)
Exemple #3
0
def rpt_phi_sw(_phi, _sw, **kwargs):
    plot_type = kwargs.pop('plot_type', 'AI-VpVs')
    ref_val = kwargs.pop(
        'ref_val', [3500., 1700., 2.6
                    ])  # ref values of Vp, Vs and rho for calculating I x G
    model = kwargs.pop('model', 'stiff')
    phic = kwargs.pop('phic', 0.4)  # critical porosity
    cn = kwargs.pop(
        'cn', 8)  # coordination number, average number of contacts per grain
    p = kwargs.pop('p', 10)  # Confining pressure in MPa (effective pressure?)
    f = kwargs.pop(
        'f', 0.3
    )  # shear modulus correction factor  (1=dry pack with perfect adhesion, 0=dry frictionless pack)
    rho_b = kwargs.pop('rho_b', 1.1)  # Brine density  g/cm3
    k_b = kwargs.pop('k_b', 2.8)  # Brine bulk modulus  GPa
    rho_hc = kwargs.pop('rho_hc', 0.2)  # HC density
    k_hc = kwargs.pop('k_hc', 0.06)  # HC bulk modulus
    rho_min = kwargs.pop('rho_min', 2.7)  # Density [g/cm3] of mineral mix
    k_min = kwargs.pop('k_min', 30.)  # Bulk modulus GPa of mineral mix
    mu_min = kwargs.pop('mu_min', 20.)  # Shear modulus of mineral mix

    # Apply the rock physics model to modify the mineral properties
    if model == 'stiff':
        k_dry, mu_dry = rp.stiffsand(k_min, mu_min, _phi, phic, cn, p, f)
    else:
        k_dry, mu_dry = rp.softsand(k_min, mu_min, _phi, phic, cn, p, f)

    # Calculate the final fluid properties for the given water saturation
    k_f2 = rp.vrh_bounds([_sw, 1. - _sw], [k_b, k_hc])[1]  # K_f
    rho_f2 = rp.vrh_bounds([_sw, 1. - _sw], [rho_b, rho_hc])[0]  #RHO_f

    # Use Gassman to calculate the final elastic properties
    vp_2, vs_2, rho_2, k_2 = rp.vels(k_dry, mu_dry, k_min, rho_min, k_f2,
                                     rho_f2, _phi)

    if plot_type == 'AI-VpVs':
        xx = rho_2 * vp_2
        yy = vp_2 / vs_2
    elif plot_type == 'Phi-Vp':
        xx = _phi
        yy = vp_2
    elif plot_type == 'I-G':
        xx = rp.intercept(ref_val[0], vp_2, ref_val[2], rho_2)
        yy = rp.gradient(ref_val[0], vp_2, ref_val[1], vs_2, ref_val[2], rho_2)
    else:
        raise IOError('No valid plot_type selected')

    return xx, yy
Exemple #4
0
def plot_one_interface(sums,
                       name1,
                       name2,
                       color,
                       fig_ig,
                       ax_ig,
                       fig_refl,
                       ax_refl,
                       n_samps=1000):

    # elastics_from_stats calculates the normally distributed variables, with correlations, given
    # the mean, std and correlation, using a multivariate function
    vp1, vs1, rho1 = elastics_from_stats(sums[name1], n_samps)
    vp2, vs2, rho2 = elastics_from_stats(sums[name2], n_samps)

    # Calculate statistics of the reflection coefficient, assuming 50 samples from 0 to 40 deg incidence angle
    theta = np.linspace(0, 40, 50)
    refs = np.full((n_samps, 50), np.nan)
    # calculate the reflectivity as a function of theta for all variations of the elastic properties
    for i, params in enumerate(zip(vp1, vp2, vs1, vs2, rho1, rho2)):
        refs[i, :] = rp.reflectivity(*params)(theta)

    refl_stds = np.std(refs, 0)

    # Calculate the mean reflectivity curve
    mean_refl = rp.reflectivity(
        sums[name1]['VpMean'],
        sums[name2]['VpMean'],
        sums[name1]['VsMean'],
        sums[name2]['VsMean'],
        sums[name1]['RhoMean'],
        sums[name2]['RhoMean'],
    )

    # plot the mean reflectivity curve together with the uncertainty
    mypr.plot(theta,
              mean_refl(theta),
              c=color,
              yerror=refl_stds,
              yerr_style='fill',
              fig=fig_refl,
              ax=ax_refl)

    intercept = rp.intercept(vp1, vp2, rho1, rho2)
    gradient = rp.gradient(vp1, vp2, vs1, vs2, rho1, rho2)

    #res = least_squares(
    #        mycf.residuals,
    #        [1.,1.],
    #        args=(intercept, gradient),
    #        kwargs={'target_function': straight_line}
    #)
    #print('{} on {}: WS = {:.4f}*I {:.4f} - G'.format(name1, name2, *res.x))
    #print(res.status)
    #print(res.message)
    #print(res.success)

    myxp.plot(intercept,
              gradient,
              cdata=color,
              fig=fig_ig,
              ax=ax_ig,
              edge_color=None,
              alpha=0.2)
    #x_new = np.linspace(-0.75, 0.75, 50)
    #ax_ig.plot(x_new, straight_line(x_new, *res.x), c=color, label='_nolegend_')

    # Do AVO classification
    c1 = len(gradient[(intercept > 0.) & (gradient > -4 * intercept) &
                      (gradient < 0.)])
    c2p = len(gradient[(intercept > 0.) & (gradient < -4 * intercept)])
    c2 = len(gradient[(intercept > -0.02) & (intercept < 0.) &
                      (gradient < 0.)])
    c3 = len(gradient[(intercept < -0.02) & (gradient < 0.)])
    c4 = len(gradient[(intercept < 0.) & (gradient > 0.)])
    rest = len(gradient[(intercept > 0.) & (gradient > 0.)])
    print(
        'Class I: {:.0f}% \nClass IIp: {:.0f}% \nClass II: {:.0f}% \nClass III: {:.0f}% \nClass IV: {:.0f}%'
        .format(100. * c1 / n_samps, 100. * c2p / n_samps, 100. * c2 / n_samps,
                100. * c3 / n_samps, 100. * c4 / n_samps))
    print('Rest:  {:.0f}%'.format(100. * rest / n_samps))
Exemple #5
0
def test_synt2():
    """
    This essentially tries to copy test_synt(), which is based on
    https://github.com/seg/tutorials-2014/blob/master/1406_Make_a_synthetic/how_to_make_synthetic.ipynb
    but using blixt_rp built in functionality instead
    :return:
    """
    import blixt_utils.io.io as uio
    import plotting.plot_logs as ppl
    from core.well import Project
    from core.well import Well
    import blixt_utils.misc.convert_data as ucd

    wp = Project()
    wells = wp.load_all_wells()
    w = wells[list(wells.keys())[0]]  # take first well
    wis = uio.project_working_intervals(wp.project_table)
    log_table = {
        'P velocity': 'vp_dry',
        'S velocity': 'vs_dry',
        'Density': 'rho_dry'
    }

    # when input is in feet and usec
    #depth = ucd.convert(w.block['Logs'].logs['depth'].data, 'ft', 'm')
    #rho_orig = w.block['Logs'].logs['rhob'].data * 1000.  # g/cm3 to kg/m3
    #vp_orig = ucd.convert(w.block['Logs'].logs['dt'].data, 'us/ft', 'm/s')
    #dt_orig = w.block['Logs'].logs['dt'].data * 3.2804  # convert usec/ft to usec/m
    # else
    depth = w.block['Logs'].logs['depth'].data
    rho_orig = w.block['Logs'].logs[
        log_table['Density']].data * 1000.  # g/cm3 to kg/m3
    vp_orig = w.block['Logs'].logs[log_table['P velocity']].data
    vs_orig = w.block['Logs'].logs[log_table['S velocity']].data

    # when input is in feet and usec
    #rho = w.block['Logs'].logs['rhob'].despike(0.1) * 1000.  # g/cm3 to kg/m3
    #vp = ucd.convert(w.block['Logs'].logs['dt'].despike(5), 'us/ft', 'm/s')
    #dt = w.block['Logs'].logs['dt'].despike(5) * 3.2804  # convert usec/ft to usec/m
    # else
    rho = w.block['Logs'].logs[log_table['Density']].despike(
        0.1) * 1000.  # g/cm3 to kg/m3
    vp = w.block['Logs'].logs[log_table['P velocity']].despike(200)
    vs = w.block['Logs'].logs[log_table['S velocity']].despike(200)

    start = 13000
    end = 14500
    # Plot despiking results
    plot = False
    if plot:
        fig, axes = plt.subplots(3, 1, sharex=True, figsize=(18, 12))
        for i, y1, y2 in zip([0, 1, 2], [rho_orig, vp_orig, vs_orig],
                             [rho, vp, vs]):
            axes[i].plot(depth[start:end], y2[start:end], 'y', lw=3)
            axes[i].plot(depth[start:end], y1[start:end], 'k', lw=0.5)
            axes[i].legend(['Smooth & despiked', 'Original'])

    tdr = w.time_to_depth(log_table['P velocity'], debug=False)
    r0 = rp.intercept(vp, None, rho, None, along_wiggle=True)

    plot = True
Exemple #6
0
def twolayer(vp0, vs0, rho0, vp1, vs1, rho1, angels=None):
    #from bruges.reflection import shuey2
    #from bruges.filters import ricker
    from rp.rp_core import reflectivity, intercept, gradient
    if angels is None:
        angels = [5, 15, 30]

    n_samples = 500
    interface = int(n_samples / 2)
    ang = np.arange(31)
    wavelet = ricker(.25, 0.001, 25)

    model_ip, model_vpvs, rc0, rc1, rc2 = (np.zeros(n_samples)
                                           for _ in range(5))
    model_z = np.arange(n_samples)
    model_ip[:interface] = vp0 * rho0
    model_ip[interface:] = vp1 * rho1
    model_vpvs[:interface] = np.true_divide(vp0, vs0)
    model_vpvs[interface:] = np.true_divide(vp1, vs1)

    #avo = shuey2(vp0, vs0, rho0, vp1, vs1, rho1, ang)
    _avo = reflectivity(vp0, vp1, vs0, vs1, rho0, rho1, version='ShueyAkiRich')
    avo = _avo(ang)
    rc0[interface] = avo[angels[0]]
    rc1[interface] = avo[angels[1]]
    rc2[interface] = avo[angels[2]]
    synt0 = np.convolve(rc0, wavelet, mode='same')
    synt1 = np.convolve(rc1, wavelet, mode='same')
    synt2 = np.convolve(rc2, wavelet, mode='same')
    clip = np.max(np.abs([synt0, synt1, synt2]))
    clip += clip * .2

    ic = intercept(vp0, vp1, rho0, rho1)
    gr = gradient(vp0, vp1, vs0, vs1, rho0, rho1)

    opz0 = {'color': 'b', 'linewidth': 4}
    opz1 = {'color': 'k', 'linewidth': 2}
    opz2 = {'linewidth': 0, 'alpha': 0.5}
    opz3 = {'color': 'tab:red', 'linewidth': 0, 'markersize': 8, 'marker': 'o'}
    opz4 = {
        'color': 'tab:blue',
        'linewidth': 0,
        'markersize': 8,
        'marker': 'o'
    }

    f = plt.subplots(figsize=(12, 10))
    ax0 = plt.subplot2grid((2, 12), (0, 0), colspan=3)  # ip
    ax1 = plt.subplot2grid((2, 12), (0, 3), colspan=3)  # vp/vs
    ax2 = plt.subplot2grid((2, 12), (0, 6), colspan=2)  # synthetic @ 0 deg
    ax3 = plt.subplot2grid((2, 12), (0, 8), colspan=2)  # synthetic @ 30 deg
    ax35 = plt.subplot2grid((2, 12), (0, 10), colspan=2)  # synthetic @ 30 deg
    ax4 = plt.subplot2grid((2, 12), (1, 0), colspan=5)  # avo curve
    ax6 = plt.subplot2grid((2, 12), (1, 7), colspan=5)  # avo curve

    ax0.plot(model_ip, model_z, **opz0)
    ax0.set_xlabel('IP')
    ax0.locator_params(axis='x', nbins=2)

    ax1.plot(model_vpvs, model_z, **opz0)
    ax1.set_xlabel('VP/VS')
    ax1.locator_params(axis='x', nbins=2)

    ax2.plot(synt0, model_z, **opz1)
    ax2.plot(synt0[interface], model_z[interface], **opz3)
    ax2.fill_betweenx(model_z,
                      0,
                      synt0,
                      where=synt0 > 0,
                      facecolor='black',
                      **opz2)
    ax2.set_xlim(-clip, clip)
    ax2.set_xlabel('angle={:.0f}'.format(angels[0]))
    ax2.locator_params(axis='x', nbins=2)

    ax3.plot(synt1, model_z, **opz1)
    ax3.plot(synt1[interface], model_z[interface], **opz3)
    ax3.fill_betweenx(model_z,
                      0,
                      synt1,
                      where=synt1 > 0,
                      facecolor='black',
                      **opz2)
    ax3.set_xlim(-clip, clip)
    ax3.set_xlabel('angle={:.0f}'.format(angels[1]))
    ax3.locator_params(axis='x', nbins=2)

    ax35.plot(synt2, model_z, **opz1)
    ax35.plot(synt2[interface], model_z[interface], **opz3)
    ax35.fill_betweenx(model_z,
                       0,
                       synt2,
                       where=synt2 > 0,
                       facecolor='black',
                       **opz2)
    ax35.set_xlim(-clip, clip)
    ax35.set_xlabel('angle={:.0f}'.format(angels[2]))
    ax35.locator_params(axis='x', nbins=2)

    ax4.plot(ang, avo, **opz0)
    ax4.axhline(0, color='k', lw=2)
    ax4.set_xlabel('angle of incidence')
    ax4.tick_params(which='major', labelsize=8)

    ax5 = ax4.twinx()
    color = 'tab:red'
    ax5.plot(angels, [s[interface] for s in [synt0, synt1, synt2]], **opz3)
    ax5.set_ylabel('Seismic amplitude')
    ax5.tick_params(axis='y', labelcolor=color, labelsize=8)

    # Calculate intercept & gradient based on the three "angle stacks"1G
    res = least_squares(
        mycf.residuals, [1., 1.],
        args=(np.array(angels),
              np.array([s[interface] for s in [synt0, synt1, synt2]])),
        kwargs={'target_function': straight_line})
    print('amp = {:.4f}*theta + {:.4f}'.format(*res.x))
    print(res.status)
    print(res.message)
    print(res.success)
    ax5.plot(ang, straight_line(ang, *res.x), c='tab:red')

    res2 = least_squares(
        mycf.residuals, [1., 1.],
        args=(np.sin(np.array(angels) * np.pi / 180.)**2,
              np.array([s[interface] for s in [synt0, synt1, synt2]])),
        kwargs={'target_function': straight_line})
    print('amp = {:.4f}*theta + {:.4f}'.format(*res2.x))
    print(res2.status)
    print(res2.message)
    print(res2.success)

    ax6.plot(ic, gr, **opz4)
    ax6.plot(*res2.x[::-1], **opz3)
    ax6.set_xlabel('Intercept')
    ax6.set_ylabel('Gradient')

    for aa in [ax0, ax1, ax2, ax3, ax35]:
        aa.set_ylim(350, 150)
        aa.tick_params(which='major', labelsize=8)
        aa.set_yticklabels([])

    plt.subplots_adjust(wspace=.8, left=0.05, right=0.95)
Exemple #7
0
def test_synt():
    """
    https://github.com/seg/tutorials-2014/blob/master/1406_Make_a_synthetic/how_to_make_synthetic.ipynb
    :return:
    """
    import blixt_utils.io.io as uio
    import plotting.plot_logs as ppl
    from core.well import Project
    from core.well import Well
    import blixt_utils.misc.convert_data as ucd

    wp = Project()
    well_table = {
        os.path.join(wp.working_dir, 'test_data/L-30.las'): {
            'Given well name': 'WELL_L',
            'logs': {
                'dt': 'Sonic',
                'cald': 'Caliper',
                'cals': 'Caliper',
                'rhob': 'Density',
                'grd': 'Gamma ray',
                'grs': 'Gamma ray',
                'ild': 'Resistivity',
                'ilm': 'Resistivity',
                'll8': 'Resistivity',
                'nphils': 'Neutron density'
            },
            'Note': 'Some notes for well A'
        }
    }
    wis = uio.project_working_intervals(wp.project_table)
    w = Well()
    w.read_well_table(well_table, 0, block_name='Logs')

    depth = w.block['Logs'].logs['depth'].data / 3.28084  # feet to m
    rho_orig = w.block['Logs'].logs['rhob'].data * 1000.  # g/cm3 to kg/m3
    vp_orig = ucd.convert(w.block['Logs'].logs['dt'].data, 'us/ft', 'm/s')
    dt_orig = w.block['Logs'].logs[
        'dt'].data * 3.2804  # convert usec/ft to usec/m

    #
    # Start of copying the notebook results:
    # https://github.com/seg/tutorials-2014/blob/master/1406_Make_a_synthetic/how_to_make_synthetic.ipynb
    #
    def f2m(item_in_feet):
        "converts feet to meters"
        try:
            return item_in_feet / 3.28084
        except TypeError:
            return float(item_in_feet) / 3.28084

    kb = f2m(w.header.kb.value)
    water_depth = f2m(w.header.gl.value)  # has a negative value
    #top_of_log = f2m(w.block['Logs'].header.strt.value)
    top_of_log = f2m(1150.5000)  # The DT log starts at this value
    repl_int = top_of_log - kb + water_depth
    water_vel = 1480  # m/s
    EGL_time = 2.0 * np.abs(kb) / water_vel
    #water_twt = 2.0 * abs(water_depth + EGL_time) / water_vel # ORIG THIS SEEMS LIKE MIXING distance with time!
    water_twt = 2.0 * abs(water_depth + np.abs(kb)) / water_vel  # My version
    repl_vel = 1600.  # m/s
    repl_time = 2. * repl_int / repl_vel
    log_start_time = water_twt + repl_time

    print('KB elevation: {} [m]'.format(kb))
    print('Seafloor elevation: {} [m]'.format(water_depth))
    print('Ground level time above SRD: {} [s]'.format(EGL_time))
    print('Water time: {} [s]'.format(water_twt))
    print('Top of Sonic log: {} [m]'.format(top_of_log))
    print('Replacement interval: {} [m]'.format(repl_int))
    print('Two-way replacement time: {} [s]'.format(repl_time))
    print('Top-of-log starting time: {} [s]'.format(log_start_time))

    def tvdss(md):
        # Assumes a vertical well
        # md in meter
        return md - kb

    def rolling_window(a, window):
        shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
        strides = a.strides + (a.strides[-1], )
        rolled = np.lib.stride_tricks.as_strided(a,
                                                 shape=shape,
                                                 strides=strides)
        return rolled

    #plt.figure(figsize=(18, 4))
    #plt.plot(depth, rho_sm, 'b', depth, rho, 'k', alpha=0.5)

    def despike(curve, curve_sm, max_clip):
        spikes = np.where(curve - curve_sm > max_clip)[0]
        spukes = np.where(curve_sm - curve > max_clip)[0]
        out = np.copy(curve)
        out[spikes] = curve_sm[
            spikes] + max_clip  # Clip at the max allowed diff
        out[spukes] = curve_sm[
            spukes] - max_clip  # Clip at the min allowed diff
        return out

    window = 13  # the length of filter is 13 samples or ~ 2 metres

    # Density
    rho_sm = np.median(rolling_window(rho_orig, window), -1)
    rho_sm = np.pad(rho_sm, int(window / 2), mode='edge')
    rho = despike(rho_orig, rho_sm, max_clip=100)
    rho_test = w.block['Logs'].logs['rhob'].despike(
        0.1) * 1000.  # g/cm3 to kg/m3

    # dt
    dt_sm = np.median(rolling_window(dt_orig, window), -1)
    dt_sm = np.pad(dt_sm, int(window / 2), mode='edge')
    dt = despike(dt_orig, dt_sm, max_clip=10)

    # My test of despiking the velocity directly
    vp_sm = np.median(rolling_window(vp_orig, window), -1)
    vp_sm = np.pad(vp_sm, int(window / 2), mode='edge')
    vp = despike(vp_orig, vp_sm, max_clip=200)

    # Plot result of despiking
    start = 13000
    end = 14500
    plot = True
    if plot:
        plt.figure(figsize=(18, 4))
        plt.plot(depth[start:end], rho_orig[start:end], 'b', lw=3)
        #plt.plot(depth[start:end], rho_sm[start:end], 'b')
        plt.plot(depth[start:end], rho[start:end], 'r', lw=2)
        plt.plot(depth[start:end], rho_test[start:end], 'k--')
        plt.title('de-spiked density')

        plt.figure(figsize=(18, 4))
        plt.plot(depth[start:end], dt_orig[start:end], 'k')
        plt.plot(depth[start:end], dt_sm[start:end], 'b')
        plt.plot(depth[start:end], dt[start:end], 'r')
        plt.title('de-spiked sonic')

        #plt.figure(figsize=(18, 4))
        #plt.plot(depth[start:end], vp_orig[start:end], 'k')
        #plt.plot(depth[start:end], vp_sm[start:end], 'b')
        #plt.plot(depth[start:end], vp[start:end], 'r')
        #plt.title('de-spiked Vp')

    # Compute the time-depth relationship
    # two-way-time to depth relationship
    scaled_dt = 0.1524 * np.nan_to_num(
        dt
    ) / 1.e6  # scale the sonic log by the sample interval (6 inches or 0.1524 m)
    # and go from usec to sec
    tcum = 2 * np.cumsum(scaled_dt)  # integration
    tdr = tcum + log_start_time
    print(tdr[:10], tdr[-10:])

    # Compute acoustic impedance
    ai = (1e6 / dt) * rho

    # Compute reflection
    rc = (ai[1:] - ai[:-1]) / (ai[1:] + ai[:-1])

    # Compute reflection "my way"
    r0 = rp.intercept(vp, None, rho, None, along_wiggle=True)
    #  The difference between rc and r0 lies basically in the difference in smoothing and clipping of dt vs. vp

    plot = False
    if plot:
        plt.figure(figsize=(18, 4))
        plt.plot(depth[start:end], rc[start:end], 'k')
        plt.plot(depth[start:end], r0[start:end], 'b')
        plt.title('Comparison of reflection coefficients')
        plt.legend(['Notebook way', 'My way'])

    def find_nearest(array, value):
        idx = (np.abs(array - value)).argmin()
        return idx

    tops = {}
    for _key in list(wis['WELL_L'].keys()):
        tops[_key] = wis['WELL_L'][_key][0]
    tops_twt = {}
    for _key in list(wis['WELL_L'].keys()):
        tops_twt[_key] = tdr[find_nearest(depth, wis['WELL_L'][_key][0])]

    # RESAMPLING FUNCTION
    t_step = 0.004
    max_t = 3.0
    t = np.arange(0, max_t, t_step)
    ai_t = np.interp(x=t, xp=tdr, fp=ai)
    rc_t = (ai_t[1:] - ai_t[:-1]) / (ai_t[1:] + ai_t[:-1])

    # Compute the depth-time relation
    dtr = np.array([depth[find_nearest(tdr, tt)] for tt in t])

    # Define a Ricker wavelet
    def ricker(_f, _length, _dt):
        _t = np.linspace(-_length / 2, (_length - _dt) / 2, _length / _dt)
        _y = (1. - 2. * (np.pi**2) * (_f**2) *
              (_t**2)) * np.exp(-(np.pi**2) * (_f**2) * (_t**2))
        return _t, _y

    # Do the convolution
    rc_t = np.nan_to_num(rc_t)
    tw, w = ricker(_f=25, _length=0.512, _dt=0.004)
    synth = np.convolve(w, rc_t, mode='same')

    plot = False
    if plot:
        f2 = plt.figure(figsize=[10, 12])

        ax1 = f2.add_axes([0.05, 0.1, 0.2, 0.9])
        ax1.plot(ai, depth, 'k', alpha=0.75)
        ax1.set_title('impedance')
        ax1.set_ylabel('measured depth ' + '$[m]$', fontsize='12')
        ax1.set_xlabel(r'$kg/m^2s^2$ ', fontsize='16')
        ax1.set_ylim(0, 4500)
        ax1.set_xticks([0.0e7, 0.5e7, 1.0e7, 1.5e7, 2.0e7])
        ax1.invert_yaxis()
        ax1.grid()

        ax2 = f2.add_axes([0.325, 0.1, 0.2, 0.9])
        ppl.wiggle_plot(ax2, dtr[:-1], synth, fill='pos')
        ax2.set_ylim(0, 4500)
        ax2.invert_yaxis()
        ax2.grid()

        ax3 = f2.add_axes([0.675, 0.1, 0.1, 0.9])
        ax3.plot(ai_t, t, 'k', alpha=0.75)
        ax3.set_title('impedance')
        ax3.set_ylabel('two-way time ' + '$[s]$', fontsize='12')
        ax3.set_xlabel(r'$kg/m^2s^2$ ', fontsize='16')
        ax3.set_ylim(0, 3)
        ax3.set_xticks([0.0e7, 0.5e7, 1.0e7, 1.5e7, 2.0e7])
        ax3.invert_yaxis()
        ax3.grid()

        ax4 = f2.add_axes([0.8, 0.1, 0.2, 0.9])
        ppl.wiggle_plot(ax4, t[:-1], synth, scaling=10, fill='pos')
        ax4.set_ylim(0, 3)
        ax4.invert_yaxis()
        ax4.grid()

        for top, depth in tops.items():
            f2.axes[0].axhline(y=float(depth),
                               color='b',
                               lw=2,
                               alpha=0.5,
                               xmin=0.05,
                               xmax=0.95)
            f2.axes[0].text(x=1e7,
                            y=float(depth) - 0.015,
                            s=top,
                            alpha=0.75,
                            color='k',
                            fontsize='12',
                            horizontalalignment='center',
                            verticalalignment='center',
                            bbox=dict(facecolor='white', alpha=0.5, lw=0.5),
                            weight='light')
        for top, depth in tops.items():
            f2.axes[1].axhline(y=float(depth),
                               color='b',
                               lw=2,
                               alpha=0.5,
                               xmin=0.05,
                               xmax=0.95)

        for i in range(2, 4):
            for twt in tops_twt.values():
                f2.axes[i].axhline(y=float(twt),
                                   color='b',
                                   lw=2,
                                   alpha=0.5,
                                   xmin=0.05,
                                   xmax=0.95)
Exemple #8
0
def plot_rp(wells,
            log_table,
            wis,
            wi_name,
            cutoffs=None,
            templates=None,
            legend_items=None,
            plot_type=None,
            ref_val=None,
            fig=None,
            ax=None,
            block_name=None,
            savefig=None,
            **kwargs):
    """
    Plots some standard rock physics crossplots for the given wells

    :param wells:
        dict
        dictionary with well names as keys, and core.well.Well object as values
        As returned from core.well.Project.load_all_wells()
    :param log_table:
        dict
        Dictionary of log type: log name key: value pairs which decides which log, under each log type, to plot
        E.G.
            log_table = {
               'P velocity': 'vp',
               'S velocity': 'vs',
               'Density': 'rhob',
               'Porosity': 'phie',
               'Volume': 'vcl'}
    :param wis:
        dict
        working intervals, as defined in the "Working intervals" sheet of the project table, and
        loaded through:
        wp = Project()
        wis = rp_utils.io.project_working_intervals(wp.project_table)
    :param wi_name:
        str
        name of working interval to plot
    :param cutoffs:
        dict
        Dictionary with log types as keys, and list with mask definition as value
        E.G.
            {'Volume': ['<', 0.5], 'Porosity': ['>', 0.1]}
    :param templates:
        dict
        templates dictionary as returned from rp_utils.io.project_templates()
    :param legend_items:
        list
        list of Line2D objects that are used in the legends.
        if None, the well names will be used
    :param plot_type:
        str
        plot_type =
            'AI-VpVs': AI versus Vp/Vs plot
            'Phi-Vp': Porosity versus Vp plot
            'I-G': Intercept versus Gradient plot
    :param ref_val:
        list
        List of reference Vp [m/s], Vs [m/s], and rho [g/cm3] that are used
        when calculating the Intercept and gradient
    :param fig:

    :param ax:

    :param block_name:
        str
        Name of the log block from where the logs are picked
    :param savefig
        str
        full pathname of file to save the plot to
    :param **kwargs:
        keyword arguments passed on to crossplot.plot()
    :return:
    """
    #
    # some initial setups
    log_table = small_log_table(log_table)
    if block_name is None:
        block_name = cw.def_lb_name

    _savefig = False
    if plot_type is None:
        plot_type = 'AI-VpVs'
    elif plot_type == 'I-G' and ref_val is None:
        ref_val = [3500., 1700., 2.6]
    logs = [n.lower() for n in list(log_table.values())]
    if savefig is not None:
        _savefig = True

    #
    # set up plotting environment
    if fig is None:
        if ax is None:
            fig = plt.figure(figsize=(10, 10))
            ax = fig.subplots()
        else:  # Only ax is set, but not fig. Which means all functionality calling fig must be turned off
            _savefig = False
    elif ax is None:
        ax = fig.subplots()

    # load
    well_names = []
    desc = ''
    for wname, _well in wells.items():
        print('Plotting well {}'.format(wname))
        # create a deep copy of the well so that the original is not altered
        well = deepcopy(_well)
        these_wis = wis[wname]
        if wi_name.upper() not in [
                _x.upper() for _x in list(these_wis.keys())
        ]:
            warn_txt = 'Working interval {} does not exist in well {}'.format(
                wi_name, wname)
            print('WARNING: {}'.format(warn_txt))
            logger.warning(warn_txt)
            continue  # this working interval does not exist in current well
        # test if necessary logs are in the well
        skip = False
        for _log in logs:
            if _log not in list(well.block[block_name].logs.keys()):
                warn_txt = '{} log is lacking in {}'.format(_log, wname)
                print('WARNING: {}'.format(warn_txt))
                logger.warning(warn_txt)
                skip = True
        if skip:
            continue
        # create mask based on working interval
        well.calc_mask({}, name='XXX', wis=wis, wi_name=wi_name)
        # apply mask (which also deletes the mask itself)
        well.apply_mask('XXX')
        # create mask based on cutoffs
        if cutoffs is not None:
            well.calc_mask(cutoffs,
                           name='cmask',
                           log_type_input=True,
                           log_table=log_table)
            mask = well.block[block_name].masks['cmask'].data
            desc = well.block[block_name].masks['cmask'].header.desc
        else:
            mask = None

        # collect data for plot
        if plot_type == 'AI-VpVs':
            if 'P velocity' in list(log_table.keys()):
                # Calculating Vp / Vs using vp and vs
                x_data = well.block[block_name].logs[log_table['P velocity'].lower()].data * \
                         well.block[block_name].logs[log_table['Density'].lower()].data
                x_unit = '{} {}'.format(
                    well.block[block_name].logs[
                        log_table['P velocity'].lower()].header.unit,
                    well.block[block_name].logs[
                        log_table['Density'].lower()].header.unit)
                y_data = well.block[block_name].logs[log_table['P velocity'].lower()].data / \
                         well.block[block_name].logs[log_table['S velocity'].lower()].data
            else:
                # Assume we are calculating Vp / Vs using sonic logs
                x_data = well.block[block_name].logs[log_table['Density'].lower()].data / \
                         well.block[block_name].logs[log_table['Sonic'].lower()].data
                x_unit = '{}/{}'.format(
                    well.block[block_name].logs[
                        log_table['Density'].lower()].header.unit,
                    well.block[block_name].logs[
                        log_table['Sonic'].lower()].header.unit)
                y_data = well.block[block_name].logs[log_table['Shear sonic'].lower()].data / \
                         well.block[block_name].logs[log_table['Sonic'].lower()].data

            y_unit = '-'
            xtempl = {'full_name': 'AI', 'unit': x_unit}
            ytempl = {'full_name': 'Vp/Vs', 'unit': y_unit}

        elif (plot_type == 'Vp-bd') or (plot_type == 'Vp-tvd'):
            if 'P velocity' in list(log_table.keys()):
                x_data = well.block[block_name].logs[
                    log_table['P velocity'].lower()].data
                x_unit = '{}'.format(well.block[block_name].logs[
                    log_table['P velocity'].lower()].header.unit)
                xtempl = {'full_name': log_table['P velocity'], 'unit': x_unit}
            else:
                x_data = 1. / well.block[block_name].logs[
                    log_table['Sonic'].lower()].data
                x_unit = '1/{}'.format(well.block[block_name].logs[
                    log_table['Sonic'].lower()].header.unit)
                xtempl = {'full_name': '1/Sonic', 'unit': x_unit}
            if plot_type == 'Vp-bd':
                y_data = well.get_burial_depth(templates, block_name)
                ytempl = {'full_name': 'Burial depth', 'unit': 'm'}
            else:
                y_data = well.block[block_name].get_tvd()
                ytempl = {'full_name': 'TVD', 'unit': 'm'}

        elif (plot_type == 'VpVs-bd') or (plot_type == 'VpVs-tvd'):
            x_data = well.block[block_name].logs[log_table['P velocity'].lower()].data / \
                     well.block[block_name].logs[log_table['S velocity'].lower()].data
            xtempl = {'full_name': 'Vp/Vs', 'unit': '-'}
            if plot_type == 'VpVs-bd':
                y_data = well.get_burial_depth(templates, block_name)
                ytempl = {'full_name': 'Burial depth', 'unit': 'm'}
            else:
                y_data = well.block[block_name].get_tvd()
                ytempl = {'full_name': 'TVD', 'unit': 'm'}

        elif (plot_type == 'AI-bd') or (plot_type == 'AI-tvd'):
            x_data = well.block[block_name].logs[log_table['P velocity'].lower()].data * \
                     well.block[block_name].logs[log_table['Density'].lower()].data
            x_unit = '{} {}'.format(
                well.block[block_name].logs[
                    log_table['P velocity'].lower()].header.unit,
                well.block[block_name].logs[
                    log_table['Density'].lower()].header.unit)
            xtempl = {'full_name': 'AI', 'unit': x_unit}
            if plot_type == 'AI-bd':
                y_data = well.get_burial_depth(templates, block_name)
                ytempl = {'full_name': 'Burial depth', 'unit': 'm'}
            else:
                y_data = well.block[block_name].get_tvd()
                ytempl = {'full_name': 'TVD', 'unit': 'm'}

        elif (plot_type == 'Rho-bd') or (plot_type == 'Rho-tvd'):
            x_data = well.block[block_name].logs[
                log_table['Density'].lower()].data
            x_unit = '{}'.format(well.block[block_name].logs[
                log_table['Density'].lower()].header.unit)
            xtempl = {'full_name': log_table['Density'], 'unit': x_unit}
            if plot_type == 'Rho-bd':
                y_data = well.get_burial_depth(templates, block_name)
                ytempl = {'full_name': 'Burial depth', 'unit': 'm'}
            else:
                y_data = well.block[block_name].get_tvd()
                ytempl = {'full_name': 'TVD', 'unit': 'm'}

        elif plot_type == 'Phi-Vp':
            x_data = well.block[block_name].logs[
                log_table['Porosity'].lower()].data
            x_unit = '{}'.format(well.block[block_name].logs[
                log_table['Porosity'].lower()].header.unit)
            if 'P velocity' in list(log_table.keys()):
                # Calculating Vp using vp
                y_data = well.block[block_name].logs[
                    log_table['P velocity'].lower()].data
                y_unit = '{}'.format(well.block[block_name].logs[
                    log_table['P velocity'].lower()].header.unit)
            else:
                # Assume we are calculating Vp using sonic logs
                y_data = cnvrt(
                    well.block[block_name].logs[
                        log_table['P velocity'].lower()].data, 'us/ft', 'm/s')
                y_unit = 'm/s'
            xtempl = {'full_name': 'Porosity', 'unit': x_unit}
            ytempl = {'full_name': 'Vp', 'unit': y_unit}
        elif plot_type == 'I-G':
            x_data = rp.intercept(
                ref_val[0], well.block[block_name].logs[
                    log_table['P velocity'].lower()].data, ref_val[2],
                well.block[block_name].logs[log_table['Density'].lower()].data)
            x_unit = '-'
            y_data = rp.gradient(
                ref_val[0], well.block[block_name].logs[
                    log_table['P velocity'].lower()].data, ref_val[1],
                well.block[block_name].logs[
                    log_table['S velocity'].lower()].data, ref_val[2],
                well.block[block_name].logs[log_table['Density'].lower()].data)
            y_unit = '-'
            xtempl = {'full_name': 'Intercept', 'unit': x_unit}
            ytempl = {'full_name': 'Gradient', 'unit': y_unit}
        else:
            raise IOError('No known plot type selected')

        well_names.append(wname)
        # start plotting

        xp.plot(x_data,
                y_data,
                cdata=templates[wname]['color'],
                mdata=templates[wname]['symbol'],
                xtempl=xtempl,
                ytempl=ytempl,
                mask=mask,
                fig=fig,
                ax=ax,
                **kwargs)
    ax.autoscale(True, axis='both')
    if ('tvd' in plot_type) or ('bd' in plot_type):
        ax.set_ylim(ax.get_ylim()[::-1])
    ax.set_title('{}, {}'.format(wi_name, desc))
    #
    if legend_items is None:
        legend_items = []
        for wname in well_names:
            legend_items.append(
                Line2D([0], [0],
                       color=templates[wname]['color'],
                       lw=0,
                       marker=templates[wname]['symbol'],
                       label=wname))

    legend_names = [x._label for x in legend_items]
    this_legend = ax.legend(legend_items,
                            legend_names,
                            prop=FontProperties(size='smaller'),
                            scatterpoints=1,
                            markerscale=2,
                            loc=1)

    if _savefig:
        fig.savefig(savefig)