def load_labeled_flat_data(trfile, vafile, begex=None, endex=None): """ Loads flattened labeled data into numpy arrays """ # Get training number of examples hftr = h5py.File(trfile, 'r') trkeys = list(hftr.keys()) ntr = int(len(trkeys) / 2) # Get the validation number of examples if (vafile is not None): hfva = h5py.File(vafile, 'r') vakeys = list(hfva.keys()) nva = int(len(vakeys) / 2) else: nva = 0 vakeys = [] # Get shape of examples xshape = hftr[trkeys[0]].shape yshape = hftr[trkeys[0 + ntr]].shape ndim = len(xshape) # Get number of examples if (begex is None or endex is None): begex = 0 endex = ntr nex = ntr else: nex = endex - begex if (ndim == 3): allx = np.zeros([(nex + nva), xshape[0], xshape[1], xshape[2]], dtype='float32') elif (ndim == 4): allx = np.zeros( [(nex + nva), xshape[0], xshape[1], xshape[2], xshape[3]], dtype='float32') ally = np.zeros([(nex + nva), yshape[0]], dtype='float32') # Get all training examples for itr in progressbar(range(begex, endex), "numtr:"): if (ndim == 3): allx[itr, :, :, :] = hftr[trkeys[itr]][:] elif (ndim == 4): allx[itr, :, :, :, :] = hftr[trkeys[itr]][:] ally[itr, :] = hftr[trkeys[itr + ntr]][:] # Get all validation examples for iva in progressbar(range(nva), "numva:"): if (ndim == 3): allx[iva, :, :, :] = hfva[vakeys[iva]][:] elif (ndim == 4): allx[iva, :, :, :, :] = hfva[vakeys[iva]][:] ally[iva, :] = hfva[vakeys[iva + nva]][:] # Close the files hftr.close() if (vafile != None): hfva.close() return allx, ally
def largehorstgraben_block(self,azim=0.0,begz=0.1,xdir=True,rand=True): """ Puts in a small horst-graben block fault system. Attempts to span most of the lateral range of the model. For now, will only give nice faults along 0,90,180,270 azimuths Parameters: azim - azimuth along which faults are oriented [0.0] begz - beginning position in z for fault (same for all) [0.5] xdir - Whether the faults should be spaced along the x direction [True] rand - small random variations in the throw of the faults [True] """ dx = 0.0; dy = 0.0 begx = 0.5; begy = 0.5 if(xdir): dx = 0.32; begx = 0.05 else: dy = 0.32; begy = 0.05 for ifl in progressbar(range(3), "ngrabens:", 40): daz = 15000; dz = 5000 if(rand): daz += np.random.rand()*(2000) - 1000 dz += np.random.rand()*(2000) - 1000 # Put in graben pair along x or y if(xdir): self.fault(begx=begx ,begy=begy,begz=begz,daz=daz,dz=dz,azim=azim+180.0,theta_die=12.0,theta_shift=4.0,dist_die=1.5,perp_die=1.0,thresh=200) self.fault(begx=begx+0.16,begy=begy,begz=begz,daz=daz,dz=dz,azim=azim ,theta_die=12.0,theta_shift=4.0,dist_die=1.5,perp_die=1.0,thresh=200) else: self.fault(begx=begx,begy=begy ,begz=begz,daz=daz,dz=dz,azim=azim+180.0,theta_die=12.0,theta_shift=4.0,dist_die=1.5,perp_die=1.0,thresh=200) self.fault(begx=begx,begy=begy+0.16,begz=begz,daz=daz,dz=dz,azim=azim ,theta_die=12.0,theta_shift=4.0,dist_die=1.5,perp_die=1.0,thresh=200) # Move along x or y begx += dx; begy += dy
def sliding_block(self,nfault=5,azim=0.0,begz=0.5,begx=0.5,begy=0.5,dx=0.2,dy=0.0,rand=True): """ Puts in sliding fault block system. For now, only will give nice faults along 0,90,180,270 azimuths Parameters: nfault - number of faults in the system [5] azim - azimuth along which faults are oriented [0.0] begz - beginning position in z for fault (same for all) [0.6] begx - beginning position in x for system [0.5] begy - beginning position in y for system [0.5] dx - spacing between faults in the x direction [0.2] dy - spacing between faults in the y direction [0.0] rand - small random variations in the positioning and throw of the faults [True] """ signx = 1; signy = 1 if(begx > 0.5): signx = -1 if(begy > 0.5): signy = -1 for ifl in progressbar(range(nfault), "ndfaults:", 40): daz = 10000; dz = 25000; dxi = dx; dyi = dy if(rand): daz += np.random.rand()*(2000) - 1000 dz += np.random.rand()*(2000) - 1000 dxi += np.random.rand()*(dxi) - dxi/2 dyi += np.random.rand()*(dyi) - dyi/2 self.fault(begx=begx,begy=begy,begz=begz,daz=daz,dz=dz,azim=azim,theta_die=12.0,theta_shift=4.0,dist_die=1.5,perp_die=1.0,thresh=200) # Move along x or y begx += signx*dxi; begy += signy*dyi
def splith5(fin, f1, f2, split=0.8, rand=False, clean=True): """ Splits an H5 file into two other files. Useful for splitting data into training and validation """ hfin = h5py.File(fin, 'r') hf1 = h5py.File(f1, 'w') hf2 = h5py.File(f2, 'w') keys = list(hfin.keys()) nb = int(len(keys) / 2) nf1 = int(split * nb) nf2 = nb - nf1 if (rand): choices = list(range(nb)) idxs = random.sample(choices, nf1) else: idxs = list(range(nf1)) for idx in progressbar(range(nb), "nbatches:"): if idx in idxs: hfin.copy(keys[idx], hf1) hfin.copy(keys[idx + nb], hf1) else: hfin.copy(keys[idx], hf2) hfin.copy(keys[idx + nb], hf2) hfin.close() hf1.close() hf2.close() # Remove the original file if (clean): sp = subprocess.check_call('rm %s' % (fin), shell=True)
def makemovie_mpl(arr,odir,ftype='png',qc=False,skip=1,pttag=False,**kwargs): """ Saves each frame on the fast axis to a png for viewing Parameters: arr - input array where the frames are on the fast axis odir - the output directory where to save the frames ftype - the type (extension) of figure to save [png] qc - look at each frame as it is saved [False] skip - whether to skip frames [1] pttag - write the frame number in pretty (unix-friendly) format wbox - the first dimension of the figure size (figure width) [10] hbox - the second dimension of the figure size (figure height) [10] xmin - the minimum lateral point in your data [0.0] xmax - the maximum lateral point in your data (typically (nx-1)*dx) [nx] zmin - the minimum depth point in your data [0.0] zmax - the maximum depth point in your data (typically (nz-1)*dz) [nz] vmin - the minumum value desired to be plotted (min(data)) vmax - the maximum value desired to be plotted (max(data)) pclip - a scale to be applied to shrink or expand the dynamic range xlabel - the label of the x-axis [None] ylabel - the label of the y-axis [None] labelsize - the fontsize of the labels [18] ticksize - the fontsize of the ticks [18] ttlstring - title to be printed. Can be printed of the form ttlstring%(ottl + dttl*(framenumber)) ottl - the first title value to be printed dttl - the sampling of the title value to be printed aratio - aspect ratio of the figure [1.0] """ # Check if directory exists if(os.path.isdir(odir) == False): os.mkdir(odir) nfr = arr.shape[2] k = 0 frames = np.arange(0,nfr,skip) vmin = np.min(arr); vmax = np.max(arr) for ifr in progressbar(frames, "frames"): fig = plt.figure(figsize=(kwargs.get("wbox",10),kwargs.get("hbox",10))) ax = fig.add_subplot(111) ax.imshow(arr[:,:,ifr],cmap=kwargs.get("cmap","gray"), extent=[kwargs.get("xmin",0),kwargs.get("xmax",arr.shape[1]), kwargs.get("zmax",arr.shape[0]),kwargs.get("zmin",0)], vmin=kwargs.get("vmin",vmin)*kwargs.get('pclip',1.0), vmax=kwargs.get("vmax",vmax)*kwargs.get('pclip',1.0)) ax.set_xlabel(kwargs.get('xlabel',''),fontsize=kwargs.get('labelsize',18)) ax.set_ylabel(kwargs.get('ylabel',''),fontsize=kwargs.get('labelsize',18)) ax.tick_params(labelsize=kwargs.get('ticksize',18)) if('%' in kwargs.get('ttlstring'),''): ax.set_title(kwargs.get('ttlstring','')%(kwargs.get('ottl',0.0) + kwargs.get('dttl',1.0)*k), fontsize=kwargs.get('labelsize',18)) ax.set_aspect(kwargs.get('aratio',1.0)) if(pttag): tag = create_inttag(k,nfr) else: tag = str(k) plt.savefig(odir+'/'+tag+'.'+ftype,bbox_inches='tight',dpi=kwargs.get("dpi",150)) k += 1 if(qc): plt.show()
def load_alldata(trfile, vafile, dsize, begex=None, endex=None, verb=False): """ Loads all data and labels into numpy arrays """ # Get training number of examples hftr = h5py.File(trfile, 'r') trkeys = list(hftr.keys()) ntr = int(len(trkeys) / 2) # Get the validation number of examples if (vafile != None): hfva = h5py.File(vafile, 'r') vakeys = list(hfva.keys()) nva = int(len(vakeys) / 2) else: nva = 0 vakeys = [] # Get shape of examples xshape = hftr[trkeys[0]].shape yshape = hftr[trkeys[0 + ntr]].shape # Get number of examples if (begex is None or endex is None): begex = 0 endex = ntr nex = ntr else: nex = endex - begex # Allocate output arrays allx = np.zeros([(nex + nva) * dsize, *xshape[1:]], dtype='float32') ally = np.zeros([(nex + nva) * dsize, *yshape[1:]], dtype='float32') k = 0 # Get all training examples for itr in progressbar(range(begex, endex), "numtr:", verb=verb): for iex in range(dsize): allx[k] = hftr[trkeys[itr]][iex] ally[k] = hftr[trkeys[itr + ntr]][iex] k += 1 # Get all validation examples for iva in progressbar(range(nva), "numva:"): for iex in range(dsize): allx[k] = hfva[vakeys[iva]][iex] ally[k] = hfva[vakeys[iva + nva]][iex] k += 1 # Close the files hftr.close() if (vafile != None): hfva.close() return allx, ally
def load_allpatchdata(trfile, vafile, dsize): """ Loads all data and labels into numpy arrays Works both for the SSIM residual migration training and the patchwise fault classification training """ # Get training number of examples hftr = h5py.File(trfile, 'r') trkeys = list(hftr.keys()) ntr = int(len(trkeys) / 2) # Get the validation number of examples if (vafile != None): hfva = h5py.File(vafile, 'r') vakeys = list(hfva.keys()) nva = int(len(vakeys) / 2) else: nva = 0 vakeys = [] # Get shape of examples xshape = hftr[trkeys[0]].shape yshape = hftr[trkeys[0 + ntr]].shape # Allocate output arrays if (len(xshape) == 4): allx = np.zeros([(ntr + nva) * dsize, xshape[1], xshape[2], xshape[3]], dtype='float32') ally = np.zeros([(ntr + nva) * dsize, yshape[1]], dtype='float32') k = 0 # Get all training examples for itr in progressbar(range(ntr), "numtr:"): for iex in range(dsize): allx[k, :, :, :] = hftr[trkeys[itr]][iex, :, :, :] ally[k, :] = hftr[trkeys[itr + ntr]][iex, :] k += 1 # Get all validation examples for iva in progressbar(range(nva), "numva:"): for iex in range(dsize): allx[k, :, :, :] = hfva[vakeys[iva]][iex, :, :, :] ally[k, :] = hfva[vakeys[iva + nva]][iex, :] k += 1 # Close the files hftr.close() if (vafile != None): hfva.close() return allx, ally
def tinyfaultblock(mb,minpos,maxpos,ofz,space,nfl=10): tfpars = mb.getfaultpos2d(minpos,maxpos,space,space,space,nfaults=nfl) for ifl in progressbar(range(nfl), "ntfaults:"): iftpar = tfpars[ifl] z = ofz + rndut.randfloat(-0.01,0.01) daz = 2000 + rndut.randfloat(-500,500) dz = 1250 + rndut.randfloat(-250,250) theta_shift = 4.0 + rndut.randfloat(-1.0,1.0) mb.fault2d(begx=iftpar[0],begz=z,daz=daz,dz=dz,azim=iftpar[1],theta_die=11,theta_shift=theta_shift,dist_die=2.0,throwsc=10.0,thresh=0.15)
def mediumfaultblock(mb,minpos,maxpos,ofz,space,nfl=10): mfpars = mb.getfaultpos2d(minpos,maxpos,minblk=space,minhor=space,mingrb=space,nfaults=nfl) for ifl in progressbar(range(nfl), "nmfaults:"): ifmpar = mfpars[ifl] z = ofz + rndut.randfloat(-0.01,0.01) daz = 4000 + rndut.randfloat(-1000,1000) dz = 2500 + rndut.randfloat(-1000,1000) theta_shift = 3.0 + rndut.randfloat(-1.0,1.0) mb.fault2d(begx=ifmpar[0],begz=z,daz=daz,dz=dz,azim=ifmpar[1],theta_die=11,theta_shift=theta_shift,dist_die=2.0,throwsc=10.0,thresh=0.2)
def slidingfaultblock(mb,minpos,maxpos,ofz,nfl=6): sfpars = mb.getfaultpos2d(minpos,maxpos,minblk=0.02,minhor=0.2,mingrb=0.2,nfaults=nfl) for ifl in progressbar(range(nfl), "nsfaults:"): ifspar = sfpars[ifl] z = ofz + rndut.randfloat(-0.01,0.01) daz = 7500 + rndut.randfloat(-1000,1000) dz = 15000 + rndut.randfloat(-1000,1000) theta_shift = 3.0 + rndut.randfloat(-1.0,1.0) mb.fault2d(begx=ifspar[0],begz=ofz,daz=daz,dz=dz,azim=ifspar[1],theta_die=11,theta_shift=theta_shift,dist_die=2.0,throwsc=10.0,thresh=0.1)
def resample(img,new_shape,kind='linear',ds=[]): """ Resamples an image. Can work up to 4D numpy arrays. assumes that the nz and nx axes are the last two (fastest) """ if(len(img.shape) >= 2): # Original coordinates length=img.shape[-1] height=img.shape[-2] x=np.linspace(0,length,length) y=np.linspace(0,height,height) # New coordinates for interpolation xnew=np.linspace(0,length,new_shape[1]) ynew=np.linspace(0,height,new_shape[0]) elif(len(img.shape) == 1): length = img.shape[0] x = np.linspace(0,length,length) # New coordinates for interpolation xnew = np.linspace(0,length,new_shape) # Compute new samplings if(len(ds) != 0): dout = [] lr = new_shape[1]/length hr = new_shape[0]/height dout.append(ds[1]/lr) dout.append(ds[0]/hr) # Perform the interpolation if len(img.shape)==4: res = np.zeros([img.shape[0],img.shape[1],new_shape[0],new_shape[1]],dtype='float32') for i in range(img.shape[0]): for j in range(img.shape[1]): f = interpolate.interp2d(x,y,img[i,j,:,:],kind=kind) res[i,j,:,:] = f(xnew,ynew) elif len(img.shape)==3: res = np.zeros([img.shape[0],new_shape[0],new_shape[1]],dtype='float32') for i in progressbar(range(img.shape[0]),"nimg:"): f = interpolate.interp2d(x,y,img[i,:,:],kind=kind) res[i,:,:] = f(xnew,ynew) elif len(img.shape)==2: res = np.zeros([new_shape[0],new_shape[1]],dtype='float32') f=interpolate.interp2d(x,y,img,kind=kind) res[:] = f(xnew,ynew) elif len(img.shape)==1: res = np.zeros(new_shape,dtype='float32') f = interpolate.interp1d(x,img,kind=kind) res[:] = f(xnew) if(len(ds) == 0): return res else: return res,dout
def load_unlabeled_flat_data(filein, begex=None, endex=None): """ Loads in flattened unlabeled data """ hftr = h5py.File(filein, 'r') trkeys = list(hftr.keys()) ntr = int(len(trkeys)) xshape = hftr[trkeys[0]].shape if (begex is None or endex is None): begex = 0 endex = ntr allx = np.zeros([ntr, xshape[0], xshape[1], xshape[2]], dtype='float32') else: nex = endex - begex allx = np.zeros([nex, xshape[0], xshape[1], xshape[2]], dtype='float32') for itr in progressbar(range(begex, endex), "numex:"): allx[itr, :, :, :] = hftr[trkeys[itr]][:] # Close H5 file hftr.close() return allx
def load_all_unlabeled_data(filein, begex=None, endex=None): """ Loads all data into a numpy array """ # Get training number of examples hftr = h5py.File(filein, 'r') trkeys = list(hftr.keys()) ntr = int(len(trkeys)) # Get shape of examples xshape = hftr[trkeys[0]].shape # Allocate output arrays allx = [] k = 0 # Get all training examples if (begex is None or endex is None): begex = 0 endex = ntr for itr in progressbar(range(begex, endex), "numtr:"): dsize = hftr[trkeys[itr]].shape[0] for iex in range(dsize): allx.append(hftr[trkeys[itr]][iex]) k += 1 # Close the file hftr.close() return np.asarray(allx)
def load_allflddata(fldfile, dsize): """ Loads all field (unlabeled) data into a numpy array """ # Get training number of examples hffld = h5py.File(fldfile, 'r') fldkeys = list(hffld.keys()) nfld = int(len(fldkeys) / 2) # Get shape of examples xshape = hffld[fldkeys[0]].shape # Allocate output arrays if (len(xshape) == 4): allx = np.zeros([(nfld) * dsize, xshape[1], xshape[2], xshape[3]], dtype='float32') elif (len(xshape) == 3): allx = np.zeros([(nfld) * dsize, xshape[1], xshape[2]], dtype='float32') k = 0 # Get all field examples for ifld in progressbar(range(nfld), "numfld:"): for iex in range(dsize): allx[k, :, :, :] = hffld[fldkeys[ifld]][iex, :, :, :] k += 1 return allx
def clean_examples(ifiles, skips, sep, verb=False) -> None: """ Cleans examples from a .H file Parameters: ifiles - input list of .H files (assumes all files same shape) skips - file indices over which to skip for cleaning verb - verbosity flag [False] """ if (type(ifiles) is not list): raise Exception("Input files must be within a list") nf = len(ifiles) # Prepare the output files ofiles = [] for ifile in ifiles: bname = opsys.path.splitext(ifile)[0] ofiles.append(bname + '-cln.H') # Get the total enumber of examples taxes = sep.read_header(ifiles[0]) nex = taxes.n[-1] os = taxes.o[:-1] ds = taxes.d[:-1] for iex in progressbar(range(nex), "nex:", verb=verb): if (iex not in skips): for ifile in range(nf): axes, dat = sep.read_wind(ifiles[ifile], fw=iex, nw=1) dat = dat.reshape(axes.n, order='F') if (iex == 0): sep.write_file(ofiles[ifile], dat, os=os, ds=ds) elif (iex == 1): sep.append_file(ofiles[ifile], dat, newaxis=True) else: sep.append_file(ofiles[ifile], dat)
def model_data(self, wav, t0, owc, dwc, vel, ref, nrmax=3, eps=0., dtmax=5e-05, ntx=0, nty=0, px=0, py=0, nthrds=1, sverb=True, wverb=True): """ 3D modeling of single scattered (Born) data with the one-way wave equation (single square root (SSR), split-step Fourier method). Parameters: wav - the input wavelet (source time function) [nt] t0 - time zero of input wavelet owc - minimum frequency of wavelet dwc - frequency sampling of wavelet vel - input velocity model [nz,ny,nx] ref - input reflectivity model [nz,ny,nx] nrmax - maximum number of reference velocities [3] eps - stability parameter [0.] dtmax - maximum time error [5e-05] ntx - size of taper in x direction (samples) [0] nty - size of taper in y direction (samples) [0] px - amount of padding in x direction (samples) py - amount of padding in y direction (samples) nthrds - number of OpenMP threads to use for frequency parallelization [1] sverb - verbosity flag for shot progress bar [True] wverb - verbosity flag for frequency progress bar [False] Returns: the data at the surface [nw,nry,nrx] """ # Get dimensions nwc = wav.shape[0] # Single square root object ssf = ssr3( self.__nx, self.__ny, self.__nz, # Spatial Sizes self.__dx, self.__dy, self.__dz, # Spatial Samplings nwc, owc, dwc, eps, # Frequency axis ntx, nty, px, py, # Taper and padding dtmax, nrmax, nthrds) # Reference velocities and threads # Compute slowness and reference slownesses slo = 1 / vel ssf.set_slows(slo) # Allocate output data (surface wavefield) and receiver data datw = np.zeros([nwc, self.__ny, self.__nx], dtype='complex64') recw = np.zeros([self.__ntr, nwc], dtype='complex64') # Allocate the source for one shot sou = np.zeros([nwc, self.__ny, self.__nx], dtype='complex64') # Loop over sources ntr = 0 for iexp in progressbar(range(self.__nexp), "nexp:", verb=sverb): # Get the source coordinates sy = self.__srcy[iexp] sx = self.__srcx[iexp] isy = int((sy - self.__oy) / self.__dy + 0.5) isx = int((sx - self.__ox) / self.__dx + 0.5) # Create the source for this shot sou[:] = 0.0 sou[:, isy, isx] = wav[:] # Downward continuation datw[:] = 0.0 ssf.modallw(ref, sou, datw, wverb) # Restrict to receiver locations datwt = np.ascontiguousarray(np.transpose( datw, (1, 2, 0))) # [nwc,ny,nx] -> [ny,nx,nwc] ssf.restrict_data(self.__nrec[iexp], self.__recy[ntr:], self.__recx[ntr:], self.__oy, self.__ox, datwt, recw[ntr:, :]) # Increase number of traces ntr += self.__nrec[iexp] # Apply phase shift to data to account for t0 recs = phzshft(recw, owc, dwc, t0) return recs
def image_data(self, dat, dt, minf, maxf, vel, jf=1, nhx=0, nhy=0, sym=True, nrmax=3, eps=0.0, dtmax=5e-05, wav=None, ntx=0, nty=0, px=0, py=0, nthrds=1, sverb=True, wverb=False) -> np.ndarray: """ 3D migration of shot profile data via the one-way wave equation (single-square root split-step fourier method). Input data are assumed to follow the default geometry (sources and receivers on a regular grid) Parameters: dat - input shot profile data [nsy,nsx,nry,nrx,nt] dt - temporal sampling of input data minf - minimum frequency to image in the data [Hz] maxf - maximum frequency to image in the data [Hz] vel - input migration velocity model [nz,ny,nx] jf - frequency decimation factor nhx - number of subsurface offsets in x to compute [0] nhy - number of subsurface offsets in y to compute [0] sym - symmetrize the subsurface offsets [True] nrmax - maximum number of reference velocities [3] eps - stability parameter [0.] dtmax - maximum time error [5e-05] wav - input wavelet [None,assumes an impulse at zero lag] ntx - size of taper in x direction [0] nty - size of taper in y direction [0] px - amount of padding in x direction (samples) [0] py - amount of padding in y direction (samples) [0] nthrds - number of OpenMP threads for parallelizing over frequency [1] sverb - verbosity flag for shot progress bar [True] wverb - verbosity flag for frequency progress bar [False] Returns: an image created from the data [nhy,nhx,nz,ny,nx] """ # Get temporal axis nt = dat.shape[-1] # Create frequency domain source if (wav is None): wav = np.zeros(nt, dtype='float32') wav[0] = 1.0 self.__nwo, self.__ow, self.__dw, wfft = self.fft1(wav, dt, minf=minf, maxf=maxf) wfftd = wfft[::jf] self.__nwc = wfftd.shape[ 0] # Get the number of frequencies for imaging self.__dwc = self.__dw * jf if (sverb or wverb): print("Frequency axis: nw=%d ow=%f dw=%f" % (self.__nwc, self.__ow, self.__dwc)) # Create frequency domain data _, _, _, dfft = self.fft1(dat, dt, minf=minf, maxf=maxf) dfftd = dfft[:, ::jf] datt = np.transpose( dfftd, (0, 1, 4, 2, 3)) # [nsy,nsx,ny,nx,nwc] -> [nsy,nsx,nwc,ny,nx] datw = np.ascontiguousarray( datt.reshape([self.__nexp, self.__nwc, self.__ny, self.__nx])) # Single square root object ssf = ssr3( self.__nx, self.__ny, self.__nz, # Spatial Sizes self.__dx, self.__dy, self.__dz, # Spatial Samplings self.__nwc, self.__ow, self.__dwc, eps, # Frequency axis ntx, nty, px, py, # Taper and padding dtmax, nrmax, nthrds) # Reference velocities # Compute slowness and reference slownesses slo = 1 / vel ssf.set_slows(slo) # Allocate partial image array if (nhx == 0 and nhy == 0): imgar = np.zeros([self.__nexp, self.__nz, self.__ny, self.__nx], dtype='float32') else: if (sym): # Create axes self.__rnhx = 2 * nhx + 1 self.__ohx = -nhx * self.__dx self.__dhx = self.__dx self.__rnhy = 2 * nhy + 1 self.__ohy = -nhy * self.__dy self.__dhy = self.__dy # Allocate image array imgar = np.zeros([ self.__nexp, self.__rnhy, self.__rnhx, self.__nz, self.__ny, self.__nx ], dtype='float32') else: # Create axes self.__rnhx = nhx + 1 self.__ohx = 0 self.__dhx = self.__dx self.__rnhy = nhy + 1 self.__ohy = 0 self.__dhy = self.__dy # Allocate image array imgar = np.zeros([ self.__nexp, self.__rnhy, self.__rnhx, self.__nz, self.__ny, self.__nx ], dtype='float32') # Allocate memory necessary for extension ssf.set_ext(nhy, nhx, sym) # Allocate the source for one shot sou = np.zeros([self.__nwc, self.__ny, self.__nx], dtype='complex64') # Loop over sources k = 0 for icrd in progressbar(self.__scoords, "nexp:", verb=sverb): # Get the source coordinates sy = icrd[0] sx = icrd[1] # Create the source for this shot sou[:] = 0.0 sou[:, sy, sx] = wfftd[:] if (nhx == 0 and nhy == 0): # Conventional imaging ssf.migallw(datw[k], sou, imgar[k], wverb) else: # Extended imaging ssf.migoffallw(datw[k], sou, imgar[k], wverb) k += 1 # Sum over all partial images img = np.sum(imgar, axis=0) # Free memory for extension if (nhx != 0 or nhy != 0): ssf.del_ext() return img
def estro_fltangfocdefoc(rimgs,foccnn,dro,oro,nzp=64,nxp=64,strdz=None,strdx=None, # Patching parameters rectz=30,rectx=30,fltthresh=75,fltlbls=None,qcimgs=True,verb=False, fmwrk='torch',device=None): """ Estimates rho by choosing the residually migrated patch that has highest angle gather and fault focus probability given by the neural network Parameters rimgs - residually migrated angle gathers images [nro,na,nz,nx] foccnn - CNN for determining if angle gather/fault is focused or not dro - residual migration sampling oro - residual migration origin nzp - size of patch in z dimension [64] nxp - size of patch in x dimension [64] strdz - size of stride in z dimension [nzp/2] strdx - size of stride in x dimension [nxp/2] rectz - length of smoother in z dimension [30] rectx - length of smoother in x dimension [30] fltlbls - input fault segmentation labels [None] qcimgs - flag for returning the fault focusing probabilities [nro,nz,nx] and fault patches [nz,nx] verb - verbosity flag [False] fmwrk - deep learning framework to be used for the prediction [torch] device - device for pytorch networks Returns an estimate of rho(x,z) """ # Get image dimensions nro = rimgs.shape[0]; na = rimgs.shape[1]; nz = rimgs.shape[2]; nx = rimgs.shape[3] # Get strides if(strdz is None): strdz = int(nzp/2) if(strdx is None): strdx = int(nxp/2) # Build the Patch Extractors pea = PatchExtractor((nro,na,nzp,nxp),stride=(nro,na,strdz,strdx)) aptch = np.squeeze(pea.extract(rimgs)) # Flatten patches and make a prediction on each numpz = aptch.shape[0]; numpx = aptch.shape[1] if(fmwrk == 'torch'): aptchf = normalize(aptch.reshape([nro*numpz*numpx,1,na,nzp,nxp])) with(torch.no_grad()): aptchft = torch.tensor(aptchf) focprdt = torch.zeros([nro*numpz*numpx,1]) for iptch in progressbar(range(aptchf.shape[0]),verb=verb): gptch = aptchft[iptch].to(device) focprdt[iptch] = torch.sigmoid(foccnn(gptch.unsqueeze(0))) focprd = focprdt.cpu().numpy() elif(fmwrk == 'tf'): aptchf = np.expand_dims(normalize(aptch.reshape([nro*numpz*numpx,na,nzp,nxp])),axis=-1) focprd = foccnn.predict(aptchf,verbose=verb) elif(fmwrk is None): aptchf = normalize(aptch.reshape([nro*numpz*numpx,na,nzp,nxp])) focprd = np.zeros([nro*numpz*numpx,1]) for iptch in progressbar(range(aptchf.shape[0]),verb=verb): focprd[iptch] = semblance_power(aptchf[iptch]) # Assign prediction to entire patch for QC focprdptch = np.zeros([numpz*numpx*nro,nzp,nxp]) for iptch in range(nro*numpz*numpx): focprdptch[iptch,:,:] = focprd[iptch] focprdptch = focprdptch.reshape([numpz,numpx,nro,nzp,nxp]) # Save predictions as a function of rho only focprdr = focprd.reshape([numpz,numpx,nro]) # Output rho image pe = PatchExtractor((nzp,nxp),stride=(strdz,strdx)) rho = np.zeros([nz,nx]) rhop = pe.extract(rho) # Output probabilities focprdnrm = np.zeros(focprdptch.shape) per = PatchExtractor((nro,nzp,nxp),stride=(nro,strdz,strdx)) focprdimg = np.zeros([nro,nz,nx]) _ = per.extract(focprdimg) if(fltlbls is None): fltptch = np.ones([numpz,numpx,nzp,nxp],dtype='int') else: pef = PatchExtractor((nzp,nxp),stride=(strdz,strdx)) fltptch = pef.extract(fltlbls) # Estimate rho from angle-fault focus probabilities hlfz = int(nzp/2); hlfx = int(nxp/2) for izp in range(numpz): for ixp in range(numpx): if(np.sum(fltptch[izp,ixp]) > fltthresh): # Find maximum probability and compute rho iprb = focprdptch[izp,ixp,:,hlfz,hlfx] rhop[izp,ixp,:,:] = np.argmax(iprb)*dro + oro # Normalize across rho within a patch for QC if(np.max(focprdptch[izp,ixp,:,hlfz,hlfx]) == 0.0): focprdnrm[izp,ixp,:,:,:] = 0.0 else: focprdnrm[izp,ixp,:,:,:] = focprdptch[izp,ixp,:,:,:]/np.max(focprdptch[izp,ixp,:,hlfz,hlfx]) else: rhop[izp,ixp,:,:] = 1.0 # Reconstruct rho and probabiliites rho = pe.reconstruct(rhop) focprdimg = per.reconstruct(focprdnrm.reshape([1,numpz,numpx,nro,nzp,nxp])) # Smooth and return rho, fault patches and fault probabilities rhosm = smooth(rho.astype('float32'),rect1=rectx,rect2=rectz) if(qcimgs): focprdimgsm = np.zeros(focprdimg.shape) # Smooth the fault focusing for each rho for iro in range(nro): focprdimgsm[iro] = smooth(focprdimg[iro].astype('float32'),rect1=rectx,rect2=rectz) # Return images return rhosm,focprdimgsm,focprdr else: return rhosm
def image_data(self, rec, owc, dwc, vel, nhx=0, nhy=0, sym=True, eps=0, nrmax=3, dtmax=5e-05, wav=None, ntx=0, nty=0, px=0, py=0, nthrds=1, sverb=True, wverb=False): """ 3D migration of shot profile data via the one-way wave equation (single-square root split-step fourier method). Input data are assumed to follow the default geometry (sources and receivers on a regular grid) Parameters: rec - flattened input shot profile data vel - input migration velocity model [nz,ny,nx] jf - frequency decimation factor nhx - number of subsurface offsets in x to compute [0] nhy - number of subsurface offsets in y to compute [0] sym - symmetrize the subsurface offsets [True] nrmax - maximum number of reference velocities [3] dtmax - maximum time error [5e-05] wav - input wavelet [None,assumes an impulse at zero lag] ntx - size of taper in x direction [0] nty - size of taper in y direction [0] px - amount of padding in x direction (samples) [0] py - amount of padding in y direction (samples) [0] nthrds - number of OpenMP threads for parallelizing over frequency [1] sverb - verbosity flag for shot progress bar [True] wverb - verbosity flag for frequency progress bar [False] nchnks - number of chunks to distribute over cluster client - dask client for distributing work over a cluster Returns: an image created from the data [nhy,nhx,nz,ny,nx] """ # Make sure data are same size as coordinates if (rec.shape[0] != self.__ntr): raise Exception( "Data must have same number of traces passed to constructor") nwc = wav.shape[0] if (rec.shape[-1] != nwc): raise Exception("Data and wavelet must have same frequency axis") # Allocate source and data for one shot datw = np.zeros([self.__ny, self.__nx, nwc], dtype='complex64') sou = np.zeros([nwc, self.__ny, self.__nx], dtype='complex64') # Single square root object ssf = ssr3( self.__nx, self.__ny, self.__nz, # Spatial Sizes self.__dx, self.__dy, self.__dz, # Spatial Samplings nwc, owc, dwc, eps, # Frequency axis ntx, nty, px, py, # Taper and padding dtmax, nrmax, nthrds) # Reference velocities and threads # Compute slowness and reference slownesses slo = 1 / vel ssf.set_slows(slo) # Allocate partial image array if (nhx == 0 and nhy == 0): imgtmp = np.zeros([self.__nz, self.__ny, self.__nx], dtype='float32') oimg = np.zeros([self.__nz, self.__ny, self.__nx], dtype='float32') else: if (sym): # Create axes self.__rnhx = 2 * nhx + 1 self.__ohx = -nhx * self.__dx self.__dhx = self.__dx self.__rnhy = 2 * nhy + 1 self.__ohy = -nhy * self.__dy self.__dhy = self.__dy imgtmp = np.zeros([ self.__rnhy, self.__rnhx, self.__nz, self.__ny, self.__nx ], dtype='float32') oimg = np.zeros([ self.__rnhy, self.__rnhx, self.__nz, self.__ny, self.__nx ], dtype='float32') else: # Create axes self.__rnhx = nhx + 1 self.__ohx = 0 self.__dhx = self.__dx self.__rnhy = nhy + 1 self.__ohy = 0 self.__dhy = self.__dy imgtmp = np.zeros([ self.__rnhy, self.__rnhx, self.__nz, self.__ny, self.__nx ], dtype='float32') oimg = np.zeros([ self.__rnhy, self.__rnhx, self.__nz, self.__ny, self.__nx ], dtype='float32') # Allocate memory necessary for extension ssf.set_ext(nhy, nhx, sym, True) #ssf.set_ext(nhy,nhx,sym,False) # Loop over sources ntr = 0 for iexp in progressbar(range(self.__nexp), "nexp:", verb=sverb): # Get the source coordinates sy = self.__srcy[iexp] sx = self.__srcx[iexp] isy = int((sy - self.__oy) / self.__dy + 0.5) isx = int((sx - self.__ox) / self.__dx + 0.5) # Create the source wavefield for this shot sou[:] = 0.0 sou[:, isy, isx] = wav[:] # Inject the data for this shot datw[:] = 0.0 ssf.inject_data(self.__nrec[iexp], self.__recy[ntr:], self.__recx[ntr:], self.__oy, self.__ox, rec[ntr:, :], datw) datwt = np.ascontiguousarray(np.transpose( datw, (2, 0, 1))) # [ny,nx,nwc] -> [nwc,ny,nx] # Initialize temporary image imgtmp[:] = 0.0 if (nhx == 0 and nhy == 0): # Conventional imaging ssf.migallw(datwt, sou, imgtmp, wverb) else: # Extended imaging ssf.migoffallw(datwt, sou, imgtmp, wverb) #ssf.migoffallwbig(datwt,sou,imgtmp,wverb) oimg += imgtmp # Increase number of traces ntr += self.__nrec[iexp] # Free memory for extension if (nhx != 0 or nhy != 0): ssf.del_ext() return oimg
def model_data(self, wav, dt, t0, minf, maxf, vel, ref, jf=1, nrmax=3, eps=0., dtmax=5e-05, time=True, ntx=0, nty=0, px=0, py=0, nthrds=1, sverb=True, wverb=False) -> np.ndarray: """ 3D modeling of single scattered (Born) data with the one-way wave equation (single square root (SSR), split-step Fourier method). Parameters: wav - the input wavelet (source time function) [nt] dt - sampling interval of wavelet t0 - time-zero of wavelet (e.g., peak of ricker wavelet) minf - minimum frequency to propagate [Hz] maxf - maximum frequency to propagate [Hz] vel - input velocity model [nz,ny,nx] ref - input reflectivity model [nz,ny,nx] jf - frequency decimation factor [1] nrmax - maximum number of reference velocities [3] eps - stability parameter [0.] dtmax - maximum time error [5e-05] time - return the data back in the time domain [True] ntx - size of taper in x direction (samples) [0] nty - size of taper in y direction (samples) [0] px - amount of padding in x direction (samples) py - amount of padding in y direction (samples) nthrds - number of OpenMP threads for parallelizing over frequency [1] sverb - verbosity flag for shot progress bar [True] wverb - verbosity flag for frequency progressbar [False] Returns the data at the surface (in time or frequency) [nw,nry,nrx] """ # Save wavelet temporal parameters nt = wav.shape[0] it0 = int(t0 / dt) # Create the input frequency domain source and get original frequency axis self.__nwo, self.__ow, self.__dw, wfft = self.fft1(wav, dt, minf=minf, maxf=maxf) wfftd = wfft[::jf] self.__nwc = wfftd.shape[0] # Get the number of frequencies to compute self.__dwc = jf * self.__dw if (sverb or wverb): print("Frequency axis: nw=%d ow=%f dw=%f" % (self.__nwc, self.__ow, self.__dwc)) # Single square root object ssf = ssr3( self.__nx, self.__ny, self.__nz, # Spatial Sizes self.__dx, self.__dy, self.__dz, # Spatial Samplings self.__nwc, self.__ow, self.__dwc, eps, # Frequency axis ntx, nty, px, py, # Taper and padding dtmax, nrmax, nthrds) # Reference velocities # Compute slowness and reference slownesses slo = 1 / vel ssf.set_slows(slo) # Allocate output data (surface wavefield) datw = np.zeros([self.__nexp, self.__nwc, self.__ny, self.__nx], dtype='complex64') # Allocate the source for one shot sou = np.zeros([self.__nwc, self.__ny, self.__nx], dtype='complex64') # Loop over sources k = 0 for icrd in progressbar(self.__scoords, "nexp:", verb=sverb): # Get the source coordinates sy = icrd[0] sx = icrd[1] # Create the source for this shot sou[:] = 0.0 sou[:, sy, sx] = wfftd[:] # Downward continuation ssf.modallw(ref, sou, datw[k], wverb) k += 1 # Reshape output data datwr = datw.reshape( [self.__nsy, self.__nsx, self.__nwc, self.__ny, self.__nx]) if (time): # Inverse fourier transform datt = self.data_f2t(datwr, self.__nwo, self.__ow, self.__dwc, nt, it0) return datt else: return datwr
def label_defocused_patches(dptchs, fptchs, fltlbls=None, fprds=None, dprds=None, pixthresh=50, thresh1=0.7, thresh2=0.5, thresh3=0.7, smbthresh=0.4, unsure=True, streamer=True, verb=False, qc=False) -> np.ndarray: """ Attempts to label patches as defocused using the focused equivalent Parameters: dptchs - the input defocused patches [nptch,ang,ptchz,ptchx] fptchs - the input focused patches [nptch,ang,ptchz,ptchx] fltlbls - the input fault labels [None] fprds - the corresponding focused fault predictions [None] dprds - the corresponding defocused fault predictions [None] pixthresh - number of fault pixel to determine if patch has fault [50] thresh1 - first threshold [0.7] thresh2 - second threshold [0.5] thresh3 - third threshold [0.7] smbthresh - semblance threshold [0.4] unsure - give the unsure label (-1) instead of focused (1) [False] streamer - streamer geometry (one-sided angle gathers) [True] verb - verbosity flag [False] qc - return the computed metrics Returns a numpy array of zeros for the defocused patches and -1 for the others """ # Check that fptchs and dptchs have the same shape if (dptchs.shape != fptchs.shape): raise Exception( "Defocused patches must have same shape as focused patches") # Dimensions of inputs [nex, na, nzp, nxp] = fptchs.shape if (streamer): nw = na // 2 else: nw = 0 # Input segmentation labels if (fltlbls is None): fltlbls = np.zeros([nzp, nxp], dtype='float32') metrics = { 'fsemb': np.zeros([nex], dtype='float32'), 'dsemb': np.zeros([nex], dtype='float32'), 'sembrat': np.zeros([nex], dtype='float32'), 'fltnum': np.zeros([nex], dtype='float32'), 'fpvar': np.zeros([nex], dtype='float32'), 'dpvar': np.zeros([nex], dtype='float32'), 'pvarrat': np.zeros([nex], dtype='float32'), 'corrprb': np.zeros([nex], dtype='float32') } # Output labels if (unsure): flbls = np.ones(nex, dtype='float32') * -1 else: flbls = np.ones(nex, dtype='float32') for iex in progressbar(range(nex), "nex:", verb=verb): # Get the example cubf = fptchs[iex] cubd = dptchs[iex] # Angle metrics metrics['fsemb'][iex] = semblance_power(cubf[nw:]) metrics['dsemb'][iex] = semblance_power(cubd[nw:]) metrics['sembrat'][iex] = metrics['dsemb'][iex] / metrics['fsemb'][iex] if (metrics['sembrat'][iex] < smbthresh): flbls[iex] = 0 continue metrics['fltnum'][iex] = np.sum(fltlbls) if (metrics['fltnum'][iex] > pixthresh): fprd = fprds[iex] dprd = dprds[iex] # Compute fault metrics metrics['fpvar'][iex] = varimax(fprd) metrics['dpvar'][iex] = varimax(dprd) metrics['pvarrat'][iex] = dpvar / fpvar metrics['corrprb'][iex] = corrsim(fprd, dprd) if (metrics['sembrat'][iex] < thresh1 and metrics['pvarrat'][iex] < thresh1): flbls[iex] = 0 elif (metrics['sembrat'][iex] < thresh2 or metrics['pvarrat'][iex] < thresh2): flbls[iex] = 0 elif (metrics['corrprb'][iex] < thresh1): flbls[iex] = 0 else: if (metrics['sembrat'][iex] < thresh3): flbls[iex] = 0 if (qc): return metrics, flbls else: return flbls
# Get work chunk = recv_zipped_pickle(socket) # If chunk is empty, keep listening if(chunk == {}): continue # If I received something, do some work ochunk = {} # Create the modeling object wei = coordgeomchunk(**chunk[0]) # Do the modeling timg = wei.image_data(**chunk[1]) # Transfer the data back if(len(timg.shape) > 3): nhx = timg.shape[1] # Send over the extended image in chunks for ihx in progressbar(range(nhx),"transfer",verb=True): # Return other parameters if desired ochunk['cid'] = chunk[2] # Tell server this is the result ochunk['msg'] = "result" # Send back the result ochunk['idx'] = ihx ochunk['result'] = timg[0,ihx] send_zipped_pickle(socket,ochunk) # Receive 'thank you' socket.recv() else: # Return other parameters if desired ochunk['cid'] = chunk[2] # Tell server this is the result ochunk['msg'] = "result"
def makemoviesbs_mpl(arr1,arr2,odir,ftype='png',qc=False,skip=1,pttag=False,**kwargs): """ Saves each frame on the fast axis to a png for viewing Parameters: arr1 - first input array (left panel) where the frames are on the fast axis arr2 - second input array (right panel) where the frames are on the fast axis odir - the output directory where to save the frames ftype - the type (extension) of figure to save [png] qc - look at each frame as it is saved [False] skip - whether to skip frames [1] pttag - write the frame number in pretty (unix-friendly) format """ # Check if directory exists if(os.path.isdir(odir) == False): os.mkdir(odir) assert(arr1.shape[2] == arr2.shape[2]),"Both movies must have same number of frames" nfr = arr1.shape[2] k = 0 frames = np.arange(0,nfr,skip) vmin1 = np.min(arr1); vmax1 = np.max(arr1) vmin2 = np.min(arr2); vmax2 = np.max(arr2) for ifr in progressbar(frames, "frames"): # Setup plot f,ax = plt.subplots(1,2,figsize=(kwargs.get("figsize1",15),kwargs.get("figsize2",8)), gridspec_kw={'width_ratios': [kwargs.get("wratio1",1), kwargs.get("wratio2",1)]}) # First plot im1 = ax[0].imshow(arr1[:,:,ifr],cmap=kwargs.get("cmap1","gray"), extent=[kwargs.get("xmin1",0),kwargs.get("xmax1",arr1.shape[1]), kwargs.get("zmax1",arr1.shape[0]),kwargs.get("zmin1",0)], vmin=kwargs.get("vmin1",vmin1)*kwargs.get('pclip',1.0), vmax=kwargs.get("vmax1",vmax1)*kwargs.get('pclip',1.0),aspect=kwargs.get('aspect1',1.0)) ax[0].set_xlabel(kwargs.get('xlabel1',''),fontsize=kwargs.get('labelsize',18)) ax[0].set_ylabel(kwargs.get('ylabel',''),fontsize=kwargs.get('labelsize',18)) ax[0].tick_params(labelsize=kwargs.get('ticksize',18)) if('%' in kwargs.get('ttlstring1'),''): ax[0].set_title(kwargs.get('ttlstring1','')%(kwargs.get('ottl1',0.0) + kwargs.get('dttl1',1.0)*k), fontsize=kwargs.get('labelsize',18)) else: ax[0].set_title(kwargs.get('ttlstring1',''),fontsize=kwargs.get('labelsize',18)) # Second plot im2 = ax[1].imshow(arr2[:,:,ifr],cmap=kwargs.get("cmap2","gray"), extent=[kwargs.get("xmin2",0),kwargs.get("xmax2",arr2.shape[1]), kwargs.get("zmax2",arr2.shape[0]),kwargs.get("zmin2",0)], vmin=kwargs.get("vmin2",vmin2)*kwargs.get('pclip',1.0), vmax=kwargs.get("vmax2",vmax2)*kwargs.get('pclip',1.0),aspect=kwargs.get('aspect2',1.0)) ax[1].set_xlabel(kwargs.get('xlabel2',''),fontsize=kwargs.get('labelsize',18)) ax[1].set_ylabel(kwargs.get('ylabel2',''),fontsize=kwargs.get('labelsize',18)) ax[1].tick_params(labelsize=kwargs.get('ticksize',18)) if('%' in kwargs.get('ttlstring2','')): ax[1].set_title(kwargs.get('ttlstring2','')%(kwargs.get('ottl2',0.0) + kwargs.get('dttl2',1.0)*k), fontsize=kwargs.get('labelsize',18)) else: ax[1].set_title(kwargs.get('ttlstring2',''),fontsize=kwargs.get('labelsize',18)) # Color bar if(kwargs.get('cbar',False)): cbar_ax = f.add_axes([kwargs.get('barx',0.91),kwargs.get('barz',0.12), kwargs.get('wbar',0.02),kwargs.get('hbar',0.75)]) cbar = f.colorbar(im2,cbar_ax,format='%.2f') cbar.ax.tick_params(labelsize=kwargs.get('ticksize',18)) cbar.set_label(kwargs.get('barlabel',''),fontsize=kwargs.get("barlabelsize",18)) cbar.draw_all() # Spacing between plots plt.subplots_adjust(wspace=kwargs.get("pltspace",0.2)) if(pttag): tag = create_inttag(k,nfr) else: tag = str(k) plt.savefig(odir+'/'+tag+'.'+ftype,bbox_inches='tight',dpi=kwargs.get("dpi",150)) k += 1 if(qc): plt.show()
def awemva(self,dimg,dat,dt,minf,maxf,vel,jf=1,nrmax=3,eps=0.,dtmax=5e-05,wav=None, ntx=0,nty=0,px=0,py=0,nthrds=1,sverb=True,wverb=False): """ 3D Adjoint WEMVA operator Parameters: dat - input shot profile data [ntr,nt] dt - temporal sampling of input data minf - minimum frequency to image in the data [Hz] maxf - maximum frequency to image in the data [Hz] vel - input migration velocity model [nz,ny,nx] jf - frequency decimation factor [1] nrmax - maximum number of reference velocities [3] eps - stability parameter [0.] dtmax - maximum time error [5e-05] wav - input wavelet [None,assumes an impulse at zero lag] ntx - size of taper in x direction [0] nty - size of taper in y direction [0] px - amount of padding in x direction (samples) [0] py - amount of padding in y direction (samples) [0] nthrds - number of OpenMP threads for frequency parallelization [1] sverb - verbosity flag for shot progress bar [True] wverb - verbosity flag for frequency progress bar [False] Returns: a slowness perturbation (adjoint wemva applied to image perturbation) [nz,ny,nx] """ # Make sure data are same size as coordinates if(dat.shape[0] != self.__ntr): raise Exception("Data must have same number of traces passed to constructor") # Get temporal axis nt = dat.shape[-1] # Create frequency domain source if(wav is None): wav = np.zeros(nt,dtype='float32') wav[0] = 1.0 self.__nwo,self.__ow,self.__dw,wfft = fft1(wav,dt,minf=minf,maxf=maxf) wfftd = wfft[::jf] self.__nwc = wfftd.shape[0] # Get the number of frequencies for imaging self.__dwc = self.__dw*jf if(sverb or wverb): print("Frequency axis: nw=%d ow=%f dw=%f"%(self.__nwc,self.__ow,self.__dwc)) # Create frequency domain data _,_,_,dfft = fft1(dat,dt,minf=minf,maxf=maxf) dfftd = dfft[:,::jf] # Allocate the data for one shot datw = np.zeros([self.__ny,self.__nx,self.__nwc],dtype='complex64') # Allocate the source for one shot sou = np.zeros([self.__nwc,self.__ny,self.__nx],dtype='complex64') # Single square root object ssf = ssr3(self.__nx ,self.__ny,self.__nz , # Spatial Sizes self.__dx ,self.__dy,self.__dz , # Spatial Samplings self.__nwc,self.__ow,self.__dwc,eps, # Frequency axis ntx,nty,px,py, # Taper and padding dtmax,nrmax,nthrds) # Reference velocities and threads # Compute slowness and reference slownesses slo = 1/vel ssf.set_slows(slo) # Allocate temporary partial image dslotmp = np.zeros([self.__nz,self.__ny,self.__nx],dtype='complex64') odslo = np.zeros([self.__nz,self.__ny,self.__nx],dtype='complex64') # Loop over sources ntr = 0 for iexp in progressbar(range(self.__nexp),"nexp:",verb=sverb): # Get the source coordinates sy = self.__srcys[iexp]; sx = self.__srcxs[iexp] isy = int((sy-self.__oy)/self.__dy+0.5); isx = int((sx-self.__ox)/self.__dx+0.5) # Create the source wavefield for this shot sou[:] = 0.0 sou[:,isy,isx] = wfftd[:] # Inject the data for this shot datw[:] = 0.0 ssf.inject_data(self.__nrec[iexp],self.__recys[ntr:],self.__recxs[ntr:],self.__oy,self.__ox,dfftd[ntr:,:],datw) datwt = np.ascontiguousarray(np.transpose(datw,(2,0,1))) # [ny,nx,nwc] -> [nwc,ny,nx] # Initialize temporary image dslotmp[:] = 0.0 # Adjoint WEMVA ssf.awemvaallw(sou,datwt,dslotmp,dimg,verb=wverb) odslo += dslotmp # Increase number of traces ntr += self.__nrec[iexp] return np.real(odslo)
def image_data(self,dat,dt,minf,maxf,vel,jf=1,nhx=0,nhy=0,sym=True,nrmax=3,eps=0.,dtmax=5e-05,wav=None, ntx=0,nty=0,px=0,py=0,nthrds=1,sverb=True,wverb=False): """ 3D migration of shot profile data via the one-way wave equation (single-square root split-step fourier method). Parameters: dat - input shot profile data [ntr,nt] dt - temporal sampling of input data minf - minimum frequency to image in the data [Hz] maxf - maximum frequency to image in the data [Hz] vel - input migration velocity model [nz,ny,nx] jf - frequency decimation factor [1] nhx - number of subsurface offsets in x to compute [0] nhy - number of subsurface offsets in y to compute [0] sym - symmetrize the subsurface offsets [True] nrmax - maximum number of reference velocities [3] eps - stability parameter [0.] dtmax - maximum time error [5e-05] wav - input wavelet [None,assumes an impulse at zero lag] ntx - size of taper in x direction [0] nty - size of taper in y direction [0] px - amount of padding in x direction (samples) [0] py - amount of padding in y direction (samples) [0] nthrds - number of OpenMP threads for frequency parallelization [1] sverb - verbosity flag for shot progress bar [True] wverb - verbosity flag for frequency progress bar [False] Returns: an image created from the data [nhy,nhx,nz,ny,nx] """ # Make sure data are same size as coordinates if(dat.shape[0] != self.__ntr): raise Exception("Data must have same number of traces passed to constructor") # Get temporal axis nt = dat.shape[-1] # Create frequency domain source if(wav is None): wav = np.zeros(nt,dtype='float32') wav[0] = 1.0 self.__nwo,self.__ow,self.__dw,wfft = fft1(wav,dt,minf=minf,maxf=maxf) wfftd = wfft[::jf] self.__nwc = wfftd.shape[0] # Get the number of frequencies for imaging self.__dwc = self.__dw*jf if(sverb or wverb): print("Frequency axis: nw=%d ow=%f dw=%f"%(self.__nwc,self.__ow,self.__dwc)) # Create frequency domain data _,_,_,dfft = fft1(dat,dt,minf=minf,maxf=maxf) dfftd = dfft[:,::jf] # Allocate the data for one shot datw = np.zeros([self.__ny,self.__nx,self.__nwc],dtype='complex64') # Allocate the source for one shot sou = np.zeros([self.__nwc,self.__ny,self.__nx],dtype='complex64') # Single square root object ssf = ssr3(self.__nx ,self.__ny,self.__nz , # Spatial Sizes self.__dx ,self.__dy,self.__dz , # Spatial Samplings self.__nwc,self.__ow,self.__dwc,eps, # Frequency axis ntx,nty,px,py, # Taper and padding dtmax,nrmax,nthrds) # Reference velocities and threads # Compute slowness and reference slownesses slo = 1/vel ssf.set_slows(slo) # Allocate partial image array if(nhx == 0 and nhy == 0): imgtmp = np.zeros([self.__nz,self.__ny,self.__nx],dtype='float32') oimg = np.zeros([self.__nz,self.__ny,self.__nx],dtype='float32') else: if(sym): # Create axes self.__rnhx = 2*nhx+1; self.__ohx = -nhx*self.__dx; self.__dhx = self.__dx self.__rnhy = 2*nhy+1; self.__ohy = -nhy*self.__dy; self.__dhy = self.__dy imgtmp = np.zeros([self.__rnhy,self.__rnhx,self.__nz,self.__ny,self.__nx],dtype='float32') oimg = np.zeros([self.__rnhy,self.__rnhx,self.__nz,self.__ny,self.__nx],dtype='float32') else: # Create axes self.__rnhx = nhx+1; self.__ohx = 0; self.__dhx = self.__dx self.__rnhy = nhy+1; self.__ohy = 0; self.__dhy = self.__dy imgtmp = np.zeros([self.__rnhy,self.__rnhx,self.__nz,self.__ny,self.__nx],dtype='float32') oimg = np.zeros([self.__rnhy,self.__rnhx,self.__nz,self.__ny,self.__nx],dtype='float32') # Allocate memory necessary for extension ssf.set_ext(nhy,nhx,sym) # Loop over sources ntr = 0 for iexp in progressbar(range(self.__nexp),"nexp:",verb=sverb): # Get the source coordinates sy = self.__srcys[iexp]; sx = self.__srcxs[iexp] isy = int((sy-self.__oy)/self.__dy+0.5); isx = int((sx-self.__ox)/self.__dx+0.5) # Create the source wavefield for this shot sou[:] = 0.0 sou[:,isy,isx] = wfftd[:] # Inject the data for this shot datw[:] = 0.0 ssf.inject_data(self.__nrec[iexp],self.__recys[ntr:],self.__recxs[ntr:],self.__oy,self.__ox,dfftd[ntr:,:],datw) datwt = np.ascontiguousarray(np.transpose(datw,(2,0,1))) # [ny,nx,nwc] -> [nwc,ny,nx] # Initialize temporary image imgtmp[:] = 0.0 if(nhx == 0 and nhy == 0): # Conventional imaging ssf.migallw(datwt,sou,imgtmp,wverb) else: # Extended imaging ssf.migoffallw(datwt,sou,imgtmp,wverb) oimg += imgtmp # Increase number of traces ntr += self.__nrec[iexp] # Free memory for extension if(nhx != 0 or nhy != 0): ssf.del_ext() return oimg
def undulatingrandfaults2d(nz=512,nx=1000,dz=12.5,dx=25.0,nlayer=21,minvel=1600,maxvel=3000,rect=0.5, nfx=3,ofx=0.4,dfx=0.1,ofz=0.3,noctaves=None,npts=None,amp=None): """ Builds a 2D faulted velocity model with undulating layers Returns the velocity model, reflectivity, fault labels and a zero-offset image Parameters: nz - number of depth samples [512] nx - number of lateral samples[1000] dz - depth sampling interval [12.5] dx - lateral sampling interval [12.5] nlayer - number of deposited layers (there exist many fine layers within a deposit) [21] nfx - number of faults [0.3] ofx - Starting position of faults (percentage of total model) [0.4] dx - Spacing between faults (percentage of total model) [0.1] ofz - Central depth of faults (percentage of total model) [0.3] rect - radius for gaussian smoother [0.5] noctaves - octaves perlin parameters for squish [varies between 3 and 6] amp - amplitude of folding [varies between 200 and 500] npts - grid size for perlin noise [3] Returns: The velocity, reflectivity, fault label and image all of size [nx,nz] """ # Model building object # Remember to change dist_die based on ny mb = mdlbuild.mdlbuild(nx,dx,ny=20,dy=dx,dz=dz,basevel=5000) nzi = 1000 # internal size is 1000 # Propagation velocities props = np.linspace(maxvel,minvel,nlayer) # Specify the thicknesses thicks = np.random.randint(40,61,nlayer) dlyr = 0.05 for ilyr in progressbar(range(nlayer), "ndeposit:", 40): mb.deposit(velval=props[ilyr],thick=thicks[ilyr],dev_pos=0.0,layer=50,layer_rand=0.00,dev_layer=dlyr) if(ilyr == int(nlayer-2)): amp = rndut.randfloat(200,500) octs = np.random.randint(2,7) npts = np.random.randint(2,5) mb.squish(amp=amp,azim=90.0,lam=0.4,rinline=0.0,rxline=0.0,mode='perlin',npts=npts,octaves=octs,order=3) # Water deposit mb.deposit(1480,thick=80,layer=150,dev_layer=0.0) # Smooth the interface mb.smooth_model(rect1=1,rect2=5,rect3=1) # Trim model before faulting mb.trim(0,1100) #XXX: Thresh should be a function of theta_shift # Generate the fault positions flttype = np.random.choice([0,1,2,3,4,5]) if(flttype == 0): largefaultblock(mb,0.3,0.7,ofz,nfl=6) elif(flttype == 1): slidingfaultblock(mb,0.3,0.7,ofz,nfl=6) elif(flttype == 2): mediumfaultblock(mb,0.3,0.7,0.25,space=0.02,nfl=10) elif(flttype == 3): mediumfaultblock(mb,0.3,0.7,0.25,space=0.005,nfl=20) elif(flttype == 4): tinyfaultblock(mb,0.3,0.7,0.25,space=0.02,nfl=10) else: tinyfaultblock(mb,0.3,0.7,0.25,space=0.005,nfl=20) # Get the model vel = gaussian_filter(mb.vel[:,:nzi].T,sigma=rect).astype('float32') lbl = mb.get_label2d()[:,:nzi].T ref = mb.get_refl2d()[:,:nzi].T # Parameters for ricker wavelet nt = 250; ot = 0.0; dt = 0.001; ns = int(nt/2) amp = 1.0; dly = 0.125 minf = 100.0; maxf = 120.0 # Create normalized image f = rndut.randfloat(minf,maxf) wav = ricker(nt,dt,f,amp,dly) img = dlut.normalize(np.array([np.convolve(ref[:,ix],wav) for ix in range(nx)])[:,ns:nzi+ns].T) nze = dlut.normalize(bandpass(np.random.rand(nzi,nx)*2-1, 2.0, 0.01, 2, pxd=43))/rndut.randfloat(3,5) img += nze # Window the models and return f1 = 50 velwind = vel[f1:f1+nz,:] lblwind = lbl[f1:f1+nz,:] refwind = ref[f1:f1+nz,:] imgwind = img[f1:f1+nz,:] return velwind,refwind,imgwind,lblwind
def awemva(self, dimg, dat, dt, minf, maxf, vel, jf=1, nrmax=3, eps=0.0, dtmax=5e-05, wav=None, ntx=0, nty=0, px=0, py=0, nthrds=1, sverb=True, wverb=False) -> np.ndarray: """ Applies the forward WEMVA operator Parameters: dimg - the input image perturbation dat - the input data dt - temporal sampling interval minf - minimum frequency to image in the data [Hz] maxf - maximim frequency to image in the data [Hz] vel - input migration velocity model [nz,ny,nx] jf - frequency decimation factor [1] nrmax - maximum number of reference velocities [3] eps - stability parameter [0.] dtmax - maximum time error [5e-05] wav - input wavelet [None,assumes an impulse at zero lag] ntx - size of taper in x direction [0] nty - size of taper in y direction [0] px - amount of padding in x direction (samples) [0] py - amount of padding in y direction (samples) [0] nthrds - number of OpenMP threads for parallelizing over frequency [1] sverb - verbosity flag for shot progress bar [True] wverb - verbosity flag for frequency progress bar [False] Returns: a slowness perturbation (adjoint wemva applied to image) [nz,ny,nx] """ # Get temporal axis nt = dat.shape[-1] # Create frequency domain source if (wav is None): wav = np.zeros(nt, dtype='float32') wav[0] = 1.0 self.__nwo, self.__ow, self.__dw, wfft = self.fft1(wav, dt, minf=minf, maxf=maxf) wfftd = wfft[::jf] self.__nwc = wfftd.shape[ 0] # Get the number of frequencies for imaging self.__dwc = self.__dw * jf if (sverb or wverb): print("Frequency axis: nw=%d ow=%f dw=%f" % (self.__nwc, self.__ow, self.__dwc)) # Create frequency domain data _, _, _, dfft = self.fft1(dat, dt, minf=minf, maxf=maxf) dfftd = dfft[:, ::jf] datt = np.transpose( dfftd, (0, 1, 4, 2, 3)) # [nsy,nsx,ny,nx,nwc] -> [nsy,nsx,nwc,ny,nx] datw = np.ascontiguousarray( datt.reshape([self.__nexp, self.__nwc, self.__ny, self.__nx])) # Single square root object ssf = ssr3( self.__nx, self.__ny, self.__nz, # Spatial Sizes self.__dx, self.__dy, self.__dz, # Spatial Samplings self.__nwc, self.__ow, self.__dwc, eps, # Frequency axis ntx, nty, px, py, # Taper and padding dtmax, nrmax, nthrds) # Reference velocities # Compute slowness and reference slownesses slo = 1 / vel ssf.set_slows(slo) dsloar = np.zeros([self.__nexp, self.__nz, self.__ny, self.__nx], dtype='complex64') # Allocate the source for one shot sou = np.zeros([self.__nwc, self.__ny, self.__nx], dtype='complex64') # Loop over sources k = 0 for icrd in progressbar(self.__scoords, "nexp:", verb=sverb): # Get the source coordinates sy = icrd[0] sx = icrd[1] # Create the source for this shot sou[:] = 0.0 sou[:, sy, sx] = wfftd[:] ssf.awemvaallw(sou, datw[k], dsloar[k], dimg, verb=wverb) k += 1 # Sum over all partial images dslo = np.sum(dsloar, axis=0) return np.real(dslo)
def model_data(self,wav,dt,t0,minf,maxf,vel,ref,jf=1,nrmax=3,eps=0.,dtmax=5e-05,time=True, ntx=0,nty=0,px=0,py=0,nthrds=1,sverb=True,wverb=False): """ 3D modeling of single scattered (Born) data with the one-way wave equation (single square root (SSR), split-step Fourier method). Parameters: wav - the input wavelet (source time function) [nt] dt - sampling interval of wavelet t0 - time-zero of wavelet (e.g., peak of ricker wavelet) minf - minimum frequency to propagate [Hz] maxf - maximum frequency to propagate [Hz] vel - input velocity model [nz,ny,nx] ref - input reflectivity model [nz,ny,nx] jf - frequency decimation factor nrmax - maximum number of reference velocities [3] eps - stability parameter [0.] dtmax - maximum time error [5e-05] time - return the data back in the time domain [True] ntx - size of taper in x direction (samples) [0] nty - size of taper in y direction (samples) [0] px - amount of padding in x direction (samples) py - amount of padding in y direction (samples) nthrds - number of OpenMP threads to use for frequency parallelization [1] sverb - verbosity flag for shot progress bar [True] wverb - verbosity flag for frequency progress bar [False] Returns: the data at the surface (in time or frequency) [nw,nry,nrx] """ # Save wavelet temporal parameters nt = wav.shape[0]; it0 = int(t0/dt) # Create the input frequency domain source and get original frequency axis self.__nwo,self.__ow,self.__dw,wfft = fft1(wav,dt,minf=minf,maxf=maxf) wfftd = wfft[::jf] self.__nwc = wfftd.shape[0] # Get the number of frequencies to compute self.__dwc = jf*self.__dw if(sverb or wverb): print("Frequency axis: nw=%d ow=%f dw=%f"%(self.__nwc,self.__ow,self.__dwc)) # Single square root object ssf = ssr3(self.__nx ,self.__ny,self.__nz , # Spatial Sizes self.__dx ,self.__dy,self.__dz , # Spatial Samplings self.__nwc,self.__ow,self.__dwc,eps, # Frequency axis ntx,nty,px,py, # Taper and padding dtmax,nrmax,nthrds) # Reference velocities and threads # Compute slowness and reference slownesses slo = 1/vel ssf.set_slows(slo) # Allocate output data (surface wavefield) and receiver data datw = np.zeros([self.__nwc,self.__ny,self.__nx],dtype='complex64') recw = np.zeros([self.__ntr,self.__nwc],dtype='complex64') # Allocate the source for one shot sou = np.zeros([self.__nwc,self.__ny,self.__nx],dtype='complex64') # Loop over sources ntr = 0 for iexp in progressbar(range(self.__nexp),"nexp:",verb=sverb): # Get the source coordinates sy = self.__srcys[iexp]; sx = self.__srcxs[iexp] isy = int((sy-self.__oy)/self.__dy+0.5); isx = int((sx-self.__ox)/self.__dx+0.5) # Create the source for this shot sou[:] = 0.0 sou[:,isy,isx] = wfftd[:] # Downward continuation datw[:] = 0.0 ssf.modallw(ref,sou,datw,wverb) # Restrict to receiver locations datwt = np.ascontiguousarray(np.transpose(datw,(1,2,0))) # [nwc,ny,nx] -> [ny,nx,nwc] ssf.restrict_data(self.__nrec[iexp],self.__recys[ntr:],self.__recxs[ntr:],self.__oy,self.__ox,datwt,recw[ntr:,:]) # Increase number of traces ntr += self.__nrec[iexp] if(time): rect = ifft1(recw,self.__nwo,self.__ow,self.__dw,nt,it0) return rect else: return recw
def off2angkzx(off, ohx, dhx, dz, ohy=0.0, dhy=1.0, oz=0.0, na=None, amax=60, oa=None, da=None, transp=False, eps=1.0, nthrds=4, cverb=False, rverb=False): """ Converts subsurface offset gathers to openeing angle gathers via a radial trace transform in the wavenumber domain Parameters off - subsurface offset gathers of shape [nro,nhy,nhx,nz,ny,nx] (nro is optional) ohx - origin of subsurface offset axis dhx - sampling of subsurface offset axis dz - sampling in depth oz - depth origin [0.0] ohy - origin of y-subsurface offsets [0.0] dhy - sampling of y-subsurface offsets [1.0] na - number of angles [nhx] amax - maximum angle [60 degrees] oa - origin of angle axis (not needed if na and amax specified) da - spacing on angle axis (not needed if na and amax specified) transp - input has shape [nro,nhy,nhx,ny,nx,nz] instead of assumed shape [False] eps - regularization parameter (larger will enforce smoother output) [1.0] nthrds - number of OpenMP threads to parallelize over gathers [4] rverb - residual migration verbosity flag [False] cverb - gather conversion verbosity flag [False] Returns the converted angle gathers of shape [nro,ny,nx,naz,na,nz] """ # Handle case of 2D residual migration [nro,nhx,nx,nz] if (len(off.shape) == 4): # Get dimensions [nro, nhx, nx, nz] = off.shape nhy = 1 ny = 1 off = off.reshape([nro, nhy, nhx, ny, nx, nz]) # [nro,nhy,nhx,ny,nx,nz] -> [nro,ny,nx,nz,nhy,nhx] offi = np.ascontiguousarray(np.transpose(off, (0, 3, 4, 5, 1, 2))) if (len(off.shape) == 5): nro = 1 if (transp == False): # Get dimensions [nhy, nhx, nz, ny, nx] = off.shape offe = np.expand_dims(off, axis=0) # Transpose to correct shape # [nro,nhy,nhx,nz,ny,nx] -> [nro,ny,nx,nz,nhy,nhx] offi = np.ascontiguousarray(np.transpose(offe, (0, 4, 5, 3, 1, 2))) else: # Get dimensions [nhy, nhx, ny, nx, nz] = off.shape offe = np.expand_dims(off, axis=0) # Transpose to correct shape # [nro,nhy,nhx,ny,nx,nz] -> [nro,ny,nx,nz,nhy,nhx] offi = np.ascontiguousarray(np.transpose(offe, (0, 3, 4, 5, 1, 2))) # Pad input based on desired number of angles if (na is None): na = nhx paddims = [(0, 0)] * (offi.ndim - 1) paddims.append((0, na - nhx)) offip = np.pad(offi, paddims, mode='constant').astype('complex64') ang = np.zeros(offip.shape, dtype='complex64') # Compute angle axis oa = -amax da = 2 * amax / na # Loop over rho for iro in progressbar(range(nro), "nrho:", verb=rverb): convert2angkzkykx( nx * ny, # Number of gathers nz, oz, dz, nhy, ohy, dhy, na, ohx, dhx, oa, da, # Axes of input and output offip[iro], ang[iro], eps, nthrds, cverb) # Input and output and parameters # Transpose, window and return if (transp): if (nro > 1): angw = ang[:, 0, :, :, 0, :] # [nro,ny,nx,nz,naz,na] -> [nro,nx,nz,na] ango = np.transpose( angw, (0, 1, 3, 2)) # [nro,nx,nz,na] -> [nro,nx,na,nz] else: angw = ang[0] ango = np.transpose( angw, (0, 1, 3, 4, 2)) # [ny,nx,nz,naz,na] -> [ny,nx,naz,na,nz] else: if (nro > 1): angw = ang[:, 0, :, :, 0, :] # [nro,ny,nx,nz,naz,na] -> [nro,nx,nz,na] ango = np.transpose( angw, (0, 3, 2, 1)) # [nro,nx,nz,na] -> [nro,na,nz,nx] else: angw = ang[0] ango = np.transpose( angw, (3, 4, 2, 0, 1)) # [ny,nx,nz,naz,na] -> [naz,na,nz,ny,nx] return np.real(np.ascontiguousarray(ango))
def velfaultsrandom(nz=512,nx=1024,ny=20,dz=12.5,dx=25.0,nlayer=20, minvel=1600,maxvel=5000,rect=0.5, verb=True,**kwargs): """ Builds a 2D highly faulted and folded velocity model. Returns the velocity model, reflectivity, fault labels and a zero-offset image Parameters: nz - number of depth samples [512] nx - number of lateral samples [1024] dz - depth sampling interval [25.0] dx - lateral sampling interval [25.0] nlayer - number of deposited layers (there exist many fine layers within a deposit) [20] minvel - minimum velocity in model [1600] maxvel - maximum velocity in model [5000] rect - length of gaussian smoothing [0.5] verb - verbosity flag [True] Returns The velocity, reflectivity, fault label and image all of size [nx,nz] """ # Internal model size nzi = 1000; nxi = 1000 # Model building object mb = mdlbuild.mdlbuild(nxi,dx,ny,dy=dx,dz=dz,basevel=5000) # First build the v(z) model props = mb.vofz(nlayer,minvel,maxvel,npts=kwargs.get('nptsvz',2)) # Specify the thicknesses thicks = np.random.randint(40,61,nlayer) # Determine when to fold the deposits sqlyrs = sorted(mb.findsqlyrs(3,nlayer,5)) csq = 0 dlyr = 0.05 for ilyr in progressbar(range(nlayer), "ndeposit:", 40, verb=verb): mb.deposit(velval=props[ilyr],thick=thicks[ilyr],dev_pos=0.0, layer=kwargs.get('layer',150),layer_rand=0.00,dev_layer=dlyr) # Random folding if(ilyr in sqlyrs): if(sqlyrs[csq] < 15): # Random amplitude variation in the folding amp = np.random.rand()*(3000-500) + 500 mb.squish(amp=amp,azim=90.0,lam=0.4,rinline=0.0,rxline=0.0,mode='perlin',order=3) elif(sqlyrs[csq] >= 15 and sqlyrs[csq] < 18): amp = np.random.rand()*(1800-500) + 500 mb.squish(amp=amp,azim=90.0,lam=0.4,rinline=0.0,rxline=0.0,mode='perlin',order=3) else: amp = np.random.rand()*(500-300) + 300 mb.squish(amp=amp,azim=90.0,lam=0.4,rinline=0.0,rxline=0.0,mode='perlin') csq += 1 # Water deposit mb.deposit(1480,thick=50,layer=150,dev_layer=0.0) # Smooth any unconformities mb.smooth_model(rect1=1,rect2=5,rect3=1) # Trim model before faulting mb.trim(0,1100) # Fault it up! azims = [0.0,180.0] fprs = [True,False] # Large faults nlf = np.random.randint(2,5) for ifl in progressbar(range(nlf), "nlfaults:", 40, verb=verb): azim = np.random.choice(azims) fpr = np.random.choice(fprs) xpos = rndut.randfloat(0.1,0.9) mb.largefault(azim=azim,begz=0.65,begx=xpos,begy=0.5,dist_die=4.0,tscale=6.0,fpr=fpr,twod=True) # Medium faults nmf = np.random.randint(3,6) for ifl in progressbar(range(nmf), "nmfaults:", 40, verb=verb): azim = np.random.choice(azims) fpr = np.random.choice(fprs) xpos = rndut.randfloat(0.05,0.95) mb.mediumfault(azim=azim,begz=0.65,begx=xpos,begy=0.5,dist_die=4.0,tscale=3.0,fpr=fpr,twod=True) # Small faults (sliding or small) nsf = np.random.randint(5,10) for ifl in progressbar(range(nsf), "nsfaults:", 40, verb=verb): azim = np.random.choice(azims) fpr = np.random.choice(fprs) xpos = rndut.randfloat(0.05,0.95) zpos = rndut.randfloat(0.2,0.5) mb.smallfault(azim=azim,begz=zpos,begx=xpos,begy=0.5,dist_die=4.0,tscale=2.0,fpr=fpr,twod=True) # Tiny faults ntf = np.random.randint(5,10) for ifl in progressbar(range(ntf), "ntfaults:", 40, verb=verb): azim = np.random.choice(azims) xpos = rndut.randfloat(0.05,0.95) zpos = rndut.randfloat(0.15,0.3) mb.tinyfault(azim=azim,begz=zpos,begx=xpos,begy=0.5,dist_die=4.0,tscale=2.0,twod=True) # Parameters for ricker wavelet nt = kwargs.get('nt',250); ot = 0.0; dt = kwargs.get('dt',0.001); ns = int(nt/2) amp = 1.0; dly = kwargs.get('dly',0.125) minf = kwargs.get('minf',60.0); maxf = kwargs.get('maxf',100.0) f = kwargs.get('f',None) # Get model vel = gaussian_filter(mb.vel[:,:nzi],sigma=rect).astype('float32') lbl = mb.get_label2d()[:,:nzi] # Resample to output size velr = dlut.resample(vel,[nx,nz],kind='quintic') lblr = dlut.thresh(dlut.resample(lbl,[nx,nz],kind='linear'),0) refr = mb.calcrefl2d(velr) # Create normalized image if(f is None): f = rndut.randfloat(minf,maxf) wav = ricker(nt,dt,f,amp,dly) img = dlut.normalize(np.array([np.convolve(refr[ix,:],wav) for ix in range(nx)])[:,ns:nz+ns]) # Create noise nze = dlut.normalize(bandpass(np.random.rand(nx,nz)*2-1, 2.0, 0.01, 2, pxd=43))/rndut.randfloat(3,5) img += nze if(kwargs.get('transp',False) == True): velt = np.ascontiguousarray(velr.T).astype('float32') reft = np.ascontiguousarray(refr.T).astype('float32') imgt = np.ascontiguousarray(img.T).astype('float32') lblt = np.ascontiguousarray(lblr.T).astype('float32') else: velt = np.ascontiguousarray(velr).astype('float32') reft = np.ascontiguousarray(refr).astype('float32') imgt = np.ascontiguousarray(img).astype('float32') lblt = np.ascontiguousarray(lblr).astype('float32') if(kwargs.get('km',True)): velt /= 1000.0 return velt,reft,imgt,lblt