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
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()