Commit 816069c0 authored by Luke Campagnola's avatar Luke Campagnola
Browse files

All scipy imports in the library are now optional (need to test each of these changes)

Several examples still require scipy.
parent 00418e49
......@@ -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
......
......@@ -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))
......
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()]
......
# -*- 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)
......
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)
......
......@@ -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<dataSize; i++ ) {
#for( int j=0; j<ncol; j++ ) {
#newData[i*newStride + j*newColStride] = flatLut[flatData[i*dataStride]*lutStride + j*lutColStride];
#}
#}
#"""
#scipy.weave.inline(code, ['flatData', 'flatLut', 'newData', 'dataSize', 'ncol', 'newStride', 'lutStride', 'dataStride', 'newColStride', 'lutColStride'])
#newData = newData.reshape(data.shape + lut.shape[1:])
##if np.any(newData != lut[data]):
##print "mismatch!"
#data = newData
#except:
#if USE_WEAVE:
#debug.printExc("Error; disabling weave.")
#USE_WEAVE = False
#data = lut[data]
#return data
def makeRGBA(*args, **kwds):
"""Equivalent to makeARGB(..., useRGBA=True)"""
......@@ -1473,7 +1411,11 @@ def traceImage(image, values, smooth=0.5):
If image is RGB or RGBA, then the shape of values should be (nvals, 3/4)
The parameter *smooth* is expressed in pixels.
"""
import scipy.ndimage as ndi
try:
import scipy.ndimage as ndi
except ImportError:
raise Exception("traceImage() requires the package scipy.ndimage, but it is not importable.")
if values.ndim == 2:
values = values.T
values = values[np.newaxis, np.newaxis, ...].astype(float)
......@@ -1967,14 +1909,16 @@ def invertQTransform(tr):
bugs in that method. (specifically, Qt has floating-point precision issues
when determining whether a matrix is invertible)
"""
if not HAVE_SCIPY:
try:
import numpy.linalg
arr = np.array([[tr.m11(), tr.m12(), tr.m13()], [tr.m21(), tr.m22(), tr.m23()], [tr.m31(), tr.m32(), tr.m33()]])
inv = numpy.linalg.inv(arr)
return QtGui.QTransform(inv[0,0], inv[0,1], inv[0,2], inv[1,0], inv[1,1], inv[1,2], inv[2,0], inv[2,1])
except ImportError:
inv = tr.inverted()
if inv[1] is False:
raise Exception("Transform is not invertible.")
return inv[0]
arr = np.array([[tr.m11(), tr.m12(), tr.m13()], [tr.m21(), tr.m22(), tr.m23()], [tr.m31(), tr.m32(), tr.m33()]])
inv = scipy.linalg.inv(arr)
return QtGui.QTransform(inv[0,0], inv[0,1], inv[0,2], inv[1,0], inv[1,1], inv[1,2], inv[2,0], inv[2,1])
def pseudoScatter(data, spacing=None, shuffle=True, bidir=False):
......
......@@ -655,7 +655,10 @@ class PlotDataItem(GraphicsObject):
dx = np.diff(x)
uniform = not np.any(np.abs(dx-dx[0]) > (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
......
......@@ -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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment