def __init__(self, parent=None): """ :param parent: Parent QWidget """ super(ArrayStackPlot, self).__init__(parent) self.__signal = None self.__signal_name = None # the Z, Y, X axes apply to the last three dimensions of the signal # (in that order) self.__z_axis = None self.__z_axis_name = None self.__y_axis = None self.__y_axis_name = None self.__x_axis = None self.__x_axis_name = None self._stack_view = StackView(self) self._hline = qt.QFrame(self) self._hline.setFrameStyle(qt.QFrame.HLine) self._hline.setFrameShadow(qt.QFrame.Sunken) self._legend = qt.QLabel(self) self._selector = NumpyAxesSelector(self) self._selector.setNamedAxesSelectorVisibility(False) self.__selector_is_connected = False layout = qt.QVBoxLayout() layout.addWidget(self._stack_view) layout.addWidget(self._hline) layout.addWidget(self._legend) layout.addWidget(self._selector) self.setLayout(layout)
def setUp(self): super(TestStackView, self).setUp() self.stackview = StackView() self.stackview.show() self.qWaitForWindowExposed(self.stackview) self.mystack = numpy.fromfunction( lambda i, j, k: numpy.sin(i / 15.) + numpy.cos(j / 4.) + 2 * numpy. sin(k / 6.), (10, 20, 30))
def setUp(self): super(TestStackView, self).setUp() self.stackview = StackView() self.stackview.show() self.qWaitForWindowExposed(self.stackview) self.mystack = numpy.fromfunction( lambda i, j, k: numpy.sin(i/15.) + numpy.cos(j/4.) + 2 * numpy.sin(k/6.), (10, 20, 30) )
def _createStackView(self): plot = StackView(self) self.stack = plot toolBar = toolbar.ProfileToolBar(plot, plot.getPlotWidget()) toolBar.setScheme("imagestack") plot.addToolBar(toolBar) toolBar = plot.getProfileToolbar() toolBar.clear()
class ArrayStackPlot(qt.QWidget): """ Widget for plotting a n-D array (n >= 3) as a stack of images. Three axis arrays can be provided to calibrate the axes. The signal array can have an arbitrary number of dimensions, the only limitation being that the last 3 dimensions must have the same length as the axes arrays. Sliders are provided to select indices on the first (n - 3) dimensions of the signal array, and the plot is updated to load the stack corresponding to the selection. """ def __init__(self, parent=None): """ :param parent: Parent QWidget """ super(ArrayStackPlot, self).__init__(parent) self.__signal = None self.__signal_name = None # the Z, Y, X axes apply to the last three dimensions of the signal # (in that order) self.__z_axis = None self.__z_axis_name = None self.__y_axis = None self.__y_axis_name = None self.__x_axis = None self.__x_axis_name = None self._stack_view = StackView(self) self._hline = qt.QFrame(self) self._hline.setFrameStyle(qt.QFrame.HLine) self._hline.setFrameShadow(qt.QFrame.Sunken) self._legend = qt.QLabel(self) self._selector = NumpyAxesSelector(self) self._selector.setNamedAxesSelectorVisibility(False) self.__selector_is_connected = False layout = qt.QVBoxLayout() layout.addWidget(self._stack_view) layout.addWidget(self._hline) layout.addWidget(self._legend) layout.addWidget(self._selector) self.setLayout(layout) def getStackView(self): """Returns the plot used for the display :rtype: StackView """ return self._stack_view def setStackData(self, signal, x_axis=None, y_axis=None, z_axis=None, signal_name=None, xlabel=None, ylabel=None, zlabel=None, title=None): """ :param signal: n-D dataset, whose last 3 dimensions are used as the 3D stack values. :param x_axis: 1-D dataset used as the image's x coordinates. If provided, its lengths must be equal to the length of the last dimension of ``signal``. :param y_axis: 1-D dataset used as the image's y. If provided, its lengths must be equal to the length of the 2nd to last dimension of ``signal``. :param z_axis: 1-D dataset used as the image's z. If provided, its lengths must be equal to the length of the 3rd to last dimension of ``signal``. :param signal_name: Label used in the legend :param xlabel: Label for X axis :param ylabel: Label for Y axis :param zlabel: Label for Z axis :param title: Graph title """ if self.__selector_is_connected: self._selector.selectionChanged.disconnect(self._updateStack) self.__selector_is_connected = False self.__signal = signal self.__signal_name = signal_name or "" self.__x_axis = x_axis self.__x_axis_name = xlabel self.__y_axis = y_axis self.__y_axis_name = ylabel self.__z_axis = z_axis self.__z_axis_name = zlabel self._selector.setData(signal) self._selector.setAxisNames(["Y", "X", "Z"]) self._stack_view.setGraphTitle(title or "") # by default, the z axis is the image position (dimension not plotted) self._stack_view.getPlotWidget().getXAxis().setLabel(self.__x_axis_name or "X") self._stack_view.getPlotWidget().getYAxis().setLabel(self.__y_axis_name or "Y") self._updateStack() ndims = len(signal.shape) self._stack_view.setFirstStackDimension(ndims - 3) # the legend label shows the selection slice producing the volume # (only interesting for ndim > 3) if ndims > 3: self._selector.setVisible(True) self._legend.setVisible(True) self._hline.setVisible(True) else: self._selector.setVisible(False) self._legend.setVisible(False) self._hline.setVisible(False) if not self.__selector_is_connected: self._selector.selectionChanged.connect(self._updateStack) self.__selector_is_connected = True @staticmethod def _get_origin_scale(axis): """Assuming axis is a regularly spaced 1D array, return a tuple (origin, scale) where: - origin = axis[0] - scale = (axis[n-1] - axis[0]) / (n -1) :param axis: 1D numpy array :return: Tuple (axis[0], (axis[-1] - axis[0]) / (len(axis) - 1)) """ return axis[0], (axis[-1] - axis[0]) / (len(axis) - 1) def _updateStack(self): """Update displayed stack according to the current axes selector data.""" stk = self._selector.selectedData() x_axis = self.__x_axis y_axis = self.__y_axis z_axis = self.__z_axis calibrations = [] for axis in [z_axis, y_axis, x_axis]: if axis is None: calibrations.append(NoCalibration()) elif len(axis) == 2: calibrations.append( LinearCalibration(y_intercept=axis[0], slope=axis[1])) else: calibrations.append(ArrayCalibration(axis)) legend = self.__signal_name + "[" for sl in self._selector.selection(): if sl == slice(None): legend += ":, " else: legend += str(sl) + ", " legend = legend[:-2] + "]" self._legend.setText("Displayed data: " + legend) self._stack_view.setStack(stk, calibrations=calibrations) self._stack_view.setLabels(labels=[ self.__z_axis_name, self.__y_axis_name, self.__x_axis_name ]) def clear(self): old = self._selector.blockSignals(True) self._selector.clear() self._selector.blockSignals(old) self._stack_view.clear()
class ArrayStackPlot(qt.QWidget): """ Widget for plotting a n-D array (n >= 3) as a stack of images. Three axis arrays can be provided to calibrate the axes. The signal array can have an arbitrary number of dimensions, the only limitation being that the last 3 dimensions must have the same length as the axes arrays. Sliders are provided to select indices on the first (n - 3) dimensions of the signal array, and the plot is updated to load the stack corresponding to the selection. """ def __init__(self, parent=None): """ :param parent: Parent QWidget """ super(ArrayStackPlot, self).__init__(parent) self.__signal = None self.__signal_name = None # the Z, Y, X axes apply to the last three dimensions of the signal # (in that order) self.__z_axis = None self.__z_axis_name = None self.__y_axis = None self.__y_axis_name = None self.__x_axis = None self.__x_axis_name = None self._stack_view = StackView(self) self._hline = qt.QFrame(self) self._hline.setFrameStyle(qt.QFrame.HLine) self._hline.setFrameShadow(qt.QFrame.Sunken) self._legend = qt.QLabel(self) self._selector = NumpyAxesSelector(self) self._selector.setNamedAxesSelectorVisibility(False) self.__selector_is_connected = False layout = qt.QVBoxLayout() layout.addWidget(self._stack_view) layout.addWidget(self._hline) layout.addWidget(self._legend) layout.addWidget(self._selector) self.setLayout(layout) def getStackView(self): """Returns the plot used for the display :rtype: StackView """ return self._stack_view def setStackData(self, signal, x_axis=None, y_axis=None, z_axis=None, signal_name=None, xlabel=None, ylabel=None, zlabel=None, title=None): """ :param signal: n-D dataset, whose last 3 dimensions are used as the 3D stack values. :param x_axis: 1-D dataset used as the image's x coordinates. If provided, its lengths must be equal to the length of the last dimension of ``signal``. :param y_axis: 1-D dataset used as the image's y. If provided, its lengths must be equal to the length of the 2nd to last dimension of ``signal``. :param z_axis: 1-D dataset used as the image's z. If provided, its lengths must be equal to the length of the 3rd to last dimension of ``signal``. :param signal_name: Label used in the legend :param xlabel: Label for X axis :param ylabel: Label for Y axis :param zlabel: Label for Z axis :param title: Graph title """ if self.__selector_is_connected: self._selector.selectionChanged.disconnect(self._updateStack) self.__selector_is_connected = False self.__signal = signal self.__signal_name = signal_name or "" self.__x_axis = x_axis self.__x_axis_name = xlabel self.__y_axis = y_axis self.__y_axis_name = ylabel self.__z_axis = z_axis self.__z_axis_name = zlabel self._selector.setData(signal) self._selector.setAxisNames(["Y", "X", "Z"]) self._stack_view.setGraphTitle(title or "") # by default, the z axis is the image position (dimension not plotted) self._stack_view.getPlot().getXAxis().setLabel(self.__x_axis_name or "X") self._stack_view.getPlot().getYAxis().setLabel(self.__y_axis_name or "Y") self._updateStack() ndims = len(signal.shape) self._stack_view.setFirstStackDimension(ndims - 3) # the legend label shows the selection slice producing the volume # (only interesting for ndim > 3) if ndims > 3: self._selector.setVisible(True) self._legend.setVisible(True) self._hline.setVisible(True) else: self._selector.setVisible(False) self._legend.setVisible(False) self._hline.setVisible(False) if not self.__selector_is_connected: self._selector.selectionChanged.connect(self._updateStack) self.__selector_is_connected = True @staticmethod def _get_origin_scale(axis): """Assuming axis is a regularly spaced 1D array, return a tuple (origin, scale) where: - origin = axis[0] - scale = (axis[n-1] - axis[0]) / (n -1) :param axis: 1D numpy array :return: Tuple (axis[0], (axis[-1] - axis[0]) / (len(axis) - 1)) """ return axis[0], (axis[-1] - axis[0]) / (len(axis) - 1) def _updateStack(self): """Update displayed stack according to the current axes selector data.""" stk = self._selector.selectedData() x_axis = self.__x_axis y_axis = self.__y_axis z_axis = self.__z_axis calibrations = [] for axis in [z_axis, y_axis, x_axis]: if axis is None: calibrations.append(NoCalibration()) elif len(axis) == 2: calibrations.append( LinearCalibration(y_intercept=axis[0], slope=axis[1])) else: calibrations.append(ArrayCalibration(axis)) legend = self.__signal_name + "[" for sl in self._selector.selection(): if sl == slice(None): legend += ":, " else: legend += str(sl) + ", " legend = legend[:-2] + "]" self._legend.setText("Displayed data: " + legend) self._stack_view.setStack(stk, calibrations=calibrations) self._stack_view.setLabels( labels=[self.__z_axis_name, self.__y_axis_name, self.__x_axis_name]) def clear(self): old = self._selector.blockSignals(True) self._selector.clear() self._selector.blockSignals(old) self._stack_view.clear()
class TestStackView(TestCaseQt): """Base class for tests of StackView.""" def setUp(self): super(TestStackView, self).setUp() self.stackview = StackView() self.stackview.show() self.qWaitForWindowExposed(self.stackview) self.mystack = numpy.fromfunction( lambda i, j, k: numpy.sin(i/15.) + numpy.cos(j/4.) + 2 * numpy.sin(k/6.), (10, 20, 30) ) def tearDown(self): self.stackview.setAttribute(qt.Qt.WA_DeleteOnClose) self.stackview.close() del self.stackview super(TestStackView, self).tearDown() def testSetStack(self): self.stackview.setStack(self.mystack) self.stackview.setColormap("viridis", autoscale=True) my_trans_stack, params = self.stackview.getStack() self.assertEqual(my_trans_stack.shape, self.mystack.shape) self.assertTrue(numpy.array_equal(self.mystack, my_trans_stack)) self.assertEqual(params["colormap"]["name"], "viridis") def testSetStackPerspective(self): self.stackview.setStack(self.mystack, perspective=1) # my_orig_stack, params = self.stackview.getStack() my_trans_stack, params = self.stackview.getCurrentView() # get stack returns the transposed data, depending on the perspective self.assertEqual(my_trans_stack.shape, (self.mystack.shape[1], self.mystack.shape[0], self.mystack.shape[2])) self.assertTrue(numpy.array_equal(numpy.transpose(self.mystack, axes=(1, 0, 2)), my_trans_stack)) def testSetStackListOfImages(self): loi = [self.mystack[i] for i in range(self.mystack.shape[0])] self.stackview.setStack(loi) my_orig_stack, params = self.stackview.getStack(returnNumpyArray=True) my_trans_stack, params = self.stackview.getStack(returnNumpyArray=True) self.assertEqual(my_trans_stack.shape, self.mystack.shape) self.assertTrue(numpy.array_equal(self.mystack, my_trans_stack)) self.assertTrue(numpy.array_equal(self.mystack, my_orig_stack)) self.assertIsInstance(my_trans_stack, numpy.ndarray) self.stackview.setStack(loi, perspective=2) my_orig_stack, params = self.stackview.getStack(copy=False) my_trans_stack, params = self.stackview.getCurrentView(copy=False) # getStack(copy=False) must return the object set in setStack self.assertIs(my_orig_stack, loi) # getCurrentView(copy=False) returns a ListOfImages whose .images # attr is the original data self.assertEqual(my_trans_stack.shape, (self.mystack.shape[2], self.mystack.shape[0], self.mystack.shape[1])) self.assertTrue(numpy.array_equal(numpy.array(my_trans_stack), numpy.transpose(self.mystack, axes=(2, 0, 1)))) self.assertIsInstance(my_trans_stack, ListOfImages) # returnNumpyArray=False by default in getStack self.assertIs(my_trans_stack.images, loi) def testPerspective(self): self.stackview.setStack(numpy.arange(24).reshape((2, 3, 4))) self.assertEqual(self.stackview._perspective, 0, "Default perspective is not 0 (dim1-dim2).") self.stackview._StackView__planeSelection.setPerspective(1) self.assertEqual(self.stackview._perspective, 1, "Plane selection combobox not updating perspective") self.stackview.setStack(numpy.arange(6).reshape((1, 2, 3))) self.assertEqual(self.stackview._perspective, 1, "Perspective not preserved when calling setStack " "without specifying the perspective parameter.") self.stackview.setStack(numpy.arange(24).reshape((2, 3, 4)), perspective=2) self.assertEqual(self.stackview._perspective, 2, "Perspective not set in setStack(..., perspective=2).") def testDefaultTitle(self): """Test that the plot title contains the proper Z information""" self.stackview.setStack(numpy.arange(24).reshape((4, 3, 2)), calibrations=[(0, 1), (-10, 10), (3.14, 3.14)]) self.assertEqual(self.stackview._plot.getGraphTitle(), "Image z=0") self.stackview.setFrameNumber(2) self.assertEqual(self.stackview._plot.getGraphTitle(), "Image z=2") self.stackview._StackView__planeSelection.setPerspective(1) self.stackview.setFrameNumber(0) self.assertEqual(self.stackview._plot.getGraphTitle(), "Image z=-10") self.stackview.setFrameNumber(2) self.assertEqual(self.stackview._plot.getGraphTitle(), "Image z=10") self.stackview._StackView__planeSelection.setPerspective(2) self.stackview.setFrameNumber(0) self.assertEqual(self.stackview._plot.getGraphTitle(), "Image z=3.14") self.stackview.setFrameNumber(1) self.assertEqual(self.stackview._plot.getGraphTitle(), "Image z=6.28") def testCustomTitle(self): """Test setting the plot title with a user defined callback""" self.stackview.setStack(numpy.arange(24).reshape((4, 3, 2)), calibrations=[(0, 1), (-10, 10), (3.14, 3.14)]) def title_callback(frame_idx): return "Cubed index title %d" % (frame_idx**3) self.stackview.setTitleCallback(title_callback) self.assertEqual(self.stackview._plot.getGraphTitle(), "Cubed index title 0") self.stackview.setFrameNumber(2) self.assertEqual(self.stackview._plot.getGraphTitle(), "Cubed index title 8") # perspective should not matter, only frame index self.stackview._StackView__planeSelection.setPerspective(1) self.stackview.setFrameNumber(0) self.assertEqual(self.stackview._plot.getGraphTitle(), "Cubed index title 0") self.stackview.setFrameNumber(2) self.assertEqual(self.stackview._plot.getGraphTitle(), "Cubed index title 8") with self.assertRaises(TypeError): # setTitleCallback should not accept non-callable objects like strings self.stackview.setTitleCallback( "Là, vous faites sirop de vingt-et-un et vous dites : " "beau sirop, mi-sirop, siroté, gagne-sirop, sirop-grelot," " passe-montagne, sirop au bon goût.") def testStackFrameNumber(self): self.stackview.setStack(self.mystack) self.assertEqual(self.stackview.getFrameNumber(), 0) listener = SignalListener() self.stackview.sigFrameChanged.connect(listener) self.stackview.setFrameNumber(1) self.assertEqual(self.stackview.getFrameNumber(), 1) self.assertEqual(listener.arguments(), [(1,)])
class TestStackView(TestCaseQt): """Base class for tests of StackView.""" def setUp(self): super(TestStackView, self).setUp() self.stackview = StackView() self.stackview.show() self.qWaitForWindowExposed(self.stackview) self.mystack = numpy.fromfunction( lambda i, j, k: numpy.sin(i / 15.) + numpy.cos(j / 4.) + 2 * numpy. sin(k / 6.), (10, 20, 30)) def tearDown(self): self.stackview.setAttribute(qt.Qt.WA_DeleteOnClose) self.stackview.close() del self.stackview super(TestStackView, self).tearDown() def testSetStack(self): self.stackview.setStack(self.mystack) self.stackview.setColormap("viridis", autoscale=True) my_trans_stack, params = self.stackview.getStack() self.assertEqual(my_trans_stack.shape, self.mystack.shape) self.assertTrue(numpy.array_equal(self.mystack, my_trans_stack)) self.assertEqual(params["colormap"]["name"], "viridis") def testSetStackPerspective(self): self.stackview.setStack(self.mystack, perspective=1) # my_orig_stack, params = self.stackview.getStack() my_trans_stack, params = self.stackview.getCurrentView() # get stack returns the transposed data, depending on the perspective self.assertEqual(my_trans_stack.shape, (self.mystack.shape[1], self.mystack.shape[0], self.mystack.shape[2])) self.assertTrue( numpy.array_equal(numpy.transpose(self.mystack, axes=(1, 0, 2)), my_trans_stack)) def testSetStackListOfImages(self): loi = [self.mystack[i] for i in range(self.mystack.shape[0])] self.stackview.setStack(loi) my_orig_stack, params = self.stackview.getStack(returnNumpyArray=True) my_trans_stack, params = self.stackview.getStack(returnNumpyArray=True) self.assertEqual(my_trans_stack.shape, self.mystack.shape) self.assertTrue(numpy.array_equal(self.mystack, my_trans_stack)) self.assertTrue(numpy.array_equal(self.mystack, my_orig_stack)) self.assertIsInstance(my_trans_stack, numpy.ndarray) self.stackview.setStack(loi, perspective=2) my_orig_stack, params = self.stackview.getStack(copy=False) my_trans_stack, params = self.stackview.getCurrentView(copy=False) # getStack(copy=False) must return the object set in setStack self.assertIs(my_orig_stack, loi) # getCurrentView(copy=False) returns a ListOfImages whose .images # attr is the original data self.assertEqual(my_trans_stack.shape, (self.mystack.shape[2], self.mystack.shape[0], self.mystack.shape[1])) self.assertTrue( numpy.array_equal(numpy.array(my_trans_stack), numpy.transpose(self.mystack, axes=(2, 0, 1)))) self.assertIsInstance( my_trans_stack, ListOfImages) # returnNumpyArray=False by default in getStack self.assertIs(my_trans_stack.images, loi) def testPerspective(self): self.stackview.setStack(numpy.arange(24).reshape((2, 3, 4))) self.assertEqual(self.stackview._perspective, 0, "Default perspective is not 0 (dim1-dim2).") self.stackview._StackView__planeSelection.setPerspective(1) self.assertEqual(self.stackview._perspective, 1, "Plane selection combobox not updating perspective") self.stackview.setStack(numpy.arange(6).reshape((1, 2, 3))) self.assertEqual(self.stackview._perspective, 0, "Default perspective not restored in setStack.") self.stackview.setStack(numpy.arange(24).reshape((2, 3, 4)), perspective=2) self.assertEqual( self.stackview._perspective, 2, "Perspective not set in setStack(..., perspective=2).") def testDefaultTitle(self): """Test that the plot title contains the proper Z information""" self.stackview.setStack(numpy.arange(24).reshape((4, 3, 2)), calibrations=[(0, 1), (-10, 10), (3.14, 3.14)]) self.assertEqual(self.stackview._plot.getGraphTitle(), "Image z=0") self.stackview.setFrameNumber(2) self.assertEqual(self.stackview._plot.getGraphTitle(), "Image z=2") self.stackview._StackView__planeSelection.setPerspective(1) self.stackview.setFrameNumber(0) self.assertEqual(self.stackview._plot.getGraphTitle(), "Image z=-10") self.stackview.setFrameNumber(2) self.assertEqual(self.stackview._plot.getGraphTitle(), "Image z=10") self.stackview._StackView__planeSelection.setPerspective(2) self.stackview.setFrameNumber(0) self.assertEqual(self.stackview._plot.getGraphTitle(), "Image z=3.14") self.stackview.setFrameNumber(1) self.assertEqual(self.stackview._plot.getGraphTitle(), "Image z=6.28") def testCustomTitle(self): """Test setting the plot title with a user defined callback""" self.stackview.setStack(numpy.arange(24).reshape((4, 3, 2)), calibrations=[(0, 1), (-10, 10), (3.14, 3.14)]) def title_callback(frame_idx): return "Cubed index title %d" % (frame_idx**3) self.stackview.setTitleCallback(title_callback) self.assertEqual(self.stackview._plot.getGraphTitle(), "Cubed index title 0") self.stackview.setFrameNumber(2) self.assertEqual(self.stackview._plot.getGraphTitle(), "Cubed index title 8") # perspective should not matter, only frame index self.stackview._StackView__planeSelection.setPerspective(1) self.stackview.setFrameNumber(0) self.assertEqual(self.stackview._plot.getGraphTitle(), "Cubed index title 0") self.stackview.setFrameNumber(2) self.assertEqual(self.stackview._plot.getGraphTitle(), "Cubed index title 8") with self.assertRaises(TypeError): # setTitleCallback should not accept non-callable objects like strings self.stackview.setTitleCallback( "Là, vous faites sirop de vingt-et-un et vous dites : " "beau sirop, mi-sirop, siroté, gagne-sirop, sirop-grelot," " passe-montagne, sirop au bon goût.")
class TestStackView(TestCaseQt): """Base class for tests of StackView.""" def setUp(self): super(TestStackView, self).setUp() self.stackview = StackView() self.stackview.show() self.qWaitForWindowExposed(self.stackview) self.mystack = numpy.fromfunction( lambda i, j, k: numpy.sin(i / 15.) + numpy.cos(j / 4.) + 2 * numpy. sin(k / 6.), (10, 20, 30)) def tearDown(self): self.stackview.setAttribute(qt.Qt.WA_DeleteOnClose) self.stackview.close() del self.stackview super(TestStackView, self).tearDown() def testSetStack(self): self.stackview.setStack(self.mystack) self.stackview.setColormap("viridis", autoscale=True) my_trans_stack, params = self.stackview.getStack() self.assertEqual(my_trans_stack.shape, self.mystack.shape) self.assertTrue(numpy.array_equal(self.mystack, my_trans_stack)) self.assertEqual(params["colormap"]["name"], "viridis") def testSetStackPerspective(self): self.stackview.setStack(self.mystack, perspective=1) # my_orig_stack, params = self.stackview.getStack() my_trans_stack, params = self.stackview.getCurrentView() # get stack returns the transposed data, depending on the perspective self.assertEqual(my_trans_stack.shape, (self.mystack.shape[1], self.mystack.shape[0], self.mystack.shape[2])) self.assertTrue( numpy.array_equal(numpy.transpose(self.mystack, axes=(1, 0, 2)), my_trans_stack)) def testSetStackListOfImages(self): loi = [self.mystack[i] for i in range(self.mystack.shape[0])] self.stackview.setStack(loi) my_orig_stack, params = self.stackview.getStack(returnNumpyArray=True) my_trans_stack, params = self.stackview.getStack(returnNumpyArray=True) self.assertEqual(my_trans_stack.shape, self.mystack.shape) self.assertTrue(numpy.array_equal(self.mystack, my_trans_stack)) self.assertTrue(numpy.array_equal(self.mystack, my_orig_stack)) self.assertIsInstance(my_trans_stack, numpy.ndarray) self.stackview.setStack(loi, perspective=2) my_orig_stack, params = self.stackview.getStack(copy=False) my_trans_stack, params = self.stackview.getCurrentView(copy=False) # getStack(copy=False) must return the object set in setStack self.assertIs(my_orig_stack, loi) # getCurrentView(copy=False) returns a ListOfImages whose .images # attr is the original data self.assertEqual(my_trans_stack.shape, (self.mystack.shape[2], self.mystack.shape[0], self.mystack.shape[1])) self.assertTrue( numpy.array_equal(numpy.array(my_trans_stack), numpy.transpose(self.mystack, axes=(2, 0, 1)))) self.assertIsInstance( my_trans_stack, ListOfImages) # returnNumpyArray=False by default in getStack self.assertIs(my_trans_stack.images, loi) def testPerspective(self): self.stackview.setStack(numpy.arange(24).reshape((2, 3, 4))) self.assertEqual(self.stackview._perspective, 0, "Default perspective is not 0 (dim1-dim2).") self.stackview._StackView__planeSelection.setPerspective(1) self.assertEqual(self.stackview._perspective, 1, "Plane selection combobox not updating perspective") self.stackview.setStack(numpy.arange(6).reshape((1, 2, 3))) self.assertEqual(self.stackview._perspective, 0, "Default perspective not restored in setStack.") self.stackview.setStack(numpy.arange(24).reshape((2, 3, 4)), perspective=2) self.assertEqual( self.stackview._perspective, 2, "Perspective not set in setStack(..., perspective=2).")
def plot3Dsilx(nodeData): from silx.gui.plot import StackView saveType = nodeData[0] plot = StackView() plot.setColormap('viridis') plot.setGraphTitle(nodeData[1] + ' ' + saveType) plot.setLabels(nodeData[3]) savedColumns = nodeData[4] for fname, props in savedColumns.items(): maps = read3D(saveType, fname, props) # applied only to one (first) 3D map: v = maps[0] plot.setStack(v) # plot.saveGraph('test.png') plot.show() # end plot3Dsilx