Added pg.gaussianFilter, removed all dependency on gaussian_filter

This commit is contained in:
Luke Campagnola 2014-03-11 19:01:34 -04:00
parent ff697ce492
commit 34802c8aec
11 changed files with 59 additions and 25 deletions

View File

@ -11,7 +11,6 @@ a 2D plane and interpolate data along that plane to generate a slice image
import initExample import initExample
import numpy as np import numpy as np
import scipy
from pyqtgraph.Qt import QtCore, QtGui from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg import pyqtgraph as pg

View File

@ -12,7 +12,6 @@ from pyqtgraph.flowchart.library.common import CtrlNode
from pyqtgraph.Qt import QtGui, QtCore from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg import pyqtgraph as pg
import numpy as np import numpy as np
import scipy.ndimage
app = QtGui.QApplication([]) app = QtGui.QApplication([])
@ -44,7 +43,7 @@ win.show()
## generate random input data ## generate random input data
data = np.random.normal(size=(100,100)) data = np.random.normal(size=(100,100))
data = 25 * scipy.ndimage.gaussian_filter(data, (5,5)) data = 25 * pg.gaussianFilter(data, (5,5))
data += np.random.normal(size=(100,100)) data += np.random.normal(size=(100,100))
data[40:60, 40:60] += 15.0 data[40:60, 40:60] += 15.0
data[30:50, 30:50] += 15.0 data[30:50, 30:50] += 15.0
@ -90,7 +89,7 @@ class ImageViewNode(Node):
## CtrlNode is just a convenience class that automatically creates its ## CtrlNode is just a convenience class that automatically creates its
## control widget based on a simple data structure. ## control widget based on a simple data structure.
class UnsharpMaskNode(CtrlNode): class UnsharpMaskNode(CtrlNode):
"""Return the input data passed through scipy.ndimage.gaussian_filter.""" """Return the input data passed through pg.gaussianFilter."""
nodeName = "UnsharpMask" nodeName = "UnsharpMask"
uiTemplate = [ uiTemplate = [
('sigma', 'spin', {'value': 1.0, 'step': 1.0, 'range': [0.0, None]}), ('sigma', 'spin', {'value': 1.0, 'step': 1.0, 'range': [0.0, None]}),
@ -110,7 +109,7 @@ class UnsharpMaskNode(CtrlNode):
# CtrlNode has created self.ctrls, which is a dict containing {ctrlName: widget} # CtrlNode has created self.ctrls, which is a dict containing {ctrlName: widget}
sigma = self.ctrls['sigma'].value() sigma = self.ctrls['sigma'].value()
strength = self.ctrls['strength'].value() strength = self.ctrls['strength'].value()
output = dataIn - (strength * scipy.ndimage.gaussian_filter(dataIn, (sigma,sigma))) output = dataIn - (strength * pg.gaussianFilter(dataIn, (sigma,sigma)))
return {'dataOut': output} return {'dataOut': output}

View File

@ -12,7 +12,6 @@ from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph.opengl as gl import pyqtgraph.opengl as gl
import pyqtgraph as pg import pyqtgraph as pg
import numpy as np import numpy as np
import scipy.ndimage as ndi
app = QtGui.QApplication([]) app = QtGui.QApplication([])
w = gl.GLViewWidget() w = gl.GLViewWidget()
@ -22,8 +21,8 @@ w.setWindowTitle('pyqtgraph example: GLImageItem')
## create volume data set to slice three images from ## create volume data set to slice three images from
shape = (100,100,70) shape = (100,100,70)
data = ndi.gaussian_filter(np.random.normal(size=shape), (4,4,4)) data = pg.gaussianFilter(np.random.normal(size=shape), (4,4,4))
data += ndi.gaussian_filter(np.random.normal(size=shape), (15,15,15))*15 data += pg.gaussianFilter(np.random.normal(size=shape), (15,15,15))*15
## slice out three planes, convert to RGBA for OpenGL texture ## slice out three planes, convert to RGBA for OpenGL texture
levels = (-0.08, 0.08) levels = (-0.08, 0.08)

View File

@ -10,7 +10,6 @@ import initExample
from pyqtgraph.Qt import QtCore, QtGui from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg import pyqtgraph as pg
import pyqtgraph.opengl as gl import pyqtgraph.opengl as gl
import scipy.ndimage as ndi
import numpy as np import numpy as np
## Create a GL View widget to display data ## Create a GL View widget to display data
@ -29,7 +28,7 @@ w.addItem(g)
## Simple surface plot example ## Simple surface plot example
## x, y values are not specified, so assumed to be 0:50 ## x, y values are not specified, so assumed to be 0:50
z = ndi.gaussian_filter(np.random.normal(size=(50,50)), (1,1)) z = pg.gaussianFilter(np.random.normal(size=(50,50)), (1,1))
p1 = gl.GLSurfacePlotItem(z=z, shader='shaded', color=(0.5, 0.5, 1, 1)) p1 = gl.GLSurfacePlotItem(z=z, shader='shaded', color=(0.5, 0.5, 1, 1))
p1.scale(16./49., 16./49., 1.0) p1.scale(16./49., 16./49., 1.0)
p1.translate(-18, 2, 0) p1.translate(-18, 2, 0)
@ -46,7 +45,7 @@ w.addItem(p2)
## Manually specified colors ## Manually specified colors
z = ndi.gaussian_filter(np.random.normal(size=(50,50)), (1,1)) z = pg.gaussianFilter(np.random.normal(size=(50,50)), (1,1))
x = np.linspace(-12, 12, 50) x = np.linspace(-12, 12, 50)
y = np.linspace(-12, 12, 50) y = np.linspace(-12, 12, 50)
colors = np.ones((50,50,4), dtype=float) colors = np.ones((50,50,4), dtype=float)

View File

@ -7,7 +7,6 @@ Use a HistogramLUTWidget to control the contrast / coloration of an image.
import initExample import initExample
import numpy as np import numpy as np
import scipy.ndimage as ndi
from pyqtgraph.Qt import QtGui, QtCore from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg import pyqtgraph as pg
@ -34,7 +33,7 @@ l.addWidget(v, 0, 0)
w = pg.HistogramLUTWidget() w = pg.HistogramLUTWidget()
l.addWidget(w, 0, 1) l.addWidget(w, 0, 1)
data = ndi.gaussian_filter(np.random.normal(size=(256, 256)), (20, 20)) data = pg.gaussianFilter(np.random.normal(size=(256, 256)), (20, 20))
for i in range(32): for i in range(32):
for j in range(32): for j in range(32):
data[i*8, j*8] += .1 data[i*8, j*8] += .1

View File

@ -14,7 +14,6 @@ displaying and analyzing 2D and 3D data. ImageView provides:
import initExample import initExample
import numpy as np import numpy as np
import scipy.ndimage
from pyqtgraph.Qt import QtCore, QtGui from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg import pyqtgraph as pg
@ -29,7 +28,7 @@ win.show()
win.setWindowTitle('pyqtgraph example: ImageView') win.setWindowTitle('pyqtgraph example: ImageView')
## Create random 3D data set with noisy signals ## Create random 3D data set with noisy signals
img = scipy.ndimage.gaussian_filter(np.random.normal(size=(200, 200)), (5, 5)) * 20 + 100 img = pg.gaussianFilter(np.random.normal(size=(200, 200)), (5, 5)) * 20 + 100
img = img[np.newaxis,:,:] img = img[np.newaxis,:,:]
decay = np.exp(-np.linspace(0,0.3,100))[:,np.newaxis,np.newaxis] decay = np.exp(-np.linspace(0,0.3,100))[:,np.newaxis,np.newaxis]
data = np.random.normal(size=(100, 200, 200)) data = np.random.normal(size=(100, 200, 200))

View File

@ -13,7 +13,6 @@ import initExample ## Add path to library (just for examples; you do not need th
from pyqtgraph.Qt import QtGui, QtCore, USE_PYSIDE from pyqtgraph.Qt import QtGui, QtCore, USE_PYSIDE
import numpy as np import numpy as np
import pyqtgraph as pg import pyqtgraph as pg
import scipy.ndimage as ndi
import pyqtgraph.ptime as ptime import pyqtgraph.ptime as ptime
if USE_PYSIDE: if USE_PYSIDE:
@ -95,10 +94,13 @@ def mkData():
if ui.rgbCheck.isChecked(): if ui.rgbCheck.isChecked():
data = np.random.normal(size=(frames,width,height,3), loc=loc, scale=scale) data = np.random.normal(size=(frames,width,height,3), loc=loc, scale=scale)
data = ndi.gaussian_filter(data, (0, 6, 6, 0)) data = pg.gaussianFilter(data, (0, 6, 6, 0))
else: else:
data = np.random.normal(size=(frames,width,height), loc=loc, scale=scale) data = np.random.normal(size=(frames,width,height), loc=loc, scale=scale)
data = ndi.gaussian_filter(data, (0, 6, 6)) print frames, width, height, loc, scale
data = pg.gaussianFilter(data, (0, 6, 6))
print data[0]
pg.image(data)
if dtype[0] != 'float': if dtype[0] != 'float':
data = np.clip(data, 0, mx) data = np.clip(data, 0, mx)
data = data.astype(dt) data = data.astype(dt)

View File

@ -7,7 +7,6 @@ the mouse.
import initExample ## Add path to library (just for examples; you do not need this) import initExample ## Add path to library (just for examples; you do not need this)
import numpy as np import numpy as np
import scipy.ndimage as ndi
import pyqtgraph as pg import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph.Point import Point from pyqtgraph.Point import Point
@ -33,8 +32,8 @@ p1.setAutoVisible(y=True)
#create numpy arrays #create numpy arrays
#make the numbers large to show that the xrange shows data from 10000 to all the way 0 #make the numbers large to show that the xrange shows data from 10000 to all the way 0
data1 = 10000 + 15000 * ndi.gaussian_filter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000) data1 = 10000 + 15000 * pg.gaussianFilter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000)
data2 = 15000 + 15000 * ndi.gaussian_filter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000) data2 = 15000 + 15000 * pg.gaussianFilter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000)
p1.plot(data1, pen="r") p1.plot(data1, pen="r")
p1.plot(data2, pen="g") p1.plot(data2, pen="g")

