Use clip_array or clip_scalar instead of np.clip
Significant performance issues have been identified with np.clip and thus clip_array was created to speed up the operation. In addition clip_scalar was created to clip a scalar value between two other values this commit replaces many uses of np.clip from operating on scalars to using clip_scalar instead
This commit is contained in:
parent
85c726e49a
commit
c4a1cf11a1
@ -8,6 +8,7 @@ Demonstrates use of GLScatterPlotItem with rapidly-updating plots.
|
||||
import initExample
|
||||
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph import functions as fn
|
||||
from pyqtgraph.Qt import QtCore, QtGui
|
||||
import pyqtgraph.opengl as gl
|
||||
import numpy as np
|
||||
@ -84,10 +85,10 @@ def update():
|
||||
global phase, sp2, d2
|
||||
s = -np.cos(d2*2+phase)
|
||||
color = np.empty((len(d2),4), dtype=np.float32)
|
||||
color[:,3] = np.clip(s * 0.1, 0, 1)
|
||||
color[:,0] = np.clip(s * 3.0, 0, 1)
|
||||
color[:,1] = np.clip(s * 1.0, 0, 1)
|
||||
color[:,2] = np.clip(s ** 3, 0, 1)
|
||||
color[:,3] = fn.clip_array(s * 0.1, 0., 1.)
|
||||
color[:,0] = fn.clip_array(s * 3.0, 0., 1.)
|
||||
color[:,1] = fn.clip_array(s * 1.0, 0., 1.)
|
||||
color[:,2] = fn.clip_array(s ** 3, 0., 1.)
|
||||
sp2.setData(color=color)
|
||||
phase -= 0.1
|
||||
|
||||
|
@ -11,7 +11,7 @@ import numpy as np
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph.Qt import QtCore, QtGui
|
||||
import pyqtgraph.opengl as gl
|
||||
from pyqtgraph.functions import clip_array
|
||||
from pyqtgraph import functions as fn
|
||||
|
||||
app = pg.mkQApp("GLVolumeItem Example")
|
||||
w = gl.GLViewWidget()
|
||||
@ -40,8 +40,8 @@ def psi(i, j, k, offset=(50,50,100)):
|
||||
|
||||
|
||||
data = np.fromfunction(psi, (100,100,200))
|
||||
positive = np.log(clip_array(data, 0, data.max())**2)
|
||||
negative = np.log(clip_array(-data, 0, -data.min())**2)
|
||||
positive = np.log(fn.clip_array(data, np.finfo(data.dtype).eps, data.max())**2)
|
||||
negative = np.log(fn.clip_array(-data, -np.finfo(data.dtype).eps, -data.min())**2)
|
||||
|
||||
d2 = np.empty(data.shape + (4,), dtype=np.ubyte)
|
||||
d2[..., 0] = positive * (255./positive.max())
|
||||
|
@ -6,14 +6,9 @@ Distributed under MIT/X11 license. See license.txt for more information.
|
||||
"""
|
||||
|
||||
from .Qt import QtCore
|
||||
from . import functions as fn
|
||||
from math import sin, acos, atan2, inf, pi, hypot
|
||||
|
||||
def clip(x, mn, mx):
|
||||
if x > mx:
|
||||
return mx
|
||||
if x < mn:
|
||||
return mn
|
||||
return x
|
||||
|
||||
class Point(QtCore.QPointF):
|
||||
"""Extension of QPointF which adds a few missing methods."""
|
||||
@ -112,7 +107,7 @@ class Point(QtCore.QPointF):
|
||||
if n1 == 0. or n2 == 0.:
|
||||
return None
|
||||
## Probably this should be done with arctan2 instead..
|
||||
ang = acos(clip(self.dot(a) / (n1 * n2), -1.0, 1.0)) ### in radians
|
||||
ang = acos(fn.clip_scalar(self.dot(a) / (n1 * n2), -1.0, 1.0)) ### in radians
|
||||
c = self.cross(a)
|
||||
if c > 0:
|
||||
ang *= -1.
|
||||
|
@ -4,8 +4,9 @@ Vector.py - Extension of QVector3D which adds a few missing methods.
|
||||
Copyright 2010 Luke Campagnola
|
||||
Distributed under MIT/X11 license. See license.txt for more information.
|
||||
"""
|
||||
|
||||
from math import acos
|
||||
from .Qt import QtGui, QtCore, QT_LIB
|
||||
from . import functions as fn
|
||||
import numpy as np
|
||||
|
||||
class Vector(QtGui.QVector3D):
|
||||
@ -88,7 +89,7 @@ class Vector(QtGui.QVector3D):
|
||||
if n1 == 0. or n2 == 0.:
|
||||
return None
|
||||
## Probably this should be done with arctan2 instead..
|
||||
ang = np.arccos(np.clip(QtGui.QVector3D.dotProduct(self, a) / (n1 * n2), -1.0, 1.0)) ### in radians
|
||||
ang = acos(fn.clip_scalar(QtGui.QVector3D.dotProduct(self, a) / (n1 * n2), -1.0, 1.0)) ### in radians
|
||||
# c = self.crossProduct(a)
|
||||
# if c > 0:
|
||||
# ang *= -1.
|
||||
|
@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import numpy as np
|
||||
from ..Qt import QtGui, QtCore, QtSvg, QT_LIB
|
||||
from .. import functions as fn
|
||||
from ..graphicsItems.ROI import ROI
|
||||
from .. import SRTTransform, ItemGroup
|
||||
import importlib
|
||||
@ -240,7 +241,7 @@ class CanvasItem(QtCore.QObject):
|
||||
self._graphicsItem.setOpacity(alpha)
|
||||
|
||||
def setAlpha(self, alpha):
|
||||
self.alphaSlider.setValue(int(np.clip(alpha * 1023, 0, 1023)))
|
||||
self.alphaSlider.setValue(int(fn.clip_scalar(alpha * 1023, 0, 1023)))
|
||||
|
||||
def alpha(self):
|
||||
return self.alphaSlider.value() / 1023.
|
||||
|
@ -63,7 +63,7 @@ class CurvePoint(GraphicsObject):
|
||||
pos = self.property('position')
|
||||
if 'QVariant' in repr(pos): ## need to support 2 APIs :(
|
||||
pos = pos.toDouble()[0]
|
||||
index = (len(x)-1) * np.clip(pos, 0.0, 1.0)
|
||||
index = (len(x)-1) * clip_scalar(pos, 0.0, 1.0)
|
||||
|
||||
if index != int(index): ## interpolate floating-point values
|
||||
i1 = int(index)
|
||||
|
@ -147,7 +147,7 @@ class GridItem(UIGraphicsItem):
|
||||
continue
|
||||
|
||||
ppl = dim[ax] / nl[ax]
|
||||
c = np.clip(5 * (ppl-3), 0., 50.).astype(int)
|
||||
c = int(fn.clip_scalar(5 * (ppl-3), 0, 50))
|
||||
|
||||
linePen = self.opts['pen']
|
||||
lineColor = self.opts['pen'].color()
|
||||
|
@ -593,7 +593,7 @@ class InfLineLabel(TextItem):
|
||||
return
|
||||
|
||||
rel = self._posToRel(ev.pos())
|
||||
self.orthoPos = np.clip(self._startPosition + rel - self._cursorOffset, 0, 1)
|
||||
self.orthoPos = fn.clip_scalar(self._startPosition + rel - self._cursorOffset, 0., 1.)
|
||||
self.updatePosition()
|
||||
if ev.isFinish():
|
||||
self._moving = False
|
||||
|
@ -372,7 +372,7 @@ class PlotItem(GraphicsWidget):
|
||||
if y is not None:
|
||||
self.ctrl.yGridCheck.setChecked(y)
|
||||
if alpha is not None:
|
||||
v = np.clip(alpha, 0, 1)*self.ctrl.gridAlphaSlider.maximum()
|
||||
v = fn.clip_scalar(alpha, 0., 1.)*self.ctrl.gridAlphaSlider.maximum()
|
||||
self.ctrl.gridAlphaSlider.setValue(v)
|
||||
|
||||
def close(self):
|
||||
|
@ -1073,7 +1073,7 @@ class ScatterPlotItem(GraphicsObject):
|
||||
# Map points using painter's world transform so they are drawn with pixel-valued sizes
|
||||
pts = np.vstack([self.data['x'], self.data['y']])
|
||||
pts = fn.transformCoordinates(p.transform(), pts)
|
||||
pts = np.clip(pts, -2 ** 30, 2 ** 30) # prevent Qt segmentation fault.
|
||||
pts = fn.clip_array(pts, -2 ** 30, 2 ** 30) # prevent Qt segmentation fault.
|
||||
p.resetTransform()
|
||||
|
||||
if self.opts['useCache'] and self._exportOpts is False:
|
||||
|
@ -666,7 +666,7 @@ class ViewBox(GraphicsWidget):
|
||||
def suggestPadding(self, axis):
|
||||
l = self.width() if axis==0 else self.height()
|
||||
if l > 0:
|
||||
padding = np.clip(1./(l**0.5), 0.02, 0.1)
|
||||
padding = fn.clip_scalar(1./(l**0.5), 0.02, 0.1)
|
||||
else:
|
||||
padding = 0.02
|
||||
return padding
|
||||
|
@ -17,10 +17,11 @@ from math import log10
|
||||
import numpy as np
|
||||
|
||||
from ..Qt import QtCore, QtGui, QT_LIB
|
||||
from .. import functions as fn
|
||||
import importlib
|
||||
ui_template = importlib.import_module(
|
||||
f'.ImageViewTemplate_{QT_LIB.lower()}', package=__package__)
|
||||
|
||||
|
||||
from ..graphicsItems.ImageItem import *
|
||||
from ..graphicsItems.ROI import *
|
||||
from ..graphicsItems.LinearRegionItem import *
|
||||
@ -513,7 +514,7 @@ class ImageView(QtGui.QWidget):
|
||||
|
||||
def setCurrentIndex(self, ind):
|
||||
"""Set the currently displayed frame index."""
|
||||
index = np.clip(ind, 0, self.getProcessedImage().shape[self.axes['t']]-1)
|
||||
index = fn.clip_scalar(ind, 0, self.getProcessedImage().shape[self.axes['t']]-1)
|
||||
self.ignorePlaying = True
|
||||
# Implicitly call timeLineChanged
|
||||
self.timeLine.setValue(self.tVals[index])
|
||||
|
@ -344,7 +344,7 @@ class GLViewWidget(QtWidgets.QOpenGLWidget):
|
||||
self.opts['rotation'] = q
|
||||
else: # default euler rotation method
|
||||
self.opts['azimuth'] += azim
|
||||
self.opts['elevation'] = np.clip(self.opts['elevation'] + elev, -90, 90)
|
||||
self.opts['elevation'] = fn.clip_scalar(self.opts['elevation'] + elev, -90., 90.)
|
||||
self.update()
|
||||
|
||||
def pan(self, dx, dy, dz, relative='global'):
|
||||
|
@ -3,7 +3,7 @@ from OpenGL.GL import *
|
||||
from OpenGL.arrays import vbo
|
||||
from .. GLGraphicsItem import GLGraphicsItem
|
||||
from .. import shaders
|
||||
from ...functions import clip_array
|
||||
from ... import functions as fn
|
||||
from ...Qt import QtGui
|
||||
import numpy as np
|
||||
|
||||
@ -62,12 +62,12 @@ class GLScatterPlotItem(GLGraphicsItem):
|
||||
|
||||
## Generate texture for rendering points
|
||||
w = 64
|
||||
def fn(x,y):
|
||||
def genTexture(x,y):
|
||||
r = np.hypot((x-(w-1)/2.), (y-(w-1)/2.))
|
||||
return 255 * (w/2. - clip_array(r, w/2.-1.0, w/2.))
|
||||
return 255 * (w / 2 - fn.clip_array(r, w / 2 - 1, w / 2))
|
||||
pData = np.empty((w, w, 4))
|
||||
pData[:] = 255
|
||||
pData[:,:,3] = np.fromfunction(fn, pData.shape[:2])
|
||||
pData[:,:,3] = np.fromfunction(genTexture, pData.shape[:2])
|
||||
pData = pData.astype(np.ubyte)
|
||||
|
||||
if getattr(self, "pointTexture", None) is None:
|
||||
|
@ -2,6 +2,7 @@ from collections import OrderedDict
|
||||
import numpy as np
|
||||
import copy
|
||||
from math import log2
|
||||
from .. import functions as fn
|
||||
|
||||
|
||||
class SystemSolver(object):
|
||||
@ -391,7 +392,7 @@ if __name__ == '__main__':
|
||||
sh = self.shutter # this raises RuntimeError if shutter has not
|
||||
# been specified
|
||||
ap = 4.0 * (sh / (1./60.)) * (iso / 100.) * (2 ** exp) * (2 ** light)
|
||||
ap = np.clip(ap, 2.0, 16.0)
|
||||
ap = fn.clip_scalar(ap, 2.0, 16.0)
|
||||
except RuntimeError:
|
||||
# program mode; we can select a suitable shutter
|
||||
# value at the same time.
|
||||
|
@ -161,7 +161,7 @@ class ColorMapParameter(ptree.types.GroupParameter):
|
||||
elif op == 'Set':
|
||||
colors[mask] = colors2[mask]
|
||||
|
||||
colors = np.clip(colors, 0, 1)
|
||||
colors = fn.clip_array(colors, 0., 1.)
|
||||
if mode == 'byte':
|
||||
colors = (colors * 255).astype(np.ubyte)
|
||||
|
||||
@ -210,7 +210,7 @@ class RangeColorMapItem(ptree.types.SimpleParameter):
|
||||
def map(self, data):
|
||||
data = data[self.fieldName]
|
||||
|
||||
scaled = np.clip((data-self['Min']) / (self['Max']-self['Min']), 0, 1)
|
||||
scaled = fn.clip_array((data-self['Min']) / (self['Max']-self['Min']), 0, 1)
|
||||
cmap = self.value()
|
||||
colors = cmap.map(scaled, mode='float')
|
||||
|
||||
|
@ -378,7 +378,7 @@ class GraphicsView(QtGui.QGraphicsView):
|
||||
return
|
||||
|
||||
if ev.buttons() == QtCore.Qt.RightButton:
|
||||
delta = Point(np.clip(delta[0], -50, 50), np.clip(-delta[1], -50, 50))
|
||||
delta = Point(fn.clip_scalar(delta[0], -50, 50), fn.clip_scalar(-delta[1], -50, 50))
|
||||
scale = 1.01 ** delta
|
||||
self.scale(scale[0], scale[1], center=self.mapToScene(self.mousePressPos))
|
||||
self.sigDeviceRangeChanged.emit(self, self.range)
|
||||
|
Loading…
Reference in New Issue
Block a user