diff --git a/examples/ViewBox.py b/examples/ViewBox.py index 2dcbb758..3a66afe3 100644 --- a/examples/ViewBox.py +++ b/examples/ViewBox.py @@ -14,7 +14,6 @@ import initExample ## This example uses a ViewBox to create a PlotWidget-like interface -#from scipy import random import numpy as np from pyqtgraph.Qt import QtGui, QtCore import pyqtgraph as pg diff --git a/pyqtgraph/SRTTransform3D.py b/pyqtgraph/SRTTransform3D.py index 417190e1..7da3c1bd 100644 --- a/pyqtgraph/SRTTransform3D.py +++ b/pyqtgraph/SRTTransform3D.py @@ -4,7 +4,6 @@ from .Vector import Vector from .Transform3D import Transform3D from .Vector import Vector import numpy as np -import scipy.linalg class SRTTransform3D(Transform3D): """4x4 Transform matrix that can always be represented as a combination of 3 matrices: scale * rotate * translate @@ -118,6 +117,7 @@ class SRTTransform3D(Transform3D): The input matrix must be affine AND have no shear, otherwise the conversion will most likely fail. """ + import numpy.linalg for i in range(4): self.setRow(i, m.row(i)) m = self.matrix().reshape(4,4) @@ -134,7 +134,7 @@ class SRTTransform3D(Transform3D): ## rotation axis is the eigenvector with eigenvalue=1 r = m[:3, :3] / scale[:, np.newaxis] try: - evals, evecs = scipy.linalg.eig(r) + evals, evecs = numpy.linalg.eig(r) except: print("Rotation matrix: %s" % str(r)) print("Scale: %s" % str(scale)) diff --git a/pyqtgraph/colormap.py b/pyqtgraph/colormap.py index 38c12097..559e6688 100644 --- a/pyqtgraph/colormap.py +++ b/pyqtgraph/colormap.py @@ -1,5 +1,4 @@ import numpy as np -import scipy.interpolate from .Qt import QtGui, QtCore class ColorMap(object): @@ -84,6 +83,11 @@ class ColorMap(object): qcolor Values are returned as an array of QColor objects. =========== =============================================================== """ + try: + import scipy.interpolate + except: + raise Exception("Colormap.map() requires the package scipy.interpolate, but it could not be imported.") + if isinstance(mode, basestring): mode = self.enumMap[mode.lower()] diff --git a/pyqtgraph/flowchart/library/Filters.py b/pyqtgraph/flowchart/library/Filters.py index 518c8c18..e5bb2453 100644 --- a/pyqtgraph/flowchart/library/Filters.py +++ b/pyqtgraph/flowchart/library/Filters.py @@ -1,9 +1,6 @@ # -*- coding: utf-8 -*- from ...Qt import QtCore, QtGui from ..Node import Node -from scipy.signal import detrend -from scipy.ndimage import median_filter, gaussian_filter -#from ...SignalProxy import SignalProxy from . import functions from .common import * import numpy as np @@ -119,7 +116,11 @@ class Median(CtrlNode): @metaArrayWrapper def processData(self, data): - return median_filter(data, self.ctrls['n'].value()) + try: + import scipy.ndimage + except ImportError: + raise Exception("MedianFilter node requires the package scipy.ndimage.") + return scipy.ndimage.median_filter(data, self.ctrls['n'].value()) class Mode(CtrlNode): """Filters data by taking the mode (histogram-based) of a sliding window""" @@ -156,7 +157,11 @@ class Gaussian(CtrlNode): @metaArrayWrapper def processData(self, data): - return gaussian_filter(data, self.ctrls['sigma'].value()) + try: + import scipy.ndimage + except ImportError: + raise Exception("GaussianFilter node requires the package scipy.ndimage.") + return scipy.ndimage.gaussian_filter(data, self.ctrls['sigma'].value()) class Derivative(CtrlNode): @@ -189,6 +194,10 @@ class Detrend(CtrlNode): @metaArrayWrapper def processData(self, data): + try: + from scipy.signal import detrend + except ImportError: + raise Exception("DetrendFilter node requires the package scipy.signal.") return detrend(data) diff --git a/pyqtgraph/flowchart/library/functions.py b/pyqtgraph/flowchart/library/functions.py index 9efb8f36..027e1386 100644 --- a/pyqtgraph/flowchart/library/functions.py +++ b/pyqtgraph/flowchart/library/functions.py @@ -1,4 +1,3 @@ -import scipy import numpy as np from ...metaarray import MetaArray @@ -47,6 +46,11 @@ def downsample(data, n, axis=0, xvals='subsample'): def applyFilter(data, b, a, padding=100, bidir=True): """Apply a linear filter with coefficients a, b. Optionally pad the data before filtering and/or run the filter in both directions.""" + try: + import scipy.signal + except ImportError: + raise Exception("applyFilter() requires the package scipy.signal.") + d1 = data.view(np.ndarray) if padding > 0: @@ -67,6 +71,11 @@ def applyFilter(data, b, a, padding=100, bidir=True): def besselFilter(data, cutoff, order=1, dt=None, btype='low', bidir=True): """return data passed through bessel filter""" + try: + import scipy.signal + except ImportError: + raise Exception("besselFilter() requires the package scipy.signal.") + if dt is None: try: tvals = data.xvals('Time') @@ -85,6 +94,11 @@ def besselFilter(data, cutoff, order=1, dt=None, btype='low', bidir=True): def butterworthFilter(data, wPass, wStop=None, gPass=2.0, gStop=20.0, order=1, dt=None, btype='low', bidir=True): """return data passed through bessel filter""" + try: + import scipy.signal + except ImportError: + raise Exception("butterworthFilter() requires the package scipy.signal.") + if dt is None: try: tvals = data.xvals('Time') @@ -175,6 +189,11 @@ def denoise(data, radius=2, threshold=4): def adaptiveDetrend(data, x=None, threshold=3.0): """Return the signal with baseline removed. Discards outliers from baseline measurement.""" + try: + import scipy.signal + except ImportError: + raise Exception("adaptiveDetrend() requires the package scipy.signal.") + if x is None: x = data.xvals(0) diff --git a/pyqtgraph/functions.py b/pyqtgraph/functions.py index 427fb01d..62df1ce3 100644 --- a/pyqtgraph/functions.py +++ b/pyqtgraph/functions.py @@ -34,17 +34,6 @@ import decimal, re import ctypes import sys, struct -try: - import scipy.ndimage - HAVE_SCIPY = True - if getConfigOption('useWeave'): - try: - import scipy.weave - except ImportError: - setConfigOptions(useWeave=False) -except ImportError: - HAVE_SCIPY = False - from . import debug def siScale(x, minVal=1e-25, allowUnicode=True): @@ -422,7 +411,9 @@ def affineSlice(data, shape, origin, vectors, axes, order=1, returnCoords=False, affineSlice(data, shape=(20,20), origin=(40,0,0), vectors=((-1, 1, 0), (-1, 0, 1)), axes=(1,2,3)) """ - if not HAVE_SCIPY: + try: + import scipy.ndimage + except ImportError: raise Exception("This function requires the scipy library, but it does not appear to be importable.") # sanity check @@ -579,15 +570,14 @@ def solve3DTransform(points1, points2): Find a 3D transformation matrix that maps points1 onto points2. Points must be specified as a list of 4 Vectors. """ - if not HAVE_SCIPY: - raise Exception("This function depends on the scipy library, but it does not appear to be importable.") + import numpy.linalg A = np.array([[points1[i].x(), points1[i].y(), points1[i].z(), 1] for i in range(4)]) B = np.array([[points2[i].x(), points2[i].y(), points2[i].z(), 1] for i in range(4)]) ## solve 3 sets of linear equations to determine transformation matrix elements matrix = np.zeros((4,4)) for i in range(3): - matrix[i] = scipy.linalg.solve(A, B[:,i]) ## solve Ax = B; x is one row of the desired transformation matrix + matrix[i] = numpy.linalg.solve(A, B[:,i]) ## solve Ax = B; x is one row of the desired transformation matrix return matrix @@ -600,8 +590,7 @@ def solveBilinearTransform(points1, points2): mapped = np.dot(matrix, [x*y, x, y, 1]) """ - if not HAVE_SCIPY: - raise Exception("This function depends on the scipy library, but it does not appear to be importable.") + import numpy.linalg ## A is 4 rows (points) x 4 columns (xy, x, y, 1) ## B is 4 rows (points) x 2 columns (x, y) A = np.array([[points1[i].x()*points1[i].y(), points1[i].x(), points1[i].y(), 1] for i in range(4)]) @@ -610,7 +599,7 @@ def solveBilinearTransform(points1, points2): ## solve 2 sets of linear equations to determine transformation matrix elements matrix = np.zeros((2,4)) for i in range(2): - matrix[i] = scipy.linalg.solve(A, B[:,i]) ## solve Ax = B; x is one row of the desired transformation matrix + matrix[i] = numpy.linalg.solve(A, B[:,i]) ## solve Ax = B; x is one row of the desired transformation matrix return matrix @@ -629,6 +618,10 @@ def rescaleData(data, scale, offset, dtype=None): try: if not getConfigOption('useWeave'): raise Exception('Weave is disabled; falling back to slower version.') + try: + import scipy.weave + except ImportError: + raise Exception('scipy.weave is not importable; falling back to slower version.') ## require native dtype when using weave if not data.dtype.isnative: @@ -671,68 +664,13 @@ def applyLookupTable(data, lut): Uses values in *data* as indexes to select values from *lut*. The returned data has shape data.shape + lut.shape[1:] - Uses scipy.weave to improve performance if it is available. Note: color gradient lookup tables can be generated using GradientWidget. """ if data.dtype.kind not in ('i', 'u'): data = data.astype(int) - ## using np.take appears to be faster than even the scipy.weave method and takes care of clipping as well. return np.take(lut, data, axis=0, mode='clip') - ### old methods: - #data = np.clip(data, 0, lut.shape[0]-1) - - #try: - #if not USE_WEAVE: - #raise Exception('Weave is disabled; falling back to slower version.') - - ### number of values to copy for each LUT lookup - #if lut.ndim == 1: - #ncol = 1 - #else: - #ncol = sum(lut.shape[1:]) - - ### output array - #newData = np.empty((data.size, ncol), dtype=lut.dtype) - - ### flattened input arrays - #flatData = data.flatten() - #flatLut = lut.reshape((lut.shape[0], ncol)) - - #dataSize = data.size - - ### strides for accessing each item - #newStride = newData.strides[0] / newData.dtype.itemsize - #lutStride = flatLut.strides[0] / flatLut.dtype.itemsize - #dataStride = flatData.strides[0] / flatData.dtype.itemsize - - ### strides for accessing individual values within a single LUT lookup - #newColStride = newData.strides[1] / newData.dtype.itemsize - #lutColStride = flatLut.strides[1] / flatLut.dtype.itemsize - - #code = """ - - #for( int i=0; i (abs(dx[0]) / 1000.)) if not uniform: - import scipy.interpolate as interp + try: + import scipy.interpolate as interp + except: + raise Exception('Fourier transform of irregularly-sampled data requires the package scipy.interpolate.') x2 = np.linspace(x[0], x[-1], len(x)) y = interp.griddata(x, y, x2, method='linear') x = x2 diff --git a/pyqtgraph/graphicsItems/ROI.py b/pyqtgraph/graphicsItems/ROI.py index c0f9008c..79be91f8 100644 --- a/pyqtgraph/graphicsItems/ROI.py +++ b/pyqtgraph/graphicsItems/ROI.py @@ -13,11 +13,8 @@ of how to build an ROI at the bottom of the file. """ from ..Qt import QtCore, QtGui -#if not hasattr(QtCore, 'Signal'): - #QtCore.Signal = QtCore.pyqtSignal import numpy as np -from numpy.linalg import norm -import scipy.ndimage as ndimage +#from numpy.linalg import norm from ..Point import * from ..SRTTransform import SRTTransform from math import cos, sin