def test_reflectivity(self): """ What happens when the input to the reflectivity is an array? :return: """ i = 10637 theta = 10. # degrees rho = RpTestCase.w.block['Logs'].logs['den'].data vp = cnvrt(RpTestCase.w.block['Logs'].logs['ac'].data, 'us/ft', 'm/s') vs = cnvrt(RpTestCase.w.block['Logs'].logs['acs'].data, 'us/ft', 'm/s') func1 = rp.reflectivity(vp[i], vp[i + 1], vs[i], vs[i + 1], rho[i], rho[i + 1]) func1_2 = rp.reflectivity(vp[i + 1], vp[i + 2], vs[i + 1], vs[i + 2], rho[i + 1], rho[i + 2]) func2 = rp.reflectivity(vp, None, vs, None, rho, None, along_wiggle=True) with self.subTest(): print('Layer based refl. coeff. at i {} at {} deg.: {}'.format( i, theta, func1(theta))) print('Layer based refl. coeff. at i {} at {} deg.: {}'.format( i + 1, theta, func1_2(theta))) print('Wiggle based refl. coeff. at i {} at {} deg.: {}'.format( i, theta, func2(theta)[i:i + 2])) self.assertTrue(True)
def main(): # Set up a test plot fig, [ax1, ax2] = plt.subplots(nrows=1, ncols=2) ref_functions = [ rp.reflectivity(2800, 3000, 1350, 1500, 2.5, 2.4), rp.reflectivity(2900, 2800, 1400, 1300, 2.5, 2.4) ] for i, ax in enumerate([ax1, ax2]): xdata = np.linspace(0, 40, 50) ydata = ref_functions[i](xdata) yerror = np.full(ydata.shape, 0.002) plot(xdata, ydata, yerror=yerror, c=cnames[i], fig=fig, ax=ax, xtempl={ 'full_name': 'X label', 'unit': '-', 'min': 0., 'max': 1. }, ytempl={ 'full_name': 'Y label', 'unit': '-', 'min': 0., 'max': 1. }) # Handle the legends legends = [] this_legend = ax1.legend(legends, prop=FontProperties(size='smaller'), scatterpoints=1, markerscale=0.5, loc=1) plt.show()
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)
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))
def plot_logs(well, log_table, wis, wi_name, templates, buffer=None, block_name=None, savefig=None, **kwargs): """ Attempts to draw a plot similar to the "CPI plots", for one working interval with some buffer. :param well: :param log_table: dict Dictionary of log type: log name key: value pairs which decides which log to use when selecting which velocity / sonic and density logs. Other logs (e.g. 'Resistivity') are selected based on their presence E.G. log_table = { 'P velocity': 'vp', 'S velocity': 'vs', 'Density': 'rhob'} :param buffer: float distance in meters Log is plotted from top of working interval - buffer to base of working interval + buffer :return: """ log_table = small_log_table(log_table) if buffer is None: buffer = 50. if block_name is None: block_name = cw.def_lb_name time_step = kwargs.pop('time_step', 0.001) c_f = kwargs.pop('center_frequency', 30.) duration = kwargs.pop('duration', 0.512) scaling = kwargs.pop('scaling', 30.0) fig = plt.figure(figsize=(20, 10)) fig.suptitle('{} interval in well {}'.format(wi_name, well.well)) n_cols = 22 # subdivide plot in this number of equally wide columns l = 0.05 w = (1 - l) / float(n_cols + 1) b = 0.05 h = 0.8 #l = 0.05; w = 0; b = 0.1; h = 0.8 rel_pos = [1, 4, 5, 6, 9, 12, 15, 18] # Column number (starting with one) of subplot rel_widths = [ _x - _y for _x, _y in zip(np.roll(rel_pos + [n_cols], -1)[:-1], rel_pos) ] ax_names = [ 'gr_ax', 'md_ax', 'twt_ax', 'res_ax', 'rho_ax', 'cpi_ax', 'ai_ax', 'synt_ax' ] header_axes = {} for i in range(len(ax_names)): header_axes[ax_names[i]] = fig.add_subplot( 2, n_cols, rel_pos[i], position=[ l + (rel_pos[i] - 1) * w, h + 0.05, rel_widths[i] * w, 1 - h - 0.1 ]) #, #figure=fig) axes = {} for i in range(len(ax_names)): axes[ax_names[i]] = fig.add_subplot( 2, n_cols, n_cols + rel_pos[i], position=[l + (rel_pos[i] - 1) * w, b, rel_widths[i] * w, h]) #, #figure=fig) # # Start plotting data # tb = well.block[block_name] # this log block depth = tb.logs['depth'].data mask = np.ma.masked_inside(depth, wis[well.well][wi_name][0] - buffer, wis[well.well][wi_name][1] + buffer).mask # # Gamma ray and Caliper try_these_log_types = ['Gamma ray', 'Caliper', 'Inclination'] log_types = [ x for x in try_these_log_types if (len(well.get_logs_of_type(x)) > 0) ] lognames = { ltype: well.get_logs_of_type(ltype)[0].name for ltype in log_types } limits = [[templates[x]['min'], templates[x]['max']] for x in log_types] styles = [{ 'lw': templates[x]['line width'], 'color': templates[x]['line color'], 'ls': templates[x]['line style'] } for x in log_types] legends = [ '{} [{}]'.format(lognames[x], templates[x]['unit']) for x in log_types ] xlims = axis_plot(axes['gr_ax'], depth[mask], [tb.logs[lognames[xx]].data[mask] for xx in log_types], limits, styles) header_plot(header_axes['gr_ax'], xlims, legends, styles) #for ax in [axes[x] for x in ax_names if x not in ['twt_ax', 'synt_ax']]: for ax in [axes[x] for x in ax_names if x not in ['twt_ax']]: ax.axhline(y=wis[well.well][wi_name][0], color='k', ls='--') ax.axhline(y=wis[well.well][wi_name][1], color='k', ls='--') # # MD header_plot(header_axes['md_ax'], None, None, None, title='MD [m]') annotate_plot(axes['md_ax'], depth[mask]) # # TWT # Get the time-depth relation (time as a function of md) _x = None tdr = None if 'P velocity' in list(log_table.keys()): _x = log_table['P velocity'] elif 'Sonic' in list(log_table.keys()): _x = log_table['Sonic'] if _x is not None: tdr = well.time_to_depth(_x, templates=templates) if tdr is None: header_plot(header_axes['twt_ax'], None, None, None, title='TWT [s]\nLacking info') annotate_plot(axes['twt_ax'], None) else: header_plot(header_axes['twt_ax'], None, None, None, title='TWT [s]') annotate_plot(axes['twt_ax'], tdr[mask]) else: header_plot(header_axes['twt_ax'], None, None, None, title='TWT [s]\nLacking info') annotate_plot(axes['twt_ax'], None) if tdr is not None: tops_twt = [ tdr[find_nearest(depth, y)] for y in wis[well.well][wi_name] ] #print(tops_twt) #for ax in [axes[x] for x in ['twt_ax', 'synt_ax']]: for ax in [axes[x] for x in ['twt_ax']]: ax.axhline(y=tops_twt[0], color='k', ls='--') ax.axhline(y=tops_twt[1], color='k', ls='--') # # Resistivity log_types = ['Resistivity'] lognames = { ltype: [x.name for x in well.get_logs_of_type(ltype)] for ltype in log_types } limits = [[templates[x]['min'], templates[x]['max']] for x in log_types] cls = ['r', 'b', 'k', 'g', 'c'] # should not plot more than 5 lines in this plot! lws = [2, 1, 1, 1, 1] lss = ['-', '--', ':', '.-', '-'] styles = [{ 'lw': lws[i], 'color': cls[i], 'ls': lss[i] } for i in range(len(lognames['Resistivity']))] legends = [ '{} [{}]'.format(x, templates['Resistivity']['unit']) for x in lognames['Resistivity'] ] xlims = axis_log_plot( axes['res_ax'], depth[mask], [tb.logs[x].data[mask] for x in lognames['Resistivity']], limits, styles, yticks=False) header_plot(header_axes['res_ax'], xlims * len(legends), legends, styles) # # Rho try_these_log_types = ['Density', 'Neutron density'] log_types = [ x for x in try_these_log_types if (len(well.get_logs_of_type(x)) > 0) ] lognames = { ltype: well.get_logs_of_type(ltype)[0].name for ltype in log_types } # Replace the density with the one selected by log_table lognames['Density'] = log_table['Density'] limits = [[templates[x]['min'], templates[x]['max']] for x in log_types] styles = [{ 'lw': templates[x]['line width'], 'color': templates[x]['line color'], 'ls': templates[x]['line style'] } for x in log_types] legends = [ '{} [{}]'.format(lognames[x], templates[x]['unit']) for x in log_types ] for xx in log_types: print(lognames[xx]) xlims = axis_plot(axes['rho_ax'], depth[mask], [tb.logs[lognames[xx]].data[mask] for xx in log_types], limits, styles, yticks=False) header_plot(header_axes['rho_ax'], xlims, legends, styles) # # CPI try_these_log_types = ['Saturation', 'Porosity', 'Volume'] log_types = [ x for x in try_these_log_types if (len(well.get_logs_of_type(x)) > 0) ] lognames = { ltype: well.get_logs_of_type(ltype)[0].name for ltype in log_types } limits = [[templates[x]['min'], templates[x]['max']] for x in log_types] styles = [{ 'lw': templates[x]['line width'], 'color': templates[x]['line color'], 'ls': templates[x]['line style'] } for x in log_types] legends = [ '{} [{}]'.format(lognames[x], templates[x]['unit']) for x in log_types ] if len(log_types) == 0: header_plot(header_axes['cpi_ax'], None, None, None, title='CPI is lacking') axis_plot(axes['cpi_ax'], None, None, None, None) else: xlims = axis_plot( axes['cpi_ax'], depth[mask], [tb.logs[lognames[xx]].data[mask] for xx in log_types], limits, styles, yticks=False) header_plot(header_axes['cpi_ax'], xlims, legends, styles) # # AI tt = '' if 'Density' in list(log_table.keys()): tt += log_table['Density'] if 'P velocity' in list(log_table.keys()): ai = tb.logs[log_table['Density']].data * tb.logs[ log_table['P velocity']].data tt += '*{}'.format(log_table['P velocity']) elif 'Sonic' in list(log_table.keys()): ai = tb.logs[log_table['Density']].data / tb.logs[ log_table['Sonic']].data tt += '/{}'.format(log_table['Sonic']) else: ai = None else: ai = None if ai is not None: #styles = [{'lw': 1, 'color': 'k', 'ls': '--'}] log_types = ['AI'] lognames = {'AI': 'AI'} limits = [[templates[x]['min'], templates[x]['max']] for x in log_types] styles = [{ 'lw': templates[x]['line width'], 'color': templates[x]['line color'], 'ls': templates[x]['line style'] } for x in log_types] legends = [ '{} [{}]'.format(lognames[x], templates[x]['unit']) for x in log_types ] # TODO # Now we blindly assumes AI is in m/s g/cm3 Make this more robust xlims = axis_plot(axes['ai_ax'], depth[mask], [ai[mask] / 1000.], limits, styles, yticks=False) #header_plot(header_axes['ai_ax'], xlims, ['AI ({})'.format(tt)], styles) header_plot(header_axes['ai_ax'], xlims, legends, styles) else: header_plot(header_axes['ai_ax'], None, None, None, title='AI is lacking') axis_plot(axes['ai_ax'], None, None, None, None) # # Wiggles #t = np.arange(tdr[mask][0], tdr[mask][-1], 0.004) # A uniformly sampled array of time steps, from A to B t = np.arange( 0., np.nanmax(tdr), time_step) # A uniformly sampled array of time steps, from 0 to 3 #print(len(t)) if 'P velocity' in list(log_table.keys()): vp_t = np.interp(x=t, xp=tdr, fp=tb.logs[log_table['P velocity']].data) elif 'Sonic' in list(log_table.keys()): vp_t = np.interp(x=t, xp=tdr, fp=1. / tb.logs[log_table['Sonic']].data) else: vp_t = None #print(len(vp_t)) if 'S velocity' in list(log_table.keys()): vs_t = np.interp(x=t, xp=tdr, fp=tb.logs[log_table['S velocity']].data) elif 'Shear sonic' in list(log_table.keys()): vs_t = np.interp(x=t, xp=tdr, fp=1. / tb.logs[log_table['Shear sonic']].data) else: vs_t = None if 'Density' in list(log_table.keys()): rho_t = np.interp(x=t, xp=tdr, fp=tb.logs[log_table['Density']].data) else: rho_t = None if (vp_t is not None) and (vs_t is not None) and (rho_t is not None): reff = rp.reflectivity(vp_t, None, vs_t, None, rho_t, None, along_wiggle=True) else: reff = None if reff is not None: #print(len(reff(10))) #tw, w = ricker(_f=c_f, _length=duration, _dt=time_step) w = tta.ricker(duration, time_step, c_f) #print(len(w)) # Compute the depth-time relation dtr = np.array([depth[find_nearest(tdr, tt)] for tt in t]) #print(np.nanmin(dtr), np.nanmax(dtr)) # Translate the mask to the time variable t_mask = np.ma.masked_inside(t[:-1], np.nanmin(tdr[mask]), np.nanmax(tdr[mask])).mask #wiggle_plot(axes['synt_ax'], t[:-1][t_mask], wig[t_mask], 10) header_plot( header_axes['synt_ax'], None, None, None, title='Incidence angle\nRicker f={:.0f} Hz, l={:.3f} s'.format( c_f, duration)) for inc_a in range(0, 35, 5): wig = np.convolve(w, np.nan_to_num(reff(inc_a)), mode='same') wiggle_plot(axes['synt_ax'], dtr[:-1][t_mask], wig[t_mask], inc_a, scaling=scaling) else: header_plot(header_axes['synt_ax'], None, None, None, title='Refl. coeff. lacking') wiggle_plot(axes['synt_ax'], None, None, None) if savefig is not None: fig.savefig(savefig) #fig.tight_layout() plt.show()
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)