Use math module methods for singular values

Using numpy methods that are intended for vectorized operations is
substantially slower than using the math module, so when feasible the
math module methods should be used.
This commit is contained in:
Ogi Moore 2021-04-17 20:08:57 -07:00
parent 1326ebe2f4
commit b0a3849960
11 changed files with 53 additions and 57 deletions

View File

@ -7,6 +7,7 @@ This example uses the isosurface function to convert a scalar field
## Add path to library (just for examples; you do not need this)
import initExample
import numpy as np
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
import pyqtgraph.opengl as gl
@ -22,23 +23,17 @@ g = gl.GLGridItem()
g.scale(2,2,1)
w.addItem(g)
import numpy as np
## Define a scalar field from which we will generate an isosurface
def psi(i, j, k, offset=(25, 25, 50)):
x = i-offset[0]
y = j-offset[1]
z = k-offset[2]
th = np.arctan2(z, (x**2+y**2)**0.5)
th = np.arctan2(z, np.sqrt(x**2+y**2))
phi = np.arctan2(y, x)
r = (x**2 + y**2 + z **2)**0.5
r = np.sqrt(x**2 + y**2 + z **2)
a0 = 1
#ps = (1./81.) * (2./np.pi)**0.5 * (1./a0)**(3/2) * (6 - r/a0) * (r/a0) * np.exp(-r/(3*a0)) * np.cos(th)
ps = (1./81.) * 1./(6.*np.pi)**0.5 * (1./a0)**(3/2) * (r/a0)**2 * np.exp(-r/(3*a0)) * (3 * np.cos(th)**2 - 1)
return ps
#return ((1./81.) * (1./np.pi)**0.5 * (1./a0)**(3/2) * (r/a0)**2 * (r/a0) * np.exp(-r/(3*a0)) * np.sin(th) * np.cos(th) * np.exp(2 * 1j * phi))**2
print("Generating scalar field..")

View File

@ -7,6 +7,7 @@ Demonstrates GLVolumeItem for displaying volumetric data.
## Add path to library (just for examples; you do not need this)
import initExample
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph.opengl as gl
@ -23,7 +24,6 @@ g = gl.GLGridItem()
g.scale(10, 10, 1)
w.addItem(g)
import numpy as np
## Hydrogen electron probability density
def psi(i, j, k, offset=(50,50,100)):
x = i-offset[0]

View File

@ -9,6 +9,7 @@ used to affect the appearance of a surface.
## Add path to library (just for examples; you do not need this)
import initExample
import numpy as np
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
import pyqtgraph.opengl as gl
@ -23,9 +24,6 @@ g = gl.GLGridItem()
g.scale(2,2,1)
w.addItem(g)
import numpy as np
md = gl.MeshData.sphere(rows=10, cols=20)
x = np.linspace(-8, 8, 6)

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from math import atan2, asin, sin, cos, sqrt, pi
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
@ -49,7 +50,7 @@ class GlassDB:
B = list(map(float, [info['B1'], info['B2'], info['B3']]))
C = list(map(float, [info['C1'], info['C2'], info['C3']]))
w2 = (wl/1000.)**2
n = np.sqrt(1.0 + (B[0]*w2 / (w2-C[0])) + (B[1]*w2 / (w2-C[1])) + (B[2]*w2 / (w2-C[2])))
n = sqrt(1.0 + (B[0]*w2 / (w2-C[0])) + (B[1]*w2 / (w2-C[1])) + (B[2]*w2 / (w2-C[2])))
cache[wl] = n
return cache[wl]
@ -249,10 +250,14 @@ class Lens(Optic):
p1 = surface.mapToItem(ray, p1)
rd = ray['dir']
a1 = np.arctan2(rd[1], rd[0])
ar = a1 - ai + np.arcsin((np.sin(ai) * ray['ior'] / ior))
a1 = atan2(rd[1], rd[0])
try:
ar = a1 - ai + asin((sin(ai) * ray['ior'] / ior))
except ValueError:
ar = np.nan
ray.setEnd(p1)
dp = Point(np.cos(ar), np.sin(ar))
dp = Point(cos(ar), sin(ar))
ray = Ray(parent=ray, ior=ior, dir=dp)
return [ray]
@ -279,10 +284,10 @@ class Mirror(Optic):
if p1 is not None:
p1 = surface.mapToItem(ray, p1)
rd = ray['dir']
a1 = np.arctan2(rd[1], rd[0])
ar = a1 + np.pi - 2*ai
a1 = atan2(rd[1], rd[0])
ar = a1 + pi - 2*ai
ray.setEnd(p1)
dp = Point(np.cos(ar), np.sin(ar))
dp = Point(cos(ar), sin(ar))
ray = Ray(parent=ray, dir=dp)
else:
ray.setEnd(None)
@ -374,7 +379,7 @@ class CircleSurface(pg.GraphicsObject):
## half-height of surface can't be larger than radius
h2 = min(h2, abs(r))
arc = QtCore.QRectF(0, -r, r*2, r*2)
a1 = np.arcsin(h2/r) * 180. / np.pi
a1 = asin(h2/r) * 180. / pi
a2 = -2*a1
a1 += 180.
self.path.arcMoveTo(arc, a1)
@ -406,7 +411,7 @@ class CircleSurface(pg.GraphicsObject):
if abs(y) > h:
return None, None
else:
return (Point(0, y), np.arctan2(dir[1], dir[0]))
return (Point(0, y), atan2(dir[1], dir[0]))
else:
#print " curve"
## find intersection of circle and line (quadratic formula)
@ -436,19 +441,12 @@ class CircleSurface(pg.GraphicsObject):
pt = Point(x2, y2)
if not br.contains(x2+r, y2):
return None, None
raise Exception("No intersection!")
norm = np.arctan2(pt[1], pt[0])
norm = atan2(pt[1], pt[0])
if r < 0:
norm += np.pi
#print " norm:", norm*180/3.1415
norm += pi
dp = p - pt
#print " dp:", dp
ang = np.arctan2(dp[1], dp[0])
#print " ang:", ang*180/3.1415
#print " ai:", (ang-norm)*180/3.1415
#print " intersection:", pt
ang = atan2(dp[1], dp[0])
return pt + Point(r, 0), ang-norm

