def gen_DCIPsurvey(endl, mesh, stype, a, b, n): """ Load in endpoints and survey specifications to generate Tx, Rx location stations. Assumes flat topo for now... Input: :param endl -> input endpoints [x1, y1, z1, x2, y2, z2] :object mesh -> SimPEG mesh object :switch stype -> "dpdp" (dipole-dipole) | "pdp" (pole-dipole) | 'gradient' : param a, n -> pole seperation, number of rx dipoles per tx Output: :param Tx, Rx -> List objects for each tx location Lines: P1x, P1y, P1z, P2x, P2y, P2z Created on Wed December 9th, 2015 @author: dominiquef !! Require clean up to deal with DCsurvey """ from SimPEG import np def xy_2_r(x1, x2, y1, y2): r = np.sqrt(np.sum((x2 - x1)**2 + (y2 - y1)**2)) return r ## Evenly distribute electrodes and put on surface # Mesure survey length and direction dl_len = xy_2_r(endl[0, 0], endl[1, 0], endl[0, 1], endl[1, 1]) dl_x = (endl[1, 0] - endl[0, 0]) / dl_len dl_y = (endl[1, 1] - endl[0, 1]) / dl_len nstn = np.floor(dl_len / a) # Compute discrete pole location along line stn_x = endl[0, 0] + np.array(range(int(nstn))) * dl_x * a stn_y = endl[0, 1] + np.array(range(int(nstn))) * dl_y * a if mesh.dim == 2: ztop = mesh.vectorNy[-1] # Create line of P1 locations M = np.c_[stn_x, np.ones(nstn).T * ztop] # Create line of P2 locations N = np.c_[stn_x + a * dl_x, np.ones(nstn).T * ztop] elif mesh.dim == 3: ztop = mesh.vectorNz[-1] # Create line of P1 locations M = np.c_[stn_x, stn_y, np.ones(nstn).T * ztop] # Create line of P2 locations N = np.c_[stn_x + a * dl_x, stn_y + a * dl_y, np.ones(nstn).T * ztop] ## Build list of Tx-Rx locations depending on survey type # Dipole-dipole: Moving tx with [a] spacing -> [AB a MN1 a MN2 ... a MNn] # Pole-dipole: Moving pole on one end -> [A a MN1 a MN2 ... MNn a B] SrcList = [] if stype != 'gradient': for ii in range(0, int(nstn) - 1): if stype == 'dipole-dipole': tx = np.c_[M[ii, :], N[ii, :]] elif stype == 'pole-dipole': tx = np.c_[M[ii, :], M[ii, :]] else: raise Exception( 'The stype must be "dipole-dipole" or "pole-dipole"') # Rx.append(np.c_[M[ii+1:indx,:],N[ii+1:indx,:]]) # Current elctrode seperation AB = xy_2_r(tx[0, 1], endl[1, 0], tx[1, 1], endl[1, 1]) # Number of receivers to fit nstn = np.min([np.floor((AB - b) / a), n]) # Check if there is enough space, else break the loop if nstn <= 0: continue # Compute discrete pole location along line stn_x = N[ii, 0] + dl_x * b + np.array(range(int(nstn))) * dl_x * a stn_y = N[ii, 1] + dl_y * b + np.array(range(int(nstn))) * dl_y * a # Create receiver poles if mesh.dim == 3: # Create line of P1 locations P1 = np.c_[stn_x, stn_y, np.ones(nstn).T * ztop] # Create line of P2 locations P2 = np.c_[stn_x + a * dl_x, stn_y + a * dl_y, np.ones(nstn).T * ztop] rxClass = DC.Rx.Dipole(P1, P2) elif mesh.dim == 2: # Create line of P1 locations P1 = np.c_[stn_x, np.ones(nstn).T * ztop] # Create line of P2 locations P2 = np.c_[stn_x + a * dl_x, np.ones(nstn).T * ztop] rxClass = DC.Rx.Dipole_ky(P1, P2) if stype == 'dipole-dipole': srcClass = DC.Src.Dipole([rxClass], M[ii, :], N[ii, :]) elif stype == 'pole-dipole': srcClass = DC.Src.Pole([rxClass], M[ii, :]) SrcList.append(srcClass) elif stype == 'gradient': # Gradient survey only requires Tx at end of line and creates a square # grid of receivers at in the middle at a pre-set minimum distance # Get the edge limit of survey area min_x = endl[0, 0] + dl_x * b min_y = endl[0, 1] + dl_y * b max_x = endl[1, 0] - dl_x * b max_y = endl[1, 1] - dl_y * b box_l = np.sqrt((min_x - max_x)**2 + (min_y - max_y)**2) box_w = box_l / 2. nstn = np.floor(box_l / a) # Compute discrete pole location along line stn_x = min_x + np.array(range(int(nstn))) * dl_x * a stn_y = min_y + np.array(range(int(nstn))) * dl_y * a # Define number of cross lines nlin = int(np.floor(box_w / a)) lind = range(-nlin, nlin + 1) ngrad = nstn * len(lind) rx = np.zeros([ngrad, 6]) for ii in range(len(lind)): # Move line in perpendicular direction by dipole spacing lxx = stn_x - lind[ii] * a * dl_y lyy = stn_y + lind[ii] * a * dl_x M = np.c_[lxx, lyy, np.ones(nstn).T * ztop] N = np.c_[lxx + a * dl_x, lyy + a * dl_y, np.ones(nstn).T * ztop] rx[(ii * nstn):((ii + 1) * nstn), :] = np.c_[M, N] if mesh.dim == 3: rxClass = DC.Rx.Dipole(rx[:, :3], rx[:, 3:]) elif mesh.dim == 2: M = M[:, [0, 2]] N = N[:, [0, 2]] rxClass = DC.Rx.Dipole_ky(rx[:, [0, 2]], rx[:, [3, 5]]) srcClass = DC.Src.Dipole([rxClass], M[0, :], N[-1, :]) SrcList.append(srcClass) else: print """stype must be either 'pole-dipole', 'dipole-dipole' or 'gradient'. """ return SrcList
# Add z coordinate nz = mesh.vectorNz endp = np.c_[np.asarray(temp), np.ones(2).T * nz[-1]] # Create dipole survey receivers and plot nrx = 10 ab = 40 a = 20 # Evenly distribute transmitters for now and put on surface dplen = np.sqrt(np.sum((endp[1, :] - endp[0, :])**2)) dp_x = (endp[1, 0] - endp[0, 0]) / dplen dp_y = (endp[1, 1] - endp[0, 1]) / dplen nstn = np.floor(dplen / ab) stn_x = endp[0, 0] + np.cumsum(np.ones(nstn) * dp_x * ab) stn_y = endp[0, 1] + np.cumsum(np.ones(nstn) * dp_y * ab) plt.scatter(stn_x, stn_y, s=100, c='w') M = np.c_[stn_x - a * dp_x, stn_y - a * dp_y, np.ones(nstn).T * nz[-1]] N = np.c_[stn_x + a * dp_x, stn_y + a * dp_y, np.ones(nstn).T * nz[-1]] plt.scatter(M[:, 0], M[:, 1], s=10, c='r') plt.scatter(N[:, 0], N[:, 1], s=10, c='b') #%% Create inversion parameter Rx = DC.RxDipole(M, N)
def gen_DCIPsurvey(endl, mesh, stype, a, b, n): from SimPEG import np import re """ Load in endpoints and survey specifications to generate Tx, Rx location stations. Assumes flat topo for now... Input: :param endl -> input endpoints [x1, y1, z1, x2, y2, z2] :object mesh -> SimPEG mesh object :switch stype -> "dpdp" (dipole-dipole) | "pdp" (pole-dipole) | 'gradient' : param a, n -> pole seperation, number of rx dipoles per tx Output: :param Tx, Rx -> List objects for each tx location Lines: P1x, P1y, P1z, P2x, P2y, P2z Created on Wed December 9th, 2015 @author: dominiquef """ def xy_2_r(x1,x2,y1,y2): r = np.sqrt( np.sum((x2 - x1)**2 + (y2 - y1)**2) ) return r ## Evenly distribute electrodes and put on surface # Mesure survey length and direction dl_len = xy_2_r(endl[0,0],endl[1,0],endl[0,1],endl[1,1]) dl_x = ( endl[1,0] - endl[0,0] ) / dl_len dl_y = ( endl[1,1] - endl[0,1] ) / dl_len nstn = np.floor( dl_len / a ) # Compute discrete pole location along line stn_x = endl[0,0] + np.array(range(int(nstn)))*dl_x*a stn_y = endl[0,1] + np.array(range(int(nstn)))*dl_y*a # Create line of P1 locations M = np.c_[stn_x, stn_y, np.ones(nstn).T*mesh.vectorNz[-1]] # Create line of P2 locations N = np.c_[stn_x+a*dl_x, stn_y+a*dl_y, np.ones(nstn).T*mesh.vectorNz[-1]] ## Build list of Tx-Rx locations depending on survey type # Dipole-dipole: Moving tx with [a] spacing -> [AB a MN1 a MN2 ... a MNn] # Pole-dipole: Moving pole on one end -> [A a MN1 a MN2 ... MNn a B] Tx = [] Rx = [] if not re.match(stype,'gradient'): for ii in range(0, int(nstn)-1): if re.match(stype,'dpdp'): tx = np.c_[M[ii,:],N[ii,:]] elif re.match(stype,'pdp'): tx = np.c_[M[ii,:],M[ii,:]] #Rx.append(np.c_[M[ii+1:indx,:],N[ii+1:indx,:]]) # Current elctrode seperation AB = xy_2_r(tx[0,1],endl[1,0],tx[1,1],endl[1,1]) # Number of receivers to fit nstn = np.min([np.floor( (AB - b) / a ) , n]) # Check if there is enough space, else break the loop if nstn <= 0: continue # Compute discrete pole location along line stn_x = N[ii,0] + dl_x*b + np.array(range(int(nstn)))*dl_x*a stn_y = N[ii,1] + dl_y*b + np.array(range(int(nstn)))*dl_y*a # Create receiver poles # Create line of P1 locations P1 = np.c_[stn_x, stn_y, np.ones(nstn).T*mesh.vectorNz[-1]] # Create line of P2 locations P2 = np.c_[stn_x+a*dl_x, stn_y+a*dl_y, np.ones(nstn).T*mesh.vectorNz[-1]] Rx.append(np.c_[P1,P2]) Tx.append(tx) #============================================================================== # elif re.match(stype,'dpdp'): # # for ii in range(0, int(nstn)-2): # # indx = np.min([ii+n+1,nstn]) # Tx.append(np.c_[M[ii,:],N[ii,:]]) # Rx.append(np.c_[M[ii+2:indx,:],N[ii+2:indx,:]]) #============================================================================== elif re.match(stype,'gradient'): # Gradient survey only requires Tx at end of line and creates a square # grid of receivers at in the middle at a pre-set minimum distance Tx.append(np.c_[M[0,:],N[-1,:]]) # Get the edge limit of survey area min_x = endl[0,0] + dl_x * b min_y = endl[0,1] + dl_y * b max_x = endl[1,0] - dl_x * b max_y = endl[1,1] - dl_y * b box_l = np.sqrt( (min_x - max_x)**2 + (min_y - max_y)**2 ) box_w = box_l/2. nstn = np.floor( box_l / a ) # Compute discrete pole location along line stn_x = min_x + np.array(range(int(nstn)))*dl_x*a stn_y = min_y + np.array(range(int(nstn)))*dl_y*a # Define number of cross lines nlin = int(np.floor( box_w / a )) lind = range(-nlin,nlin+1) ngrad = nstn * len(lind) rx = np.zeros([ngrad,6]) for ii in range( len(lind) ): # Move line in perpendicular direction by dipole spacing lxx = stn_x - lind[ii]*a*dl_y lyy = stn_y + lind[ii]*a*dl_x M = np.c_[ lxx, lyy , np.ones(nstn).T*mesh.vectorNz[-1]] N = np.c_[ lxx+a*dl_x, lyy+a*dl_y, np.ones(nstn).T*mesh.vectorNz[-1]] rx[(ii*nstn):((ii+1)*nstn),:] = np.c_[M,N] Rx.append(rx) else: print """stype must be either 'pdp', 'dpdp' or 'gradient'. """ return Tx, Rx
def gen_DCIPsurvey(endl, mesh, stype, a, b, n): """ Load in endpoints and survey specifications to generate Tx, Rx location stations. Assumes flat topo for now... Input: :param endl -> input endpoints [x1, y1, z1, x2, y2, z2] :object mesh -> SimPEG mesh object :switch stype -> "dpdp" (dipole-dipole) | "pdp" (pole-dipole) | 'gradient' : param a, n -> pole seperation, number of rx dipoles per tx Output: :param Tx, Rx -> List objects for each tx location Lines: P1x, P1y, P1z, P2x, P2y, P2z Created on Wed December 9th, 2015 @author: dominiquef !! Require clean up to deal with DCsurvey """ from SimPEG import np def xy_2_r(x1,x2,y1,y2): r = np.sqrt( np.sum((x2 - x1)**2 + (y2 - y1)**2) ) return r ## Evenly distribute electrodes and put on surface # Mesure survey length and direction dl_len = xy_2_r(endl[0,0],endl[1,0],endl[0,1],endl[1,1]) dl_x = ( endl[1,0] - endl[0,0] ) / dl_len dl_y = ( endl[1,1] - endl[0,1] ) / dl_len nstn = np.floor( dl_len / a ) # Compute discrete pole location along line stn_x = endl[0,0] + np.array(range(int(nstn)))*dl_x*a stn_y = endl[0,1] + np.array(range(int(nstn)))*dl_y*a if mesh.dim==2: ztop = mesh.vectorNy[-1] # Create line of P1 locations M = np.c_[stn_x, np.ones(nstn).T*ztop] # Create line of P2 locations N = np.c_[stn_x+a*dl_x, np.ones(nstn).T*ztop] elif mesh.dim==3: ztop = mesh.vectorNz[-1] # Create line of P1 locations M = np.c_[stn_x, stn_y, np.ones(nstn).T*ztop] # Create line of P2 locations N = np.c_[stn_x+a*dl_x, stn_y+a*dl_y, np.ones(nstn).T*ztop] ## Build list of Tx-Rx locations depending on survey type # Dipole-dipole: Moving tx with [a] spacing -> [AB a MN1 a MN2 ... a MNn] # Pole-dipole: Moving pole on one end -> [A a MN1 a MN2 ... MNn a B] SrcList = [] if stype != 'gradient': for ii in range(0, int(nstn)-1): if stype == 'dipole-dipole': tx = np.c_[M[ii,:],N[ii,:]] elif stype == 'pole-dipole': tx = np.c_[M[ii,:],M[ii,:]] else: raise Exception('The stype must be "dipole-dipole" or "pole-dipole"') # Rx.append(np.c_[M[ii+1:indx,:],N[ii+1:indx,:]]) # Current elctrode seperation AB = xy_2_r(tx[0,1],endl[1,0],tx[1,1],endl[1,1]) # Number of receivers to fit nstn = np.min([np.floor( (AB - b) / a ) , n]) # Check if there is enough space, else break the loop if nstn <= 0: continue # Compute discrete pole location along line stn_x = N[ii,0] + dl_x*b + np.array(range(int(nstn)))*dl_x*a stn_y = N[ii,1] + dl_y*b + np.array(range(int(nstn)))*dl_y*a # Create receiver poles if mesh.dim==3: # Create line of P1 locations P1 = np.c_[stn_x, stn_y, np.ones(nstn).T*ztop] # Create line of P2 locations P2 = np.c_[stn_x+a*dl_x, stn_y+a*dl_y, np.ones(nstn).T*ztop] rxClass = DC.Rx.Dipole(P1, P2) elif mesh.dim==2: # Create line of P1 locations P1 = np.c_[stn_x, np.ones(nstn).T*ztop] # Create line of P2 locations P2 = np.c_[stn_x+a*dl_x, np.ones(nstn).T*ztop] rxClass = DC.Rx.Dipole_ky(P1, P2) if stype == 'dipole-dipole': srcClass = DC.Src.Dipole([rxClass], M[ii,:],N[ii,:]) elif stype == 'pole-dipole': srcClass = DC.Src.Pole([rxClass], M[ii,:]) SrcList.append(srcClass) elif stype == 'gradient': # Gradient survey only requires Tx at end of line and creates a square # grid of receivers at in the middle at a pre-set minimum distance # Get the edge limit of survey area min_x = endl[0,0] + dl_x * b min_y = endl[0,1] + dl_y * b max_x = endl[1,0] - dl_x * b max_y = endl[1,1] - dl_y * b box_l = np.sqrt( (min_x - max_x)**2 + (min_y - max_y)**2 ) box_w = box_l/2. nstn = np.floor( box_l / a ) # Compute discrete pole location along line stn_x = min_x + np.array(range(int(nstn)))*dl_x*a stn_y = min_y + np.array(range(int(nstn)))*dl_y*a # Define number of cross lines nlin = int(np.floor( box_w / a )) lind = list(range(-nlin,nlin+1)) ngrad = nstn * len(lind) rx = np.zeros([ngrad,6]) for ii in range( len(lind) ): # Move line in perpendicular direction by dipole spacing lxx = stn_x - lind[ii]*a*dl_y lyy = stn_y + lind[ii]*a*dl_x M = np.c_[ lxx, lyy , np.ones(nstn).T*ztop] N = np.c_[ lxx+a*dl_x, lyy+a*dl_y, np.ones(nstn).T*ztop] rx[(ii*nstn):((ii+1)*nstn),:] = np.c_[M,N] if mesh.dim==3: rxClass = DC.Rx.Dipole(rx[:,:3], rx[:,3:]) elif mesh.dim==2: M = M[:,[0,2]] N = N[:,[0,2]] rxClass = DC.Rx.Dipole_ky(rx[:,[0,2]], rx[:,[3,5]]) srcClass = DC.Src.Dipole([rxClass], M[0,:], N[-1,:]) SrcList.append(srcClass) else: print("""stype must be either 'pole-dipole', 'dipole-dipole' or 'gradient'. """) return SrcList
ymin = np.min(rxLoc[:, 1]) ymax = np.max(rxLoc[:, 1]) var = np.c_[np.r_[xmin, ymin], np.r_[xmax, ymin], np.r_[xmin, ymax]] var = np.c_[var.T, np.ones(3) * mesh.vectorCCz[-1]] # First put a tile on both corners of the mesh indx = Utils.closestPoints(mesh, var) endl = np.c_[mesh.gridCC[indx, 0], mesh.gridCC[indx, 1]] dx = np.median(mesh.hx) # Add intermediate tiles until the min_Olap is respected # First in the x-direction lx = np.floor((max_mcell / mesh.nCz)**0.5) ntile = 2 Olap = -1 while Olap < min_Olap: ntile += 1 # Set location of SW corners #x0 = np.c_[xmin,xmax-lx*dx] dx_t = np.round((endl[1, 0] - endl[0, 0]) / ((ntile - 1) * dx)) x1 = np.r_[endl[0, 0], endl[0, 0] + np.cumsum( (np.ones(ntile - 2)) * dx_t * dx), endl[1, 0]] x2 = x1 + lx * dx
def interpFFT(x, y, m): """ Load in a 2D grid and resample OUTPUT: m_out """ from SimPEG import np, sp import scipy.signal as sn # Add padding values by reflection (2**n) lenx = np.round(np.log2(2 * len(x))) npadx = int(np.floor((2**lenx - len(x)) / 2.)) #Create hemming taper if np.mod(npadx * 2 + len(x), 2) != 0: oddx = 1 else: oddx = 0 tap0 = sn.hamming(npadx * 2) tapl = sp.spdiags(tap0[0:npadx], 0, npadx, npadx) tapr = sp.spdiags(tap0[npadx:], 0, npadx, npadx + oddx) # Mirror the 2d data over the half lenght and apply 0-taper mpad = np.hstack( [np.fliplr(m[:, 0:npadx]) * tapl, m, np.fliplr(m[:, -npadx:]) * tapr]) # Repeat along the second dimension leny = np.round(np.log2(2 * len(y))) npady = int(np.floor((2**leny - len(y)) / 2.)) #Create hemming taper if np.mod(npady * 2 + len(y), 2) != 0: oddy = 1 else: oddy = 0 tap0 = sn.hamming(npady * 2) tapu = sp.spdiags(tap0[0:npady], 0, npady, npady) tapd = sp.spdiags(tap0[npady:], 0, npady + oddy, npady) mpad = np.vstack([ tapu * np.flipud(mpad[0:npady, :]), mpad, tapd * np.flipud(mpad[-npady:, :]) ]) # Compute FFT FFTm = np.fft.fft2(mpad) # Do an FFT shift FFTshift = np.fft.fftshift(FFTm) # Pad high frequencies with zeros to increase the sampling rate py = int(FFTm.shape[0] / 2) px = int(FFTm.shape[1] / 2) FFTshift = np.hstack([ np.zeros((FFTshift.shape[0], px)), FFTshift, np.zeros((FFTshift.shape[0], px)) ]) FFTshift = np.vstack([ np.zeros((py, FFTshift.shape[1])), FFTshift, np.zeros((py, FFTshift.shape[1])) ]) # Inverse shift FFTm = np.fft.ifftshift(FFTshift) # Compute inverse FFT IFFTm = np.fft.ifft2(FFTm) * FFTm.size / mpad.size m_out = np.real(IFFTm) # Extract core #m_out = np.real(IFFTm[npady*2:-(npady*2+oddy+1),npadx*2:-(npadx*2+oddx+1)]) m_out = m_out[npady * 2:-(npady + oddy) * 2, npadx * 2:-(npadx + oddx) * 2] if np.mod(m.shape[0], 2) != 0: m_out = m_out[:-1, :] if np.mod(m.shape[1], 2) != 0: m_out = m_out[:, :-1] return m_out