def __init__(self, *args, **kwargs): """ Initialize a rectangular element hRect = rect(args,*,hw=1.0, hh=1.0, center=[0,0,0],euler=[0,0,0],conv='yxz',intrinsic=True,nAbcissa=[1,1]) A rect object is returned, which can be used for computing a continuous wave field (ARFI pressure) hw - half width of the element hh - half height of the element center - center of element euler - orientation of element conv - convention used for the orientation, order of rotations intrinsic - if true, the coordinate system is rotating nAbcissa - number of Gaussian abcissas used for integration [nWidth,nHeight] """ opt = dotdict({ 'hw': 1, 'hh': 1, 'center': [0, 0, 0], 'euler': [0, 0, 0], 'conv': 'yxz', 'intrinsic': True, 'nAbcissa': 1 }) opt.update(*args, **kwargs) opt.nAbcissa = np.array(opt.nAbcissa).flatten() super(rect, self).update(**opt) if len(self.nAbcissa) == 1: self.nAbcissa = np.r_[self.nAbcissa[0], self.nAbcissa[0]] self.center = np.array(self.center).flatten() self.euler = np.array(self.euler).flatten()
def __init__(self,*args, **kwargs): """ Initialize a rectangular element hRect = rect(args,*,hw=1.0, hh=1.0, center=[0,0,0],euler=[0,0,0],conv='yxz',intrinsic=True,nAbcissa=[1,1]) A rect object is returned, which can be used for computing a continuous wave field (ARFI pressure) hw - half width of the element hh - half height of the element center - center of element euler - orientation of element conv - convention used for the orientation, order of rotations intrinsic - if true, the coordinate system is rotating nAbcissa - number of Gaussian abcissas used for integration [nWidth,nHeight] """ opt = dotdict({'hw' : 1, 'hh' : 1, 'center' : [0,0,0], 'euler' : [0,0,0], 'conv' : 'yxz', 'intrinsic' : True, 'nAbcissa' : 1}) opt.update(*args,**kwargs) opt.nAbcissa = np.array(opt.nAbcissa).flatten() super(rect,self).update(**opt) if len(self.nAbcissa)==1: self.nAbcissa = np.r_[self.nAbcissa[0], self.nAbcissa[0]] self.center = np.array(self.center).flatten() self.euler = np.array(self.euler).flatten()
def FourierToSpaceTimeNorway(P12,fx1,fy1,f1,**kwargs): opt = dotdict({'resolution' : np.r_[6e-5, 6e-5, 6e-5], 'c' : 1540.0}) opt.update(**kwargs) resolution = opt.resolution c = opt.c testPlot = False dfx=(fx1[1]-fx1[0]); dfy=(fy1[1]-fy1[0]); df=(f1[1]-f1[0]); Nfx=int(2*np.round(c/dfx/resolution[0]/2)+1) Nfy=int(2*np.round(c/dfy/resolution[1]/2)+1) Nfs=int(2*np.round(c/2/df/resolution[2]/2)+1) xax=np.linspace(-1/dfx*c/2,1/dfx*c/2,Nfx); yax=np.linspace(-1/dfy*c/2,1/dfy*c/2,Nfy); zax=np.linspace(-1/df*c/4,1/df*c/4,Nfs); [Nx,Ny,Nf]=P12.shape P12zp=np.zeros((Nfx,Nfy,Nfs),dtype=np.complex128) ix1=int(np.round(1+(Nfx-1)/2-(Nx-1)/2)) iy1=int(np.round(1+(Nfy-1)/2-(Ny-1)/2)) if1=int(np.round(1+(Nfs-1)/2+1+f1[0]/df) - 1) P12zp[ix1:ix1+Nx,iy1:iy1+Ny,if1:if1+Nf]=P12; P12zp=np.fft.fftshift(P12zp); p12=ifftn(P12zp); p12=np.fft.fftshift(p12); return (p12,xax,yax,zax)
def FieldAtFocus(xdc, **kwargs): opt = dotdict({'nx' : 100, 'ny' : 100, 'dx' : 6e-5, 'dy' : 6e-5}) # Maximum frequency fmax = None if xdc.bandwidth == 0.0: fmax = xdc.f0
def compareWithReference(**kwargs): opt = dotdict({'method0' : 'CalcCwFieldRef', 'method1' : 'CalcCwFieldRef', 'location' : 'inside', 'ndiv' : 2, 'eps' : 1e-5, 'quiet' : False}) opt.update(**kwargs) quiet = opt.quiet areas = [2.0,3.0,4.0,5.0] widths = np.array([areas[0],1.0,areas[2],1.0],dtype=np.float32) heights = np.array([1.0,areas[1],1.0,areas[3]],dtype=np.float32) xsign = np.array([1.0,-1.0,-1.0,1.0],dtype=np.float32) ysign = np.array([1.0,1.0,-1.0,-1.0],dtype=np.float32) # Ensure that we either slightly inside or outside scale = 40.0 * np.finfo(np.float32).eps epss = dict({'inside' : -scale, 'outside' : scale}) ndiv = opt.ndiv iCorners = [0,1,2,3] eps = epss[opt.location] method0 = opt.method0 method1 = opt.method1 scatters = np.c_[(widths+eps)/2.0 * xsign, (heights+eps)/2.0 * ysign, np.ones(4,dtype=np.float32)] if not(quiet): print('Testing: %s vs %s: %s' % (opt.method0,opt.method1, opt.location)) success = True for iCorner in iCorners: a = fnm.ApertureFloat(1, float(widths[iCorner]), float(0.0), float(heights[iCorner])) a.nthreads = 1 a.nDivH = ndiv a.nDivW = ndiv a.f0 = 1 a.c = 1 exec('result0 = a.'+method0+'([scatters[iCorner]])[1].flatten()') exec('result1 = a.'+method1+'([scatters[iCorner]])[1].flatten()') diff = np.abs(result0)-np.abs(result1) reldiff = diff / np.mean(np.abs(result0)+np.abs(result1)) success = success and (reldiff < opt.eps) if not(quiet): print('Relative difference: %f' % (reldiff)) return success
def getData(self): opt = dotdict({}) # Consider returning full data opt['nx'], _ = self.data(self.index(0,0),Qt.DisplayRole).toInt() opt['dx'] = float(self.data(self.index(2,0),Qt.DisplayRole).toString()) opt['offset_x'] = float(self.data(self.index(1,0),Qt.DisplayRole).toString()) opt['nz'], _ = self.data(self.index(0,2),Qt.DisplayRole).toInt() opt['dz'] = float(self.data(self.index(2,2),Qt.DisplayRole).toString()) opt['offset_z'] = float(self.data(self.index(1,2),Qt.DisplayRole).toString()) opt['ny'], _ = self.data(self.index(0,1),Qt.DisplayRole).toInt() opt['dy'] = float(self.data(self.index(2,1),Qt.DisplayRole).toString()) opt['offset_y'] = float(self.data(self.index(1,1),Qt.DisplayRole).toString()) return opt
def __init__(self, **kwargs): opt = dotdict({'pitch0' : 0.2e-3, 'N0' : 64, 'pitch1' : 0.2e-3, 'N1' : 64, 'f0' : 7e6, 'focus' : np.r_[0.0,0.0,3.0e-2]}) opt.update(**kwargs) self._f0 = opt.f0 self._focus = opt.focus self._bandwidth = 1.0 self.N0 = opt.N0 self.pitch0 = opt.pitch0 self.N1 = opt.N1 self.pitch1 = opt.pitch1
def getData(self): opt = dotdict({}) # Consider returning full data opt['nx'], _ = self.data(self.index(0, 0), Qt.DisplayRole).toInt() opt['dx'] = float( self.data(self.index(2, 0), Qt.DisplayRole).toString()) opt['offset_x'] = float( self.data(self.index(1, 0), Qt.DisplayRole).toString()) opt['nz'], _ = self.data(self.index(0, 2), Qt.DisplayRole).toInt() opt['dz'] = float( self.data(self.index(2, 2), Qt.DisplayRole).toString()) opt['offset_z'] = float( self.data(self.index(1, 2), Qt.DisplayRole).toString()) opt['ny'], _ = self.data(self.index(0, 1), Qt.DisplayRole).toInt() opt['dy'] = float( self.data(self.index(2, 1), Qt.DisplayRole).toString()) opt['offset_y'] = float( self.data(self.index(1, 1), Qt.DisplayRole).toString()) return opt
def __init__(self,*args, **kwargs): opt = dotdict({'hw' : 0, 'hh' : 0, 'center' : [0,0,0], 'euler' : [0,0,0], 'conv' : 'yxz', 'intrinsic' : True}) opt.update(*args,**kwargs) super(rect,self).update(**opt) # Only 2 conventions are supported by Sofus conventionsSupported3 = ['yxy'] conventionsSupported2 = ['yxz', 'yxy'] if not(conventionsSupported2.count(opt.conv) > 0): raise Exception('Convention not supported') if (opt.euler[2] != 0.0): if not(conventionsSupported3.count(opt.conv) > 0): raise Exception('If convention yxz is used, z must be zero') self.center = np.array(self.center).flatten() self.euler = np.array(self.euler).flatten()
def __init__(self, *args, **kwargs): opt = dotdict({ 'hw': 0, 'hh': 0, 'center': [0, 0, 0], 'euler': [0, 0, 0], 'conv': 'yxz', 'intrinsic': True }) opt.update(*args, **kwargs) super(rect, self).update(**opt) # Only 2 conventions are supported by Sofus conventionsSupported3 = ['yxy'] conventionsSupported2 = ['yxz', 'yxy'] if not (conventionsSupported2.count(opt.conv) > 0): raise Exception('Convention not supported') if (opt.euler[2] != 0.0): if not (conventionsSupported3.count(opt.conv) > 0): raise Exception('If convention yxz is used, z must be zero') self.center = np.array(self.center).flatten() self.euler = np.array(self.euler).flatten()
def FieldAtFocusNorway(xdc, **kwargs): """ Field computed in the focal plane using the Fraunhofer approximation. This implementation is taken from Hans Torp, Trondheim. K-space is not computed properly to be used with FFT's. """ opt = dotdict({'Apod' : np.r_[0.0,0.0], # Rectangular windows 'oversampling' : 1, 'P' : None, 'rng' : np.array([0.006, 0.006, 0.0006])}) oversampling = opt.oversampling c = xdc.c # Focus distance (azimuth, elevation) - assumed equal for now Rx = xdc.focus[2] Ry = xdc.focus[2] # Diameter (azimuth, elevation) [Dx,Dy,_] = xdc.extent[:,1] - xdc.extent[:,0] # Range (x,y,z) rng = opt.rng Rxy = np.r_[Rx, Ry] R = np.mean(Rxy) [betax, betay] = opt.Apod circsymm = 1 bw = xdc.f0 * xdc.bandwidth f0 = xdc.f0 if opt.P == None: df=c/2.0/rng[2] Nf=np.round(bw/df) + 1 pData = dotdict({}) pData.f1 = np.linspace(f0 - bw/2, f0 + bw/2, Nf) # Trond W. variant - exp(x**4), -1.5 < x < 1.5 pData.P = trondwin(len(pData.f1),1.5).T res = pData.P opt.f = pData.f1 opt.P = pData.P e = None f = opt.f P = opt.P # TODO(JMH): Enable this ROCcorrection = 1 sphericalCorrection = 1 if (len(f) == 1): fmax = f[0] else: fmax = 1.1*f[-1] # Always odd number FFT (TODO: Specify freely instead of using Dx, Dy) Nx=1+2*np.round(rng[0]*fmax*Dx/R/c) Ny=1+2*np.round(rng[1]*fmax*Dy/R/c) fx=np.linspace(-fmax*Dx/R,fmax*Dx/R,Nx) fy=np.linspace(-fmax*Dy/R,fmax*Dy/R,Ny) fxi=np.linspace(-fmax*Dx/R,fmax*Dx/R,1+oversampling*(Nx-1))[None,:] fyi=np.linspace(-fmax*Dy/R,fmax*Dy/R,1+oversampling*(Ny-1))[None,:] fxm=np.dot(fxi.T,np.ones((1,fyi.shape[1]))) fym=np.dot(np.ones((fxi.shape[1],1)),fyi) # 2D low-pass filter hlp2=np.ones((oversampling,oversampling))/(oversampling)**2 P1=np.zeros((len(fx),len(fy),len(f)),dtype=np.complex128) P1i0=np.zeros((len(fxi.T),len(fyi.T)),dtype=np.complex128) # Loop over frequencies for k in range(len(f)): fxmax=0.5*Dx/R*f[k] fymax=0.5*Dy/R*f[k] Ix=np.where(np.abs(fxi)<fxmax)[1] Iy=np.where(np.abs(fyi)<fymax)[1] wx=tukeywin(len(Ix),betax) wy=tukeywin(len(Iy),betay) w=np.dot(wx[:,None],wy[None,:]) if circsymm: w=tukey2(len(Ix),betax) P1k=P1i0 P1k[Ix[0]:Ix[-1]+1,Iy[0]:Iy[-1]+1] = w*P[k] if oversampling>1: # Low-pass filter P1k=convolve2d(P1k,hlp2,'same') if ROCcorrection: Ha=apertureCorrection(R,Rxy[0],Rxy[1],f[k],fxi,fyi) P1k=P1k*Ha if sphericalCorrection: Hs=focalcorrection(R,f[k],fxi,fyi) P1u=P1k P1k=convolve2d(P1k,Hs,'same') P1k=P1k[0::oversampling,0::oversampling] # Decimation to correct sampling rate P1[:,:,k] = P1k return (P1,fx,fy,f)
def convex_array(*args, **kwargs): opt = dotdict({ 'radius': 6.1e-2, 'nElements': 192, 'nSubH': 1, # Elevation 'nSubW': 1, # Not used 'pitch': None, 'kerf': None, 'height': 1.0e-2, 'efocus': 0.02, 'sector': 60.0 / 180 * np.pi, # Redundant }) opt.updateset(**kwargs) half_width = (opt.pitch - opt.kerf) / 2.0 half_height = opt.height / 2.0 R = 1.0 focus = 1.0 bFocused = opt.efocus != None and opt.nSubH > 1 if bFocused: focus = opt.efocus elSector = 2 * np.arctan2(half_height, focus) R = np.sqrt(focus**2 + (half_height)**2) else: elSector = 0 if (opt.sector != None): dAz = opt.sector / max((opt.nElements - 1), 1) if (opt.pitch == None): # We compute a pitch based on sector size opt.pitch = 2.0 * opt.radius * np.sin(dAz / 2.0) print('pitch is %f' % opt.pitch) else: # We compute sector based on pitch opt.sector = \ (opt.nElements - 1) * 2.0 * np.arcsin(0.5 * opt.pitch / opt.radius) dAz = opt.sector / max((opt.nElements - 1), 1) azAngles = (np.r_[0:opt.nElements] - (opt.nElements - 1.0) / 2) * dAz rects = [] el = 0.0 dEl = elSector / max((opt.nSubH - 1), 1) elAngles = (np.r_[0:opt.nSubH] - (opt.nSubH - 1.0) / 2) * dEl chordLength = \ {True : 2 * focus * np.sin(dEl/2), False : opt.height}[opt.nSubH > 1] R = np.sqrt(focus**2 + (opt.height / 2.0)**2) if opt.kerf == None: opt.kerf = 0.0 half_width = (opt.pitch - opt.kerf) / 2.0 for iAz in range(opt.nElements): for iEl in range(opt.nSubH): # Center position on element center = np.r_[0, 0, opt.radius] # Candidate (no rotation is done around elevation focus) center = center + np.r_[0, focus * np.tan(elAngles[iEl]), -(R * np.cos(elAngles[iEl]) - focus)] rotm = \ euler2rot(azAngles[iAz],0,0,conv='yxz',intrinsic=True) # Rotate about origin center = np.dot(rotm, center) # Translate center = center - [0, 0, opt.radius] # Translate sub-elements rots = euler2rot(azAngles[iAz], elAngles[iEl], 0, conv='yxz', intrinsic=True) for iSubW in range(opt.nSubW): # Shift center coordinate center1 = center + 2 * half_width / opt.nSubW * rots[:, 0] * ( iSubW - (opt.nSubW - 1) / 2.0) r = rect(hw=half_width / opt.nSubW, hh=chordLength / 2.0, center=center1, euler=[azAngles[iAz], -elAngles[iEl], 0], conv='yxz', intrinsic=True) rects.append(r) elements = np.r_[[rects[i].element() for i in range(len(rects))]] elements = elements.reshape((opt.nElements, opt.nSubH * opt.nSubW, 8)) a = fnm.ApertureFloat() a.subelements = elements.astype(np.float32) return a
def convex_array3(*args, **kwargs): """ Tissue-side ceramic radius, azimuth is outer radius """ opt = dotdict({ 'radius': 6.1e-2, 'nElements': 192, 'nSubH': 1, # Elevation 'nSubW': 1, # Not used 'pitch': 2.3e-4, 'kerf': None, 'height': 1.0e-2, 'efocus': 0.0, 'elePlacement': 'Outer', }) opt.updateset(**kwargs) focus = opt.efocus if (focus == None): focus = 0.0 azR = opt.radius # Arc-length from center to center azArcLength = opt.pitch * (opt.nElements - 1.0) azSegment = azArcLength / azR dAz = azSegment / max(opt.nElements - 1.0, 1.0) azTanLength = 2.0 * azR * np.tan(dAz / 2.0) azAngles = (np.r_[0:opt.nElements] - (opt.nElements - 1.0) / 2) * dAz elR = np.sqrt(focus**2 + (opt.height / 2.0)**2) # Sector from outer edge to outer edge elSector = 2.0 * np.arctan2(opt.height / 2.0, focus) dEl = elSector / opt.nSubH elChordLength = 2.0 * elR * np.sin(dEl / 2.0) if (focus != 0.0): elTanLength = 2.0 * elR * np.tan(dEl / 2.0) else: elTanLength = opt.height / 2.0 if opt.elePlacement == 'Outer': elAngles = (np.r_[0:(opt.nSubH)] - (opt.nSubH - 1.0) / 2.0) * dEl hh = elTanLength / 2.0 else: elAngles = (np.r_[0:(opt.nSubH + 1)] - opt.nSubH / 2.0) * dEl hh = elChordLength / 2.0 hw = 0.5 * (opt.pitch - opt.kerf) #azTanLength / 2.0 rects = [] for iEl in range(opt.nSubH): # Rotation in elevation center = \ np.r_[0.0, np.sin(elAngles[iEl])*elR, -(np.cos(elAngles[iEl])*elR - elR) + azR] # focus replaced by elR for iAz in range(opt.nElements): # Rotation in azimuth rotm = \ euler2rot(azAngles[iAz],0,0,conv='yxz',intrinsic=True) # Rotate about origin center1 = np.dot(rotm, center) - np.r_[0, 0, azR] r = rect(hw=hw, hh=hh, center=center1, euler=[azAngles[iAz], elAngles[iEl], 0], conv='yxz', intrinsic=True) rects.append(r) elements = np.r_[[rects[i].element() for i in range(len(rects))]] elements = elements.reshape((opt.nElements, opt.nSubH * opt.nSubW, 8)) a = fnm.ApertureFloat() a.subelements = elements.astype(np.float32) return a
from dicts import dotdict def log_compression(img, dBrange=60): logenv = 20 * np.log10(img / img.max()) logenv[logenv < -dBrange] = -dBrange return logenv plt.ion() opt = dotdict({ 'c': 1540.0, 'fs': 25e6, 'f0': 5e6, 'fprf': 10e3, 'echo': True, 'depth_offset': 0.03, 'meanfilter': True, 'threshold_ratio': -20 }) filedir = os.path.dirname(os.path.realpath(__file__)) datadir = os.path.join(filedir, '../data/') bmodeFile = glob.glob(os.path.join(datadir, 'b*.mat'))[0] rfdata = loadmat(bmodeFile)['bdata'] rfdata = rfdata / (2.0**15)
def linear_array3(*args, **kwargs): """ Works for outer/inner radius. Outer is crazy if efocus is 0.0 """ opt = dotdict({ 'nElements': 192, 'nSubH': 1, # Elevation 'elePlacement': 'Outer', 'nSubW': 1, 'pitch': 0.2e-3, 'kerf': 0.2e-4, 'height': 1.0e-2, 'efocus': 0.0 }) opt.update(**kwargs) focus = opt.efocus R = np.sqrt(focus**2 + (opt.height / 2.0)**2) # Sector from outer edge to outer edge elSector = 2.0 * np.arctan2(opt.height / 2.0, focus) dEl = elSector / opt.nSubH hw = (opt.pitch - opt.kerf) / 2.0 chordLength = 2.0 * R * np.sin(dEl / 2.0) tanLength = 2.0 * R * np.tan(dEl / 2.0) if opt.elePlacement == 'Outer': elAngles = (np.r_[0:(opt.nSubH)] - (opt.nSubH - 1.0) / 2.0) * dEl eleSize = tanLength else: elAngles = (np.r_[0:(opt.nSubH + 1)] - opt.nSubH / 2.0) * dEl eleSize = chordLength # Sagitta (height) of the segment (not used) h = R * (1.0 - np.cos(dEl)) # Height of triangular portion (not used) d = R - h rects = [] if opt.elePlacement == 'Outer': for iElement in range(opt.nElements): for iSubH in range(opt.nSubH): center = \ np.r_[(iElement - (opt.nElements-1.0)/2)*opt.pitch, np.sin(elAngles[iSubH])*R, -(np.cos(elAngles[iSubH])*R - focus)] for iSubW in range(opt.nSubW): center1 = center + \ 2 * hw/opt.nSubW * np.r_[1,0,0] * (iSubW - (opt.nSubW-1)/2.0) r = rect(hw=hw / opt.nSubW, hh=eleSize / 2.0, center=center1, euler=[0, elAngles[iSubH], 0], conv='yxz', intrinsic=True) rects.append(r) else: for iElement in range(opt.nElements): for iSubH in range(opt.nSubH): center = \ np.r_[(iElement - (opt.nElements-1.0)/2)*opt.pitch, 0.5*(np.sin(elAngles[iSubH]) + np.sin(elAngles[iSubH+1]))*R, -(0.5*(np.cos(elAngles[iSubH]) + np.cos(elAngles[iSubH+1]))*R - focus)] for iSubW in range(opt.nSubW): center1 = center + \ 2 * hw/opt.nSubW * np.r_[1,0,0] * (iSubW - (opt.nSubW-1)/2.0) r = rect(hw=hw / opt.nSubW, hh=eleSize / 2.0, center=center1, euler=[ 0, 0.5 * (elAngles[iSubH] + elAngles[iSubH + 1]), 0 ], conv='yxz', intrinsic=True) rects.append(r) elements = np.r_[[rects[i].element() for i in range(len(rects))]] elements = elements.reshape((opt.nElements, opt.nSubH * opt.nSubW, 8)) a = fnm.ApertureFloat() a.subelements = elements.astype(np.float32) return a
def getData(self): opt = dotdict({}) for i in range(self.columnCount()): exec("opt['%s']" % (str(self.headerData(i, Qt.Horizontal, Qt.DisplayRole).toString())) + "=%s" %(self.data(self.index(0,i),Qt.DisplayRole).toString())) return opt
import numpy as np import matplotlib.pyplot as plt filedir = os.path.dirname(os.path.realpath(__file__)) sys.path.append(os.path.join(filedir, '../fnm')) from dicts import dotdict from fhfields import (FraunhoferAperture, FraunhoferField) from parula import parula_map plt.ion() opt = dotdict({'pitch0' : 0.2e-3, 'N0' : 64, 'pitch1' : 0.2e-3, 'N1' : 64, 'f0' : 7e6, 'focus' : np.r_[0.0,0.0,3.0e-2]}) xdc = FraunhoferAperture(**opt) xdc.bandwidth = 0.2 resolution = np.r_[1.000e-004, 1.000e-004, 1.0000e-005] rng = np.r_[0.003, 0.003, 0.006] opt = dotdict({'resolution' : resolution, 'rng' : rng}) [P12, fx1, fy1, f1] = FraunhoferField.FieldAtFocusNorway(xdc, **opt) [p12,xax,yax,zax] = FraunhoferField.FourierToSpaceTimeNorway(P12,fx1,fy1,f1,**opt)
def linear_array(*args,**kwargs): """ Key-value arguments: nElements, nSubH, pitch, kerf, height, focus """ opt = dotdict({'nElements' : 192, 'nSubH' : 1, # Elevation 'nSubW' : 1, 'pitch' : 0.2e-3, 'kerf' : 0.2e-4, 'height' : 1.0e-2, 'efocus' : None}) opt.update(**kwargs) half_width = (opt.pitch - opt.kerf) / 2.0 half_height = opt.height / 2.0 rects = [] focus = 1.0 R = 1.0 bFocused = opt.efocus != None and opt.nSubH > 1 if bFocused: focus = opt.efocus elSector = 2 * np.arctan2(half_height, focus) R = np.sqrt(focus**2 + (opt.height / 2.0)**2) else: elSector = 0 dEl = elSector / max((opt.nSubH-1),1) elAngles = (np.r_[0:opt.nSubH] - (opt.nSubH - 1.0)/2) * dEl if bFocused: chordLength = 2 * focus * np.sin(dEl/2) else: chordLength = opt.height/opt.nSubH for iElement in range(opt.nElements): for iSubH in range(opt.nSubH): if bFocused: center = np.r_[(iElement - (opt.nElements-1.0)/2)*opt.pitch, focus * np.tan(elAngles[iSubH]), -(R * np.cos(elAngles[iSubH]) - focus)] else: center = np.r_[(iElement - (opt.nElements-1.0)/2)*opt.pitch, (iSubH - (opt.nSubH - 1.0)/2.0)*chordLength, 0] for iSubW in range(opt.nSubW): center1 = center + 2 * half_width/opt.nSubW * np.r_[1,0,0] * (iSubW - (opt.nSubW-1)/2.0) r = rect(hw=half_width/opt.nSubW, hh=chordLength/2.0, center=center1, euler=[0,-elAngles[iSubH],0],conv='yxz',intrinsic=True) rects.append(r) elements = np.r_[[rects[i].element() for i in range(len(rects))]] elements = elements.reshape((opt.nElements, opt.nSubH * opt.nSubW, 8)) a = fnm.ApertureFloat() a.subelements = elements.astype(np.float32) return a
def linear_array3(*args, **kwargs): """ Works for outer/inner radius. Outer is crazy if efocus is 0.0 """ opt = dotdict({'nElements' : 192, 'nSubH' : 1, # Elevation 'elePlacement' : 'Outer', 'nSubW' : 1, 'pitch' : 0.2e-3, 'kerf' : 0.2e-4, 'height' : 1.0e-2, 'efocus' : 0.0}) opt.update(**kwargs) focus = opt.efocus R = np.sqrt(focus**2 + (opt.height / 2.0)**2) # Sector from outer edge to outer edge elSector = 2.0 * np.arctan2(opt.height/2.0, focus) dEl = elSector / opt.nSubH hw = (opt.pitch - opt.kerf) / 2.0 chordLength = 2.0 * R * np.sin(dEl/2.0) tanLength = 2.0 * R * np.tan(dEl/2.0) if opt.elePlacement == 'Outer': elAngles = (np.r_[0:(opt.nSubH)] - (opt.nSubH-1.0)/2.0) * dEl eleSize = tanLength else: elAngles = (np.r_[0:(opt.nSubH+1)] - opt.nSubH/2.0) * dEl eleSize = chordLength # Sagitta (height) of the segment (not used) h = R*(1.0-np.cos(dEl)) # Height of triangular portion (not used) d = R - h rects = [] if opt.elePlacement == 'Outer': for iElement in range(opt.nElements): for iSubH in range(opt.nSubH): center = \ np.r_[(iElement - (opt.nElements-1.0)/2)*opt.pitch, np.sin(elAngles[iSubH])*R, -(np.cos(elAngles[iSubH])*R - focus)] for iSubW in range(opt.nSubW): center1 = center + \ 2 * hw/opt.nSubW * np.r_[1,0,0] * (iSubW - (opt.nSubW-1)/2.0) r = rect(hw=hw/opt.nSubW, hh=eleSize/2.0, center=center1, euler=[0,elAngles[iSubH],0], conv='yxz', intrinsic=True) rects.append(r) else: for iElement in range(opt.nElements): for iSubH in range(opt.nSubH): center = \ np.r_[(iElement - (opt.nElements-1.0)/2)*opt.pitch, 0.5*(np.sin(elAngles[iSubH]) + np.sin(elAngles[iSubH+1]))*R, -(0.5*(np.cos(elAngles[iSubH]) + np.cos(elAngles[iSubH+1]))*R - focus)] for iSubW in range(opt.nSubW): center1 = center + \ 2 * hw/opt.nSubW * np.r_[1,0,0] * (iSubW - (opt.nSubW-1)/2.0) r = rect(hw=hw/opt.nSubW, hh=eleSize/2.0, center=center1, euler=[0,0.5*(elAngles[iSubH]+elAngles[iSubH+1]),0], conv='yxz', intrinsic=True) rects.append(r) elements = np.r_[[rects[i].element() for i in range(len(rects))]] elements = elements.reshape((opt.nElements, opt.nSubH * opt.nSubW, 8)) a = fnm.ApertureFloat() a.subelements = elements.astype(np.float32) return a
def convex_array(*args,**kwargs): opt = dotdict({'radius' : 6.1e-2, 'nElements' : 192, 'nSubH' : 1, # Elevation 'nSubW' : 1, # Not used 'pitch' : None, 'kerf' : None, 'height' : 1.0e-2, 'efocus' : 0.02, 'sector' : 60.0/180 * np.pi, # Redundant }) opt.updateset(**kwargs) half_width = (opt.pitch - opt.kerf) / 2.0 half_height = opt.height / 2.0 R = 1.0 focus = 1.0 bFocused = opt.efocus != None and opt.nSubH > 1 if bFocused: focus = opt.efocus elSector = 2 * np.arctan2(half_height, focus) R = np.sqrt(focus**2 + (half_height)**2) else: elSector = 0 if (opt.sector != None): dAz = opt.sector / max((opt.nElements - 1),1) if (opt.pitch == None): # We compute a pitch based on sector size opt.pitch = 2.0*opt.radius*np.sin(dAz/2.0) print('pitch is %f' % opt.pitch) else: # We compute sector based on pitch opt.sector = \ (opt.nElements - 1) * 2.0 * np.arcsin(0.5 * opt.pitch / opt.radius) dAz = opt.sector / max((opt.nElements - 1),1) azAngles = (np.r_[0:opt.nElements] - (opt.nElements - 1.0)/2) * dAz rects = [] el = 0.0 dEl = elSector / max((opt.nSubH-1),1) elAngles = (np.r_[0:opt.nSubH] - (opt.nSubH - 1.0)/2) * dEl chordLength = \ {True : 2 * focus * np.sin(dEl/2), False : opt.height}[opt.nSubH > 1] R = np.sqrt(focus**2 + (opt.height / 2.0)**2) if opt.kerf == None: opt.kerf = 0.0 half_width = (opt.pitch - opt.kerf) / 2.0 for iAz in range(opt.nElements): for iEl in range(opt.nSubH): # Center position on element center = np.r_[0,0,opt.radius] # Candidate (no rotation is done around elevation focus) center = center + np.r_[0, focus * np.tan(elAngles[iEl]), -(R * np.cos(elAngles[iEl]) - focus) ] rotm = \ euler2rot(azAngles[iAz],0,0,conv='yxz',intrinsic=True) # Rotate about origin center = np.dot(rotm,center) # Translate center = center - [0,0,opt.radius] # Translate sub-elements rots = euler2rot(azAngles[iAz],elAngles[iEl],0,conv='yxz',intrinsic=True) for iSubW in range(opt.nSubW): # Shift center coordinate center1 = center + 2 * half_width/opt.nSubW * rots[:,0] * (iSubW - (opt.nSubW-1)/2.0) r = rect(hw=half_width/opt.nSubW,hh=chordLength/2.0, center=center1, euler=[azAngles[iAz],-elAngles[iEl],0],conv='yxz',intrinsic=True) rects.append(r) elements = np.r_[[rects[i].element() for i in range(len(rects))]] elements = elements.reshape((opt.nElements, opt.nSubH * opt.nSubW, 8)) a = fnm.ApertureFloat() a.subelements = elements.astype(np.float32) return a
def __init__(self, *args, **kwargs): opt = dotdict({ 'nElements': 192, 'nSubH': 1, 'nAbcissa': [1, 1], 'pitch': 0.2e-3, 'kerf': 0.2e-4, 'height': 1.0e-2, 'c': 1540.0, 'focus': None }) opt.update(**kwargs) half_width = (opt.pitch - opt.kerf) / 2.0 half_height = opt.height / 2.0 self.rects = [] self.nElements = opt.nElements self.nSubH = opt.nSubH assert (self.nSubH % 2 == 1) focus = 1.0 R = 1.0 if (opt.focus != None): focus = opt.focus elSector = 2 * np.arctan2(half_height, focus) R = np.sqrt(focus**2 + (opt.height / 2.0)**2) else: elSector = 0 dEl = elSector / max((opt.nSubH - 1), 1) elAngles = (np.r_[0:opt.nSubH] - (opt.nSubH - 1.0) / 2) * dEl if (opt.focus != None): chordLength = 2 * focus * np.sin(dEl / 2) else: chordLength = opt.height / opt.nSubH for iElement in range(opt.nElements): for iSubH in range(opt.nSubH): if opt.focus != None: center = np.r_[(iElement - (opt.nElements - 1.0) / 2) * opt.pitch, focus * np.tan(elAngles[iSubH]), -(R * np.cos(elAngles[iSubH]) - focus)] else: center = np.r_[(iElement - (opt.nElements - 1.0) / 2) * opt.pitch, (iSubH - (opt.nSubH - 1.0) / 2.0) * chordLength, 0] for iSubW in range(1): center1 = center + 2 * half_width / 1.0 * np.r_[ 1, 0, 0] * (iSubW - (1 - 1) / 2.0) r = rect(hw=half_width / 1.0, hh=chordLength / 2.0, center=center1, euler=[0, elAngles[iSubH], 0], conv='yxz', intrinsic=True, nAbcissa=opt.nAbcissa) self.rects.append(r) self.phases = np.ones(opt.nElements, dtype=np.complex128) self.c = opt.c
import addpaths from dicts import dotdict xdc_data = dotdict({'Linear' : dotdict({'N' : int, 'width' : float, 'kerf' : float, 'pitch' : float, 'height' : float,}), 'Linear (focused)' : dotdict({'N' : int, 'width' : float, 'kerf' : float, 'pitch' : float, 'M' : int, 'height' : float, 'efocus' : float}), 'Curvelinear' : dotdict({'N' : int, 'width' : float, 'kerf' : float, 'pitch' : float, 'radius' : float, 'height' : float,}), 'Curvelinear (focused)' : dotdict({'N' : int, 'width' : float, 'kerf' : float, 'pitch' : float, 'radius' : float, 'M' : int, 'height' : float, 'efocus' : float,})}) class ElevationPlacementModel(QtCore.QAbstractListModel):
def __init__(self,*args, **kwargs): opt = dotdict({'nElements' : 192, 'nSubH' : 1, 'nAbcissa' : [1,1], 'pitch' : 0.2e-3, 'kerf' : 0.2e-4, 'height' : 1.0e-2, 'c' : 1540.0, 'focus' : None}) opt.update(**kwargs) half_width = (opt.pitch - opt.kerf) / 2.0 half_height = opt.height / 2.0 self.rects = [] self.nElements = opt.nElements self.nSubH = opt.nSubH assert(self.nSubH % 2 == 1) focus = 1.0 R = 1.0 if (opt.focus != None): focus = opt.focus elSector = 2 * np.arctan2(half_height, focus) R = np.sqrt(focus**2 + (opt.height / 2.0)**2) else: elSector = 0 dEl = elSector / max((opt.nSubH-1),1) elAngles = (np.r_[0:opt.nSubH] - (opt.nSubH - 1.0)/2) * dEl if (opt.focus != None): chordLength = 2 * focus * np.sin(dEl/2) else: chordLength = opt.height/opt.nSubH for iElement in range(opt.nElements): for iSubH in range(opt.nSubH): if opt.focus != None: center = np.r_[(iElement - (opt.nElements-1.0)/2)*opt.pitch, focus * np.tan(elAngles[iSubH]), -(R * np.cos(elAngles[iSubH]) - focus)] else: center = np.r_[(iElement - (opt.nElements-1.0)/2)*opt.pitch, (iSubH - (opt.nSubH - 1.0)/2.0)*chordLength, 0] for iSubW in range(1): center1 = center + 2 * half_width/1.0 * np.r_[1,0,0] * (iSubW - (1-1)/2.0) r = rect(hw=half_width/1.0,hh=chordLength/2.0, center=center1, euler=[0,elAngles[iSubH],0], conv='yxz', intrinsic=True, nAbcissa=opt.nAbcissa) self.rects.append(r) self.phases = np.ones(opt.nElements,dtype=np.complex128) self.c = opt.c
def convex_array3(*args,**kwargs): """ Tissue-side ceramic radius, azimuth is outer radius """ opt = dotdict({'radius' : 6.1e-2, 'nElements' : 192, 'nSubH' : 1, # Elevation 'nSubW' : 1, # Not used 'pitch' : 2.3e-4, 'kerf' : None, 'height' : 1.0e-2, 'efocus' : 0.0, 'elePlacement' : 'Outer', }) opt.updateset(**kwargs) focus = opt.efocus if (focus == None): focus = 0.0 azR = opt.radius # Arc-length from center to center azArcLength = opt.pitch * (opt.nElements-1.0) azSegment = azArcLength / azR dAz = azSegment / max(opt.nElements - 1.0,1.0) azTanLength = 2.0 * azR * np.tan(dAz/2.0) azAngles = (np.r_[0:opt.nElements] - (opt.nElements - 1.0)/2) * dAz elR = np.sqrt(focus**2 + (opt.height / 2.0)**2) # Sector from outer edge to outer edge elSector = 2.0 * np.arctan2(opt.height/2.0, focus) dEl = elSector / opt.nSubH elChordLength = 2.0 * elR * np.sin(dEl/2.0) if (focus != 0.0): elTanLength = 2.0 * elR * np.tan(dEl/2.0) else: elTanLength = opt.height / 2.0 if opt.elePlacement == 'Outer': elAngles = (np.r_[0:(opt.nSubH)] - (opt.nSubH-1.0)/2.0) * dEl hh = elTanLength / 2.0 else: elAngles = (np.r_[0:(opt.nSubH+1)] - opt.nSubH/2.0) * dEl hh = elChordLength / 2.0 hw = 0.5*(opt.pitch - opt.kerf)#azTanLength / 2.0 rects = [] for iEl in range(opt.nSubH): # Rotation in elevation center = \ np.r_[0.0, np.sin(elAngles[iEl])*elR, -(np.cos(elAngles[iEl])*elR - elR) + azR] # focus replaced by elR for iAz in range(opt.nElements): # Rotation in azimuth rotm = \ euler2rot(azAngles[iAz],0,0,conv='yxz',intrinsic=True) # Rotate about origin center1 = np.dot(rotm,center) - np.r_[0,0,azR] r = rect(hw=hw,hh=hh, center=center1, euler=[azAngles[iAz],elAngles[iEl],0],conv='yxz',intrinsic=True) rects.append(r) elements = np.r_[[rects[i].element() for i in range(len(rects))]] elements = elements.reshape((opt.nElements, opt.nSubH * opt.nSubW, 8)) a = fnm.ApertureFloat() a.subelements = elements.astype(np.float32) return a
def linear_array(*args, **kwargs): """ Key-value arguments: nElements, nSubH, pitch, kerf, height, focus """ opt = dotdict({ 'nElements': 192, 'nSubH': 1, # Elevation 'nSubW': 1, 'pitch': 0.2e-3, 'kerf': 0.2e-4, 'height': 1.0e-2, 'efocus': None }) opt.update(**kwargs) half_width = (opt.pitch - opt.kerf) / 2.0 half_height = opt.height / 2.0 rects = [] focus = 1.0 R = 1.0 bFocused = opt.efocus != None and opt.nSubH > 1 if bFocused: focus = opt.efocus elSector = 2 * np.arctan2(half_height, focus) R = np.sqrt(focus**2 + (opt.height / 2.0)**2) else: elSector = 0 dEl = elSector / max((opt.nSubH - 1), 1) elAngles = (np.r_[0:opt.nSubH] - (opt.nSubH - 1.0) / 2) * dEl if bFocused: chordLength = 2 * focus * np.sin(dEl / 2) else: chordLength = opt.height / opt.nSubH for iElement in range(opt.nElements): for iSubH in range(opt.nSubH): if bFocused: center = np.r_[(iElement - (opt.nElements - 1.0) / 2) * opt.pitch, focus * np.tan(elAngles[iSubH]), -(R * np.cos(elAngles[iSubH]) - focus)] else: center = np.r_[(iElement - (opt.nElements - 1.0) / 2) * opt.pitch, (iSubH - (opt.nSubH - 1.0) / 2.0) * chordLength, 0] for iSubW in range(opt.nSubW): center1 = center + 2 * half_width / opt.nSubW * np.r_[ 1, 0, 0] * (iSubW - (opt.nSubW - 1) / 2.0) r = rect(hw=half_width / opt.nSubW, hh=chordLength / 2.0, center=center1, euler=[0, -elAngles[iSubH], 0], conv='yxz', intrinsic=True) rects.append(r) elements = np.r_[[rects[i].element() for i in range(len(rects))]] elements = elements.reshape((opt.nElements, opt.nSubH * opt.nSubW, 8)) a = fnm.ApertureFloat() a.subelements = elements.astype(np.float32) return a
def compareWithPython(**kwargs): opt = dotdict({'show' : False, 'method' : 'CalcCwFieldRef', 'location' : 'inside'}) opt.update(**kwargs) areas = [2.0,3.0,4.0,5.0] widths = np.array([areas[0],1.0,areas[2],1.0],dtype=np.float32) heights = np.array([1.0,areas[1],1.0,areas[3]],dtype=np.float32) xsign = np.array([1.0,-1.0,-1.0,1.0],dtype=np.float32) ysign = np.array([1.0,1.0,-1.0,-1.0],dtype=np.float32) show = opt.show # Ensure that we either slightly inside or outside scale = 40.0 * np.finfo(np.float32).eps epss = dict({'inside' : -scale, 'outside' : scale}) ndiv = 2 iCorners = [0,1,2,3] eps = epss[opt.location] method = opt.method scatters = np.c_[(widths+eps)/2.0 * xsign, (heights+eps)/2.0 * ysign, np.ones(4,dtype=np.float32)] print('Testing: %s vs %s: %s' % (opt.method,'H_accurate (Python)',opt.location)) for iCorner in iCorners: a = fnm.ApertureFloat(1,float(widths[iCorner]), float(0.0), float(heights[iCorner])) a.nthreads = 1 a.nDivH = ndiv a.nDivW = ndiv a.f0 = 1 a.c = 1 if show: a.show() ax = plt.gca() ax.scatter([scatters[iCorner][0]], [scatters[iCorner][1]], [scatters[iCorner][2]],color='black',marker='o',s=20) ax.set_xlim([-widths.max(),widths.max()]) ax.set_ylim([-heights.max(),heights.max()]) ax.set_zlim([-5,5]) ax.set_aspect('equal') plt.show() exec('result = a.'+method+'([scatters[iCorner]])') r = rect(hw=widths[iCorner]/2.0,hh=heights[iCorner]/2.0,center=[0,0,0],nAbcissa=ndiv) k = 2*np.pi / (a.c / a.f0) xs = np.ones((1,1))*scatters[iCorner][0] ys = np.ones((1,1))*scatters[iCorner][1] zs = np.ones((1,1))*scatters[iCorner][2] reference = r.H_accurate(xs,ys,zs,k) assert(np.abs(reference) - np.abs(result[1]) < np.finfo(np.float32).eps) diff = np.abs(reference)-np.abs(result[1]) print('Relative difference: %f' % (diff / np.mean(np.abs(reference)+np.abs(result[1]))))
def compareWithPython(**kwargs): opt = dotdict({ 'show': False, 'method': 'CalcCwFieldRef', 'location': 'inside' }) opt.update(**kwargs) areas = [2.0, 3.0, 4.0, 5.0] widths = np.array([areas[0], 1.0, areas[2], 1.0], dtype=np.float32) heights = np.array([1.0, areas[1], 1.0, areas[3]], dtype=np.float32) xsign = np.array([1.0, -1.0, -1.0, 1.0], dtype=np.float32) ysign = np.array([1.0, 1.0, -1.0, -1.0], dtype=np.float32) show = opt.show # Ensure that we either slightly inside or outside scale = 40.0 * np.finfo(np.float32).eps epss = dict({'inside': -scale, 'outside': scale}) ndiv = 2 iCorners = [0, 1, 2, 3] eps = epss[opt.location] method = opt.method scatters = np.c_[(widths + eps) / 2.0 * xsign, (heights + eps) / 2.0 * ysign, np.ones(4, dtype=np.float32)] print('Testing: %s vs %s: %s' % (opt.method, 'H_accurate (Python)', opt.location)) for iCorner in iCorners: a = fnm.ApertureFloat(1, float(widths[iCorner]), float(0.0), float(heights[iCorner])) a.nthreads = 1 a.nDivH = ndiv a.nDivW = ndiv a.f0 = 1 a.c = 1 if show: a.show() ax = plt.gca() ax.scatter([scatters[iCorner][0]], [scatters[iCorner][1]], [scatters[iCorner][2]], color='black', marker='o', s=20) ax.set_xlim([-widths.max(), widths.max()]) ax.set_ylim([-heights.max(), heights.max()]) ax.set_zlim([-5, 5]) ax.set_aspect('equal') plt.show() exec('result = a.' + method + '([scatters[iCorner]])') r = rect(hw=widths[iCorner] / 2.0, hh=heights[iCorner] / 2.0, center=[0, 0, 0], nAbcissa=ndiv) k = 2 * np.pi / (a.c / a.f0) xs = np.ones((1, 1)) * scatters[iCorner][0] ys = np.ones((1, 1)) * scatters[iCorner][1] zs = np.ones((1, 1)) * scatters[iCorner][2] reference = r.H_accurate(xs, ys, zs, k) assert (np.abs(reference) - np.abs(result[1]) < np.finfo( np.float32).eps) diff = np.abs(reference) - np.abs(result[1]) print('Relative difference: %f' % (diff / np.mean(np.abs(reference) + np.abs(result[1]))))