ROI tests pass with row-major axis order
This commit is contained in:
parent
956251f7ee
commit
df691596a7
@ -3,6 +3,7 @@ from .Qt import QtCore, QtGui
|
||||
from .Point import Point
|
||||
import numpy as np
|
||||
|
||||
|
||||
class SRTTransform(QtGui.QTransform):
|
||||
"""Transform that can always be represented as a combination of 3 matrices: scale * rotate * translate
|
||||
This transform has no shear; angles are always preserved.
|
||||
@ -165,6 +166,7 @@ class SRTTransform(QtGui.QTransform):
|
||||
|
||||
def matrix(self):
|
||||
return np.array([[self.m11(), self.m12(), self.m13()],[self.m21(), self.m22(), self.m23()],[self.m31(), self.m32(), self.m33()]])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from . import widgets
|
||||
|
@ -37,9 +37,6 @@ class GraphicsItem(object):
|
||||
if register:
|
||||
GraphicsScene.registerObject(self) ## workaround for pyqt bug in graphicsscene.items()
|
||||
|
||||
|
||||
|
||||
|
||||
def getViewWidget(self):
|
||||
"""
|
||||
Return the view widget for this item.
|
||||
@ -95,7 +92,6 @@ class GraphicsItem(object):
|
||||
def forgetViewBox(self):
|
||||
self._viewBox = None
|
||||
|
||||
|
||||
def deviceTransform(self, viewportTransform=None):
|
||||
"""
|
||||
Return the transform that converts local item coordinates to device coordinates (usually pixels).
|
||||
|
@ -279,6 +279,42 @@ class ImageItem(GraphicsObject):
|
||||
if gotNewData:
|
||||
self.sigImageChanged.emit()
|
||||
|
||||
def dataTransform(self):
|
||||
"""Return the transform that maps from this image's input array to its
|
||||
local coordinate system.
|
||||
|
||||
This transform corrects for the transposition that occurs when image data
|
||||
is interpreted in row-major order.
|
||||
"""
|
||||
# Might eventually need to account for downsampling / clipping here
|
||||
tr = QtGui.QTransform()
|
||||
if self.axisOrder == 'row-major':
|
||||
# transpose
|
||||
tr.scale(1, -1)
|
||||
tr.rotate(-90)
|
||||
return tr
|
||||
|
||||
def inverseDataTransform(self):
|
||||
"""Return the transform that maps from this image's local coordinate
|
||||
system to its input array.
|
||||
|
||||
See dataTransform() for more information.
|
||||
"""
|
||||
tr = QtGui.QTransform()
|
||||
if self.axisOrder == 'row-major':
|
||||
# transpose
|
||||
tr.scale(1, -1)
|
||||
tr.rotate(-90)
|
||||
return tr
|
||||
|
||||
def mapToData(self, obj):
|
||||
tr = self.inverseDataTransform()
|
||||
return tr.map(obj)
|
||||
|
||||
def mapFromData(self, obj):
|
||||
tr = self.dataTransform()
|
||||
return tr.map(obj)
|
||||
|
||||
def quickMinMax(self, targetSize=1e6):
|
||||
"""
|
||||
Estimate the min/max values of the image data by subsampling.
|
||||
|
@ -1017,7 +1017,7 @@ class ROI(GraphicsObject):
|
||||
If returnSlice is set to False, the function returns a pair of tuples with the values that would have
|
||||
been used to generate the slice objects. ((ax0Start, ax0Stop), (ax1Start, ax1Stop))
|
||||
|
||||
If the slice can not be computed (usually because the scene/transforms are not properly
|
||||
If the slice cannot be computed (usually because the scene/transforms are not properly
|
||||
constructed yet), then the method returns None.
|
||||
"""
|
||||
## Determine shape of array along ROI axes
|
||||
@ -1104,7 +1104,8 @@ class ROI(GraphicsObject):
|
||||
|
||||
shape, vectors, origin = self.getAffineSliceParams(data, img, axes, fromBoundingRect=fromBR)
|
||||
if not returnMappedCoords:
|
||||
return fn.affineSlice(data, shape=shape, vectors=vectors, origin=origin, axes=axes, **kwds)
|
||||
rgn = fn.affineSlice(data, shape=shape, vectors=vectors, origin=origin, axes=axes, **kwds)
|
||||
return rgn
|
||||
else:
|
||||
kwds['returnCoords'] = True
|
||||
result, coords = fn.affineSlice(data, shape=shape, vectors=vectors, origin=origin, axes=axes, **kwds)
|
||||
@ -1119,29 +1120,34 @@ class ROI(GraphicsObject):
|
||||
(shape, vectors, origin) to extract a subset of *data* using this ROI
|
||||
and *img* to specify the subset.
|
||||
|
||||
If *fromBoundingRect* is True, then the ROI's bounding rectangle is used
|
||||
rather than the shape of the ROI.
|
||||
|
||||
See :func:`getArrayRegion <pyqtgraph.ROI.getArrayRegion>` for more information.
|
||||
"""
|
||||
if self.scene() is not img.scene():
|
||||
raise Exception("ROI and target item must be members of the same scene.")
|
||||
|
||||
origin = self.mapToItem(img, QtCore.QPointF(0, 0))
|
||||
origin = img.mapToData(self.mapToItem(img, QtCore.QPointF(0, 0)))
|
||||
|
||||
## vx and vy point in the directions of the slice axes, but must be scaled properly
|
||||
vx = self.mapToItem(img, QtCore.QPointF(1, 0)) - origin
|
||||
vy = self.mapToItem(img, QtCore.QPointF(0, 1)) - origin
|
||||
vx = img.mapToData(self.mapToItem(img, QtCore.QPointF(1, 0))) - origin
|
||||
vy = img.mapToData(self.mapToItem(img, QtCore.QPointF(0, 1))) - origin
|
||||
|
||||
lvx = np.sqrt(vx.x()**2 + vx.y()**2)
|
||||
lvy = np.sqrt(vy.x()**2 + vy.y()**2)
|
||||
pxLen = img.width() / float(data.shape[axes[0]])
|
||||
#img.width is number of pixels, not width of item.
|
||||
#need pxWidth and pxHeight instead of pxLen ?
|
||||
sx = pxLen / lvx
|
||||
sy = pxLen / lvy
|
||||
#pxLen = img.width() / float(data.shape[axes[0]])
|
||||
##img.width is number of pixels, not width of item.
|
||||
##need pxWidth and pxHeight instead of pxLen ?
|
||||
#sx = pxLen / lvx
|
||||
#sy = pxLen / lvy
|
||||
sx = 1.0 / lvx
|
||||
sy = 1.0 / lvy
|
||||
|
||||
vectors = ((vx.x()*sx, vx.y()*sx), (vy.x()*sy, vy.y()*sy))
|
||||
if fromBoundingRect is True:
|
||||
shape = self.boundingRect().width(), self.boundingRect().height()
|
||||
origin = self.mapToItem(img, self.boundingRect().topLeft())
|
||||
origin = img.mapToData(self.mapToItem(img, self.boundingRect().topLeft()))
|
||||
origin = (origin.x(), origin.y())
|
||||
else:
|
||||
shape = self.state['size']
|
||||
@ -1150,10 +1156,10 @@ class ROI(GraphicsObject):
|
||||
shape = [abs(shape[0]/sx), abs(shape[1]/sy)]
|
||||
|
||||
if getConfigOption('imageAxisOrder') == 'row-major':
|
||||
vectors = [vectors[1][::-1], vectors[0][::-1]]
|
||||
# transpose output
|
||||
vectors = vectors[::-1]
|
||||
shape = shape[::-1]
|
||||
origin = origin[::-1]
|
||||
|
||||
|
||||
return shape, vectors, origin
|
||||
|
||||
def renderShapeMask(self, width, height):
|
||||
|
@ -8,7 +8,7 @@ from pyqtgraph.tests import assertImageApproved, mouseMove, mouseDrag, mouseClic
|
||||
app = pg.mkQApp()
|
||||
|
||||
|
||||
def test_getArrayRegion():
|
||||
def test_getArrayRegion(transpose=False):
|
||||
pr = pg.PolyLineROI([[0, 0], [27, 0], [0, 28]], closed=True)
|
||||
pr.setPos(1, 1)
|
||||
rois = [
|
||||
@ -23,13 +23,19 @@ def test_getArrayRegion():
|
||||
|
||||
origMode = pg.getConfigOption('imageAxisOrder')
|
||||
try:
|
||||
pg.setConfigOptions(imageAxisOrder='col-major')
|
||||
check_getArrayRegion(roi, 'roi/'+name, testResize)
|
||||
pg.setConfigOptions(imageAxisOrder='row-major')
|
||||
check_getArrayRegion(roi, 'roi/'+name, testResize, transpose=True)
|
||||
if transpose:
|
||||
pg.setConfigOptions(imageAxisOrder='row-major')
|
||||
check_getArrayRegion(roi, 'roi/'+name, testResize, transpose=True)
|
||||
else:
|
||||
pg.setConfigOptions(imageAxisOrder='col-major')
|
||||
check_getArrayRegion(roi, 'roi/'+name, testResize)
|
||||
finally:
|
||||
pg.setConfigOptions(imageAxisOrder=origMode)
|
||||
|
||||
|
||||
def test_getArrayRegion_axisorder():
|
||||
test_getArrayRegion(transpose=True)
|
||||
|
||||
|
||||
def check_getArrayRegion(roi, name, testResize=True, transpose=False):
|
||||
initState = roi.getState()
|
||||
@ -55,8 +61,8 @@ def check_getArrayRegion(roi, name, testResize=True, transpose=False):
|
||||
vb2.setPos(6, 203)
|
||||
vb2.resize(188, 191)
|
||||
|
||||
img1 = TransposedImageItem(border='w', transpose=transpose)
|
||||
img2 = TransposedImageItem(border='w', transpose=transpose)
|
||||
img1 = pg.ImageItem(border='w')
|
||||
img2 = pg.ImageItem(border='w')
|
||||
|
||||
vb1.addItem(img1)
|
||||
vb2.addItem(img2)
|
||||
@ -68,6 +74,9 @@ def check_getArrayRegion(roi, name, testResize=True, transpose=False):
|
||||
data[:, :, 2, :] += 10
|
||||
data[:, :, :, 3] += 10
|
||||
|
||||
if transpose:
|
||||
data = data.transpose(0, 2, 1, 3)
|
||||
|
||||
img1.setImage(data[0, ..., 0])
|
||||
vb1.setAspectLocked()
|
||||
vb1.enableAutoRange(True, True)
|
||||
@ -75,6 +84,12 @@ def check_getArrayRegion(roi, name, testResize=True, transpose=False):
|
||||
roi.setZValue(10)
|
||||
vb1.addItem(roi)
|
||||
|
||||
if isinstance(roi, pg.RectROI):
|
||||
if transpose:
|
||||
assert roi.getAffineSliceParams(data, img1, axes=(1, 2)) == ([28.0, 27.0], ((1.0, 0.0), (0.0, 1.0)), (1.0, 1.0))
|
||||
else:
|
||||
assert roi.getAffineSliceParams(data, img1, axes=(1, 2)) == ([27.0, 28.0], ((1.0, 0.0), (0.0, 1.0)), (1.0, 1.0))
|
||||
|
||||
rgn = roi.getArrayRegion(data, img1, axes=(1, 2))
|
||||
#assert np.all((rgn == data[:, 1:-2, 1:-2, :]) | (rgn == 0))
|
||||
img2.setImage(rgn[0, ..., 0])
|
||||
|
Loading…
Reference in New Issue
Block a user