From f8cefa628482420a3d4df5ad778444554ed69b69 Mon Sep 17 00:00:00 2001 From: Ogi Moore Date: Sat, 17 Apr 2021 22:38:21 -0700 Subject: [PATCH] Use hypot method to avoid over/underflow errors Use hypot instead of manual calculation --- examples/GLIsosurface.py | 2 +- examples/GLLinePlotItem.py | 4 ++-- examples/GLVolumeItem.py | 7 ++----- examples/optics/pyoptic.py | 7 +++---- pyqtgraph/Point.py | 18 +++--------------- pyqtgraph/graphicsItems/ArrowItem.py | 3 ++- pyqtgraph/graphicsItems/GraphicsItem.py | 3 ++- pyqtgraph/graphicsItems/ROI.py | 8 ++++---- pyqtgraph/opengl/items/GLScatterPlotItem.py | 8 ++++---- pyqtgraph/widgets/JoystickButton.py | 7 ++++--- 10 files changed, 27 insertions(+), 40 deletions(-) diff --git a/examples/GLIsosurface.py b/examples/GLIsosurface.py index 3da8dfa5..0f773885 100644 --- a/examples/GLIsosurface.py +++ b/examples/GLIsosurface.py @@ -28,7 +28,7 @@ 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, np.sqrt(x**2+y**2)) + th = np.arctan2(z, np.hypot(x, y)) phi = np.arctan2(y, x) r = np.sqrt(x**2 + y**2 + z **2) a0 = 1 diff --git a/examples/GLLinePlotItem.py b/examples/GLLinePlotItem.py index b375c1c1..9be9c07c 100644 --- a/examples/GLLinePlotItem.py +++ b/examples/GLLinePlotItem.py @@ -30,14 +30,14 @@ gz.translate(0, 0, -10) w.addItem(gz) def fn(x, y): - return np.cos((x**2 + y**2)**0.5) + return np.cos(np.hypot(x, y)) n = 51 y = np.linspace(-10,10,n) x = np.linspace(-10,10,100) for i in range(n): yi = np.array([y[i]]*100) - d = (x**2 + yi**2)**0.5 + d = np.hypot(x, yi) z = 10 * np.cos(d) / (d+1) pts = np.vstack([x,yi,z]).transpose() plt = gl.GLLinePlotItem(pos=pts, color=pg.glColor((i,n*1.3)), width=(i+1)/10., antialias=True) diff --git a/examples/GLVolumeItem.py b/examples/GLVolumeItem.py index 601ddfa1..ae2e90ff 100644 --- a/examples/GLVolumeItem.py +++ b/examples/GLVolumeItem.py @@ -29,16 +29,13 @@ def psi(i, j, k, offset=(50,50,100)): 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.hypot(x, y)) phi = np.arctan2(y, x) - r = (x**2 + y**2 + z **2)**0.5 + r = np.sqrt(x**2 + y**2 + z **2) a0 = 2 #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 data = np.fromfunction(psi, (100,100,200)) diff --git a/examples/optics/pyoptic.py b/examples/optics/pyoptic.py index 811ae665..442a4f5d 100644 --- a/examples/optics/pyoptic.py +++ b/examples/optics/pyoptic.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from math import atan2, asin, sin, cos, sqrt, pi +from math import atan2, asin, sin, cos, sqrt, pi, hypot import pyqtgraph as pg from pyqtgraph.Qt import QtGui, QtCore import numpy as np @@ -417,7 +417,7 @@ class CircleSurface(pg.GraphicsObject): ## find intersection of circle and line (quadratic formula) dx = dir[0] dy = dir[1] - dr = (dx**2 + dy**2) ** 0.5 + dr = hypot(dx, dy) # length D = p[0] * (p[1]+dy) - (p[0]+dx) * p[1] idr2 = 1.0 / dr**2 disc = r**2 * dr**2 - D**2 @@ -428,8 +428,7 @@ class CircleSurface(pg.GraphicsObject): sgn = -1 else: sgn = 1 - - + br = self.path.boundingRect() x1 = (D*dy + sgn*dx*disc2) * idr2 y1 = (-D*dx + abs(dy)*disc2) * idr2 diff --git a/pyqtgraph/Point.py b/pyqtgraph/Point.py index 148178f9..78a3a681 100644 --- a/pyqtgraph/Point.py +++ b/pyqtgraph/Point.py @@ -6,7 +6,7 @@ Distributed under MIT/X11 license. See license.txt for more information. """ from .Qt import QtCore -from math import sin, acos, atan2, inf, pi +from math import sin, acos, atan2, inf, pi, hypot def clip(x, mn, mx): if x > mx: @@ -93,25 +93,13 @@ class Point(QtCore.QPointF): return self._math_('__pow__', a) def _math_(self, op, x): - #print "point math:", op - #try: - #fn = getattr(QtCore.QPointF, op) - #pt = fn(self, x) - #print fn, pt, self, x - #return Point(pt) - #except AttributeError: x = Point(x) return Point(getattr(self[0], op)(x[0]), getattr(self[1], op)(x[1])) def length(self): """Returns the vector length of this Point.""" - try: - return (self[0]**2 + self[1]**2) ** 0.5 - except OverflowError: - try: - return self[1] / sin(atan2(self[1], self[0])) - except OverflowError: - return inf + return hypot(self[0], self[1]) # length + def norm(self): """Returns a vector in the same direction with unit length.""" diff --git a/pyqtgraph/graphicsItems/ArrowItem.py b/pyqtgraph/graphicsItems/ArrowItem.py index 77b6c44c..2d79d360 100644 --- a/pyqtgraph/graphicsItems/ArrowItem.py +++ b/pyqtgraph/graphicsItems/ArrowItem.py @@ -1,3 +1,4 @@ +from math import hypot from ..Qt import QtGui, QtCore from .. import functions as fn import numpy as np @@ -135,7 +136,7 @@ class ArrowItem(QtGui.QGraphicsPathItem): pad = 0 if self.opts['pxMode']: br = self.boundingRect() - pad += (br.width()**2 + br.height()**2) ** 0.5 + pad += hypot(br.width(), br.height()) pen = self.pen() if pen.isCosmetic(): pad += max(1, pen.width()) * 0.7072 diff --git a/pyqtgraph/graphicsItems/GraphicsItem.py b/pyqtgraph/graphicsItems/GraphicsItem.py index 61f48a45..273d419f 100644 --- a/pyqtgraph/graphicsItems/GraphicsItem.py +++ b/pyqtgraph/graphicsItems/GraphicsItem.py @@ -1,4 +1,5 @@ import warnings +from math import hypot from collections import OrderedDict from functools import reduce from ..Qt import QtGui, QtCore, isQObjectAlive @@ -308,7 +309,7 @@ class GraphicsItem(object): v = self.pixelVectors() if v == (None, None): return None, None - return (v[0].x()**2+v[0].y()**2)**0.5, (v[1].x()**2+v[1].y()**2)**0.5 + return (hypot(v[0].x(), v[0].y()), hypot(v[1].x(), v[1].y())) # lengths def pixelWidth(self): ## deprecated diff --git a/pyqtgraph/graphicsItems/ROI.py b/pyqtgraph/graphicsItems/ROI.py index 566651b8..d7037582 100644 --- a/pyqtgraph/graphicsItems/ROI.py +++ b/pyqtgraph/graphicsItems/ROI.py @@ -17,7 +17,7 @@ import numpy as np #from numpy.linalg import norm from ..Point import * from ..SRTTransform import SRTTransform -from math import atan2, cos, sin, pi, sqrt +from math import atan2, cos, sin, pi, sqrt, hypot 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 = sqrt(vx.x()**2 + vx.y()**2) - lvy = sqrt(vy.x()**2 + vy.y()**2) + lvx = hypot(vx.x(), vx.y()) # length + lvy = hypot(vy.x(), vy.y()) # length ##img.width is number of pixels, not width of item. ##need pxWidth and pxHeight instead of pxLen ? sx = 1.0 / lvx @@ -1887,7 +1887,7 @@ class EllipseROI(ROI): h = arr.shape[axes[1]] ## generate an ellipsoidal mask - mask = np.fromfunction(lambda x,y: (((x+0.5)/(w/2.)-1)**2+ ((y+0.5)/(h/2.)-1)**2)**0.5 < 1, (w, h)) + mask = np.fromfunction(lambda x,y: np.hypot(((x+0.5)/(w/2.)-1), ((y+0.5)/(h/2.)-1)) < 1, (w, h)) # reshape to match array axes if axes[0] > axes[1]: diff --git a/pyqtgraph/opengl/items/GLScatterPlotItem.py b/pyqtgraph/opengl/items/GLScatterPlotItem.py index 5d81515b..09e7ec2f 100644 --- a/pyqtgraph/opengl/items/GLScatterPlotItem.py +++ b/pyqtgraph/opengl/items/GLScatterPlotItem.py @@ -3,7 +3,8 @@ from OpenGL.GL import * from OpenGL.arrays import vbo from .. GLGraphicsItem import GLGraphicsItem from .. import shaders -from ... import QtGui +from ...functions import clip_array +from ...Qt import QtGui import numpy as np __all__ = ['GLScatterPlotItem'] @@ -62,12 +63,11 @@ class GLScatterPlotItem(GLGraphicsItem): ## Generate texture for rendering points w = 64 def fn(x,y): - r = ((x-(w-1)/2.)**2 + (y-(w-1)/2.)**2) ** 0.5 - return 255 * (w/2. - np.clip(r, w/2.-1.0, w/2.)) + r = np.hypot((x-(w-1)/2.), (y-(w-1)/2.)) + return 255 * (w/2. - clip_array(r, w/2.-1.0, w/2.)) pData = np.empty((w, w, 4)) pData[:] = 255 pData[:,:,3] = np.fromfunction(fn, pData.shape[:2]) - #print pData.shape, pData.min(), pData.max() pData = pData.astype(np.ubyte) if getattr(self, "pointTexture", None) is None: diff --git a/pyqtgraph/widgets/JoystickButton.py b/pyqtgraph/widgets/JoystickButton.py index 4e4a335f..53674df2 100644 --- a/pyqtgraph/widgets/JoystickButton.py +++ b/pyqtgraph/widgets/JoystickButton.py @@ -1,4 +1,5 @@ -from ..Qt import QtGui, QtCore +from math import hypot +from ..Qt import QtGui, QtCore, mkQApp __all__ = ['JoystickButton'] @@ -41,7 +42,7 @@ class JoystickButton(QtGui.QPushButton): def setState(self, *xy): xy = list(xy) - d = (xy[0]**2 + xy[1]**2)**0.5 + d = hypot(xy[0], xy[1]) # length nxy = [0, 0] for i in [0,1]: if xy[i] == 0: @@ -84,7 +85,7 @@ class JoystickButton(QtGui.QPushButton): if __name__ == '__main__': - app = pg.mkQApp() + app = mkQApp() w = QtGui.QMainWindow() b = JoystickButton() w.setCentralWidget(b)