View File

@ -10,7 +10,6 @@ import initExample ## Add path to library (just for examples; you do not need th
from pyqtgraph.Qt import QtGui, QtCore from pyqtgraph.Qt import QtGui, QtCore
import numpy as np import numpy as np
import pyqtgraph as pg import pyqtgraph as pg
import scipy.ndimage as ndi
app = QtGui.QApplication([]) app = QtGui.QApplication([])
@ -18,7 +17,7 @@ app = QtGui.QApplication([])
frames = 200 frames = 200
data = np.random.normal(size=(frames,30,30), loc=0, scale=100) data = np.random.normal(size=(frames,30,30), loc=0, scale=100)
data = np.concatenate([data, data], axis=0) data = np.concatenate([data, data], axis=0)
data = ndi.gaussian_filter(data, (10, 10, 10))[frames/2:frames + frames/2] data = pg.gaussianFilter(data, (10, 10, 10))[frames/2:frames + frames/2]
data[:, 15:16, 15:17] += 1 data[:, 15:16, 15:17] += 1
win = pg.GraphicsWindow() win = pg.GraphicsWindow()

View File

@ -2,6 +2,7 @@
from ...Qt import QtCore, QtGui from ...Qt import QtCore, QtGui
from ..Node import Node from ..Node import Node
from . import functions from . import functions
from ... import functions as pgfn
from .common import * from .common import *
import numpy as np import numpy as np
@ -161,7 +162,7 @@ class Gaussian(CtrlNode):
import scipy.ndimage import scipy.ndimage
except ImportError: except ImportError:
raise Exception("GaussianFilter node requires the package scipy.ndimage.") raise Exception("GaussianFilter node requires the package scipy.ndimage.")
return scipy.ndimage.gaussian_filter(data, self.ctrls['sigma'].value()) return pgfn.gaussianFilter(data, self.ctrls['sigma'].value())
class Derivative(CtrlNode): class Derivative(CtrlNode):

