def siemens_B(alpha, beta, x1, y1, z1, R0): ''' Calculate displacement field from Siemens coefficients ''' nmax = alpha.shape[0] - 1 x1 = x1 + 0.0001 # hack to avoid singularities at R=0 # convert to spherical coordinates r = np.sqrt(x1 * x1 + y1 * y1 + z1 * z1) theta = np.arccos(z1 / r) phi = np.arctan2(y1 / r, x1 / r) b = np.zeros(x1.shape) for n in xrange(0, nmax + 1): f = np.power(r / R0, n) for m in xrange(0, n + 1): f2 = alpha[n, m] * np.cos(m * phi) + beta[n, m] * np.sin(m * phi) _ptemp = utils.legendre(n, m, np.cos(theta)) #_ptemp = scipy.special.lpmv(m, n, np.cos(theta)) normfact = 1 # this is Siemens normalization if m > 0: normfact = math.pow(-1, m) * \ math.sqrt(float((2 * n + 1) * factorial(n - m)) \ / float(2 * factorial(n + m))) _p = normfact * _ptemp b = b + f * _p * f2 return b
def dixon(n): base = dixon_base(n) base = [-1] + list(filter(lambda bi: utils.legendre(n, bi) == 1, base)) h = len(base) - 1 ps = [] alphas = [] es = [] convergent = gen_convergent(gen_square_chain_fraction(n)) while len(ps) < h + 2: try: pi, qi = next(convergent) except ValueError: return None pi2 = pi**2 % n if n - pi2 < pi2: pi2 = -(n - pi2) smooth, alpha, e = is_b_smooth(pi2, base) if smooth: ps.append(pi) alphas.append(alpha) es.append(e) for ks in gaussian.gen_gaussian(es): s = 1 for k in ks: s = (s * ps[k]) % n t = 1 for b_idx, b in enumerate(base): t = (t * pow( b, functools.reduce(int.__add__, (alphas[k][b_idx] for k in ks)) // 2, n)) % n # проверка, что ks - не решение системы assert pow(s, 2, n) == pow(t, 2, n) if s != t and s != n - t: p = gcd((s - t) % n, n) return p
def ge_D(alpha, beta, x1, y1, z1): ''' GE Gradwarp coeffs define the error rather than the total gradient field''' nmax = alpha.shape[0] - 1 x1 = x1 + 0.0001 # hack to avoid singularities r = np.sqrt(x1 * x1 + y1 * y1 + z1 * z1) # For consistency with GE papers, use theta & phi -> phi & theta phi = np.arccos(z1 / r) theta = np.arctan2(y1 / r, x1 / r) r = r * 100.0 # GE wants cm, so meters -> cm d = np.zeros(x1.shape) for n in xrange(0, nmax + 1): # So GE uses the usual unnormalized legendre polys. f = np.power(r, n) for m in xrange(0, n + 1): f2 = alpha[n, m] * np.cos(m * theta) + beta[n, m] \ * np.sin(m * theta) _p = utils.legendre(n, m, np.cos(phi)) d = d + f * _p * f2 d = d / 100.0 # cm back to meters return d