def test_do_convolve( self ): # Make a spike dataset [samp, trace, theta] data = np.zeros( (1000,100,10) ) data[500,50,:] = 1.0 dt = 0.001 duration = .2 f = (20,40,60) wavelets = ricker( duration, dt, f ) con = do_convolve( wavelets, data ) truth = np.zeros( (1000,100,10,3) ) for i in range(10): truth[:wavelets.shape[0], 50, i, :] += wavelets truth = np.roll( truth, 401, axis=0 ) self.assertTrue( np.allclose( truth, con ) )
def run_script(earth_model, seismic_model, theta=None, traces=None): if earth_model.reflectivity() is None: if earth_model.units == "depth": earth_model.depth2time(seismic_model.dt, samples=seismic_model.n_sensors) else: earth_model.resample(seismic_model.dt) earth_model.update_reflectivity(seismic_model.offset_angles(), seismic_model.n_sensors) wavelets = seismic_model.wavelets() ref = earth_model.reflectivity(theta=theta) #noise = np.random.randn(ref.shape[0], ref.shape[1], # ref.shape[2]) * seismic_model.noise seismic = do_convolve(wavelets, ref, traces=traces, theta=theta) return seismic
def run_script(earth_model, seismic_model, theta=None, traces=None, snr=50): if earth_model.reflectivity() is None: if earth_model.units == "depth": earth_model.depth2time(seismic_model.dt, samples=seismic_model.n_sensors) else: earth_model.resample(seismic_model.dt) earth_model.update_reflectivity(seismic_model.offset_angles(), seismic_model.n_sensors) snr_scale = np.linspace(-50,50,1000) wavelets = seismic_model.wavelets() ref = earth_model.reflectivity(theta=theta) noise = noise_db(ref, snr_scale[snr]) ref += noise seismic = do_convolve(wavelets, ref, traces=traces, theta=theta) return seismic
def test_do_convolve(self): # Make a spike dataset [samp, trace, theta] data = np.zeros((1000, 100, 10)) data[500, 50, :] = 1.0 dt = 0.001 duration = .2 f = (20, 40, 60) wavelets = ricker(duration, dt, f) con = do_convolve(wavelets, data) truth = np.zeros((1000, 100, 10, 3)) for i in range(10): truth[:wavelets.shape[0], 50, i, :] += wavelets truth = np.roll(truth, 401, axis=0) self.assertTrue(np.allclose(truth, con))
def run_script(json_payload): """ Calculates synthetic seismic data from a convolution model. Creates data for a cross section, angle gather, and wavelet gather. Inputs json_payload = {"earth_model": See ImageModel in modelr.api, "seismic": See SeismicModel in modelr.api, "trace": The trace number to use for the angle and wavelet gathers. "offset": The offset index to use for the wavelet and seismic cross section.} """ try: seismic = Seismic.from_json(json_payload["seismic"]) # parse json earth_model = ImageModelPersist.from_json(json_payload["earth_model"]) if earth_model.domain == 'time': earth_model.resample(seismic.dt) trace = json_payload["trace"] offset = json_payload["offset"] # seismic data = do_convolve( seismic.src, earth_model.rpp_t(seismic.dt)[..., offset][..., np.newaxis]).squeeze() # Hard coded, could be changed to be part of the seismic object f0 = 4.0 f1 = 100.0 f = np.logspace(max(np.log2(f0), np.log2(7)), np.log2(f1), 50, endpoint=True, base=2.0) duration = .3 wavelets = rotate_phase(seismic.wavelet(duration, seismic.dt, f), seismic.phase) wavelet_gather = do_convolve( wavelets, earth_model.rpp_t(seismic.dt)[..., trace, offset][..., np.newaxis, np.newaxis]).squeeze() offset_gather = do_convolve( seismic.src, earth_model.rpp_t(seismic.dt)[..., trace, :][..., np.newaxis, ...]).squeeze() if seismic.snr: wavelet_gather += noise_db(wavelet_gather, seismic.snr) offset_gather += noise_db(offset_gather, seismic.snr) data += noise_db(data, seismic.snr) # METADATA metadata = {} metadata["moduli"] = {} for rock in earth_model.get_rocks(): if rock.name not in metadata["moduli"]: metadata["moduli"][rock.name] = rock.moduli if earth_model.domain == "time": dt = earth_model.zrange / float(data.shape[0]) else: dt = seismic.dt * 1000.0 payload = { "seismic": data.T.tolist(), "dt": dt, "min": float(np.amin(data)), "max": float(np.amax(data)), "dx": earth_model.dx, "wavelet_gather": wavelet_gather.T.tolist(), "offset_gather": offset_gather.T.tolist(), "f": f.tolist(), "theta": earth_model.theta, "metadata": metadata } return payload except Exception as e: traceback.print_exc(file=sys.stdout)
def run_script(json_payload): """ Calculates synthetic seismic data from a convolution model. Creates data for a cross section, angle gather, and wavelet gather. Inputs json_payload = {"earth_model": See ImageModel in modelr.api, "seismic": See SeismicModel in modelr.api, "trace": The trace number to use for the angle and wavelet gathers. "offset": The offset index to use for the wavelet and seismic cross section.} """ try: seismic = Seismic.from_json(json_payload["seismic"]) # parse json earth_model = ImageModelPersist.from_json(json_payload["earth_model"]) if earth_model.domain == 'time': earth_model.resample(seismic.dt) trace = json_payload["trace"] offset = json_payload["offset"] ph = seismic.phase src = seismic.src # seismic data = do_convolve(src, earth_model.rpp_t(seismic.dt)[..., offset] [..., np.newaxis]).squeeze() # angle gather offset_gather = do_convolve(src, earth_model.rpp_t(seismic.dt)[..., trace, :] [..., np.newaxis, ...]).squeeze() # frequency gather f0 = 4.0 f1 = 100.0 f = np.logspace(max(np.log2(f0), np.log2(7)), np.log2(f1), 50, endpoint=True, base=2.0) wavelets = rotate_phase(seismic.wavelet(seismic.wavelet_duration, seismic.dt, f), ph, degrees=True) wavelet_gather = do_convolve(wavelets, earth_model.rpp_t(seismic.dt) [..., trace, offset] [..., np.newaxis, np.newaxis]).squeeze() # add noise if required if seismic.snr: data += noise_db(data, seismic.snr) offset_gather += noise_db(offset_gather, seismic.snr) wavelet_gather += noise_db(wavelet_gather, seismic.snr) # METADATA metadata = {} metadata["moduli"] = {} for rock in earth_model.get_rocks(): if rock.name not in metadata["moduli"]: metadata["moduli"][rock.name] = rock.moduli if earth_model.domain == "time": dt = earth_model.zrange / float(data.shape[0]) else: dt = seismic.dt * 1000.0 payload = {"seismic": data.T.tolist(), "dt": dt, "min": float(np.amin(data)), "max": float(np.amax(data)), "dx": earth_model.dx, "wavelet_gather": wavelet_gather.T.tolist(), "offset_gather": offset_gather.T.tolist(), "f": f.tolist(), "theta": earth_model.theta, "metadata": metadata} return payload except Exception as e: traceback.print_exc(file=sys.stdout)
def run_script(json_payload): # parse json fs_model = FluidSub1D.from_json(json_payload["earth_model"]) seismic = Seismic.from_json(json_payload["seismic"]) # extract rock properties vp, vs, rho = (fs_model.vp, fs_model.vs, fs_model.rho) vp_sub, vs_sub, rho_sub = fs_model.smith_sub() # convert to time dt = seismic.dt dz = fs_model.dz z = fs_model.z # use indices so we only run the algorithm once index = np.arange(vp.size, dtype=int) t_index = depth_to_time(index, vp, dz, dt).astype(int) sub_t_index = depth_to_time(index, vp_sub, dz, dt).astype(int) vp_t, vs_t, rho_t = (vp[t_index], vs[t_index], rho[t_index]) vp_sub_t, vs_sub_t, rho_sub_t = (vp_sub[sub_t_index], vs_sub[sub_t_index], rho_sub[sub_t_index]) # calculate reflectivities rpp = np.nan_to_num( np.array([ zoep(vp_t[:-1], vs_t[:-1], rho_t[:-1], vp_t[1:], vs_t[1:], rho_t[1:], float(theta)) for theta in seismic.theta[::-1] ]).T) rpp_sub = np.nan_to_num( np.array([ zoep(vp_sub_t[:-1], vs_sub_t[:-1], rho_sub_t[:-1], vp_sub_t[1:], vs_sub_t[1:], rho_sub_t[1:], float(theta)) for theta in seismic.theta[::-1] ]).T) # trim to be the same size n = min(rpp.shape[0], rpp_sub.shape[0]) rpp = rpp[:n, :] rpp_sub = rpp_sub[:n, :] t = np.arange(n) * dt # create synthetic seismic traces = np.squeeze(do_convolve(seismic.src, rpp[:, np.newaxis, :])) sub_traces = np.squeeze(do_convolve(seismic.src, rpp_sub[:, np.newaxis, :])) output = { "vp": vp.tolist(), "vs": vs.tolist(), "rho": rho.tolist(), "vp_sub": vp_sub.tolist(), "vs_sub": vs_sub.tolist(), "rho_sub": rho_sub.tolist(), "synth": np.nan_to_num(traces).T.tolist(), "synth_sub": np.nan_to_num(sub_traces).T.tolist(), "theta": seismic.theta, "rpp": rpp[:, 0].tolist(), "rpp_sub": rpp_sub[:, 0].tolist(), "t_lim": [float(np.amin(t)), float(np.amax(t))], "z_lim": [float(np.amin(z)), float(np.amax(z))], "vp_lim": [float(np.amin((vp, vp_sub))), float(np.amax((vp, vp_sub)))], "vs_lim": [float(np.amin((vs, vs_sub))), float(np.amax((vs, vs_sub)))], "rho_lim": [float(np.amin((rho, rho_sub))), float(np.amax((rho, rho_sub)))], "rpp_lim": [float(np.amin((rpp, rpp_sub))), float(np.amax((rpp, rpp_sub)))], "synth_lim": [ float(np.amin((traces, sub_traces))), float(np.amax((traces, sub_traces))) ], "dt": dt, "dz": dz } return output
def modelr_plot(model, colourmap, args): """ Calculates reflectivities from the earth model then convolves against a bank of wavelets. Figures of various slices are created based on the args structure. :param model: The earth model image to use for forward modeling. :param colourmap: A Dict that maps colour values in the earth model to physical rock properties. :param args: Structure of parsed arguments. :returns: a png graphic of the forward model results. """ from modelr.constants import dt, wavelet_duration as duration model_aspect = float(model.shape[1]) / model.shape[0] if not hasattr(args, 'xscale'): args.xscale = 0 if not hasattr(args, "twt_range"): args.twt_range = (0, model.shape[0] * dt * 1000.0) if not hasattr(args, 'fs'): args.fs = 10 if args.slice == 'spatial': traces = range( args.ntraces ) else: traces = args.trace - 1 if traces >= args.ntraces: traces = args.ntraces -1 if args.slice == 'angle': theta0 = args.theta[0] theta1 = args.theta[1] try: theta_step = args.theta[2] except: theta_step = 1 theta = np.linspace(theta0, theta1, int((theta1-theta0) / theta_step)) else: try: theta = args.theta[0] except: theta = args.theta if args.slice == 'frequency': f0 = args.f[0] f1 = args.f[1] try: f_step = args.f[2] except: f_step = 1 if (args.xscale) == 0: f = np.linspace(f0, f1, (int((f1-f0)/f_step)) ) else: f = np.logspace(max(np.log2(f0),np.log2(7)),np.log2(f1),300,endpoint=True, base=2.0) else: f = args.f tstart = args.twt_range[0] fs = int(args.fs) model = model[:, traces, :] model = np.reshape(model, (model.shape[0], np.size(traces),3)) ############################ # Get reflectivities reflectivity = get_reflectivity( data=model, colourmap=colourmap, theta=theta, reflectivity_method = \ args.reflectivity_method ) # Do convolution if ( ( duration / dt ) > ( reflectivity.shape[0] ) ): duration = reflectivity.shape[0] * dt wavelet = args.wavelet( duration, dt, f ) if( wavelet.ndim == 1 ): wavelet = \ wavelet.reshape( ( wavelet.size, 1 ) ) warray_amp = do_convolve( wavelet, reflectivity ) nsamps, ntraces, ntheta, n_wavelets = warray_amp.shape dx = 10 #trace offset (in metres) ################################# # Build the plot(s) # Simplify the plot request a bit # This will need to be a loop if we want to cope with # an arbitrary number of base plots; or allow up to 6 (say) base1 = args.base1 if args.overlay1 == 'none': overlay1 = None else: overlay1 = args.overlay1 if args.overlay2 == 'none': overlay2 = None else: overlay2 = args.overlay2 if args.base2 == 'none': base2 = None plots = [(base1, overlay1)] else: base2 = args.base2 plots = [(base1, overlay1), (base2, overlay2)] if( args.slice == 'spatial' ): plot_data = warray_amp[ :, :, 0,:] reflectivity = reflectivity[:,:,0] xax = traces xlabel = 'trace' elif( args.slice == 'angle' ): plot_data = warray_amp[ :, 0, :, 0 ] reflectivity = reflectivity[ :, 0, : ] xax = theta xlabel = 'angle' elif( args.slice == 'frequency' ): plot_data = warray_amp[ :, 0, 0, : ] reflectivity = np.reshape( np.repeat( reflectivity[:,0,0], warray_amp.shape[1] ), ( reflectivity.shape[0], warray_amp.shape[1] ) ) xax = f xlabel = 'frequency [Hz]' else: # Default to spatial plot_data = warray_amp[ :, :, 0, 0 ] # Calculate some basic stuff plot_data = np.nan_to_num(plot_data) # This doesn't work well for non-spatial slices #aspect = float(warray_amp.shape[1]) / warray_amp.shape[0] # This is *better* for non-spatial slices, but can't have # overlays stretch = args.aspect_ratio pad = np.ceil((plot_data.shape[0] - model.shape[0]) / 2) # First, set up the matplotlib figure #fig = plt.figure(figsize=(width, 2*height)) fig, axarr = plt.subplots(2, len(plots)) #, sharex='col', sharey='row') if len(plots) == 1: axarr = np.transpose(np.array([axarr])) # Work out the size of the figure each_width = 6 fig.set_figwidth(each_width*len(plots)) fig.set_figheight(each_width*stretch*2) # Start a loop for the figures... for plot in plots: # If there's no base plot for this plot, # then there are no more plots and we're done if not plot[0]: break # Establish what sort of subplot grid we need p = plots.index(plot) if args.xscale: axarr[0, p].set_xscale('log', basex = int(args.xscale) ) # Each plot can have two layers (maybe more later?) # Display the two layers by looping over the non-blank # elements # of the tuple for layer in filter(None, plot): # for starters, find out if this is a base or an overlay if plot.index(layer) == 1: # then we're in an overlay so... alpha = args.opacity else: alpha = 1.0 # Now find out what sort of plot we're making on this # loop... if layer == 'earth-model': axarr[0, p].imshow(model.astype('uint8'), cmap = plt.get_cmap('gist_earth'), vmin = np.amin(model)-np.amax(model)/2, vmax = np.amax(model)+np.amax(model)/2, alpha = alpha, aspect='auto', extent=[min(xax),max(xax), args.twt_range[1], args.twt_range[0] ], origin = 'upper' ) elif layer == 'variable-density': vddata=plot_data if vddata.ndim == 3: vddata = np.sum(plot_data,axis=-1) extreme = np.percentile(vddata,99) axarr[0, p].imshow( vddata, cmap = args.colourmap, vmin = -extreme, vmax = extreme, alpha = alpha, aspect='auto', extent=[min(xax),max(xax), args.twt_range[1], args.twt_range[0] ], origin = 'upper' ) elif layer == 'reflectivity': # Show unconvolved reflectivities # #TO DO:put transparent when null / zero # masked_refl = np.ma.masked_where(reflectivity == 0.0, reflectivity) axarr[0,p].imshow(masked_refl, cmap = plt.get_cmap('Greys'), aspect='auto', extent=[min(xax),max(xax), args.twt_range[1], args.twt_range[0] ], origin = 'upper' , vmin = np.amin( masked_refl ), vmax = np.amax( masked_refl ) ) elif layer == 'wiggle': wigdata=plot_data if wigdata.ndim == 3: wigdata= np.sum(plot_data,axis=-1) wiggle(wigdata, tstart = int(args.twt_range[0]), dt = dt, skipt = args.wiggle_skips, gain = args.wiggle_skips + 1, line_colour = 'black', fill_colour = 'black', opacity = args.opacity, xax = xax, quadrant = axarr[0, p] ) if plot.index(layer) == 0: # then we're in an base layer so... axarr[0, p].set_ylim(max(axarr[0, p].set_ylim()),min(axarr[0, p].set_ylim())) elif layer == 'RGB': exponent = 2 envelope = abs(hilbert(plot_data)) envelope = envelope**exponent envelope[:,:,0]= envelope[:,:,0]/np.amax(envelope[:,:,0]) envelope[:,:,1]= envelope[:,:,1]/np.amax(envelope[:,:,1]) envelope[:,:,2]= envelope[:,:,2]/np.amax(envelope[:,:,2]) extreme = np.amax(abs(envelope)) axarr[0, p].imshow(envelope, cmap = args.colourmap, vmin = -extreme, vmax = extreme, alpha = alpha, aspect='auto', extent=[min(xax),max(xax), args.twt_range[1], args.twt_range[0] ], origin = 'upper' ) else: # We should never get here continue axarr[0, p].set_xlabel(xlabel, fontsize=fs) axarr[0, p].set_ylabel('time [ms]', fontsize=fs) axarr[0, p].set_title(args.title % locals(), fontsize=fs ) for tick in axarr[0,p].xaxis.get_major_ticks(): tick.label.set_fontsize(fs) for tick in axarr[0,p].yaxis.get_major_ticks(): tick.label.set_fontsize(fs) #plot inst. amplitude at 150 ms (every 6 samples, we should parameterize) t = args.tslice t_index = int(np.amin([t, plot_data.shape[0]-1])) y = plot_data[t_index,:].flatten() # compute lines for instantaneous chart amax_tune = np.amax(y) amin_tune = np.amin(y) aun_tuned = plot_data[t_index,-1] # instantaneous charts axarr[1,p].plot(xax[:],y,'ko-',lw=3,alpha=0.2, color = 'g') if args.xscale: #check for log plot on graphs too axarr[1, p].set_xscale('log', basex = int(args.xscale) ) axarr[1,p].set_xlabel(xlabel, fontsize=fs) # horizontal line, plot min, plot max axarr[1, p].axhline(y=amin_tune, alpha=0.15, lw=3, color = 'g') axarr[1, p].axhline(y=amax_tune, alpha=0.15, lw=3, color = 'g' ) #plot ave axarr[1, p].axhline(y=aun_tuned, alpha=0.15, lw=3, color = 'g') # vertical line axarr[1, p].axvline(x=xax[np.argmax(y)], alpha=0.15, lw=3, color='b' ) axarr[1, p].axvline(x=xax[np.argmin(y)], alpha=0.15, lw=3, color='b' ) axarr[0, p].axvline(x=xax[np.argmax(y)], alpha=0.15, lw=3, color='b' ) axarr[0, p].axvline(x=xax[np.argmin(y)], alpha=0.15, lw=3, color='b' ) # draw vertical line at onset of steady state y_r = np.array(y[::-1]) try: steady_state = np.where(abs(np.gradient(y_r)) >= (0.001*np.ptp(y)))[0][0] axarr[1, p].axvline(x=xax[-steady_state], alpha=0.15, lw=3, color='r' ) axarr[0, p].axvline(x=xax[-steady_state], alpha=0.15, lw=3, color='r' ) except: pass #labels axarr[1, p].set_title('instantaneous attribute at %s ms' % int(t), fontsize=fs ) axarr[1, p].set_ylabel('amplitude', fontsize=fs) axarr[1,p].grid() for tick in axarr[1,p].xaxis.get_major_ticks(): tick.label.set_fontsize(fs) for tick in axarr[1,p].yaxis.get_major_ticks(): tick.label.set_fontsize(fs) plt.xlim((xax[0], xax[-1])) #plot horizontal green line on model image, and steady state axarr[0,p].axhline(y=t, alpha=0.5, lw=2, color = 'g') fig.tight_layout() return get_figure_data()
def modelr_plot(model, colourmap, args): """ Calculates reflectivities from the earth model then convolves against a bank of wavelets. Figures of various slices are created based on the args structure. :param model: The earth model image to use for forward modeling. :param colourmap: A Dict that maps colour values in the earth model to physical rock properties. :param args: Structure of parsed arguments. :returns: a png graphic of the forward model results. """ from modelr.constants import dt, wavelet_duration as duration model_aspect = float(model.shape[1]) / model.shape[0] if not hasattr(args, 'xscale'): args.xscale = 0 if not hasattr(args, "twt_range"): args.twt_range = (0, model.shape[0] * dt * 1000.0) if not hasattr(args, 'fs'): args.fs = 10 if args.slice == 'spatial': traces = range(args.ntraces) else: traces = args.trace - 1 if traces >= args.ntraces: traces = args.ntraces - 1 if args.slice == 'angle': theta0 = args.theta[0] theta1 = args.theta[1] try: theta_step = args.theta[2] except: theta_step = 1 theta = np.linspace(theta0, theta1, int( (theta1 - theta0) / theta_step)) else: try: theta = args.theta[0] except: theta = args.theta if args.slice == 'frequency': f0 = args.f[0] f1 = args.f[1] try: f_step = args.f[2] except: f_step = 1 if (args.xscale) == 0: f = np.linspace(f0, f1, (int((f1 - f0) / f_step))) else: f = np.logspace(max(np.log2(f0), np.log2(7)), np.log2(f1), 300, endpoint=True, base=2.0) else: f = args.f tstart = args.twt_range[0] fs = int(args.fs) model = model[:, traces, :] model = np.reshape(model, (model.shape[0], np.size(traces), 3)) ############################ # Get reflectivities reflectivity = get_reflectivity( data=model, colourmap=colourmap, theta=theta, reflectivity_method = \ args.reflectivity_method ) # Do convolution if ((duration / dt) > (reflectivity.shape[0])): duration = reflectivity.shape[0] * dt wavelet = args.wavelet(duration, dt, f) if( wavelet.ndim == 1 ): wavelet = \ wavelet.reshape( ( wavelet.size, 1 ) ) warray_amp = do_convolve(wavelet, reflectivity) nsamps, ntraces, ntheta, n_wavelets = warray_amp.shape dx = 10 #trace offset (in metres) ################################# # Build the plot(s) # Simplify the plot request a bit # This will need to be a loop if we want to cope with # an arbitrary number of base plots; or allow up to 6 (say) base1 = args.base1 if args.overlay1 == 'none': overlay1 = None else: overlay1 = args.overlay1 if args.overlay2 == 'none': overlay2 = None else: overlay2 = args.overlay2 if args.base2 == 'none': base2 = None plots = [(base1, overlay1)] else: base2 = args.base2 plots = [(base1, overlay1), (base2, overlay2)] if (args.slice == 'spatial'): plot_data = warray_amp[:, :, 0, :] reflectivity = reflectivity[:, :, 0] xax = traces xlabel = 'trace' elif (args.slice == 'angle'): plot_data = warray_amp[:, 0, :, 0] reflectivity = reflectivity[:, 0, :] xax = theta xlabel = 'angle' elif (args.slice == 'frequency'): plot_data = warray_amp[:, 0, 0, :] reflectivity = np.reshape( np.repeat(reflectivity[:, 0, 0], warray_amp.shape[1]), (reflectivity.shape[0], warray_amp.shape[1])) xax = f xlabel = 'frequency [Hz]' else: # Default to spatial plot_data = warray_amp[:, :, 0, 0] # Calculate some basic stuff plot_data = np.nan_to_num(plot_data) # This doesn't work well for non-spatial slices #aspect = float(warray_amp.shape[1]) / warray_amp.shape[0] # This is *better* for non-spatial slices, but can't have # overlays stretch = args.aspect_ratio pad = np.ceil((plot_data.shape[0] - model.shape[0]) / 2) # First, set up the matplotlib figure #fig = plt.figure(figsize=(width, 2*height)) fig, axarr = plt.subplots(2, len(plots)) #, sharex='col', sharey='row') if len(plots) == 1: axarr = np.transpose(np.array([axarr])) # Work out the size of the figure each_width = 6 fig.set_figwidth(each_width * len(plots)) fig.set_figheight(each_width * stretch * 2) # Start a loop for the figures... for plot in plots: # If there's no base plot for this plot, # then there are no more plots and we're done if not plot[0]: break # Establish what sort of subplot grid we need p = plots.index(plot) if args.xscale: axarr[0, p].set_xscale('log', basex=int(args.xscale)) # Each plot can have two layers (maybe more later?) # Display the two layers by looping over the non-blank # elements # of the tuple for layer in filter(None, plot): # for starters, find out if this is a base or an overlay if plot.index(layer) == 1: # then we're in an overlay so... alpha = args.opacity else: alpha = 1.0 # Now find out what sort of plot we're making on this # loop... if layer == 'earth-model': axarr[0, p].imshow(model.astype('uint8'), cmap=plt.get_cmap('gist_earth'), vmin=np.amin(model) - np.amax(model) / 2, vmax=np.amax(model) + np.amax(model) / 2, alpha=alpha, aspect='auto', extent=[ min(xax), max(xax), args.twt_range[1], args.twt_range[0] ], origin='upper') elif layer == 'variable-density': vddata = plot_data if vddata.ndim == 3: vddata = np.sum(plot_data, axis=-1) extreme = np.percentile(vddata, 99) axarr[0, p].imshow(vddata, cmap=args.colourmap, vmin=-extreme, vmax=extreme, alpha=alpha, aspect='auto', extent=[ min(xax), max(xax), args.twt_range[1], args.twt_range[0] ], origin='upper') elif layer == 'reflectivity': # Show unconvolved reflectivities # #TO DO:put transparent when null / zero # masked_refl = np.ma.masked_where(reflectivity == 0.0, reflectivity) axarr[0, p].imshow(masked_refl, cmap=plt.get_cmap('Greys'), aspect='auto', extent=[ min(xax), max(xax), args.twt_range[1], args.twt_range[0] ], origin='upper', vmin=np.amin(masked_refl), vmax=np.amax(masked_refl)) elif layer == 'wiggle': wigdata = plot_data if wigdata.ndim == 3: wigdata = np.sum(plot_data, axis=-1) wiggle(wigdata, tstart=int(args.twt_range[0]), dt=dt, skipt=args.wiggle_skips, gain=args.wiggle_skips + 1, line_colour='black', fill_colour='black', opacity=args.opacity, xax=xax, quadrant=axarr[0, p]) if plot.index(layer) == 0: # then we're in an base layer so... axarr[0, p].set_ylim(max(axarr[0, p].set_ylim()), min(axarr[0, p].set_ylim())) elif layer == 'RGB': exponent = 2 envelope = abs(hilbert(plot_data)) envelope = envelope**exponent envelope[:, :, 0] = envelope[:, :, 0] / np.amax(envelope[:, :, 0]) envelope[:, :, 1] = envelope[:, :, 1] / np.amax(envelope[:, :, 1]) envelope[:, :, 2] = envelope[:, :, 2] / np.amax(envelope[:, :, 2]) extreme = np.amax(abs(envelope)) axarr[0, p].imshow(envelope, cmap=args.colourmap, vmin=-extreme, vmax=extreme, alpha=alpha, aspect='auto', extent=[ min(xax), max(xax), args.twt_range[1], args.twt_range[0] ], origin='upper') else: # We should never get here continue axarr[0, p].set_xlabel(xlabel, fontsize=fs) axarr[0, p].set_ylabel('time [ms]', fontsize=fs) axarr[0, p].set_title(args.title % locals(), fontsize=fs) for tick in axarr[0, p].xaxis.get_major_ticks(): tick.label.set_fontsize(fs) for tick in axarr[0, p].yaxis.get_major_ticks(): tick.label.set_fontsize(fs) #plot inst. amplitude at 150 ms (every 6 samples, we should parameterize) t = args.tslice t_index = int(np.amin([t, plot_data.shape[0] - 1])) y = plot_data[t_index, :].flatten() # compute lines for instantaneous chart amax_tune = np.amax(y) amin_tune = np.amin(y) aun_tuned = plot_data[t_index, -1] # instantaneous charts axarr[1, p].plot(xax[:], y, 'ko-', lw=3, alpha=0.2, color='g') if args.xscale: #check for log plot on graphs too axarr[1, p].set_xscale('log', basex=int(args.xscale)) axarr[1, p].set_xlabel(xlabel, fontsize=fs) # horizontal line, plot min, plot max axarr[1, p].axhline(y=amin_tune, alpha=0.15, lw=3, color='g') axarr[1, p].axhline(y=amax_tune, alpha=0.15, lw=3, color='g') #plot ave axarr[1, p].axhline(y=aun_tuned, alpha=0.15, lw=3, color='g') # vertical line max_loc = xax[np.argmax(y)] min_loc = xax[np.argmin(y)] axarr[1, p].axvline(x=max_loc, alpha=0.15, lw=3, color='b') axarr[1, p].axvline(x=min_loc, alpha=0.15, lw=3, color='b') axarr[0, p].axvline(x=max_loc, alpha=0.15, lw=3, color='b') axarr[0, p].axvline(x=min_loc, alpha=0.15, lw=3, color='b') # draw vertical line at onset of steady state y_r = np.array(y[::-1]) try: steady_state = np.where( abs(np.gradient(y_r)) >= (0.001 * np.ptp(y)))[0][0] axarr[1, p].axvline(x=xax[-steady_state], alpha=0.15, lw=3, color='r') axarr[0, p].axvline(x=xax[-steady_state], alpha=0.15, lw=3, color='r') except: pass #labels axarr[1, p].set_title('instantaneous attribute at %s ms' % int(t), fontsize=fs) axarr[1, p].set_ylabel('amplitude', fontsize=fs) axarr[1, p].grid() for tick in axarr[1, p].xaxis.get_major_ticks(): tick.label.set_fontsize(fs) for tick in axarr[1, p].yaxis.get_major_ticks(): tick.label.set_fontsize(fs) plt.xlim((xax[0], xax[-1])) #plot horizontal green line on model image, and steady state axarr[0, p].axhline(y=t, alpha=0.5, lw=2, color='g') fig.tight_layout() metadata = { "steady state": np_float(xax[-steady_state]), "tuning max. loc.": np.float(max_loc), "tuning min. loc.": np.float(min_loc), "tuning max. amp.": np_float(amax_tune), "tuning min. amp.": np_float(amin_tune), "tuning avg. amp.": np_float(aun_tuned) } return get_figure_data(), metadata
def run_script(json_payload): # parse json fs_model = FluidSub1D.from_json(json_payload["earth_model"]) seismic = Seismic.from_json(json_payload["seismic"]) # extract rock properties vp, vs, rho = (fs_model.vp, fs_model.vs, fs_model.rho) vp_sub, vs_sub, rho_sub = fs_model.smith_sub() # convert to time dt = seismic.dt dz = fs_model.dz z = fs_model.z # use indices so we only run the algorithm once index = np.arange(vp.size, dtype=int) t_index = depth_to_time(index, vp, dz, dt).astype(int) sub_t_index = depth_to_time(index, vp_sub, dz, dt).astype(int) vp_t, vs_t, rho_t = (vp[t_index], vs[t_index], rho[t_index]) vp_sub_t, vs_sub_t, rho_sub_t = (vp_sub[sub_t_index], vs_sub[sub_t_index], rho_sub[sub_t_index]) # calculate reflectivities rpp = np.nan_to_num(np.array([zoep(vp_t[:-1], vs_t[:-1], rho_t[:-1], vp_t[1:], vs_t[1:], rho_t[1:], float(theta)) for theta in seismic.theta[::-1]]).T) rpp_sub = np.nan_to_num(np.array([zoep(vp_sub_t[:-1], vs_sub_t[:-1], rho_sub_t[:-1], vp_sub_t[1:], vs_sub_t[1:], rho_sub_t[1:], float(theta)) for theta in seismic.theta[::-1]]).T) # trim to be the same size n = min(rpp.shape[0], rpp_sub.shape[0]) rpp = rpp[:n, :] rpp_sub = rpp_sub[:n, :] t = np.arange(n) * dt # create synthetic seismic traces = np.squeeze(do_convolve(seismic.src, rpp[:, np.newaxis, :])) sub_traces = np.squeeze(do_convolve(seismic.src, rpp_sub[:, np.newaxis, :])) output = {"vp": vp.tolist(), "vs": vs.tolist(), "rho": rho.tolist(), "vp_sub": vp_sub.tolist(), "vs_sub": vs_sub.tolist(), "rho_sub": rho_sub.tolist(), "synth": np.nan_to_num(traces).T.tolist(), "synth_sub": np.nan_to_num(sub_traces).T.tolist(), "theta": seismic.theta, "rpp": rpp[:, 0].tolist(), "rpp_sub": rpp_sub[:, 0].tolist(), "t_lim": [float(np.amin(t)), float(np.amax(t))], "z_lim": [float(np.amin(z)), float(np.amax(z))], "vp_lim": [float(np.amin((vp, vp_sub))), float(np.amax((vp, vp_sub)))], "vs_lim": [float(np.amin((vs, vs_sub))), float(np.amax((vs, vs_sub)))], "rho_lim": [float(np.amin((rho, rho_sub))), float(np.amax((rho, rho_sub)))], "rpp_lim": [float(np.amin((rpp, rpp_sub))), float(np.amax((rpp, rpp_sub)))], "synth_lim": [float(np.amin((traces, sub_traces))), float(np.amax((traces, sub_traces)))], "dt": dt, "dz": dz} return output