def geodetic2isometric(geodetic_lat: ndarray, ell: Ellipsoid = None, deg: bool = True) -> float: """ computes isometric latitude on an ellipsoid like Matlab map.geodesy.IsometricLatitudeConverter.forward() Parameters ---------- lat : float geodetic latitude ell : Ellipsoid, optional reference ellipsoid (default WGS84) deg : bool, optional degrees input/output (False: radians in/out) Returns ------- isolat : float isometric latiude Notes ----- Isometric latitude is an auxiliary latitude proportional to the spacing of parallels of latitude on an ellipsoidal mercator projection. Based on Deakin, R.E., 2010, 'The Loxodrome on an Ellipsoid', Lecture Notes, School of Mathematical and Geospatial Sciences, RMIT University, January 2010 """ geodetic_lat, ell = sanitize(geodetic_lat, ell, deg) e = ell.eccentricity isometric_lat = asinh(tan(geodetic_lat)) - e * atanh(e * sin(geodetic_lat)) # same results # a1 = e * sin(geodetic_lat) # y = (1 - a1) / (1 + a1) # a2 = pi / 4 + geodetic_lat / 2 # isometric_lat = log(tan(a2) * (y ** (e / 2))) # isometric_lat = log(tan(a2)) + e/2 * log((1-e*sin(geodetic_lat)) / (1+e*sin(geodetic_lat))) try: isometric_lat[abs(geodetic_lat - pi / 2) <= 1e-9] = inf isometric_lat[abs(-geodetic_lat - pi / 2) <= 1e-9] = -inf except TypeError: if abs(geodetic_lat - pi / 2) <= 1e-9: isometric_lat = inf elif abs(-geodetic_lat - pi / 2) <= 1e-9: isometric_lat = -inf return degrees(isometric_lat) if deg else isometric_lat
def geodetic2isometric_point(geodetic_lat: float, ell: Ellipsoid = None, deg: bool = True) -> float: geodetic_lat, ell = sanitize(geodetic_lat, ell, deg) e = ell.eccentricity if abs(geodetic_lat - pi / 2) <= 1e-9: isometric_lat = inf elif abs(-geodetic_lat - pi / 2) <= 1e-9: isometric_lat = -inf else: isometric_lat = asinh( tan(geodetic_lat)) - e * atanh(e * sin(geodetic_lat)) # same results # a1 = e * sin(geodetic_lat) # y = (1 - a1) / (1 + a1) # a2 = pi / 4 + geodetic_lat / 2 # isometric_lat = log(tan(a2) * (y ** (e / 2))) # isometric_lat = log(tan(a2)) + e/2 * log((1-e*sin(geodetic_lat)) / (1+e*sin(geodetic_lat))) return degrees(isometric_lat) if deg else isometric_lat
def test_unary_fun(self): import math data = [1., 2., 3.] c = np.array(data) d = np.acos(c / 3) for i, ei in enumerate(d): self.assertEqual(ei, math.acos(data[i] / 3)) d = np.asin(c / 3) for i, ei in enumerate(d): self.assertEqual(ei, math.asin(data[i] / 3)) d = np.atan(c) for i, ei in enumerate(d): self.assertEqual(ei, math.atan(data[i])) d = np.sin(c) for i, ei in enumerate(d): self.assertEqual(ei, math.sin(data[i])) d = np.cos(c) for i, ei in enumerate(d): self.assertEqual(ei, math.cos(data[i])) d = np.tan(c) for i, ei in enumerate(d): self.assertEqual(ei, math.tan(data[i])) d = np.acosh(c) for i, ei in enumerate(d): self.assertEqual(ei, math.acosh(data[i])) d = np.asinh(c) for i, ei in enumerate(d): self.assertEqual(ei, math.asinh(data[i])) d = np.atanh(c / 3.1) for i, ei in enumerate(d): self.assertEqual(ei, math.atanh(data[i] / 3.1)) d = np.sinh(c) for i, ei in enumerate(d): self.assertEqual(ei, math.sinh(data[i])) d = np.cosh(c) for i, ei in enumerate(d): self.assertEqual(ei, math.cosh(data[i])) d = np.tanh(c) for i, ei in enumerate(d): self.assertEqual(ei, math.tanh(data[i])) d = np.ceil(c * 2.7) for i, ei in enumerate(d): self.assertEqual(ei, math.ceil(data[i] * 2.7)) d = np.floor(c * 2.7) for i, ei in enumerate(d): self.assertEqual(ei, math.floor(data[i] * 2.7)) d = np.erf(c) for i, ei in enumerate(d): self.assertEqual(ei, math.erf(data[i])) d = np.erfc(c) for i, ei in enumerate(d): self.assertEqual(ei, math.erfc(data[i])) d = np.exp(c) for i, ei in enumerate(d): self.assertEqual(ei, math.exp(data[i])) d = np.expm1(c) for i, ei in enumerate(d): self.assertEqual(ei, math.expm1(data[i])) d = np.gamma(c) for i, ei in enumerate(d): self.assertEqual(ei, math.gamma(data[i])) d = np.lgamma(c) for i, ei in enumerate(d): self.assertEqual(ei, math.lgamma(data[i])) d = np.log(c) for i, ei in enumerate(d): self.assertEqual(ei, math.log(data[i])) d = np.log10(c) for i, ei in enumerate(d): self.assertEqual(ei, math.log10(data[i])) d = np.log2(c) for i, ei in enumerate(d): self.assertEqual(ei, math.log2(data[i])) d = np.sqrt(c) for i, ei in enumerate(d): self.assertEqual(ei, math.sqrt(data[i])) # slices data = [1., 2., 3.] c = np.array(data + data) d = np.cos(c[::2]) mm = data + data for i, ei in enumerate(d): self.assertEqual(ei, math.cos(mm[2 * i])) # 2d array data = [1., 2., 3.] c = np.array([data, data]) d = np.cos(c) mm = [data, data] for i, ei in enumerate(d): for j, eij in enumerate(ei): self.assertEqual(eij, math.cos(mm[i][j])) # 2d array slices data = [1., 2., 3.] c = np.array([data + data, data + data]) d = np.cos(c[:, ::2]) mm = [data + data, data + data] for i, ei in enumerate(d): for j, eij in enumerate(ei): self.assertEqual(eij, math.cos(mm[i][2 * j]))
def spheroidalCF2(r, psize, axrat): """Spheroidal nanoparticle characteristic function. Form factor for ellipsoid with radii (psize/2, psize/2, axrat*psize/2) r -- distance of interaction psize -- The equatorial diameter axrat -- The ratio of axis lengths From Lei et al., Phys. Rev. B, 80, 024118 (2009) """ pelpt = 1.0 * axrat if psize <= 0 or pelpt <= 0: return numpy.zeros_like(r) # to simplify the equations v = pelpt d = 1.0 * psize d2 = d*d v2 = v*v if v == 1: return sphericalCF(r, psize) rx = r if v < 1: r = rx[rx <= v*psize] r2 = r*r f1 = 1 - 3*r/(4*d*v)*(1-r2/(4*d2)*(1+2.0/(3*v2))) \ - 3*r/(4*d)*(1-r2/(4*d2))*v/sqrt(1-v2)*atanh(sqrt(1-v2)) r = rx[numpy.logical_and(rx > v*psize, rx <= psize)] r2 = r*r f2 = (3*d/(8*r)*(1+r2/(2*d2))*sqrt(1-r2/d2) \ - 3*r/(4*d)*(1-r2/(4*d2))*atanh(sqrt(1-r2/d2)) \ ) * v/sqrt(1-v2) r = rx[rx > psize] f3 = numpy.zeros_like(r) f = numpy.concatenate((f1,f2,f3)) elif v > 1: r = rx[rx <= psize] r2 = r*r f1 = 1 - 3*r/(4*d*v)*(1-r2/(4*d2)*(1+2.0/(3*v2))) \ - 3*r/(4*d)*(1-r2/(4*d2))*v/sqrt(v2-1)*atan(sqrt(v2-1)) r = rx[numpy.logical_and(rx > psize, rx <= v*psize)] r2 = r*r f2 = 1 - 3*r/(4*d*v)*(1-r2/(4*d2)*(1+2.0/(3*v2))) \ - 3.0/8*(1+r2/(2*d2))*sqrt(1-d2/r2)*v/sqrt(v2-1) \ - 3*r/(4*d)*(1-r2/(4*d2))*v/sqrt(v2-1) \ * (atan(sqrt(v2-1)) - atan(sqrt(r2/d2-1))) r = rx[rx > v*psize] f3 = numpy.zeros_like(r) f = numpy.concatenate((f1,f2,f3)) return f
def _spheroidalCF2(r, psize, axrat): """Spheroidal nanoparticle characteristic function. Form factor for ellipsoid with radii (psize/2, psize/2, axrat*psize/2) r -- distance of interaction psize -- The equatorial diameter axrat -- The ratio of axis lengths From Lei et al., Phys. Rev. B, 80, 024118 (2009) """ pelpt = axrat if psize <= 0 or pelpt <= 0: return numpy.zeros_like(r) # to simplify the equations v = pelpt d = psize d2 = d * d v2 = v * v if v == 1: return _sphericalCF(r, psize) rx = r if v < 1: r = rx[rx <= v * psize] r2 = r * r f1 = 1 - 3*r/(4*d*v)*(1-r2/(4*d2)*(1+2.0/(3*v2))) \ - 3*r/(4*d)*(1-r2/(4*d2))*v/sqrt(1-v2)*atanh(sqrt(1-v2)) r = rx[numpy.logical_and(rx > v * psize, rx <= psize)] r2 = r * r f2 = (3*d/(8*r)*(1+r2/(2*d2))*sqrt(1-r2/d2) \ - 3*r/(4*d)*(1-r2/(4*d2))*atanh(sqrt(1-r2/d2)) \ ) * v/sqrt(1-v2) r = rx[rx > psize] f3 = numpy.zeros_like(r) f = numpy.concatenate((f1, f2, f3)) elif v > 1: r = rx[rx <= psize] r2 = r * r f1 = 1 - 3*r/(4*d*v)*(1-r2/(4*d2)*(1+2.0/(3*v2))) \ - 3*r/(4*d)*(1-r2/(4*d2))*v/sqrt(v2-1)*atan(sqrt(v2-1)) r = rx[numpy.logical_and(rx > psize, rx <= v * psize)] r2 = r * r f2 = 1 - 3*r/(4*d*v)*(1-r2/(4*d2)*(1+2.0/(3*v2))) \ - 3.0/8*(1+r2/(2*d2))*sqrt(1-d2/r2)*v/sqrt(v2-1) \ - 3*r/(4*d)*(1-r2/(4*d2))*v/sqrt(v2-1) \ * (atan(sqrt(v2-1)) - atan(sqrt(r2/d2-1))) r = rx[rx > v * psize] f3 = numpy.zeros_like(r) f = numpy.concatenate((f1, f2, f3)) return f
def ejecutar_trigo(self, funcion): if funcion.funcion == 'acos': try: return np.acos(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en acos ') return 0 elif funcion.funcion == 'acosd': try: return np.acosd(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en acosd ') return 0 elif funcion.funcion == 'asin': try: return np.asin(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en asin ') return 0 elif funcion.funcion == 'asind': try: return np.asind(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en asind ') return 0 elif funcion.funcion == 'atan': try: return np.atan(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores ') return 0 elif funcion.funcion == 'atand': try: return np.atand(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores atand ') return 0 elif funcion.funcion == 'atan2': try: return np.atan2(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en atan2 ') return 0 elif funcion.funcion == 'cos': try: return np.cos(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en cos ') return 0 elif funcion.funcion == 'cosd': try: return np.cosd(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores cosd cosd') return 0 elif funcion.funcion == 'cot': try: return np.cot(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores cot') return 0 elif funcion.funcion == 'cotd': try: return np.cotd(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en cotd ') return 0 elif funcion.funcion == 'sin': try: return np.sin(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en sin ') return 0 elif funcion.funcion == 'sind': try: return np.sind(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en sind ') return 0 elif funcion.funcion == 'tan': try: return np.tan(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en tan ') return 0 elif funcion.funcion == 'tand': try: return np.tand(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en tand') return 0 elif funcion.funcion == 'sinh': try: return np.sinh(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en sinh') return 0 elif funcion.funcion == 'cosh': try: return np.cosh(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en cosh ') return 0 elif funcion.funcion == 'tanh': try: return np.tanh(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en tanh ') return 0 elif funcion.funcion == 'asinh': try: return np.asinh(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en asinh') return 0 elif funcion.funcion == 'acosh': try: return np.acosh(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en acosh ') return 0 elif funcion.funcion == 'atanh': try: return np.atanh(self.aritexc.ejecutar_operacion(funcion.op1)) except: errorsem.append('error al convertir valores en atanh ') return 0
def ppf(self, z): w = self.width.value * self._scale if w <= 0.0: return 0*z else: return (w/Tanh.C)*atanh(2*z-1)
def ppf(self, z): w = self.width.value * self._scale if w <= 0.0: return 0 * z else: return (w / Tanh.C) * atanh(2 * z - 1)
class Tanh(Interface): r""" Hyperbolic tangent profile *width* (Parameter: 0 Angstroms) 1-\ $\sigma$ equivalent roughness. For roughness $w$ measured by the full width at half maximum (FWHM), use Tanh.as_fwhm(w). *name* (string: "tanh") The tanh profile has the form: .. math: \text{CDF}(z) = (1 + \tanh(C/wz))/2 \text{PDF}(z) = C/(2w) \sech((C/w)z)^2 \text{PPF}(z) = (w/C) \tanh^{-1}(2z-1) where $w$ is the interface roughness and $C$ is a scaling constant. $C$ is $\tanh^{-1}(\text{erf}(1/\sqrt{2}))$ for width defined by 1-\ $\sigma$, or $C$ is $2\cosh^{-1}(\sqrt{2})$ for width defined by FWHM. .. Note:: This profile was derived from the free energy of a nonuniform system: * J.W. Cahn and J. E. Hilliard, J. Chem. Phys. 28, 258 (1958) .. seealso:: This profile has an analytic solution. E.S. Wu, and W. W. Webb, Phys Rev A 8(4) 2065-2076 (1973) """ # Derivation # ========== # # To find C where w is defined as 1-sigma equivalent, use the # identity Erf.CDF(z=sigma;w=sigma) = tanh.CDF(z=sigma;w=sigma). # This simplifies to:: # # erf.CDF = (1+erf(z/(w*sqrt(2)))/2 = (1+erf(1/sqrt(2)))/2 # tanh.CDF = (1+tanh(C/w*z))/2 = (1+tanh(C))/2 # # erf.CDF = tanh.CDF => C = atanh(erf(1/sqrt(2))) # # To find C where w is defined as FWHM, use the equivalent probability # density function:: # # PDF(z) = C/2w * sech(C/w*z)**2 # # Solving PDF(w/2) = PDF(0)/2 yields:: # # Pw = PDF(w/2) = C/2w * sech(C/2)**2 # Po = PDF(0) = C/2w * sech(0)**2/2 = C/2w # # Pw = Po/2 => sech(C/2)**2 = 1/2 # => C = 2 acosh(sqrt(2)) # # To find ws 1-sigma given tanh fwhm of w, use the scale factor # s = C_1_sigma/C_fwhm = 1/2 atanh(erf(1/sqrt(2)))/acosh(sqrt(2)) # to form ws = w*s C = atanh(erf(1 / sqrt(2))) Cfwhm = 2 * acosh(sqrt(2)) @classmethod def as_fwhm(cls, *args, **kw): """ Defines interface using FWHM rather than 1-\ $\sigma$. """ self = cls(*args, **kw) self._scale = Tanh.C / Tanh.Cfwhm return self def __init__(self, width=0, name="tanh"): self._scale = 1 self.width = Parameter.default(width, limits=(0, inf), name=name) def parameters(self): return {'width': self.width} def cdf(self, z): w = self.width.value * self._scale if w <= 0.0: return 1. * (z > 0) else: return 0.5 * (1 + tanh((Tanh.C / w) * z)) def pdf(self, z): w = self.width.value * self._scale if w <= 0.0: return inf * (z == 0) else: return sech((Tanh.C / w) * z)**2 * (Tanh.C / (2 * w)) def ppf(self, z): w = self.width.value * self._scale if w <= 0.0: return 0 * z else: return (w / Tanh.C) * atanh(2 * z - 1)
def atanh(self): rst = self.ensureVector(np.atanh(self)) rst = self.setGradFn(rst, "atanh") return rst
def atanh(x: Number = 0.0) -> Number: return np.atanh(x)