View File

@ -1121,6 +1121,45 @@ def colorToAlpha(data, color):
#raise Exception() #raise Exception()
return np.clip(output, 0, 255).astype(np.ubyte) return np.clip(output, 0, 255).astype(np.ubyte)
def gaussianFilter(data, sigma):
"""
Drop-in replacement for scipy.ndimage.gaussian_filter.
(note: results are only approximately equal to the output of
gaussian_filter)
"""
if np.isscalar(sigma):
sigma = (sigma,) * data.ndim
baseline = data.mean()
filtered = data - baseline
for ax in range(data.ndim):
s = sigma[ax]
if s == 0:
continue
# generate 1D gaussian kernel
ksize = int(s * 6)
x = np.arange(-ksize, ksize)
kernel = np.exp(-x**2 / (2*s**2))
kshape = [1,] * data.ndim
kshape[ax] = len(kernel)
kernel = kernel.reshape(kshape)
# convolve as product of FFTs
shape = data.shape[ax] + ksize
scale = 1.0 / (abs(s) * (2*np.pi)**0.5)
filtered = scale * np.fft.irfft(np.fft.rfft(filtered, shape, axis=ax) *
np.fft.rfft(kernel, shape, axis=ax),
axis=ax)
# clip off extra data
sl = [slice(None)] * data.ndim
sl[ax] = slice(filtered.shape[ax]-data.shape[ax],None,None)
filtered = filtered[sl]
return filtered + baseline
def downsample(data, n, axis=0, xvals='subsample'): def downsample(data, n, axis=0, xvals='subsample'):
"""Downsample by averaging points together across axis. """Downsample by averaging points together across axis.
If multiple axes are specified, runs once per axis. If multiple axes are specified, runs once per axis.
@ -1556,7 +1595,7 @@ def traceImage(image, values, smooth=0.5):
paths = [] paths = []
for i in range(diff.shape[-1]): for i in range(diff.shape[-1]):
d = (labels==i).astype(float) d = (labels==i).astype(float)
d = ndi.gaussian_filter(d, (smooth, smooth)) d = gaussianFilter(d, (smooth, smooth))
lines = isocurve(d, 0.5, connected=True, extendToEdge=True) lines = isocurve(d, 0.5, connected=True, extendToEdge=True)
path = QtGui.QPainterPath() path = QtGui.QPainterPath()
for line in lines: for line in lines: