def _o(x0, m, n): """Overlap function between |nx> = m and |nx'> = n under translation in the x direction with the amplitude x0. Keeping the name indecently short, as this function should not be called from outside the module. Args: x0: translation amplitude. m, n: principal quantum numbers for harmonic oscillator states to compute overlap between. Note that only the relevant numbers (i.e. the ones in x direction without spin) are considered. Returns: The overlap amplitude, which is always real. """ x0_ = x0 / np.sqrt(2) ax02 = abs(x0_)**2 if m >= n: L = genlaguerre(n, m - n) return (sqrt(1 / rising_factorial(n + 1, m - n)) * (x0_**(m - n)) * exp(-ax02 / 2) * L(ax02)) else: L = genlaguerre(m, n - m) return (sqrt(1 / rising_factorial(m + 1, n - m)) * ((-x0_)**(n - m)) * exp(-ax02 / 2) * L(ax02))
def genlaguerre_array( size ): height = size width = size ret = [ [ 0 for a in range(width) ] for n in range(height) ] for a in range(width): ret[0][a] = genlaguerre(0,a) ret[1][a] = genlaguerre(1,a) for n in range(2,height): ret[n][a] = ((2*(n-1)+a+1-poly1d([1,0]))*ret[n-1][a] - \ (n-1+a)*ret[n-2][a] ) /n return ret
def derivTy(z, y, x, t): r_w_z_2_1 = (y**2 + x**2) / w1(z)**2 r_w_z_2_2 = ((z + pos(t))**2 + y**2) / w2(x)**2 lag_1 = eval_genlaguerre(p, l, 2 * r_w_z_2_1) lag_2 = eval_genlaguerre(p, l, 2 * r_w_z_2_2) return (w0 / w1(z))**2 * (2 * r_w_z_2_1)**(l - 1) * np.exp( -2 * r_w_z_2_1) * lag_1 * (4 * y / w1(z)**2) * ( (l - 2 * r_w_z_2_1) * lag_1 + 4 * r_w_z_2_1 * np.polyval(np.polyder(genlaguerre(p, l)), 2 * r_w_z_2_1) ) + (w0 / w2(x))**2 * (2 * r_w_z_2_2)**(l - 1) * np.exp( -2 * r_w_z_2_2) * lag_2 * (4 * y / w2(x)**2) * ( (l - 2 * r_w_z_2_2) * lag_2 + 4 * r_w_z_2_2 * np.polyval(np.polyder(genlaguerre(p, l)), 2 * r_w_z_2_2))
def derivTz(z, y, x, t): r_w_z_2_1 = (y**2 + x**2) / w1(z)**2 r_w_z_2_2 = ((z + pos(t))**2 + y**2) / w2(x)**2 lag_1 = eval_genlaguerre(p, l, 2 * r_w_z_2_1) lag_2 = eval_genlaguerre(p, l, 2 * r_w_z_2_2) return np.exp(-2 * r_w_z_2_1) * lag_1 * 2 * ( 2 * r_w_z_2_1)**l * la1**2 * z / np.pi**2 / w1(z)**4 * ( (-(1 + l) + 2 * r_w_z_2_1) * lag_1 - 4 * r_w_z_2_1 * np.polyval(np.polyder(genlaguerre(p, l)), 2 * r_w_z_2_1) ) + (w0 / w2(x))**2 * (2 * r_w_z_2_2)**(l - 1) * np.exp( -2 * r_w_z_2_2) * lag_2 * (4 * (z + pos(t)) / w2(x)**2) * ( (l - 2 * r_w_z_2_2) * lag_2 + 4 * r_w_z_2_2 * np.polyval(np.polyder(genlaguerre(p, l)), 2 * r_w_z_2_2))
def _wigner_laguerre(rho, xvec, yvec, g, parallel): """ Using Laguerre polynomials from scipy to evaluate the Wigner function for the density matrices :math:`|m><n|`, :math:`W_{mn}`. The total Wigner function is calculated as :math:`W = \sum_{mn} \\rho_{mn} W_{mn}`. """ M = np.prod(rho.shape[0]) X, Y = meshgrid(xvec, yvec) A = 0.5 * g * (X + 1.0j * Y) W = zeros(np.shape(A)) # compute wigner functions for density matrices |m><n| and # weight by all the elements in the density matrix B = 4 * abs(A) ** 2 if sp.isspmatrix_csr(rho.data): # for compress sparse row matrices if parallel: iterator = ( (m, rho, A, B) for m in range(len(rho.data.indptr) - 1)) W1_out = parfor(_par_wig_eval, iterator) W += sum(W1_out) else: for m in range(len(rho.data.indptr) - 1): for jj in range(rho.data.indptr[m], rho.data.indptr[m + 1]): n = rho.data.indices[jj] if m == n: W += real(rho[m, m] * (-1) ** m * genlaguerre(m, 0)(B)) elif n > m: W += 2.0 * real(rho[m, n] * (-1) ** m * (2 * A) ** (n - m) * sqrt(factorial(m) / factorial(n)) * genlaguerre(m, n - m)(B)) else: # for dense density matrices B = 4 * abs(A) ** 2 for m in range(M): if abs(rho[m, m]) > 0.0: W += real(rho[m, m] * (-1) ** m * genlaguerre(m, 0)(B)) for n in range(m + 1, M): if abs(rho[m, n]) > 0.0: W += 2.0 * real(rho[m, n] * (-1) ** m * (2 * A) ** (n - m) * sqrt(factorial(m) / factorial(n)) * genlaguerre(m, n - m)(B)) return 0.5 * W * g ** 2 * np.exp(-B / 2) / pi
def GaussLaguerre(p, l, A, w0, Fin): """ Fout = GaussLaguerre(p, l, A, w0, Fin) :ref:`Substitutes a Laguerre-Gauss mode (beam waist) in the field. <GaussLaguerre>` :math:`F_{p,l}(x,y,z=0) = A \\left(\\frac{\\rho}{2}\\right)^{\\frac{|l|}{2} }L^p_l\\left(\\rho\\right)e^{-\\frac{\\rho}{2}}\\cos(l\\theta)`, with :math:`\\rho=\\frac{2(x^2+y^2)}{w_0^2}` Args:: p, l: mode indices A: Amplitude w0: Guaussian spot size parameter in the beam waist (1/e amplitude point) Fin: input field Returns:: Fout: output field (N x N square array of complex numbers). Reference:: A. Siegman, "Lasers", p. 642 """ Fout = Field.copy(Fin) R, Phi = Fout.mgrid_polar w02 = w0 * w0 la = abs(l) rho = 2 * R * R / w02 Fout.field = A * rho**(la / 2) * genlaguerre(p, la)(rho) * _np.exp( -rho / 2) * _np.cos(l * Phi) return Fout
def polar_shapelets_refregier(N, M, beta): """ Return callable function for normalized generalized Laguerre polynomials with separated exp(-1j*M*phi) to Cos (M>0) and Sin (M<0) and ordinary radial part for M == 0 """ coeff_1, coeff_2, coeff_3 = coeff(N, M, beta) gen_laguerre = special.genlaguerre(n=(N-np.abs(M))/2, alpha=np.abs(M)) if (M > 0): laguer_N_M = lambda x, phi: coeff_1 * coeff_2 \ * x**(np.abs(M)) \ * gen_laguerre(x**2/beta**2) \ * np.exp(-x**2/2./beta**2) \ * coeff_3 * np.cos(M*phi) elif (M < 0): laguer_N_M = lambda x, phi: coeff_1 * coeff_2 \ * x**(np.abs(M)) \ * gen_laguerre(x**2/beta**2) \ * np.exp(-x**2/2./beta**2) \ * coeff_3 * np.sin(M*phi) elif (M == 0): laguer_N_M = lambda x, phi: coeff_1 * coeff_2 \ * x**(np.abs(M)) \ * gen_laguerre(x**2/beta**2) \ * np.exp(-x**2/2./beta**2) return laguer_N_M
def lambda_gen(): return lambda r: (np.sqrt( (2 * Z_ind * A / (n * au))**3 * factorial(n - l - 1) / (2 * n * factorial(n + l))) * np.exp(-Z_ind * r * A / (n * au)) * (2 * Z_ind * r * A / (n * au))**l * sc.genlaguerre(n - l - 1, l * 2 + 1) (2 * Z_ind * r * A / (n * au)))
def hyd3d(n, l, r, Z=1): """Analytical 3D hydrogenoid eigenfunctions and eigenenergies, normalized numerically.""" reduced_radius = Z * r / n aux = special.genlaguerre(n - l - 1, 2 * l + 1)(2 * reduced_radius) unl = reduced_radius**(l + 1) * np.exp(-reduced_radius) * aux Enl = -Z**2 / 2 / n**2 return unl / np.sqrt(integrate.simps(unl**2, r)), Enl
def brainsuite_shore_basis(radial_order, zeta, gtab, tau=1 / (4 * np.pi**2)): """Calculate the brainsuite shore basis functions.""" # If deltas are defined, use them try: qvals = gtab.qvals except TypeError: qvals = np.sqrt(gtab.bvals / (4 * np.pi**2 * tau)) qvals[gtab.b0s_mask] = 0 bvecs = gtab.bvecs qgradients = qvals[:, None] * bvecs r, theta, phi = cart2sphere(qgradients[:, 0], qgradients[:, 1], qgradients[:, 2]) theta[np.isnan(theta)] = 0 # Angular part of the basis - Spherical harmonics S, Z, L = real_sym_sh_brainsuite(radial_order, theta, phi) Snew = [] R = [] for n in range(radial_order + 1): for l in range(0, n + 1, 2): Snew.append(S[:, L == l]) for m in range(-l, l + 1): # Radial part R.append(genlaguerre(n - l, l + 0.5)(r ** 2 / zeta) * np.exp(- r ** 2 / (2.0 * zeta)) * _kappa(zeta, n, l) * (r ** 2 / zeta) ** (l / 2)) R = np.column_stack(R) Snew = np.column_stack(Snew) Sh = R * Snew return Sh
def shore_phi_matrix(radial_order, mu, q): '''Computed the Q matrix completely without separation into mu-depenent / -independent. See shore_Q_mu_independent for help. ''' qval, theta, phi = cart2sphere(q[:, 0], q[:, 1], q[:, 2]) theta[np.isnan(theta)] = 0 ind_mat = shore_index_matrix(radial_order) n_elem = ind_mat.shape[0] n_qgrad = q.shape[0] M = np.zeros((n_qgrad, n_elem)) counter = 0 for n in range(0, radial_order + 1, 2): for j in range(1, 2 + n / 2): l = n + 2 - 2 * j const = (-1) ** (l / 2) * np.sqrt(4.0 * np.pi) *\ (2 * np.pi ** 2 * mu ** 2 * qval ** 2) ** (l / 2) *\ np.exp(-2 * np.pi ** 2 * mu ** 2 * qval ** 2) *\ genlaguerre(j - 1, l + 0.5)(4 * np.pi ** 2 * mu ** 2 * qval ** 2) for m in range(-l, l + 1): M[:, counter] = const * real_sph_harm(m, l, theta, phi) counter += 1 return M
def LandauLevelSpinor(self, B , n , x , y ,type=1): # Symmetric Gauge def energy(n): return np.sqrt( (self.mass*self.c**2)**2 + 2*B*self.c*self.hBar*n ) K = B*( (self.X-x)**2 + (self.Y-y)**2)/( 4.*self.c*self.hBar ) psi1 = np.exp(-K)*( energy(n) + self.mass*self.c**2 )*laguerre(n)( 2*K ) psi3 = np.exp(-K)*( energy(n) - self.mass*self.c**2 )*laguerre(n)( 2*K ) if n>0: psi2 = 1j*np.exp(-K)*( self.X-x + 1j*(self.Y-y) )*genlaguerre(n-1,1)( 2*K ) else: psi2 = 0.*K psi4 = psi2 if type==1: spinor = np.array([ psi1 , 0*psi2 , 0*psi3 , psi4 ]) elif type ==2: spinor = np.array([ 0*psi1 , psi2 , psi3 , 0*psi4 ]) else : print 'Error: type spinor must be 1 or 2' norm = self.Norm(spinor) spinor /= norm return spinor
def _par_wig_eval(args): """ Private function for calculating terms of Laguerre Wigner function in parfor. """ m,rho,A,B=args W1 = zeros(shape(A)) for jj in range(rho.data.indptr[m], rho.data.indptr[m+1]): n = rho.data.indices[jj] if m == n: W1 += real(rho[m,m] * (-1)**m * genlaguerre(m,0)(B)) elif n > m: W1 += 2.0 * real(rho[m,n] * (-1)**m * (2*A)**(n-m) * \ sqrt(factorial(m)/factorial(n)) * genlaguerre(m,n-m)(B)) return W1
def shore_psi_matrix(radial_order, mu, rgrad): """Computes the K matrix without optimization. """ r, theta, phi = cart2sphere(rgrad[:, 0], rgrad[:, 1], rgrad[:, 2]) theta[np.isnan(theta)] = 0 ind_mat = shore_index_matrix(radial_order) n_elem = ind_mat.shape[0] n_rgrad = rgrad.shape[0] K = np.zeros((n_rgrad, n_elem)) counter = 0 for n in range(0, radial_order + 1, 2): for j in range(1, 2 + n / 2): l = n + 2 - 2 * j const = (-1) ** (j - 1) * \ (np.sqrt(2) * np.pi * mu ** 3) ** (-1) *\ (r ** 2 / (2 * mu ** 2)) ** (l / 2) *\ np.exp(- r ** 2 / (2 * mu ** 2)) *\ genlaguerre(j - 1, l + 0.5)(r ** 2 / mu ** 2) for m in range(-l, l + 1): K[:, counter] = const * real_sph_harm(m, l, theta, phi) counter += 1 return K
def matrix(radial_order, angular_order, zeta, gtab, tau=1 / (4 * np.pi**2)): assert (radial_order >= angular_order) NGRADS = len(gtab.bvals) q = np.sqrt(gtab.bvals / (4 * np.pi**2 * tau)) q[gtab.bvals < 40] = 0 qgradients = q[:, None] * gtab.bvecs # r, theta, phi rtp = cart_to_sphere(qgradients) rsqrz = rtp[:, 0]**2 / zeta angles = rtp[:, 1:] sh = esh.matrix(angular_order, angles) size = get_size(radial_order, angular_order) M = np.zeros((NGRADS, size)) counter = 0 for l in range(0, angular_order + 1, 2): for n in range(l, (radial_order + l) // 2 + 1): c = genlaguerre(n - l, l + 0.5)(rsqrz) * np.exp( -rsqrz / 2.0) * _kappa(zeta, n, l) * rsqrz**(l / 2) for m in range(-l, l + 1): M[:, counter] = sh[:, esh.index(l, m)] * c counter += 1 return M
def prepare_for_matrix(radial_order, angular_order, zeta, gtab, tau=1 / (4 * np.pi**2)): assert (radial_order >= angular_order) NGRADS = len(gtab.bvals) q = np.sqrt(gtab.bvals / (4 * np.pi**2 * tau)) q[gtab.bvals < 40] = 0 qgradients = q[:, None] * gtab.bvecs # r, theta, phi rtp = cart_to_sphere(qgradients) rsqrz = rtp[:, 0]**2 / zeta angles = rtp[:, 1:] sh = esh.matrix(angular_order, angles) size = get_size(radial_order, angular_order) # M = np.zeros((NGRADS, size)) f_radial = np.zeros((NGRADS, angular_order + 1, radial_order + 1)) for l in range(0, angular_order + 1, 2): for n in range(l, (radial_order + l) // 2 + 1): c = genlaguerre(n - l, l + 0.5)(rsqrz) * np.exp( -rsqrz / 2.0) * _kappa(zeta, n, l) * rsqrz**(l / 2) f_radial[:, l, n] = c return (radial_order, angular_order, zeta, tau, size, f_radial)
def hydrogen_phi_nlm(r, n, l, m, exact_factorial=False): ''' The radial part of the normalized hydrogen wavefunction, multiplied by the radial coordinate `r`. - Considered only the electron mass, instead of the reduced mass concept, which includes proton. - The atomic unit is used. ''' _a_0_star = 1.0 # the reduced Bohr radius for quantum_number in (n, l, m): assert isinstance(quantum_number, Integral) assert isinstance(exact_factorial, bool) assert (n >= 1) and (l >= 0) and (m <= l) and (m >= -l) _n, _l, _m = n, l, m _r = r _rho = 2.0 * _r / (_n * _a_0_star) _constant = np.sqrt((2.0 / (_n * _a_0_star)) * factorial(_n - _l - 1, exact=exact_factorial) / (2.0 * _n * factorial(_n + _l, exact=exact_factorial))) _result = np.exp(-_rho * 0.5) _result *= np.power(_rho, _l + 1) # `_l+1` due to multiplied `r` _result *= genlaguerre(_n - _l - 1, 2 * _l + 1, monic=False)(_rho) _result *= _constant return _result
def SHOREmatrix_pdf(radial_order, zeta, rtab): """Compute the SHORE matrix" Parameters ---------- radial_order : unsigned int, Radial Order zeta : unsigned int, scale factor rtab : array, shape (N,3) r-space points in which calculates the pdf """ r, theta, phi = cart2sphere(rtab[:, 0], rtab[:, 1], rtab[:, 2]) theta[np.isnan(theta)] = 0 psi = np.zeros( (r.shape[0], (radial_order + 1) * ((radial_order + 1) / 2) * (2 * radial_order + 1))) counter = 0 for n in range(radial_order + 1): for l in range(0, n + 1, 2): for m in range(-l, l + 1): psi[:, counter] = real_sph_harm(m, l, theta, phi) * \ genlaguerre(n - l, l + 0.5)(4 * np.pi ** 2 * zeta * r ** 2 ) *\ np.exp(-2 * np.pi ** 2 * zeta * r ** 2) *\ __kappa_pdf(zeta, n, l) *\ (4 * np.pi ** 2 * zeta * r ** 2) ** (l / 2) * \ (-1) ** (n - l / 2) counter += 1 return psi[:, 0:counter]
def derivTy(z, y, x): r_w_z_2 = (y**2 + x**2) / w(z)**2 lag = eval_genlaguerre(p, l, 2 * r_w_z_2) return (w0 / w(z))**2 * (2 * r_w_z_2)**(l - 1) * np.exp( -2 * r_w_z_2) * lag * (4 * y / w(z)**2) * ( (l - 2 * r_w_z_2) * lag + 4 * r_w_z_2 * np.polyval(np.polyder(genlaguerre(p, l)), 2 * r_w_z_2))
def wigner_mat(disps, d): """ Construct the matrix M such that M(alpha)*vec(rho) = Wigner(alpha) The matrix M will be of dimension (N, d^2) where N is the number of displacements and d is the maximum photon number. Here vec(rho) deconstructs rho into a basis of d^2 hermitian operators. The first d elements of vec(rho) are the diagonal elements of rho, the next d*(d-1)/2 elements are the real parts of the upper triangle, and the last d*(d-1)/2 elements are the imaginary parts of the upper triangle. Elements of M are then M(a, (i, j)) = <j|D(-a) P D(a) |i> with displacement operator D and parity operator P. See http://dx.doi.org/10.1103/PhysRev.177.1882, esp. eq. 7.15 """ n_disp = len(disps) n_offd = (d * (d - 1)) // 2 dm = np.zeros((n_disp, d * d)) A = disps B = 4 * abs(A) ** 2 i = 0 for m in range(d): dm[:, m] = np.real((-1) ** m * genlaguerre(m, 0)(B)) for n in range(m + 1, d): off_d = 2.0*(-1)**m * (2*A)**(n-m) * sqrt(factorial(m)/float(factorial(n))) * genlaguerre(m, n-m)(B) dm[:, d + i] = off_d.real dm[:, d + n_offd + i] = -off_d.imag i += 1 dm = np.einsum('ij,i->ij', dm, np.exp(-B / 2)) return dm
def derivTz(z, y, x): r_w_z_2 = (y**2 + x**2) / w(z)**2 lag = eval_genlaguerre(p, l, 2 * r_w_z_2) return np.exp(-2 * r_w_z_2) * lag * 2 * ( 2 * r_w_z_2)**l * la**2 * z / np.pi**2 / w(z)**4 * ( (-(1 + l) + 2 * r_w_z_2) * lag - 4 * r_w_z_2 * np.polyval(np.polyder(genlaguerre(p, l)), 2 * r_w_z_2))
def transitionAmplitude(eta, n, m): eta2 = eta * eta nl = min(n, m) ng = max(n, m) d = abs(n - m) return exp(-eta2 / 2) * pow(eta, d) * genlaguerre(nl, d)(eta2) / sqrt( factorialRatio(ng, nl)) if n >= 0 and m >= 0 else 0
def calc_mode(modes, idx, degenerate_mode, R, TH, a, alpha): m = modes.m[idx] l = modes.l[idx] aR2 = alpha * R.ravel()**2 phase = m * TH.ravel() psi = 0 # Non-zero transverse component if degenerate_mode == 'sin': # two pi/2 rotated degenerate modes for m < 0 psi = np.pi / 2 if m[idx] < 0 else 0 phase_mult = np.cos(phase + psi) elif degenerate_mode == 'exp': # noticably faster than writing exp(1j*phase) phase_mult = np.cos(phase) + 1j * np.sin(phase) amplitude = np.exp(-aR2 / 2) * aR2**(np.abs(m) / 2) * genlaguerre( l - 1, np.abs(m))(aR2) Et = phase_mult * amplitude mode = Et.astype(np.complex64) mode /= np.sqrt(np.sum(np.abs(mode)**2)) return mode
def Morse_wavefunction(r, re=2, v=1, alpha=1, A=68.8885): # default parameters Morse oscillator 1. 10.1016/j.jms.2022.111621 y = A * np.exp(-alpha * (r - re)) beta = A - 2 * v - 1 Nv = np.sqrt(alpha * beta * np.math.factorial(v) / gamma(A - v)) wf = Nv * np.exp(-y / 2) * y**(beta / 2) * genlaguerre(v, beta)(y) return wf
def lgaus(xx, yy, width): order = 4 lorder = 0 width *= xx.shape[0] * 100 r = np.sqrt(xx**2 + yy**2) laguerre = special.genlaguerre(order, lorder) return 1 * (r**lorder) * laguerre(2 * r**2 / width**2) * np.exp( -r**2 / width**2) * np.exp(1j * lorder * math.pi) #replace 1 by phi
def _par_wig_eval(args): """ Private function for calculating terms of Laguerre Wigner function using parfor. """ m, rho, A, B = args W1 = zeros(np.shape(A)) for jj in range(rho.data.indptr[m], rho.data.indptr[m + 1]): n = rho.data.indices[jj] if m == n: W1 += real(rho[m, m] * (-1)**m * genlaguerre(m, 0)(B)) elif n > m: W1 += 2.0 * real(rho[m, n] * (-1)**m * (2 * A)**(n - m) * sqrt( factorial(m) / factorial(n)) * genlaguerre(m, n - m)(B)) return W1
def radial_wave_function(r, n): const1 = np.sqrt( ((2 / (n * a_0))**3) * (np.math.factorial(n - l - 1) / (2 * n * np.math.factorial(n + l)))) const2 = genlaguerre(n - l - 1, 2 * l + 1)(2 * r / (n * a_0)) expon = np.exp(-r / (n * a_0)) other = ((2 * r) / (n * 1_0))**l return const1 * expon * other * const2
def radial_wave_function_prob(r, theta = 0, phi = 0, n=3 ): const1 = np.sqrt(((2/(n*a_0))**3)*(np.math.factorial(n-l-1)/(2*n*np.math.factorial(n+l)))) const2 = genlaguerre(n-l-1, 2*l+1)(2*r/(n*a_0)) expon = np.exp(-r/(n*a_0)) other = ((2*r)/(n*1_0))**l #f_lm = np.sqrt(np.math.factorial((2*l + 1)*(l-m))/(4*np.pi*np.math.factorial(l+m)))*lpmv(m, l, theta) #g_m = np.exp(m*phi) return ((4*np.pi*(r**2))*(const1*expon*other*const2)**2)
def compute_e0(shorefit): signal_0 = 0 for n in range(int(shorefit.model.radial_order / 2) + 1): signal_0 += shorefit.shore_coeff[n] * (genlaguerre(n, 0.5)(0) * ((factorial(n)) / (2 * np.pi * (shorefit.model.zeta ** 1.5) * gamma(n + 1.5))) ** 0.5) return signal_0
def polar_shapelets_berry(N,M, beta): coeff = coeff_berry(N,M,beta) gen_laguerre = special.genlaguerre(n = (N-np.abs(M))/2, alpha = np.abs(M)) laguer_N_M = lambda r, phi: coeff * (r/beta)**(np.abs(M)) * np.exp(-(r**2/beta**2)/2.) * gen_laguerre(r**2/beta**2) * np.exp(-1j*M*phi) return laguer_N_M
def polar_shapelets_radial(N, M, beta): coeff_1, coeff_2, coeff_3 = coeff(N, M, beta) gen_laguerre = special.genlaguerre(n=(N-np.abs(M))/2, alpha=np.abs(M)) laguer_N_M = lambda x: coeff_1 *coeff_2 * x**(np.abs(M)) \ * gen_laguerre(x**2/beta**2) * np.exp(-x**2/(2*beta**2)) return laguer_N_M
def calc_psi_z(self, v, z): alpha = 2 * (self.lam - v) - 1 psi = (z**(self.lam - v - 0.5) * np.exp(-z / 2) * genlaguerre(v, alpha)(z)) Nv = np.sqrt( factorial(v) * (2 * self.lam - 2 * v - 1) / gamma(2 * self.lam - v)) return Nv * psi
def compute_e0(shorefit): signal_0 = 0 for n in range(int(shorefit.model.radial_order / 2) + 1): signal_0 += shorefit.shore_coeff[n] * (genlaguerre(n, 0.5)(0) * ( (factorial(n)) / (2 * np.pi * (shorefit.model.zeta**1.5) * gamma(n + 1.5)))**0.5) return signal_0
def tabulate_laguerre(self): """ tabulate_laguerre() Evaluates all relevant Laguerre polynomials in all the quadrature points. Sets the table as a class/instance variable. Notes ----- The first axis is the m axis. The index is order/2, i.e. only even ms are included. The second axis is the nu axis. The index gives the degree. The third axis is the x axis. The polynomials are evaluated in the nodes of the [2 + m_max + nu_max] order Gauss Laguerre quadrature formula. """ #Shorthand for useful parameters. For convenience. m_max = self.config.m_max nu_max = self.config.nu_max X = self.quadrature_object.nodes #Initiate array. laguerre_table = zeros([ 2 * m_max + 1, m_max + nu_max + 3, self.rule_order]) for i, order in enumerate(range(0, 2 * m_max + 1, 2)): for j, degree in enumerate(range(nu_max + m_max + 3)): #Alternative 1 #TODO #Warning: This method is unstable for high degree/order. # laguerre_table[i,j,:] = genlaguerre(degree, order)(X) #------------- #Alternative 2 #More stable, but sloooow, #and (as of yet) only for m = 0. #TODO Could probably be more effective. if order == 0: for k, x in enumerate(X): p1 = 1.0 p2 = 0.0 #Loop the recurrence relation to get the Laguerre polynomial #evaluated at x. for l in range(1, degree + 1): p3 = p2 p2 = p1 p1 = ((2 * l - 1 - x) * p2 - (l - 1) * p3)/l laguerre_table[i,j,k] = p1 else: laguerre_table[i,j,:] = genlaguerre(degree, order)(X) #--------------- self.laguerre_table = laguerre_table
def polar_shapelets_real(N, M, beta): coeff_1, coeff_2 = Coeff(N, M, beta) gen_laguerre = special.genlaguerre(n=(N - np.abs(M)) / 2, alpha=np.abs(M)) Laguer_N_M = lambda x, phi: coeff_1 * coeff_2 * x**(np.abs( M)) * gen_laguerre(x**2 / beta**2) * np.exp( -x**2 / 2. / beta**2) * np.exp(-1j * M * phi).real return Laguer_N_M
def gen_lg_pattern(l, p, aux_mat, scale): """ Generate phase pattern for LG_{lp} modes, returns a matrix with dimension size x size. The width is assumed to be ''scale''*2 waist radii. """ if l == p == 0: return np.zeros_like(aux_mat[0]) rr = aux_mat[2] * scale phi = np.arctan2(aux_mat[0],aux_mat[1]) L = genlaguerre(p, l) return -l*phi + np.pi*theta(-L(2*rr**2))
def gen_R_nl(n, l, nu): """ Generates a radial eigenfunction for the Spherical Harmonic Oscillator. Used to speed up calculations. """ norm = sp.sqrt( sp.sqrt(2*nu**3/sp.pi)* 2**(n + 2*l + 3)*factorial(n, exact=True)* nu**l/factorial2(2*n + 2*l + 1, exact=True) ) laguerre = genlaguerre(n, l + .5) def R_nl(r): return norm * r**l * sp.exp(-nu * r**2) * laguerre(2*nu*r**2) return R_nl
def rtop_pdf(self): r""" Calculates the analytical return to origin probability from the pdf. """ rtop = 0 c = self._shore_coef counter = 0 for n in range(self.radial_order + 1): for l in range(0, n + 1, 2): for m in range(-l, l + 1): if l == 0: rtop += c[counter] * (-1) ** n * \ ((4 * np.pi ** 2 * self.zeta ** 1.5 * factorial(n)) / (gamma(n + 1.5))) ** 0.5 * \ genlaguerre(n, 0.5)(0) counter += 1 return rtop
def rtop_pdf(self): r""" Calculates the analytical return to origin probability (RTOP) from the pdf [1]_. References ---------- .. [1] Ozarslan E. et. al, "Mean apparent propagator (MAP) MRI: A novel diffusion imaging method for mapping tissue microstructure", NeuroImage, 2013. """ rtop = 0 c = self._shore_coef for n in range(int(self.radial_order / 2) + 1): rtop += c[n] * (-1) ** n * \ ((4 * np.pi ** 2 * self.zeta ** 1.5 * factorial(n)) / (gamma(n + 1.5))) ** 0.5 * \ genlaguerre(n, 0.5)(0) return np.clip(rtop, 0, rtop.max())
def evaluate_U(self, xi_grid, m, nu): """ result = evaluate_U(xi_grid, m, nu): Evaluates U on a grid. U is the basis function for the xi coordinate. U is defined in eq. (7) in Kamta2005. Parameters ---------- xi_grid : 1D float array, the xi values for which one wants to evaluate U. m : integer, the angular momentum projection quantum number. nu : integer, some sort of quantum number associated with U. Returns ------- result : 1D complex array, the result of the evaluation. """ #Eq. (7) in Kamta2005. #--------------------- alpha = self.config.alpha m = abs(m) #Normalization factor, N^m_nu. N = self.find_N(m, nu) #Exponential factor. exponential_factor = exp(-alpha * (xi_grid - 1)) #Generalized/associated Laguerre polynomial. # L^a_b(x) => genlaguerre(b,a)(x) # Warning! Not reliable results for higher orders. laguerre_factor = genlaguerre(nu - m, 2*m)(2*alpha * (xi_grid - 1)) #All together now. result = N * exponential_factor * (xi_grid**2 - 1)**(m/2.) * laguerre_factor return result
def hydrogenic_radial(n,l,r, Z=1): """ r assumed to be in units of Bohr """ from scipy.misc import factorial from scipy.special import genlaguerre # Messiah's L's are different from ours, so this norm is incorrect #N = (2.0 / n**2) * np.sqrt(factorial(n-l-1) / factorial(n+l)**3) # correct norm: N = (2.0/n**2) * np.sqrt(factorial(n-l-1) / factorial(n+l)) x = 2.0 * r * Z / n #L = laguerre(n-l-1, 2*l+1, x) L = genlaguerre(n-l-1, 2*l+1)(x) F = x**l * np.exp(-x/2.0) * L R = Z**(1.5) * F * N return R
def SHOREmatrix(radial_order, zeta, gtab, tau=1 / (4 * np.pi ** 2)): """Compute the SHORE matrix" Parameters ---------- radial_order : unsigned int, Radial Order zeta : unsigned int, scale factor gtab : GradientTable, Gradient directions and bvalues container class tau : float, diffusion time. By default the value that makes q=sqrt(b). """ qvals = np.sqrt(gtab.bvals / (4 * np.pi ** 2 * tau)) bvecs = gtab.bvecs qgradients = qvals[:, None] * bvecs r, theta, phi = cart2sphere( qgradients[:, 0], qgradients[:, 1], qgradients[:, 2]) theta[np.isnan(theta)] = 0 M = np.zeros( (r.shape[0], (radial_order + 1) * ((radial_order + 1) / 2) * (2 * radial_order + 1))) counter = 0 for n in range(radial_order + 1): for l in range(0, n + 1, 2): for m in range(-l, l + 1): M[:, counter] = real_sph_harm(m, l, theta, phi) * \ genlaguerre(n - l, l + 0.5)(r ** 2 / float(zeta)) * \ np.exp(- r ** 2 / (2.0 * zeta)) * \ __kappa(zeta, n, l) * \ (r ** 2 / float(zeta)) ** (l / 2) counter += 1 return M[:, 0:counter]
def fit(self, data): Lshore = l_shore(self.radial_order) Nshore = n_shore(self.radial_order) # Generate the SHORE basis M = self.cache_get('shore_matrix', key=self.gtab) if M is None: M = shore_matrix(self.radial_order, self.zeta, self.gtab, self.tau) self.cache_set('shore_matrix', self.gtab, M) # Compute the signal coefficients in SHORE basis pseudoInv = np.dot(np.linalg.inv(np.dot(M.T, M) + self.lambdaN * Nshore + self.lambdaL * Lshore), M.T) coef = np.dot(pseudoInv, data) signal_0 = 0 for n in range(int(self.radial_order / 2) + 1): signal_0 += coef[n] * genlaguerre(n, 0.5)(0) * \ ((factorial(n)) / (2 * np.pi * (self.zeta ** 1.5) * gamma(n + 1.5))) ** 0.5 coef = coef / signal_0 return ShoreFit(self, coef)
def shore_matrix_pdf(radial_order, zeta, rtab): r"""Compute the SHORE propagator matrix [1]_" Parameters ---------- radial_order : unsigned int, an even integer that represent the order of the basis zeta : unsigned int, scale factor rtab : array, shape (N,3) real space points in which calculates the pdf References ---------- .. [1] Merlet S. et. al, "Continuous diffusion signal, EAP and ODF estimation via Compressive Sensing in diffusion MRI", Medical Image Analysis, 2013. """ r, theta, phi = cart2sphere(rtab[:, 0], rtab[:, 1], rtab[:, 2]) theta[np.isnan(theta)] = 0 F = radial_order / 2 n_c = int(np.round(1 / 6.0 * (F + 1) * (F + 2) * (4 * F + 3))) psi = np.zeros((r.shape[0], n_c)) counter = 0 for l in range(0, radial_order + 1, 2): for n in range(l, int((radial_order + l) / 2) + 1): for m in range(-l, l + 1): psi[:, counter] = real_sph_harm(m, l, theta, phi) * \ genlaguerre(n - l, l + 0.5)(4 * np.pi ** 2 * zeta * r ** 2) *\ np.exp(-2 * np.pi ** 2 * zeta * r ** 2) *\ _kappa_pdf(zeta, n, l) *\ (4 * np.pi ** 2 * zeta * r ** 2) ** (l / 2) * \ (-1) ** (n - l / 2) counter += 1 return psi
def test_d_U(): """ When caluculating the matrix elements for the electronic hamiltonian, or more specifically in eq. (A6) in Kamta2005, the differentiation of U makes an appearance. Analytical formulas for dU and d2U are shown in the note A_6.pdf in the Documentation folder. This method checks the validity of these formulas, using numerical differentiation for comparison. """ basis = psc_basis.PSC_basis(m = 6, nu = 6, mu = 5, R = 2.0, beta = 0.8, theta= pi/6.) dxi = .05 #An extra point, since one will be lost. xi = r_[1:10 + 2 * dxi:dxi] m = abs(4) nu = 5 alpha = basis.config.alpha #Alternative variable. X = 2 * alpha * (xi - 1) #Evaluation of U. U_num = basis.evaluate_U(xi, m, nu) #Analytical U U = basis.find_N(m,nu) * exp(-alpha * (xi - 1)) * (xi**2 - 1)**(abs(m)/2.) * genlaguerre(nu - abs(m), 2 * abs(m))(2 * alpha * (xi - 1)) #single diff. #------------------------------------------------------- #Numerical differentiation. dU_num = (U_num[2:] - U_num[:-2])/(2. * dxi) L_0 = genlaguerre(nu - abs(m) + 0, 2 * abs(m))(2. * alpha * (xi-1)) L_1 = genlaguerre(nu - abs(m) + 1, 2 * abs(m))(2. * alpha * (xi-1)) L_2 = genlaguerre(nu - abs(m) + 2, 2 * abs(m))(2. * alpha * (xi-1)) N = basis.find_N(m,nu) #Analytical differentiation, 2nd formula. dU = N * exp(- alpha * (xi - 1.)) * (xi**2. - 1.)**(abs(m)/2.) * ( (alpha - abs(m)/(xi**2. - 1.) - (nu + 1.)/(xi-1)) * L_0 + (nu - abs(m) + 1)/(xi - 1.) * L_1) #Analytical differentiation, X formula. dU_X = N * exp(-0.5 * X) * (X/(2* alpha))**(abs(m)/2.) * (X/(2* alpha) + 2)**(abs(m)/2.) * ( (alpha - 4* alpha**2 * abs(m)/(X*(X + 4*alpha)) - 2* alpha*(nu + 1.)/X) * L_0 + 2 * alpha * (nu - abs(m) + 1)/X * L_1) #double diff. #------------------------------------------------------ #Numerical differentiation. d2U_num = (U_num[2:] - 2*U_num[1:-1] + U_num[:-2])/(dxi**2) #Diff of this : N * exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2) * [ # (alpha - m/(xi**2 - 1) - (nu + 1)/(xi - 1)) * L_0 # + (nu - m + 1)/(xi-1) * L_1 # ] # #Analytical differentiation. # d2U = N * exp(-alpha * (xi - 1)) * (xi**2 - 1)**(m/2.) * ( # ( # alpha * ( # alpha # + m * xi / (xi**2 - 1) # - (nu + m + 1) / (xi - 1)) # - m * ( # alpha / (xi**2 - 1) # - ((nu + 3) * (xi + 1) - 2 + m)/(xi**2 - 1)**2) # - (nu + 1) * ( # alpha / (xi - 1) # + (m - 1)/(xi - 1)**2 # - m / ((xi**2 - 1)*(xi - 1)) # - (nu + m + 1) / (xi - 1)**2) # ) * L_0 # + # ( # (nu - m + 1) * ( # alpha / (xi - 1) # - m/((xi**2 - 1) * (xi - 1)) # - (nu + 1) / (xi - 1)**2 # + alpha / (xi - 1) # + (m - 1)/(xi - 1)**2 # - m / ((xi**2 - 1)*(xi - 1)) # - (nu + m + 2) / (xi - 1)**2 ) # ) * L_1 # + # ( # (nu - m + 1) * (nu - m + 2) / (xi - 1)**2 # ) * L_2 # ) #Analytical differentiation. d2U_simplified = N * exp(-alpha * (xi - 1)) * (xi**2 - 1)**(m/2.) * ( ( ( alpha**2 + alpha * m / (xi + 1) - alpha * (2 * nu + m + 2) / (xi - 1)) + m * (m - 2)/ (xi**2 - 1)**2 + (nu + 1) * (nu + 2) / (xi - 1)**2 + 2 * m * (nu + 2) / ((xi**2 - 1)*(xi - 1)) ) * L_0 + ( 2 * (nu - m + 1) * ( alpha / (xi - 1) - (nu + 2) / (xi - 1)**2 - m / ((xi**2 - 1)*(xi - 1))) ) * L_1 + ( (nu - m + 1) * (nu - m + 2) / (xi - 1)**2 ) * L_2 ) d2U_X = N * exp(-X/2) * (X/(2*alpha))**(m/2.) *(X/(2*alpha) + 2)**(m/2.) * ( ( alpha**2 + 2* alpha**2 * m / (X + 4*alpha) - 2 * alpha**2 * (2 * nu + m + 2) / X + 16 * alpha**4 * m * (m - 2)/ (X**2* (X + 4*alpha)**2) + 4 * alpha**2 * (nu + 1) * (nu + 2) / X**2 + 16 * alpha**3 * m * (nu + 2) / (X**2*(X + 4*alpha)) ) * L_0 + ( 4 * alpha * (nu - m + 1) * ( alpha / X - 2 * alpha * (nu + 2) / X**2 - 4 * alpha**2 * m / (X**2 * (X + 4 * alpha))) ) * L_1 + ( 4 * alpha **2 * (nu - m + 1) * (nu - m + 2) / X**2 ) * L_2 ) #Plotting result. figure() plot(X[1:-1], dU_num, X[1:-1], dU[1:-1], X[1:-1], dU_X[1:-1]) show() figure() plot(X[1:-1], d2U_num, X[1:-1], d2U_X[1:-1], X[1:-1], d2U_simplified[1:-1] ) show()
def R(n, l, r): assert n > l a0 = 0.3 return (2 * r / n / a0) ** l * exp(-r / n / a0) * genlaguerre(n - l - 1, 2 * l + 1)(2 * r / n / a0)
def R_nl(n, l, nu, r): norm = sp.sqrt( sp.sqrt(2 * nu ** 3 / sp.pi) * 2 ** (n + 2 * l + 3) * factorial(n) * nu ** l / factorial2(2 * n + 2 * l + 1) ) lagge = genlaguerre(n, l + 0.5)(2 * nu * r ** 2) return norm * r ** l * sp.e ** (-nu * r ** 2) * lagge
def fit(self, data): Lshore = l_shore(self.radial_order) Nshore = n_shore(self.radial_order) # Generate the SHORE basis M = self.cache_get('shore_matrix', key=self.gtab) if M is None: M = shore_matrix(self.radial_order, self.zeta, self.gtab, self.tau) self.cache_set('shore_matrix', self.gtab, M) MpseudoInv = self.cache_get('shore_matrix_reg_pinv', key=self.gtab) if MpseudoInv is None: MpseudoInv = np.dot(np.linalg.inv(np.dot(M.T, M) + self.lambdaN * Nshore + self.lambdaL * Lshore), M.T) self.cache_set('shore_matrix_reg_pinv', self.gtab, MpseudoInv) # Compute the signal coefficients in SHORE basis if not self.constrain_e0: coef = np.dot(MpseudoInv, data) signal_0 = 0 for n in range(int(self.radial_order / 2) + 1): signal_0 += ( coef[n] * (genlaguerre(n, 0.5)(0) * ( (factorial(n)) / (2 * np.pi * (self.zeta ** 1.5) * gamma(n + 1.5)) ) ** 0.5) ) coef = coef / signal_0 else: data = data / data[self.gtab.b0s_mask].mean() if cvxopt is not None: # If cvxopt is not available use scipy (~100 times slower) M0 = M[self.gtab.b0s_mask, :] M0_mean = M0.mean(0)[None, :] Mprime = np.r_[M0_mean, M[~self.gtab.b0s_mask, :]] Q = cvxopt.matrix(np.ascontiguousarray( np.dot(Mprime.T, Mprime) + self.lambdaN * Nshore + self.lambdaL * Lshore )) data_b0 = data[self.gtab.b0s_mask].mean() data_single_b0 = np.r_[data_b0, data[~self.gtab.b0s_mask]] / data_b0 p = cvxopt.matrix(np.ascontiguousarray( -1 * np.dot(Mprime.T, data_single_b0)) ) cvxopt.solvers.options['show_progress'] = False G = None h = None A = cvxopt.matrix(np.ascontiguousarray(M0_mean)) b = cvxopt.matrix(np.array([1.])) sol = cvxopt.solvers.qp(Q, p, G, h, A, b) if sol['status'] != 'optimal': warn('Optimization did not find a solution') coef = np.array(sol['x'])[:, 0] else: raise ValueError('CVXOPT package needed to enforce constraints') return ShoreFit(self, coef)
def test_shore_metrics(): gtab = get_gtab_taiwan_dsi() mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003])) angl = [(0, 0), (60, 0)] S, sticks = MultiTensor(gtab, mevals, S0=100.0, angles=angl, fractions=[50, 50], snr=None) # test shore_indices n = 7 l = 6 m = -4 radial_order, c = shore_order(n, l, m) n2, l2, m2 = shore_indices(radial_order, c) assert_equal(n, n2) assert_equal(l, l2) assert_equal(m, m2) radial_order = 6 c = 41 n, l, m = shore_indices(radial_order, c) radial_order2, c2 = shore_order(n, l, m) assert_equal(radial_order, radial_order2) assert_equal(c, c2) # since we are testing without noise we can use higher order and lower lambdas, with respect to the default. radial_order = 8 zeta = 700 lambdaN = 1e-12 lambdaL = 1e-12 asm = ShoreModel(gtab, radial_order=radial_order, zeta=zeta, lambdaN=lambdaN, lambdaL=lambdaL) asmfit = asm.fit(S) c_shore = asmfit.shore_coeff cmat = shore_matrix(radial_order, zeta, gtab) S_reconst = np.dot(cmat, c_shore) # test the signal reconstruction S = S / S[0] nmse_signal = np.sqrt(np.sum((S - S_reconst) ** 2)) / (S.sum()) assert_almost_equal(nmse_signal, 0.0, 4) # test if the analytical integral of the pdf is equal to one integral = 0 for n in range(int((radial_order)/2 +1)): integral += c_shore[n] * (np.pi**(-1.5) * zeta **(-1.5) * genlaguerre(n,0.5)(0)) ** 0.5 assert_almost_equal(integral, 1.0, 10) # test if the integral of the pdf calculated on a discrete grid is equal to one pdf_discrete = asmfit.pdf_grid(17, 40e-3) integral = pdf_discrete.sum() assert_almost_equal(integral, 1.0, 1) # compare the shore pdf with the ground truth multi_tensor pdf sphere = get_sphere('symmetric724') v = sphere.vertices radius = 10e-3 pdf_shore = asmfit.pdf(v * radius) pdf_mt = multi_tensor_pdf(v * radius, mevals=mevals, angles=angl, fractions= [50, 50]) nmse_pdf = np.sqrt(np.sum((pdf_mt - pdf_shore) ** 2)) / (pdf_mt.sum()) assert_almost_equal(nmse_pdf, 0.0, 2) # compare the shore rtop with the ground truth multi_tensor rtop rtop_shore_signal = asmfit.rtop_signal() rtop_shore_pdf = asmfit.rtop_pdf() assert_almost_equal(rtop_shore_signal, rtop_shore_pdf, 9) rtop_mt = multi_tensor_rtop([.5, .5], mevals=mevals) assert_equal(rtop_mt / rtop_shore_signal <1.10 and rtop_mt / rtop_shore_signal > 0.95, True) # compare the shore msd with the ground truth multi_tensor msd msd_mt = multi_tensor_msd([.5, .5], mevals=mevals) msd_shore = asmfit.msd() assert_equal(msd_mt / msd_shore < 1.05 and msd_mt / msd_shore > 0.95, True)
def shore_matrix(radial_order, zeta, gtab, tau=1 / (4 * np.pi ** 2)): r"""Compute the SHORE matrix for modified Merlet's 3D-SHORE [1]_ ..math:: :nowrap: \begin{equation} \textbf{E}(q\textbf{u})=\sum_{l=0, even}^{N_{max}} \sum_{n=l}^{(N_{max}+l)/2} \sum_{m=-l}^l c_{nlm} \phi_{nlm}(q\textbf{u}) \end{equation} where $\phi_{nlm}$ is ..math:: :nowrap: \begin{equation} \phi_{nlm}^{SHORE}(q\textbf{u})=\Biggl[\dfrac{2(n-l)!} {\zeta^{3/2} \Gamma(n+3/2)} \Biggr]^{1/2} \Biggl(\dfrac{q^2}{\zeta}\Biggr)^{l/2} exp\Biggl(\dfrac{-q^2}{2\zeta}\Biggr) L^{l+1/2}_{n-l} \Biggl(\dfrac{q^2}{\zeta}\Biggr) Y_l^m(\textbf{u}). \end{equation} Parameters ---------- radial_order : unsigned int, an even integer that represent the order of the basis zeta : unsigned int, scale factor gtab : GradientTable, gradient directions and bvalues container class tau : float, diffusion time. By default the value that makes q=sqrt(b). References ---------- .. [1] Merlet S. et. al, "Continuous diffusion signal, EAP and ODF estimation via Compressive Sensing in diffusion MRI", Medical Image Analysis, 2013. """ qvals = np.sqrt(gtab.bvals / (4 * np.pi ** 2 * tau)) qvals[gtab.b0s_mask] = 0 bvecs = gtab.bvecs qgradients = qvals[:, None] * bvecs r, theta, phi = cart2sphere(qgradients[:, 0], qgradients[:, 1], qgradients[:, 2]) theta[np.isnan(theta)] = 0 F = radial_order / 2 n_c = int(np.round(1 / 6.0 * (F + 1) * (F + 2) * (4 * F + 3))) M = np.zeros((r.shape[0], n_c)) counter = 0 for l in range(0, radial_order + 1, 2): for n in range(l, int((radial_order + l) / 2) + 1): for m in range(-l, l + 1): M[:, counter] = real_sph_harm(m, l, theta, phi) * \ genlaguerre(n - l, l + 0.5)(r ** 2 / zeta) * \ np.exp(- r ** 2 / (2.0 * zeta)) * \ _kappa(zeta, n, l) * \ (r ** 2 / zeta) ** (l / 2) counter += 1 return M
def fit(self, data): Lshore = l_shore(self.radial_order) Nshore = n_shore(self.radial_order) # Generate the SHORE basis M = self.cache_get('shore_matrix', key=self.gtab) if M is None: M = shore_matrix( self.radial_order, self.zeta, self.gtab, self.tau) self.cache_set('shore_matrix', self.gtab, M) MpseudoInv = self.cache_get('shore_matrix_reg_pinv', key=self.gtab) if MpseudoInv is None: MpseudoInv = np.dot( np.linalg.inv(np.dot(M.T, M) + self.lambdaN * Nshore + self.lambdaL * Lshore), M.T) self.cache_set('shore_matrix_reg_pinv', self.gtab, MpseudoInv) # Compute the signal coefficients in SHORE basis if not self.constrain_e0: coef = np.dot(MpseudoInv, data) signal_0 = 0 for n in range(int(self.radial_order / 2) + 1): signal_0 += ( coef[n] * (genlaguerre(n, 0.5)(0) * ( (factorial(n)) / (2 * np.pi * (self.zeta ** 1.5) * gamma(n + 1.5)) ) ** 0.5) ) coef = coef / signal_0 else: data_norm = data / data[self.gtab.b0s_mask].mean() M0 = M[self.gtab.b0s_mask, :] c = cvxpy.Variable(M.shape[1]) design_matrix = cvxpy.Constant(M) objective = cvxpy.Minimize( cvxpy.sum_squares(design_matrix * c - data_norm) + self.lambdaN * cvxpy.quad_form(c, Nshore) + self.lambdaL * cvxpy.quad_form(c, Lshore) ) if not self.positive_constraint: constraints = [M0[0] * c == 1] else: lg = int(np.floor(self.pos_grid ** 3 / 2)) v, t = create_rspace(self.pos_grid, self.pos_radius) psi = self.cache_get( 'shore_matrix_positive_constraint', key=(self.pos_grid, self.pos_radius) ) if psi is None: psi = shore_matrix_pdf( self.radial_order, self.zeta, t[:lg]) self.cache_set( 'shore_matrix_positive_constraint', (self.pos_grid, self.pos_radius), psi) constraints = [M0[0] * c == 1., psi * c > 1e-3] prob = cvxpy.Problem(objective, constraints) try: prob.solve(solver=self.cvxpy_solver) coef = np.asarray(c.value).squeeze() except: warn('Optimization did not find a solution') coef = np.zeros(M.shape[1]) return ShoreFit(self, coef)
def transitionAmplitude(eta, n, m): eta2 = eta*eta nl = min(n, m) ng = max(n, m) d = abs(n-m) return exp(-eta2/2) * pow(eta, d) * genlaguerre(nl, d)(eta2) / sqrt( factorialRatio(ng, nl ) ) if n>=0 and m>=0 else 0
def test_L0(): basis = psc_basis.PSC_basis(m = 6, nu = 6, mu = 5, R = 2.0, beta = 0.8, theta= pi/6.) dxi = .05 #An extra point, since one will be lost. xi = r_[1:10 + 2 * dxi:dxi] m = abs(4) nu = 5 alpha = basis.config.alpha N = basis.find_N(m,nu) L_0 = genlaguerre(nu - abs(m) + 0, 2 * abs(m))(2. * alpha * (xi-1)) L_1 = genlaguerre(nu - abs(m) + 1, 2 * abs(m))(2. * alpha * (xi-1)) L_2 = genlaguerre(nu - abs(m) + 2, 2 * abs(m))(2. * alpha * (xi-1)) #Part 1 : exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2) * alpha * L_0 #---------------------------------------------------------- #Numerical expression. U_num = exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2) * alpha * L_0 #Numerical differentiation. dU_num = (U_num[2:] - U_num[:-2])/(2. * dxi) #Analytical differentiation. dU = exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2) * ( ( alpha**2 + alpha * m * xi / (xi**2 - 1) - alpha * (nu + m + 1) / (xi - 1) ) * L_0 + ( alpha * (nu - m + 1) / (xi - 1) ) * L_1 ) #OK! #---------------------------------------------------------- #Part 2 : - exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2) * m/(xi**2 - 1) * L_0 #---------------------------------------------------------- #Numerical expression. U_num = - exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2) * m/(xi**2 - 1) * L_0 #Numerical differentiation. dU_num += (U_num[2:] - U_num[:-2])/(2. * dxi) #Analytical differentiation. # dU = - m * exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2) * ( # ( # - alpha / (xi**2 - 1) # + 2 * (m/2. - 1) * xi / (xi**2 - 1)**2 # - (nu + m + 1 - 2* alpha * (xi - 1))/((xi**2 - 1) * (xi - 1)) # ) * L_0 # + # (nu - m + 1)/((xi**2 - 1) * (xi - 1)) * L_1 # ) #Analytical differentiation, simplified. dU += - m * exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2) * ( ( + alpha / (xi**2 - 1) - ((nu + 3) * (xi + 1) - 2 + m)/(xi**2 - 1)**2 ) * L_0 + (nu - m + 1)/((xi**2 - 1) * (xi - 1)) * L_1 ) #OK! #---------------------------------------------------------- #Part 3 : - exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2) * (nu + 1)/(xi-1) * L_0 #---------------------------------------------------------- #Numerical expression. U_num = - exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2) * (nu + 1)/(xi-1) * L_0 #Numerical differentiation. dU_num += (U_num[2:] - U_num[:-2])/(2. * dxi) #Analytical differentiation. dU += - (nu + 1) * exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2.) * ( ( + alpha / (xi - 1) + (m - 1)/(xi - 1)**2 - m / ((xi**2 - 1)*(xi - 1)) - (nu + m + 1) / (xi - 1)**2 ) * L_0 + (nu - m + 1) / (xi - 1)**2 * L_1 ) #OK! #---------------------------------------------------------- #Part 4 : exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2) * (nu - m + 1)/(xi-1) * L_1 #---------------------------------------------------------- #Numerical expression. U_num = exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2) * (nu -m + 1)/(xi-1) * L_1 #Numerical differentiation. dU_num += (U_num[2:] - U_num[:-2])/(2. * dxi) #Analytical differentiation. dU += (nu - m + 1) * exp(-alpha*(xi - 1)) * (xi**2 - 1)**(m/2.) * ( ( + alpha / (xi - 1) + (m - 1)/(xi - 1)**2 - m / ((xi**2 - 1)*(xi - 1)) - (nu + m + 2) / (xi - 1)**2 ) * L_1 + (nu - m + 2) / (xi - 1)**2 * L_2 ) #OK! #---------------------------------------------------------- #Analytical differentiation. d2U = N * exp(-alpha * (xi - 1)) * (xi**2 - 1)**(m/2.) * ( ( alpha * ( alpha + m * xi / (xi**2 - 1) - (nu + m + 1) / (xi - 1)) - m * ( alpha / (xi**2 - 1) - ((nu + 3) * (xi + 1) - 2 + m)/(xi**2 - 1)**2) - (nu + 1) * ( alpha / (xi - 1) + (m - 1)/(xi - 1)**2 - m / ((xi**2 - 1)*(xi - 1)) - (nu + m + 1) / (xi - 1)**2) ) * L_0 + ( (nu - m + 1) * ( alpha / (xi - 1) - m/((xi**2 - 1) * (xi - 1)) - (nu + 1) / (xi - 1)**2 + alpha / (xi - 1) + (m - 1)/(xi - 1)**2 - m / ((xi**2 - 1)*(xi - 1)) - (nu + m + 2) / (xi - 1)**2 ) ) * L_1 + ( (nu - m + 1) *(nu - m + 2) / (xi - 1)**2 ) * L_2 ) #Plotting result. figure() plot(xi[1:-1], N * dU_num, xi[1:-1], N * dU[1:-1],xi[1:-1], d2U[1:-1] ) show()
def fit(self, data): Lshore = l_shore(self.radial_order) Nshore = n_shore(self.radial_order) # Generate the SHORE basis M = self.cache_get('shore_matrix', key=self.gtab) if M is None: M = shore_matrix( self.radial_order, self.zeta, self.gtab, self.tau) self.cache_set('shore_matrix', self.gtab, M) MpseudoInv = self.cache_get('shore_matrix_reg_pinv', key=self.gtab) if MpseudoInv is None: MpseudoInv = np.dot( np.linalg.inv(np.dot(M.T, M) + self.lambdaN * Nshore + self.lambdaL * Lshore), M.T) self.cache_set('shore_matrix_reg_pinv', self.gtab, MpseudoInv) # Compute the signal coefficients in SHORE basis if not self.constrain_e0: coef = np.dot(MpseudoInv, data) signal_0 = 0 for n in range(int(self.radial_order / 2) + 1): signal_0 += ( coef[n] * (genlaguerre(n, 0.5)(0) * ( (factorial(n)) / (2 * np.pi * (self.zeta ** 1.5) * gamma(n + 1.5)) ) ** 0.5) ) coef = coef / signal_0 else: data = data / data[self.gtab.b0s_mask].mean() # If cvxopt is not available, bail (scipy is ~100 times slower) if not have_cvxopt: raise ValueError( 'CVXOPT package needed to enforce constraints') w_s = "The implementation of SHORE depends on CVXOPT " w_s += " (http://cvxopt.org/). This software is licensed " w_s += "under the GPL (see: http://cvxopt.org/copyright.html) " w_s += " and you may be subject to this license when using SHORE." warn(w_s) M0 = M[self.gtab.b0s_mask, :] M0_mean = M0.mean(0)[None, :] Mprime = np.r_[M0_mean, M[~self.gtab.b0s_mask, :]] Q = cvxopt.matrix(np.ascontiguousarray( np.dot(Mprime.T, Mprime) + self.lambdaN * Nshore + self.lambdaL * Lshore )) data_b0 = data[self.gtab.b0s_mask].mean() data_single_b0 = np.r_[ data_b0, data[~self.gtab.b0s_mask]] / data_b0 p = cvxopt.matrix(np.ascontiguousarray( -1 * np.dot(Mprime.T, data_single_b0)) ) cvxopt.solvers.options['show_progress'] = False if not(self.positive_constraint): G = None h = None else: lg = int(np.floor(self.pos_grid ** 3 / 2)) G = self.cache_get( 'shore_matrix_positive_constraint', key=(self.pos_grid, self.pos_radius)) if G is None: v, t = create_rspace(self.pos_grid, self.pos_radius) psi = shore_matrix_pdf( self.radial_order, self.zeta, t[:lg]) G = cvxopt.matrix(-1 * psi) self.cache_set( 'shore_matrix_positive_constraint', (self.pos_grid, self.pos_radius), G) h = cvxopt.matrix((1e-10) * np.ones((lg)), (lg, 1)) A = cvxopt.matrix(np.ascontiguousarray(M0_mean)) b = cvxopt.matrix(np.array([1.])) sol = cvxopt.solvers.qp(Q, p, G, h, A, b) if sol['status'] != 'optimal': warn('Optimization did not find a solution') coef = np.array(sol['x'])[:, 0] return ShoreFit(self, coef)
def laguerre(n0,m0): """Return a generalized Laguerre polynomial L^(|m|)_((n-|m|)/2)(x)""" l0=special.genlaguerre(n=(n0-np.abs(m0))/2,alpha=np.abs(m0)) return l0