View File

@ -6,7 +6,7 @@ Distributed under MIT/X11 license. See license.txt for more information.
"""
from .Qt import QtCore
import numpy as np
from math import sin, acos, atan2, inf, pi
def clip(x, mn, mx):
if x > mx:
@ -109,9 +109,9 @@ class Point(QtCore.QPointF):
return (self[0]**2 + self[1]**2) ** 0.5
except OverflowError:
try:
return self[1] / np.sin(np.arctan2(self[1], self[0]))
return self[1] / sin(atan2(self[1], self[0]))
except OverflowError:
return np.inf
return inf
def norm(self):
"""Returns a vector in the same direction with unit length."""
@ -124,11 +124,11 @@ class Point(QtCore.QPointF):
if n1 == 0. or n2 == 0.:
return None
## Probably this should be done with arctan2 instead..
ang = np.arccos(clip(self.dot(a) / (n1 * n2), -1.0, 1.0)) ### in radians
ang = acos(clip(self.dot(a) / (n1 * n2), -1.0, 1.0)) ### in radians
c = self.cross(a)
if c > 0:
ang *= -1.
return ang * 180. / np.pi
return ang * 180. / pi
def dot(self, a):
"""Returns the dot product of a and this Point."""

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from math import atan2, pi
from .Qt import QtCore, QtGui
from .Point import Point
import numpy as np
@ -76,7 +77,7 @@ class SRTTransform(QtGui.QTransform):
self._state = {
'pos': Point(p1),
'scale': Point(dp2.length(), dp3.length() * sy),
'angle': (np.arctan2(dp2[1], dp2[0]) * 180. / np.pi) + da
'angle': (atan2(dp2[1], dp2[0]) * 180. / pi) + da
}
self.update()

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from math import atan2, pi
from .Qt import QtCore, QtGui
from .Vector import Vector
from .Transform3D import Transform3D
@ -164,7 +165,7 @@ class SRTTransform3D(Transform3D):
sin = (r-r.T)[rInd] / (2. * sign * axis[axisInd])
## finally, we get the complete angle from arctan(sin/cos)
self._state['angle'] = np.arctan2(sin, cos) * 180 / np.pi
self._state['angle'] = atan2(sin, cos) * 180 / pi
if self._state['angle'] == 0:
self._state['axis'] = (0,0,1)

View File

@ -1,5 +1,7 @@
from math import atan2, pi
from ..Qt import QtGui, QtCore
from . import ArrowItem
from ..functions import clip_scalar
import numpy as np
from ..Point import Point
import weakref
@ -65,22 +67,22 @@ class CurvePoint(GraphicsObject):
if index != int(index): ## interpolate floating-point values
i1 = int(index)
i2 = np.clip(i1+1, 0, len(x)-1)
i2 = clip_scalar(i1+1, 0, len(x)-1)
s2 = index-i1
s1 = 1.0-s2
newPos = (x[i1]*s1+x[i2]*s2, y[i1]*s1+y[i2]*s2)
else:
index = int(index)
i1 = np.clip(index-1, 0, len(x)-1)
i2 = np.clip(index+1, 0, len(x)-1)
i1 = clip_scalar(index-1, 0, len(x)-1)
i2 = clip_scalar(index+1, 0, len(x)-1)
newPos = (x[index], y[index])
p1 = self.parentItem().mapToScene(QtCore.QPointF(x[i1], y[i1]))
p2 = self.parentItem().mapToScene(QtCore.QPointF(x[i2], y[i2]))
ang = np.arctan2(p2.y()-p1.y(), p2.x()-p1.x()) ## returns radians
ang = atan2(p2.y()-p1.y(), p2.x()-p1.x()) ## returns radians
self.resetTransform()
if self._rotate:
self.setRotation(180 + np.rad2deg(ang)) ## takes degrees
self.setRotation(180 + ang * (180. / pi))
QtGui.QGraphicsItem.setPos(self, *newPos)
return True

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from math import atan2, pi
from ..Qt import QtGui, QtCore
from ..Point import Point
from .GraphicsObject import GraphicsObject
@ -359,7 +360,7 @@ class InfiniteLine(GraphicsObject):
up = tr.map(Point(left, 1))
dif = end - start
length = Point(dif).length()
angle = np.arctan2(dif.y(), dif.x()) * 180 / np.pi
angle = atan2(dif.y(), dif.x()) * 180 / pi
p.translate(start)
p.rotate(angle)

View File

@ -17,7 +17,7 @@ import numpy as np
#from numpy.linalg import norm
from ..Point import *
from ..SRTTransform import SRTTransform
from math import cos, sin
from math import atan2, cos, sin, pi, sqrt
from .. import functions as fn
from .GraphicsObject import GraphicsObject
from .UIGraphicsItem import UIGraphicsItem
@ -1247,8 +1247,8 @@ class ROI(GraphicsObject):
vx = img.mapToData(self.mapToItem(img, QtCore.QPointF(1, 0))) - origin
vy = img.mapToData(self.mapToItem(img, QtCore.QPointF(0, 1))) - origin
lvx = np.sqrt(vx.x()**2 + vx.y()**2)
lvy = np.sqrt(vy.x()**2 + vy.y()**2)
lvx = sqrt(vx.x()**2 + vx.y()**2)
lvy = sqrt(vy.x()**2 + vy.y()**2)
##img.width is number of pixels, not width of item.
##need pxWidth and pxHeight instead of pxLen ?
sx = 1.0 / lvx
@ -1332,8 +1332,8 @@ class Handle(UIGraphicsItem):
properties of the ROI they are attached to.
"""
types = { ## defines number of sides, start angle for each handle type
't': (4, np.pi/4),
'f': (4, np.pi/4),
't': (4, pi/4),
'f': (4, pi/4),
's': (4, 0),
'r': (12, 0),
'sr': (12, 0),
@ -1481,7 +1481,7 @@ class Handle(UIGraphicsItem):
size = self.radius
self.path = QtGui.QPainterPath()
ang = self.startAng
dt = 2*np.pi / self.sides
dt = 2 * pi / self.sides
for i in range(0, self.sides+1):
x = size * cos(ang)
y = size * sin(ang)
@ -1518,13 +1518,13 @@ class Handle(UIGraphicsItem):
return None
v = dt.map(QtCore.QPointF(1, 0)) - dt.map(QtCore.QPointF(0, 0))
va = np.arctan2(v.y(), v.x())
va = atan2(v.y(), v.x())
dti = fn.invertQTransform(dt)
devPos = dt.map(QtCore.QPointF(0,0))
tr = QtGui.QTransform()
tr.translate(devPos.x(), devPos.y())
tr.rotate(va * 180. / 3.1415926)
tr.rotate(va * 180. / pi)
return dti.map(tr.map(self.path))
@ -1663,7 +1663,7 @@ class LineROI(ROI):
d = pos2-pos1
l = d.length()
ang = Point(1, 0).angle(d)
ra = ang * np.pi / 180.
ra = ang * pi / 180.
c = Point(-width/2. * sin(ra), -width/2. * cos(ra))
pos1 = pos1 + c
@ -1914,7 +1914,7 @@ class EllipseROI(ROI):
center = br.center()
r1 = br.width() / 2.
r2 = br.height() / 2.
theta = np.linspace(0, 2*np.pi, 24)
theta = np.linspace(0, 2 * pi, 24)
x = center.x() + r1 * np.cos(theta)
y = center.y() + r2 * np.sin(theta)
path.moveTo(x[0], y[0])
@ -2396,7 +2396,7 @@ class TriangleROI(ROI):
def __init__(self, pos, size, **args):
ROI.__init__(self, pos, [size, size], **args)
self.aspectLocked = True
angles = np.linspace(0, np.pi * 4 / 3, 3)
angles = np.linspace(0, pi * 4 / 3, 3)
verticies = (np.array((np.sin(angles), np.cos(angles))).T + 1.0) / 2.0
self.poly = QtGui.QPolygonF()
for pt in verticies:

View File

@ -1,4 +1,4 @@
import numpy as np
from math import pi, atan2
from ..Qt import QtCore, QtGui
from ..Point import Point
from .. import functions as fn
@ -208,7 +208,7 @@ class TextItem(GraphicsObject):
angle = -self.angle
if self.rotateAxis is not None:
d = pt.map(self.rotateAxis) - pt.map(Point(0, 0))
a = np.arctan2(d.y(), d.x()) * 180 / np.pi
a = atan2(d.y(), d.x()) * 180 / pi
angle += a
t.rotate(angle)
self.setTransform(t)