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 ) )
Exemple #2
0
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
Exemple #4
0
    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))
Exemple #5
0
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)
Exemple #7
0
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
Exemple #8
0
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()
Exemple #9
0
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
Exemple #10
0
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