class GeometryMap: """Base class for geometry map. """ def __init__(self, syms, exprs): from sympy import Array, oo if not isinstance(exprs, list) and not isinstance(exprs, Array): raise ValueError( "The ctor arg of GeometryMap -- exprs -- should be a list of sympy expressions." ) self._exprs = Array(exprs) # if not isinstance(syms, list): # raise ValueError("The ctor arg of GeometryMap -- syms -- should be a list of sympy variables, or a list of (sympy.Symbol, inf, sup)") self._syms = [] for sym in syms: if isinstance(sym, tuple): assert (len(sym) == 3) self._syms.append(sym) else: self._syms.append((sym, -oo, +oo)) @property def exprs(self): return self._exprs def expr(self, i: int): return self._exprs[i] def subs(self, *arg): return GeometryMap(self, self._exprs.subs(*arg), self._syms) @property def syms(self): return [sym[0] for sym in self._syms] def sym(self, i: int): return self._syms[i][0] @property def sym_limits(self): return [sym[1:] for sym in self._syms] def sym_limit(self, i: int): return self._syms[i][1:] @cached_property def jacobian(self): from sympy import Array return self.exprs.diff(Array(self.syms)) def lambdified(self, *arg, **kwarg): from sympy import lambdify return lambdify(self.syms, self.exprs.tolist(), *arg, **kwarg)
def create_inverse_stencil_(self): m = self.c_stencil.shape[0] K = 5 from sympy import symbols, Array,Matrix p = K >> 1 X = [] for x in range(K): Y = [] for y in range(K): Z = [] for z in range(K): s = symbols("s{}{}{}".format(x,y,z)) Z.append(s) Y.append(Z) X.append(Y) M = X for x in range(0,p+1): for y in range(0,p+1): for z in range(0,p+1): c = (p,p,p) for x_ in [-1,1]: for y_ in [-1,1]: for z_ in [-1,1]: xi = p + x_*x yi = p + y_*y zi = p + z_*z M[xi][yi][zi] = M[p-x][p-y][p-z] M = Array(M) #print(M) self.inverse_stencil = S0 u = [] for e in M: if e not in u: u.append(e) print("Degrees of freedom : {}".format(len(u))) #pad with K-1 zeros pad = 2*(K-1) C = np.zeros([m+pad,m+pad,m+pad]) C[K-1:K-1+m,K-1:K-1+m,K-1:K-1+m] = self.c_stencil N = C.shape[0] p = N >> 1 eqs = [] B = [] w = [] for i in range(N-K): for j in range(i,N-K): for k in range(j,N-K): constraint = 0 for a in range(K): for b in range(K): for c in range(K): constraint += C[i+a,j+b,k+c]*M[a,b,c] eq = [] for e in u: eq.append(constraint.diff(e)) eqs.append(eq) if i==p and j == p and k == p: B.append(1.) w.append(0.) else: B.append(0.) w.append(np.sqrt((a-K/2.)**2 + (b-K/2.)**2 + (c-K/2.)**2)) A = np.array(eqs,dtype=float) B = np.array(B,dtype=float) w = np.array(w,dtype=float) print("A : {}".format(A.shape)) x = np.linalg.pinv(A).dot(B) print(x) from scipy.optimize import minimize # w = np.exp(-w/(np.max(w)/2.)) # w[(w<0.75)*(w>0.25)] = 0 w = np.zeros(B.shape) w[B==1] = 1. w[B==0] = 1./np.sum(B==0) res = minimize(lambda x: np.sum(((A.dot(x) - B))**2),x) print(res) x = res.x M_ = M.subs({u[i]:x[i] for i in range(len(u))}) M = np.zeros([K,K,K],dtype=float) for a in range(K): for b in range(K): for c in range(K): M[a,b,c] = M_[a,b,c] M1 = self.create_inverse_stencil_() print(M) print(M1) print(M-M1) delta = np.zeros([N,N,N]) for i in range(N-K): for j in range(N-K): for k in range(N-K): constraint = 0 for a in range(K): for b in range(K): for c in range(K): delta[i,j,k] += C[i+a,j+b,k+c]*M1[a,b,c] #delta = convolve(self.c_stencil,M,mode='constant') print(delta) peak = np.max(delta) delta[delta == peak] = 0. print("Peak {} max sidelobe {}".format(peak,np.max(np.abs(delta)))) print("Peak / max sidelobe {}".format(peak/np.max(np.abs(delta))))