class TestCurvesROIWidget(TestCaseQt): """Basic test for CurvesROIWidget""" def setUp(self): super(TestCurvesROIWidget, self).setUp() self.plot = PlotWindow() self.plot.show() self.qWaitForWindowExposed(self.plot) self.widget = CurvesROIWidget.CurvesROIDockWidget(plot=self.plot, name='TEST') self.widget.show() self.qWaitForWindowExposed(self.widget) def tearDown(self): self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() del self.plot self.widget.setAttribute(qt.Qt.WA_DeleteOnClose) self.widget.close() del self.widget super(TestCurvesROIWidget, self).tearDown() def testEmptyPlot(self): """Empty plot, display ROI widget""" pass def testWithCurves(self): """Plot with curves: test all ROI widget buttons""" for offset in range(2): self.plot.addCurve(numpy.arange(1000), offset + numpy.random.random(1000), legend=str(offset)) # Add two ROI self.mouseClick(self.widget.roiWidget.addButton, qt.Qt.LeftButton) self.mouseClick(self.widget.roiWidget.addButton, qt.Qt.LeftButton) # Change active curve self.plot.setActiveCurve(str(1)) # Delete a ROI self.mouseClick(self.widget.roiWidget.delButton, qt.Qt.LeftButton) with temp_dir() as tmpDir: self.tmpFile = os.path.join(tmpDir, 'test.ini') # Save ROIs self.widget.roiWidget.save(self.tmpFile) self.assertTrue(os.path.isfile(self.tmpFile)) # Reset ROIs self.mouseClick(self.widget.roiWidget.resetButton, qt.Qt.LeftButton) # Load ROIs self.widget.roiWidget.load(self.tmpFile) del self.tmpFile
def __init__(self, parent=None): qt.QWidget.__init__(self, parent) self.setWindowTitle("Strip and SNIP Configuration Window") self.mainLayout = qt.QVBoxLayout(self) self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(2) self.parametersWidget = StripParametersWidget(self) self.graphWidget = PlotWindow(self, position=False, aspectRatio=False, colormap=False, yInverted=False, roi=False, mask=False, fit=False) toolBar = self.graphWidget.getInteractiveModeToolBar() toolBar.getZoomModeAction().setVisible(False) toolBar.getPanModeAction().setVisible(False) self.mainLayout.addWidget(self.parametersWidget) self.mainLayout.addWidget(self.graphWidget) self.getParameters = self.parametersWidget.getParameters self.setParameters = self.parametersWidget.setParameters self._x = None self._y = None self.parametersWidget.sigStripParametersWidgetSignal.connect( \ self._slot)
def __init__(self, parent=None, initdict=None): qt.QWidget.__init__(self, parent) self.l = qt.QVBoxLayout(self) self.l.setContentsMargins(0, 0, 0, 0) self.l.setSpacing(0) self.tubeWidget = TubeWidget(self, initdict=initdict) self.setParameters = self.tubeWidget.setParameters self.getParameters = self.tubeWidget.getParameters label = qt.QLabel(self) hbox = qt.QWidget(self) hboxl = qt.QHBoxLayout(hbox) hboxl.setContentsMargins(0, 0, 0, 0) hboxl.setSpacing(0) self.plotButton = qt.QPushButton(hbox) self.plotButton.setText("Plot Continuum") self.exportButton = qt.QPushButton(hbox) self.exportButton.setText("Export to Fit") #grid.addWidget(self.plotButton, 7, 1) #grid.addWidget(self.exportButton, 7, 3) hboxl.addWidget(self.plotButton) hboxl.addWidget(self.exportButton) self.l.addWidget(self.tubeWidget) f = label.font() f.setItalic(1) label.setFont(f) label.setAlignment(qt.Qt.AlignRight) label.setText("H. Ebel, X-Ray Spectrometry 28 (1999) 255-266 ") self.l.addWidget(label) self.l.addWidget(hbox) self.graph = PlotWindow(self, colormap=False, yInverted=False, aspectRatio=False, control=False, position=False, roi=False, mask=False, fit=False) self.pluginsToolButton = PluginsToolButton(plot=self.graph) self.graph.toolBar().addWidget(self.pluginsToolButton) self.graph.getInteractiveModeToolBar().getZoomModeAction().setVisible( False) self.graph.getInteractiveModeToolBar().getPanModeAction().setVisible( False) self.l.addWidget(self.graph) self.graph.setGraphXLabel("Energy (keV)") self.graph.setGraphYLabel("photons/sr/mA/keV/s") self.plotButton.clicked.connect(self.plot) self.exportButton.clicked.connect(self._export)
def testCustomProfileWindow(self): from silx.gui.plot import ProfileMainWindow self.plot = PlotWindow() profileWindow = ProfileMainWindow.ProfileMainWindow(self.plot) toolBar = Profile.ProfileToolBar(parent=self.plot, plot=self.plot, profileWindow=profileWindow) self.plot.show() self.qWaitForWindowExposed(self.plot) profileWindow.show() self.qWaitForWindowExposed(profileWindow) self.qapp.processEvents() self.plot.addImage(numpy.arange(10 * 10).reshape(10, -1)) profile = rois.ProfileImageHorizontalLineROI() profile.setPosition(5) toolBar.getProfileManager().getRoiManager().addRoi(profile) toolBar.getProfileManager().getRoiManager().setCurrentRoi(profile) for _ in range(20): self.qWait(200) if not toolBar.getProfileManager().hasPendingOperations(): break # There is a displayed profile self.assertIsNotNone(profileWindow.getProfile()) self.assertIs(toolBar.getProfileMainWindow(), profileWindow) # There is nothing anymore but the window is still there toolBar.getProfileManager().clearProfile() self.qapp.processEvents() self.assertIsNone(profileWindow.getProfile())
def setUp(self): super(TestPositionInfo, self).setUp() self.plot = PlotWindow() self.plot.show() self.qWaitForWindowExposed(self.plot) self.mouseMove(self.plot, pos=(1, 1)) self.qapp.processEvents() self.qWait(100)
def setUp(self): super(TestScatterProfileToolBar, self).setUp() self.plot = PlotWindow() self.manager = manager.ProfileManager(plot=self.plot) self.manager.setItemType(scatter=True) self.manager.setActiveItemTracking(True) self.plot.show() self.qWaitForWindowExposed(self.plot)
def setUp(self): super(TestCurvesROIWidget, self).setUp() self.plot = PlotWindow() self.plot.show() self.qWaitForWindowExposed(self.plot) self.widget = CurvesROIWidget.CurvesROIDockWidget(plot=self.plot, name='TEST') self.widget.show() self.qWaitForWindowExposed(self.widget)
def setUp(self): super(TestCurvesROIWidget, self).setUp() self.plot = PlotWindow() self.plot.show() self.qWaitForWindowExposed(self.plot) self.widget = self.plot.getCurvesRoiDockWidget() self.widget.show() self.qWaitForWindowExposed(self.widget)
def setUp(self): super(TestScatterProfileToolBar, self).setUp() self.plot = PlotWindow() self.profile = profile.ScatterProfileToolBar(plot=self.plot) self.plot.addToolBar(self.profile) self.plot.show() self.qWaitForWindowExposed(self.plot)
def __init__(self, parent=None, analyzer=None, backend=None): super(XASMdiArea, self).__init__(parent) if analyzer is None: analyzer = XASClass.XASClass() self.analyzer = analyzer #self.setActivationOrder(qt.QMdiArea.CreationOrder) self._windowDict = {} self._windowList = ["Spectrum", "Post-edge", "Signal", "FT"] self._windowList.reverse() for title in self._windowList: plot = PlotWindow(self, position=True, aspectRatio=False, colormap=False, yInverted=False, roi=False, mask=False, fit=False, backend=backend) toolbar = plot.getInteractiveModeToolBar() toolbar.getZoomModeAction().setVisible(False) toolbar.getPanModeAction().setVisible(False) pluginsToolButton = PluginsToolButton(plot=plot) plot.toolBar().addWidget(pluginsToolButton) plot.setWindowTitle(title) self.addSubWindow(plot) self._windowDict[title] = plot plot.setDataMargins(0, 0, 0.025, 0.025) self._windowList.reverse() self.setActivationOrder(qt.QMdiArea.StackingOrder) self.tileSubWindows()
def setUp(self): super(TestRegionOfInterestManager, self).setUp() self.plot = PlotWindow() self.roiTableWidget = roi.RegionOfInterestTableWidget() dock = qt.QDockWidget() dock.setWidget(self.roiTableWidget) self.plot.addDockWidget(qt.Qt.BottomDockWidgetArea, dock) self.plot.show() self.qWaitForWindowExposed(self.plot)
def setUp(self): super(TestProfileToolBar, self).setUp() self.plot = PlotWindow() self.toolBar = Profile.ProfileToolBar(plot=self.plot) self.plot.addToolBar(self.toolBar) self.plot.show() self.qWaitForWindowExposed(self.plot) self.mouseMove(self.plot) # Move to center self.qapp.processEvents() deprecation.FORCE = True
def setUp(self): super(TestMaskToolsWidget, self).setUp() self.plot = PlotWindow() self.widget = MaskToolsWidget.MaskToolsDockWidget(plot=self.plot, name='TEST') self.plot.addDockWidget(qt.Qt.BottomDockWidgetArea, self.widget) self.plot.show() self.qWaitForWindowExposed(self.plot) self.maskWidget = self.widget.widget()
def __init__(self, *args): super(PlotWidget, self).__init__( logScale=False, grid=True, yInverted=False, roi=False, mask=False, print_=False, backend=BackendMatplotlibQt) self.setActiveCurveHandling(False) self.setGraphGrid('both') profileWindow = PlotWindow( logScale=False, grid=True, yInverted=False, roi=False, mask=False, print_=False) profileWindow.setWindowTitle('') self.profile = ProfileToolBar(plot=self, profileWindow=profileWindow) self.addToolBar(self.profile)
def setUp(self): super(TestCurveLegendsWidget, self).setUp() self.plot = PlotWindow() self.legends = CurveLegendsWidget.CurveLegendsWidget() self.legends.setPlotWidget(self.plot) dock = qt.QDockWidget() dock.setWindowTitle('Curve Legends') dock.setWidget(self.legends) self.plot.addTabbedDockWidget(dock) self.plot.show() self.qWaitForWindowExposed(self.plot)
class TestDeprecatedProfileToolBar(TestCaseQt): """Tests old features of the ProfileToolBar widget.""" def setUp(self): self.plot = None super(TestDeprecatedProfileToolBar, self).setUp() def tearDown(self): if self.plot is not None: self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() self.plot = None self.qWait() super(TestDeprecatedProfileToolBar, self).tearDown() @testutils.test_logging(deprecation.depreclog.name, warning=2) def testCustomProfileWindow(self): from silx.gui.plot import ProfileMainWindow self.plot = PlotWindow() profileWindow = ProfileMainWindow.ProfileMainWindow(self.plot) toolBar = Profile.ProfileToolBar(parent=self.plot, plot=self.plot, profileWindow=profileWindow) self.plot.show() self.qWaitForWindowExposed(self.plot) profileWindow.show() self.qWaitForWindowExposed(profileWindow) self.qapp.processEvents() self.plot.addImage(numpy.arange(10 * 10).reshape(10, -1)) profile = rois.ProfileImageHorizontalLineROI() profile.setPosition(5) toolBar.getProfileManager().getRoiManager().addRoi(profile) toolBar.getProfileManager().getRoiManager().setCurrentRoi(profile) for _ in range(20): self.qWait(200) if not toolBar.getProfileManager().hasPendingOperations(): break # There is a displayed profile self.assertIsNotNone(profileWindow.getProfile()) self.assertIs(toolBar.getProfileMainWindow(), profileWindow) # There is nothing anymore but the window is still there toolBar.getProfileManager().clearProfile() self.qapp.processEvents() self.assertIsNone(profileWindow.getProfile())
def setUp(self): super(TestProfileToolBar, self).setUp() profileWindow = PlotWindow() self.plot = PlotWindow() self.toolBar = Profile.ProfileToolBar( plot=self.plot, profileWindow=profileWindow) self.plot.addToolBar(self.toolBar) self.plot.show() self.qWaitForWindowExposed(self.plot) profileWindow.show() self.qWaitForWindowExposed(profileWindow) self.mouseMove(self.plot) # Move to center self.qapp.processEvents()
def build(self,comments, height): a = [] for key in Elements.Material.keys(): a.append(key) a.sort() if self.__toolMode: layout = qt.QHBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) else: layout = qt.QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) self.__hboxMaterialCombo = qt.QWidget(self) hbox = self.__hboxMaterialCombo hboxlayout = qt.QHBoxLayout(hbox) hboxlayout.setContentsMargins(0, 0, 0, 0) hboxlayout.setSpacing(0) label = qt.QLabel(hbox) label.setText("Enter name of material to be defined:") self.matCombo = MaterialComboBox(hbox,options=a) hboxlayout.addWidget(label) hboxlayout.addWidget(self.matCombo) layout.addWidget(hbox) #self.matCombo.setEditable(True) self.matCombo.sigMaterialComboBoxSignal.connect( \ self._comboSlot) self.materialGUI = MaterialGUI(self, comments=comments, height=height, toolmode=self.__toolMode) self.materialGUI.sigMaterialTransmissionSignal.connect( \ self._transmissionSlot) self.materialGUI.sigMaterialMassAttenuationSignal.connect( \ self._massAttenuationSlot) if self.__toolMode: self.materialGUI.setCurrent(a[0]) if (self.graph is None): self.graph = PlotWindow(self, control=True, position=True, colormap=False, aspectRatio=False, yInverted=False, roi=False, mask=False) self.graph.setDefaultPlotPoints(True) layout.addWidget(self.materialGUI) layout.addWidget(self.graph) else: self.materialGUI.setCurrent(a[0]) layout.addWidget(self.materialGUI)
def setUp(self): super(TestPositionInfo, self).setUp() self.plot = PlotWindow() self.plot.show() self.qWaitForWindowExposed(self.plot) self.mouseMove(self.plot) # Move to center self.qapp.processEvents()
def __init__(self, parent, spectrum, energy=None): qt.QWidget.__init__(self, parent) self.setWindowTitle("XAS Normalization Configuration Window") self.mainLayout = qt.QVBoxLayout(self) self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(2) if energy is None: self.energy = range(len(spectrum)) else: self.energy = energy self.spectrum = spectrum self.parametersWidget = XASNormalizationParametersWidget(self) self.graph = PlotWindow(self, position=False, aspectRatio=False, colormap=False, yInverted=False, roi=False, mask=False, fit=False) # next two lines deprecated with silx 0.8.0 # self.graph.zoomModeAction.setVisible(False) # self.graph.panModeAction.setVisible(False) toolbar = self.graph.getInteractiveModeToolBar() toolbar.getZoomModeAction().setVisible(False) toolbar.getPanModeAction().setVisible(False) self.__lastDict = {} self.graph.sigPlotSignal.connect(self._handleGraphSignal) self.graph.addCurve(self.energy, spectrum, legend="Spectrum") self.graph.setActiveCurve("Spectrum") self.mainLayout.addWidget(self.parametersWidget) self.mainLayout.addWidget(self.graph) # initialize variables edgeEnergy, sortedX, sortedY, xPrime, yPrime =\ XASNormalization.estimateXANESEdge(spectrum, energy=self.energy, full=True) self._xPrime = xPrime self._yPrime = yPrime self.parametersWidget.setEdgeEnergy(edgeEnergy, emin=self.energy.min(), emax=self.energy.max()) self.getParameters = self.parametersWidget.getParameters self.setParameters = self.parametersWidget.setParameters self.parametersWidget.sigXASNormalizationParametersSignal.connect( \ self.updateGraph) self.updateGraph(self.getParameters())
def __init__(self, parent=None, initdict = None): qt.QWidget.__init__(self, parent) self.l = qt.QVBoxLayout(self) self.l.setContentsMargins(0, 0, 0, 0) self.l.setSpacing(0) self.tubeWidget = TubeWidget(self, initdict = initdict) self.setParameters = self.tubeWidget.setParameters self.getParameters = self.tubeWidget.getParameters label = qt.QLabel(self) hbox = qt.QWidget(self) hboxl = qt.QHBoxLayout(hbox) hboxl.setContentsMargins(0, 0, 0, 0) hboxl.setSpacing(0) self.plotButton = qt.QPushButton(hbox) self.plotButton.setText("Plot Continuum") self.exportButton = qt.QPushButton(hbox) self.exportButton.setText("Export to Fit") #grid.addWidget(self.plotButton, 7, 1) #grid.addWidget(self.exportButton, 7, 3) hboxl.addWidget(self.plotButton) hboxl.addWidget(self.exportButton) self.l.addWidget(self.tubeWidget) f = label.font() f.setItalic(1) label.setFont(f) label.setAlignment(qt.Qt.AlignRight) label.setText("H. Ebel, X-Ray Spectrometry 28 (1999) 255-266 ") self.l.addWidget(label) self.l.addWidget(hbox) self.graph = PlotWindow(self, colormap=False, yInverted=False, aspectRatio=False, control=False, position=False, roi=False, mask=False, fit=False) self.pluginsToolButton = PluginsToolButton(plot=self.graph) self.graph.toolBar().addWidget(self.pluginsToolButton) self.graph.getInteractiveModeToolBar().getZoomModeAction().setVisible(False) self.graph.getInteractiveModeToolBar().getPanModeAction().setVisible(False) self.l.addWidget(self.graph) self.graph.setGraphXLabel("Energy (keV)") self.graph.setGraphYLabel("photons/sr/mA/keV/s") self.plotButton.clicked.connect(self.plot) self.exportButton.clicked.connect(self._export)
def setUp(self): super(TestMaskToolsWidget, self).setUp() self.plot = PlotWindow() self.widget = MaskToolsWidget.MaskToolsDockWidget(self.plot, 'TEST') self.plot.addDockWidget(qt.Qt.BottomDockWidgetArea, self.widget) self.plot.show() self.qWaitForWindowExposed(self.plot) self.maskWidget = self.widget.widget()
def setUp(self): TestCaseQt.setUp(self) # define plot self.plot = PlotWindow() self.plot.addImage(numpy.arange(10000).reshape(100, 100), legend='img1') self.img_item = self.plot.getImage('img1') self.plot.addCurve(x=numpy.linspace(0, 10, 56), y=numpy.arange(56), legend='curve1') self.curve_item = self.plot.getCurve('curve1') self.plot.addHistogram(edges=numpy.linspace(0, 10, 56), histogram=numpy.arange(56), legend='histo1') self.histogram_item = self.plot.getHistogram(legend='histo1') self.plot.addScatter(x=numpy.linspace(0, 10, 56), y=numpy.linspace(0, 10, 56), value=numpy.arange(56), legend='scatter1') self.scatter_item = self.plot.getScatter(legend='scatter1') # stats widget self.statsWidget = ROIStatsWidget(plot=self.plot) # define stats stats = [ ('sum', numpy.sum), ('mean', numpy.mean), ] self.statsWidget.setStats(stats=stats) # define rois self.roi1D = ROI(name='range1', fromdata=0, todata=4, type_='energy') self.rectangle_roi = RectangleROI() self.rectangle_roi.setGeometry(origin=(0, 0), size=(20, 20)) self.rectangle_roi.setName('Initial ROI') self.polygon_roi = PolygonROI() points = numpy.array([[0, 5], [5, 0], [10, 5], [5, 10]]) self.polygon_roi.setPoints(points)
class TestPlotWindow(TestCaseQt): """Base class for tests of PlotWindow.""" def setUp(self): super(TestPlotWindow, self).setUp() self.plot = PlotWindow() self.plot.show() self.qWaitForWindowExposed(self.plot) def tearDown(self): self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() del self.plot super(TestPlotWindow, self).tearDown() def testActions(self): """Test the actions QToolButtons""" self.plot.setLimits(1, 100, 1, 100) checkList = [ # QAction, Plot state getter (self.plot.xAxisAutoScaleAction, self.plot.isXAxisAutoScale), (self.plot.yAxisAutoScaleAction, self.plot.isYAxisAutoScale), (self.plot.xAxisLogarithmicAction, self.plot.isXAxisLogarithmic), (self.plot.yAxisLogarithmicAction, self.plot.isYAxisLogarithmic), (self.plot.gridAction, self.plot.getGraphGrid), (self.plot.keepDataAspectRatioAction, self.plot.isKeepDataAspectRatio), (self.plot.yAxisInvertedAction, self.plot.isYAxisInverted), ] for action, getter in checkList: self.mouseMove(self.plot) initialState = getter() toolButton = getQToolButtonFromAction(action) self.assertIsNot(toolButton, None) self.mouseClick(toolButton, qt.Qt.LeftButton) self.assertNotEqual(getter(), initialState, msg='"%s" state not changed' % action.text()) self.mouseClick(toolButton, qt.Qt.LeftButton) self.assertEqual(getter(), initialState, msg='"%s" state not changed' % action.text()) # Trigger a zoom reset self.mouseMove(self.plot) resetZoomAction = self.plot.resetZoomAction toolButton = getQToolButtonFromAction(resetZoomAction) self.assertIsNot(toolButton, None) self.mouseClick(toolButton, qt.Qt.LeftButton)
def plot_histo(self, x, y, progressBarValue, tabs_canvas_index, plot_canvas_index, title="", xtitle="", ytitle="", log_x=False, log_y=False, color='blue', replace=True, control=False): if self.plot_canvas[plot_canvas_index] is None: self.plot_canvas[plot_canvas_index] = PlotWindow(parent=None, backend=None, resetzoom=True, autoScale=False, logScale=True, grid=True, curveStyle=True, colormap=False, aspectRatio=False, yInverted=False, copy=True, save=True, print_=True, control=control, position=True, roi=False, mask=False, fit=False) self.plot_canvas[plot_canvas_index].setDefaultPlotLines(True) self.plot_canvas[plot_canvas_index].setActiveCurveColor(color="#00008B") self.plot_canvas[plot_canvas_index].setGraphXLabel(xtitle) self.plot_canvas[plot_canvas_index].setGraphYLabel(ytitle) self.tab[tabs_canvas_index].layout().addWidget(self.plot_canvas[plot_canvas_index]) XoppyPlot.plot_histo(self.plot_canvas[plot_canvas_index], x, y, title, xtitle, ytitle, color, replace) self.plot_canvas[plot_canvas_index].setXAxisLogarithmic(log_x) self.plot_canvas[plot_canvas_index].setYAxisLogarithmic(log_y) if min(y) < 0: if log_y: self.plot_canvas[plot_canvas_index].setGraphYLimits(min(y)*1.2, max(y)*1.2) else: self.plot_canvas[plot_canvas_index].setGraphYLimits(min(y)*1.01, max(y)*1.01) else: if log_y: self.plot_canvas[plot_canvas_index].setGraphYLimits(min(y), max(y)*1.2) else: self.plot_canvas[plot_canvas_index].setGraphYLimits(min(y), max(y)*1.01) self.progressBarSet(progressBarValue)
def plot_data1D(self, dataX, dataY, tabs_canvas_index, plot_canvas_index, title="", xtitle="", ytitle=""): self.tab[tabs_canvas_index].layout().removeItem(self.tab[tabs_canvas_index].layout().itemAt(0)) self.plot_canvas[plot_canvas_index] = PlotWindow() self.plot_canvas[plot_canvas_index].addCurve(dataX, dataY,) self.plot_canvas[plot_canvas_index].resetZoom() self.plot_canvas[plot_canvas_index].setXAxisAutoScale(True) self.plot_canvas[plot_canvas_index].setYAxisAutoScale(True) self.plot_canvas[plot_canvas_index].setGraphGrid(False) self.plot_canvas[plot_canvas_index].setXAxisLogarithmic(False) self.plot_canvas[plot_canvas_index].setYAxisLogarithmic(False) self.plot_canvas[plot_canvas_index].setGraphXLabel(xtitle) self.plot_canvas[plot_canvas_index].setGraphYLabel(ytitle) self.plot_canvas[plot_canvas_index].setGraphTitle(title) self.tab[tabs_canvas_index].layout().addWidget(self.plot_canvas[plot_canvas_index])
def __init__(self, parent=None, backend=None): super(RateLawMdiArea, self).__init__(parent) self._windowDict = {} self._windowList = ["Original", "Zero", "First", "Second"] self._windowList.reverse() for title in self._windowList: plot = PlotWindow(self, position=True, backend=backend, colormap=False, aspectRatio=False, yInverted=False, roi=False, mask=False) self.pluginsToolButton = PluginsToolButton(plot=plot) plot.toolBar().addWidget(self.pluginsToolButton) plot.setWindowTitle(title) self.addSubWindow(plot) self._windowDict[title] = plot plot.setDataMargins(0, 0, 0.025, 0.025) self._windowList.reverse() self.setActivationOrder(qt.QMdiArea.StackingOrder) self.tileSubWindows()
def plot_array(ar, title, xlabel, ylabel): window = PlotWindow(fit=True) window.setGraphTitle(title) window.addCurve(ar[:, 0], ar[:, 1], xlabel=xlabel, ylabel=ylabel) window.show()
def __init__(self, parent=None, fit=None, graph=None, actions=True): qt.QWidget.__init__(self, parent) self.setWindowTitle("SimpleFitGui") if fit is None: self.fitModule = SimpleFitModule.SimpleFit() self.fitModule.importFunctions(SimpleFitUserEstimatedFunctions) self.fitModule.loadUserFunctions() else: self.fitModule = fit if graph is None: self.__useTab = True self.graph = PlotWindow(self, aspectRatio=False, colormap=False, yInverted=False, roi=False, mask=False, fit=False, control=True, position=True) self.graph.getInteractiveModeToolBar().setVisible(False) # No context menu by default, execute zoomBack on right click plotArea = self.graph.getWidgetHandle() plotArea.setContextMenuPolicy(qt.Qt.CustomContextMenu) plotArea.customContextMenuRequested.connect(self._zoomBack) else: self.__useTab = False self.graph = graph self._configurationDialog = None self.mainLayout = qt.QVBoxLayout(self) self.mainLayout.setContentsMargins(2, 2, 2, 2) self.mainLayout.setSpacing(2) self.topWidget = TopWidget(self) config = self.fitModule.getConfiguration() self.topWidget.setFunctions(config['fit']['functions']) config = None if self.__useTab: self.mainTab = qt.QTabWidget(self) self.mainLayout.addWidget(self.mainTab) self.parametersTable = Parameters.Parameters() self.mainTab.addTab(self.graph, 'GRAPH') self.mainTab.addTab(self.parametersTable, 'FIT') else: self.parametersTable = Parameters.Parameters(self) self.statusWidget = StatusWidget(self) self.mainLayout.addWidget(self.topWidget) if self.__useTab: self.mainLayout.addWidget(self.mainTab) else: self.mainLayout.addWidget(self.parametersTable) self.mainLayout.addWidget(self.statusWidget) if actions: #build the actions widget self.fitActions = qt.QWidget(self) self.fitActions.mainLayout = qt.QHBoxLayout(self.fitActions) self.fitActions.mainLayout.setContentsMargins(2, 2, 2, 2) self.fitActions.mainLayout.setSpacing(2) self.fitActions.estimateButton = qt.QPushButton(self.fitActions) self.fitActions.estimateButton.setText("Estimate") self.fitActions.startFitButton = qt.QPushButton(self.fitActions) self.fitActions.startFitButton.setText("Start Fit") self.fitActions.dismissButton = qt.QPushButton(self.fitActions) self.fitActions.dismissButton.setText("Dismiss") self.fitActions.mainLayout.addWidget(self.fitActions.estimateButton) self.fitActions.mainLayout.addWidget(self.fitActions.startFitButton) self.fitActions.mainLayout.addWidget(self.fitActions.dismissButton) self.mainLayout.addWidget(self.fitActions) #connect top widget self.topWidget.addFunctionButton.clicked.connect(\ self.importFunctions) self.topWidget.fitFunctionCombo.currentIndexChanged[int].connect(\ self.fitFunctionComboSlot) self.topWidget.backgroundCombo.currentIndexChanged[int].connect(\ self.backgroundComboSlot) self.topWidget.configureButton.clicked.connect(\ self.configureButtonSlot) if actions: #connect actions self.fitActions.estimateButton.clicked.connect(self.estimate) self.fitActions.startFitButton.clicked.connect(self.startFit) self.fitActions.dismissButton.clicked.connect(self.dismiss)
class SimpleFitGui(qt.QWidget): sigSimpleFitSignal = qt.pyqtSignal(object) def __init__(self, parent=None, fit=None, graph=None, actions=True): qt.QWidget.__init__(self, parent) self.setWindowTitle("SimpleFitGui") if fit is None: self.fitModule = SimpleFitModule.SimpleFit() self.fitModule.importFunctions(SimpleFitUserEstimatedFunctions) self.fitModule.loadUserFunctions() else: self.fitModule = fit if graph is None: self.__useTab = True self.graph = PlotWindow(self, aspectRatio=False, colormap=False, yInverted=False, roi=False, mask=False, fit=False, control=True, position=True) self.graph.getInteractiveModeToolBar().setVisible(False) # No context menu by default, execute zoomBack on right click plotArea = self.graph.getWidgetHandle() plotArea.setContextMenuPolicy(qt.Qt.CustomContextMenu) plotArea.customContextMenuRequested.connect(self._zoomBack) else: self.__useTab = False self.graph = graph self._configurationDialog = None self.mainLayout = qt.QVBoxLayout(self) self.mainLayout.setContentsMargins(2, 2, 2, 2) self.mainLayout.setSpacing(2) self.topWidget = TopWidget(self) config = self.fitModule.getConfiguration() self.topWidget.setFunctions(config['fit']['functions']) config = None if self.__useTab: self.mainTab = qt.QTabWidget(self) self.mainLayout.addWidget(self.mainTab) self.parametersTable = Parameters.Parameters() self.mainTab.addTab(self.graph, 'GRAPH') self.mainTab.addTab(self.parametersTable, 'FIT') else: self.parametersTable = Parameters.Parameters(self) self.statusWidget = StatusWidget(self) self.mainLayout.addWidget(self.topWidget) if self.__useTab: self.mainLayout.addWidget(self.mainTab) else: self.mainLayout.addWidget(self.parametersTable) self.mainLayout.addWidget(self.statusWidget) if actions: #build the actions widget self.fitActions = qt.QWidget(self) self.fitActions.mainLayout = qt.QHBoxLayout(self.fitActions) self.fitActions.mainLayout.setContentsMargins(2, 2, 2, 2) self.fitActions.mainLayout.setSpacing(2) self.fitActions.estimateButton = qt.QPushButton(self.fitActions) self.fitActions.estimateButton.setText("Estimate") self.fitActions.startFitButton = qt.QPushButton(self.fitActions) self.fitActions.startFitButton.setText("Start Fit") self.fitActions.dismissButton = qt.QPushButton(self.fitActions) self.fitActions.dismissButton.setText("Dismiss") self.fitActions.mainLayout.addWidget(self.fitActions.estimateButton) self.fitActions.mainLayout.addWidget(self.fitActions.startFitButton) self.fitActions.mainLayout.addWidget(self.fitActions.dismissButton) self.mainLayout.addWidget(self.fitActions) #connect top widget self.topWidget.addFunctionButton.clicked.connect(\ self.importFunctions) self.topWidget.fitFunctionCombo.currentIndexChanged[int].connect(\ self.fitFunctionComboSlot) self.topWidget.backgroundCombo.currentIndexChanged[int].connect(\ self.backgroundComboSlot) self.topWidget.configureButton.clicked.connect(\ self.configureButtonSlot) if actions: #connect actions self.fitActions.estimateButton.clicked.connect(self.estimate) self.fitActions.startFitButton.clicked.connect(self.startFit) self.fitActions.dismissButton.clicked.connect(self.dismiss) def importFunctions(self, functionsfile=None): if functionsfile is None: fn = qt.QFileDialog.getOpenFileName() if fn.isEmpty(): functionsfile = "" else: functionsfile= qt.safe_str(fn) if not len(functionsfile): return try: self.fitModule.importFunctions(functionsfile) except: if _logger.getEffectiveLevel() == logging.DEBUG: raise qt.QMessageBox.critical(self, "ERROR", "Function not imported") config = self.fitModule.getConfiguration() self.topWidget.setFunctions(config['fit']['functions']) def fitFunctionComboSlot(self, idx): if idx <= 0: fname = "None" else: fname = qt.safe_str(self.topWidget.fitFunctionCombo.itemText(idx)) self.fitModule.setFitFunction(fname) def backgroundComboSlot(self, idx): if idx <= 0: fname = "None" else: fname = qt.safe_str(self.topWidget.backgroundCombo.itemText(idx)) self.setBackgroundFunction(fname) def configureButtonSlot(self): if self._configurationDialog is None: self._configurationDialog =\ SimpleFitConfigurationGui.SimpleFitConfigurationGui() self._configurationDialog.setSimpleFitInstance(self.fitModule) if not self._configurationDialog.exec_(): _logger.debug("NOT UPDATING CONFIGURATION") oldConfig = self.fitModule.getConfiguration() self._configurationDialog.setConfiguration(oldConfig) return newConfig = self._configurationDialog.getConfiguration() self.topWidget.setFunctions(newConfig['fit']['functions']) self.fitModule.setConfiguration(newConfig) newConfig = self.fitModule.getConfiguration() #self.topWidget.setFunctions(newConfig['fit']['functions']) fname = self.fitModule.getFitFunction() if fname in [None, "None", "NONE"]: idx = 0 else: idx = newConfig['fit']['functions'].index(fname) + 1 self.topWidget.fitFunctionCombo.setCurrentIndex(idx) fname = self.fitModule.getBackgroundFunction() if fname in [None, "None", "NONE"]: idx = 0 else: idx = newConfig['fit']['functions'].index(fname) + 1 idx = self.topWidget.backgroundCombo.findText(fname) self.topWidget.backgroundCombo.setCurrentIndex(idx) _logger.debug("TABLE TO BE CLEANED") #self.estimate() def setFitFunction(self, fname): current = self.fitModule.getFitFunction() if current != fname: self.fitModule.setFitFunction(fname) idx = self.topWidget.fitFunctionCombo.findText(fname) self.topWidget.fitFunctionCombo.setCurrentIndex(idx) def setBackgroundFunction(self, fname): current = self.fitModule.getBackgroundFunction() if current != fname: self.fitModule.setBackgroundFunction(fname) idx = self.topWidget.backgroundCombo.findText(fname) self.topWidget.backgroundCombo.setCurrentIndex(idx) def setData(self, *var, **kw): returnValue = self.fitModule.setData(*var, **kw) if self.__useTab: if hasattr(self.graph, "addCurve"): self.graph.clear() self.graph.addCurve(self.fitModule._x, self.fitModule._y, legend='Data') self.graph.setActiveCurve('Data') elif hasattr(self.graph, "newCurve"): # TODO: remove if not used self.graph.clearCurves() self.graph.newCurve('Data', self.fitModule._x, self.fitModule._y) self.graph.replot() return returnValue def estimate(self): self.setStatus("Estimate started") self.statusWidget.chi2Line.setText("") try: x = self.fitModule._x y = self.fitModule._y self.graph.clear() self.graph.addCurve(x, y, 'Data') self.graph.setActiveCurve('Data') self.fitModule.estimate() self.setStatus() self.parametersTable.fillTableFromFit(self.fitModule.paramlist) except: if _logger.getEffectiveLevel() == logging.DEBUG: raise text = "%s:%s" % (sys.exc_info()[0], sys.exc_info()[1]) msg = qt.QMessageBox(self) msg.setIcon(qt.QMessageBox.Critical) msg.setText(text) msg.exec_() self.setStatus("Ready (after estimate error)") def setStatus(self, text=None): if text is None: text = "%s" % self.fitModule.getStatus() self.statusWidget.statusLine.setText(text) def startFit(self): #get parameters from table self.fitModule.paramlist = self.parametersTable.fillFitFromTable() try: values,chisq,sigma,niter,lastdeltachi = self.fitModule.startFit() self.setStatus() except: if _logger.getEffectiveLevel() == logging.DEBUG: raise text = "%s:%s" % (sys.exc_info()[0], sys.exc_info()[1]) msg = qt.QMessageBox(self) msg.setIcon(qt.QMessageBox.Critical) msg.setText(text) msg.exec_() self.setStatus("Ready (after fit error)") return self.parametersTable.fillTableFromFit(self.fitModule.paramlist) self.statusWidget.chi2Line.setText("%f" % chisq) ddict = {} ddict['event'] = "FitFinished" ddict['x'] = self.fitModule._x ddict['y'] = self.fitModule._y ddict['yfit'] = self.evaluateDefinedFunction() self.sigSimpleFitSignal.emit(ddict) self.updateGraph() def updateGraph(self): #this is to be overwritten and for test purposes if self.graph is None: return ddict = self.fitModule.evaluateContributions() ddict['event'] = "FitFinished" ddict['x'] = self.fitModule._x ddict['y'] = self.fitModule._y #ddict['yfit'] = self.evaluateDefinedFunction() #ddict['background'] = self.fitModule._evaluateBackground() self.graph.clear() self.graph.addCurve(ddict['x'], ddict['y'], 'Data') self.graph.addCurve(ddict['x'], ddict['yfit'], 'Fit') self.graph.addCurve(ddict['x'], ddict['background'], 'Background') contributions = ddict['contributions'] if len(contributions) > 1: background = ddict['background'] i = 0 for contribution in contributions: i += 1 self.graph.addCurve(ddict['x'], background + contribution, legend='Contribution %d' % i) self.graph.setActiveCurve('Data') self.graph.show() def dismiss(self): self.close() def evaluateDefinedFunction(self, x=None): return self.fitModule.evaluateDefinedFunction(x) def evaluateContributions(self, x=None): return self.fitModule.evaluateContributions(x) def _zoomBack(self, pos): self.graph.getLimitsHistory().pop()
class TestRegionOfInterestManager(TestCaseQt, ParametricTestCase): """Tests for RegionOfInterestManager class""" def setUp(self): super(TestRegionOfInterestManager, self).setUp() self.plot = PlotWindow() self.roiTableWidget = roi.RegionOfInterestTableWidget() dock = qt.QDockWidget() dock.setWidget(self.roiTableWidget) self.plot.addDockWidget(qt.Qt.BottomDockWidgetArea, dock) self.plot.show() self.qWaitForWindowExposed(self.plot) def tearDown(self): del self.roiTableWidget self.qapp.processEvents() self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() del self.plot super(TestRegionOfInterestManager, self).tearDown() def test(self): """Test ROI of different shapes""" tests = ( # shape, points=[list of (x, y), list of (x, y)] ('point', numpy.array(([(10., 15.)], [(20., 25.)]))), ('rectangle', numpy.array((((1., 10.), (11., 20.)), ((2., 3.), (12., 13.))))), ('polygon', numpy.array((((0., 1.), (0., 10.), (10., 0.)), ((5., 6.), (5., 16.), (15., 6.))))), ('line', numpy.array((((10., 20.), (10., 30.)), ((30., 40.), (30., 50.))))), ('hline', numpy.array((((10., 20.), (10., 30.)), ((30., 40.), (30., 50.))))), ('vline', numpy.array((((10., 20.), (10., 30.)), ((30., 40.), (30., 50.))))), ) for kind, points in tests: with self.subTest(kind=kind): manager = roi.RegionOfInterestManager(self.plot) self.roiTableWidget.setRegionOfInterestManager(manager) manager.start(kind) self.assertEqual(manager.getRegionOfInterests(), ()) finishListener = SignalListener() manager.sigInteractiveModeFinished.connect(finishListener) changedListener = SignalListener() manager.sigRegionOfInterestChanged.connect(changedListener) # Add a point manager.createRegionOfInterest(kind, points[0]) self.qapp.processEvents() self.assertTrue(numpy.all(numpy.equal( manager.getRegionOfInterestPoints(), (points[0],)))) self.assertEqual(changedListener.callCount(), 1) # Remove it manager.removeRegionOfInterest(manager.getRegionOfInterests()[0]) self.assertEqual(manager.getRegionOfInterests(), ()) self.assertEqual(changedListener.callCount(), 2) # Add two point manager.createRegionOfInterest(kind, points[0]) self.qapp.processEvents() manager.createRegionOfInterest(kind, points[1]) self.qapp.processEvents() self.assertTrue(numpy.all(numpy.equal( manager.getRegionOfInterestPoints(), (points[0], points[1])))) self.assertEqual(changedListener.callCount(), 4) # Reset it result = manager.clearRegionOfInterests() self.assertTrue(result) self.assertEqual(manager.getRegionOfInterests(), ()) self.assertEqual(changedListener.callCount(), 5) changedListener.clear() # Add two point manager.createRegionOfInterest(kind, points[0]) self.qapp.processEvents() manager.createRegionOfInterest(kind, points[1]) self.qapp.processEvents() self.assertTrue(numpy.all(numpy.equal( manager.getRegionOfInterestPoints(), (points[0], points[1])))) self.assertEqual(changedListener.callCount(), 2) # stop result = manager.stop() self.assertTrue(result) self.assertTrue(numpy.all(numpy.equal( manager.getRegionOfInterestPoints(), (points[0], points[1])))) self.qapp.processEvents() self.assertEqual(finishListener.callCount(), 1) manager.clearRegionOfInterests() def testMaxROI(self): """Test Max ROI""" kind = 'rectangle' points = numpy.array((((1., 10.), (11., 20.)), ((2., 3.), (12., 13.)))) manager = roi.InteractiveRegionOfInterestManager(self.plot) self.roiTableWidget.setRegionOfInterestManager(manager) self.assertEqual(manager.getRegionOfInterests(), ()) changedListener = SignalListener() manager.sigRegionOfInterestChanged.connect(changedListener) # Add two point manager.createRegionOfInterest(kind, points[0]) manager.createRegionOfInterest(kind, points[1]) self.qapp.processEvents() self.assertTrue(numpy.all(numpy.equal( manager.getRegionOfInterestPoints(), (points[0], points[1])))) self.assertEqual(changedListener.callCount(), 2) # Try to set max ROI to 1 while there is 2 ROIs with self.assertRaises(ValueError): manager.setMaxRegionOfInterests(1) manager.clearRegionOfInterests() self.assertEqual(manager.getRegionOfInterests(), ()) self.assertEqual(changedListener.callCount(), 3) # Set max limit to 1 manager.setMaxRegionOfInterests(1) # Add a point manager.createRegionOfInterest(kind, points[0]) self.qapp.processEvents() self.assertTrue(numpy.all(numpy.equal( manager.getRegionOfInterestPoints(), (points[0],)))) self.assertEqual(changedListener.callCount(), 4) # Add a 2nd point while max ROI is 1 manager.createRegionOfInterest(kind, points[1]) self.qapp.processEvents() self.assertTrue(numpy.all(numpy.equal( manager.getRegionOfInterestPoints(), (points[1],)))) self.assertEqual(changedListener.callCount(), 6) def testChangeInteractionMode(self): """Test change of interaction mode""" manager = roi.RegionOfInterestManager(self.plot) self.roiTableWidget.setRegionOfInterestManager(manager) manager.start('point') interactiveModeToolBar = self.plot.getInteractiveModeToolBar() panAction = interactiveModeToolBar.getPanModeAction() for kind in manager.getSupportedRegionOfInterestKinds(): with self.subTest(kind=kind): # Change to pan mode panAction.trigger() # Change to interactive ROI mode action = manager.getInteractionModeAction(kind) action.trigger() self.assertEqual(kind, manager.getRegionOfInterestKind()) manager.clearRegionOfInterests()
class StripBackgroundWidget(qt.QWidget): def __init__(self, parent=None): qt.QWidget.__init__(self, parent) self.setWindowTitle("Strip and SNIP Configuration Window") self.mainLayout = qt.QVBoxLayout(self) self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.setSpacing(2) self.parametersWidget = StripParametersWidget(self) self.graphWidget = PlotWindow(self, position=False, aspectRatio=False, colormap=False, yInverted=False, roi=False, mask=False, fit=False) toolBar = self.graphWidget.getInteractiveModeToolBar() toolBar.getZoomModeAction().setVisible(False) toolBar.getPanModeAction().setVisible(False) self.mainLayout.addWidget(self.parametersWidget) self.mainLayout.addWidget(self.graphWidget) self.getParameters = self.parametersWidget.getParameters self.setParameters = self.parametersWidget.setParameters self._x = None self._y = None self.parametersWidget.sigStripParametersWidgetSignal.connect( \ self._slot) def setData(self, x, y): self._x = x self._y = y self.update() self.graphWidget.resetZoom() def _slot(self, ddict): self.update() def update(self): if self._y is None: return pars = self.getParameters() #smoothed data y = numpy.ravel(numpy.array(self._y)).astype(numpy.float) ysmooth = SpecfitFuns.SavitskyGolay(y, pars['stripfilterwidth']) f=[0.25,0.5,0.25] ysmooth[1:-1] = numpy.convolve(ysmooth,f,mode=0) ysmooth[0] = 0.5 *(ysmooth[0] + ysmooth[1]) ysmooth[-1] = 0.5 * (ysmooth[-1] + ysmooth[-2]) #loop for anchors x = self._x niter = pars['stripiterations'] anchorslist = [] if pars['stripanchorsflag']: if pars['stripanchorslist'] is not None: ravelled = x for channel in pars['stripanchorslist']: if channel <= ravelled[0]:continue index = numpy.nonzero(ravelled >= channel)[0] if len(index): index = min(index) if index > 0: anchorslist.append(index) if niter > 1000: stripBackground = SpecfitFuns.subac(ysmooth, pars['stripconstant'], niter, pars['stripwidth'], anchorslist) #final smoothing stripBackground = SpecfitFuns.subac(stripBackground, pars['stripconstant'], 500,1, anchorslist) elif niter > 0: stripBackground = SpecfitFuns.subac(ysmooth, pars['stripconstant'], niter, pars['stripwidth'], anchorslist) else: stripBackground = 0.0 * ysmooth + ysmooth.min() if len(anchorslist) == 0: anchorslist = [0, len(ysmooth)-1] anchorslist.sort() snipBackground = 0.0 * ysmooth lastAnchor = 0 width = pars['snipwidth'] for anchor in anchorslist: if (anchor > lastAnchor) and (anchor < len(ysmooth)): snipBackground[lastAnchor:anchor] =\ SpecfitFuns.snip1d(ysmooth[lastAnchor:anchor], width, 0) lastAnchor = anchor if lastAnchor < len(ysmooth): snipBackground[lastAnchor:] =\ SpecfitFuns.snip1d(ysmooth[lastAnchor:], width, 0) self.graphWidget.addCurve(x, y, legend='Input Data', resetzoom=False) self.graphWidget.addCurve(x, stripBackground, resetzoom=False, legend='Strip Background') self.graphWidget.addCurve(x, snipBackground, resetzoom=False, legend='SNIP Background') self.graphWidget.setActiveCurve('Input Data')
def _createPlot(self): return PlotWindow()
class TestMaskToolsWidget(TestCaseQt): """Basic test for MaskToolsWidget""" def setUp(self): super(TestMaskToolsWidget, self).setUp() self.plot = PlotWindow() self.widget = MaskToolsWidget.MaskToolsDockWidget(self.plot, 'TEST') self.plot.addDockWidget(qt.Qt.BottomDockWidgetArea, self.widget) self.plot.show() self.qWaitForWindowExposed(self.plot) self.maskWidget = self.widget.widget() def tearDown(self): del self.maskWidget del self.widget self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() del self.plot super(TestMaskToolsWidget, self).tearDown() def testEmptyPlot(self): """Empty plot, display MaskToolsDockWidget, toggle multiple masks""" self.maskWidget.setMultipleMasks('single') self.qapp.processEvents() self.maskWidget.setMultipleMasks('exclusive') self.qapp.processEvents() def _drag(self): """Drag from plot center to offset position""" plot = self.plot.centralWidget() xCenter, yCenter = plot.width() // 2, plot.height() // 2 offset = min(plot.width(), plot.height()) // 10 pos0 = xCenter, yCenter pos1 = xCenter + offset, yCenter + offset self.mouseMove(plot, pos=pos0) self.mousePress(plot, qt.Qt.LeftButton, pos=pos0) self.mouseMove(plot, pos=pos1) self.mouseRelease(plot, qt.Qt.LeftButton, pos=pos1) def _drawPolygon(self): """Draw a star polygon in the plot""" plot = self.plot.centralWidget() x, y = plot.width() // 2, plot.height() // 2 offset = min(plot.width(), plot.height()) // 10 star = [(x, y + offset), (x - offset, y - offset), (x + offset, y), (x - offset, y), (x + offset, y - offset)] for pos in star: self.mouseMove(plot, pos=pos) btn = qt.Qt.LeftButton if pos != star[-1] else qt.Qt.RightButton self.mouseClick(plot, btn, pos=pos) def _drawPencil(self): """Draw a star polygon in the plot""" plot = self.plot.centralWidget() x, y = plot.width() // 2, plot.height() // 2 offset = min(plot.width(), plot.height()) // 10 star = [(x, y + offset), (x - offset, y - offset), (x + offset, y), (x - offset, y), (x + offset, y - offset)] self.mouseMove(plot, pos=star[0]) self.mousePress(plot, qt.Qt.LeftButton, pos=star[0]) for pos in star: self.mouseMove(plot, pos=pos) self.mouseRelease( plot, qt.Qt.LeftButton, pos=star[-1]) def testWithAnImage(self): """Plot with an image: test MaskToolsWidget interactions""" # Add and remove a image (this should enable/disable GUI + change mask) self.plot.addImage(numpy.random.random(1024**2).reshape(1024, 1024), legend='test') self.qapp.processEvents() self.plot.remove('test', kind='image') self.qapp.processEvents() self.plot.addImage(numpy.arange(1024**2).reshape(1024, 1024), legend='test') self.qapp.processEvents() # Test draw rectangle # toolButton = getQToolButtonFromAction(self.maskWidget.rectAction) self.assertIsNot(toolButton, None) self.mouseClick(toolButton, qt.Qt.LeftButton) # mask self.maskWidget.maskStateGroup.button(1).click() self.qapp.processEvents() self._drag() self.assertFalse( numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0))) # unmask same region self.maskWidget.maskStateGroup.button(0).click() self.qapp.processEvents() self._drag() self.assertTrue( numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0))) # Test draw polygon # toolButton = getQToolButtonFromAction(self.maskWidget.polygonAction) self.assertIsNot(toolButton, None) self.mouseClick(toolButton, qt.Qt.LeftButton) # mask self.maskWidget.maskStateGroup.button(1).click() self.qapp.processEvents() self._drawPolygon() self.assertFalse( numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0))) # unmask same region self.maskWidget.maskStateGroup.button(0).click() self.qapp.processEvents() self._drawPolygon() self.assertTrue( numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0))) # Test draw pencil # toolButton = getQToolButtonFromAction(self.maskWidget.pencilAction) self.assertIsNot(toolButton, None) self.mouseClick(toolButton, qt.Qt.LeftButton) self.maskWidget.pencilSpinBox.setValue(10) self.qapp.processEvents() # mask self.maskWidget.maskStateGroup.button(1).click() self.qapp.processEvents() self._drawPencil() self.assertFalse( numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0))) # unmask same region self.maskWidget.maskStateGroup.button(0).click() self.qapp.processEvents() self._drawPencil() self.assertTrue( numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0))) # Test no draw tool # toolButton = getQToolButtonFromAction(self.maskWidget.browseAction) self.assertIsNot(toolButton, None) self.mouseClick(toolButton, qt.Qt.LeftButton) def testLoadSave(self): """Plot with an image: test MaskToolsWidget operations""" self.plot.addImage(numpy.arange(1024**2).reshape(1024, 1024), legend='test') self.qapp.processEvents() # Draw a polygon mask toolButton = getQToolButtonFromAction(self.maskWidget.polygonAction) self.assertIsNot(toolButton, None) self.mouseClick(toolButton, qt.Qt.LeftButton) self._drawPolygon() ref_mask = self.maskWidget.getSelectionMask() self.assertFalse(numpy.all(numpy.equal(ref_mask, 0))) with temp_dir() as tmp: success = self.maskWidget.save( os.path.join(tmp, 'mask.npy'), 'npy') self.assertTrue(success) self.maskWidget.resetSelectionMask() self.assertTrue( numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0))) result = self.maskWidget.load(os.path.join(tmp, 'mask.npy')) self.assertTrue(result) self.assertTrue(numpy.all(numpy.equal( self.maskWidget.getSelectionMask(), ref_mask)))
class TestPlotWindow(TestCaseQt): """Base class for tests of PlotWindow.""" def setUp(self): super(TestPlotWindow, self).setUp() self.plot = PlotWindow() self.plot.show() self.qWaitForWindowExposed(self.plot) def tearDown(self): self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() del self.plot super(TestPlotWindow, self).tearDown() def testActions(self): """Test the actions QToolButtons""" self.plot.setLimits(1, 100, 1, 100) checkList = [ # QAction, Plot state getter (self.plot.xAxisAutoScaleAction, self.plot.getXAxis().isAutoScale), (self.plot.yAxisAutoScaleAction, self.plot.getYAxis().isAutoScale), (self.plot.xAxisLogarithmicAction, self.plot.getXAxis()._isLogarithmic), (self.plot.yAxisLogarithmicAction, self.plot.getYAxis()._isLogarithmic), (self.plot.gridAction, self.plot.getGraphGrid), ] for action, getter in checkList: self.mouseMove(self.plot) initialState = getter() toolButton = getQToolButtonFromAction(action) self.assertIsNot(toolButton, None) self.mouseClick(toolButton, qt.Qt.LeftButton) self.assertNotEqual(getter(), initialState, msg='"%s" state not changed' % action.text()) self.mouseClick(toolButton, qt.Qt.LeftButton) self.assertEqual(getter(), initialState, msg='"%s" state not changed' % action.text()) # Trigger a zoom reset self.mouseMove(self.plot) resetZoomAction = self.plot.resetZoomAction toolButton = getQToolButtonFromAction(resetZoomAction) self.assertIsNot(toolButton, None) self.mouseClick(toolButton, qt.Qt.LeftButton) def testToolAspectRatio(self): self.plot.toolBar() self.plot.keepDataAspectRatioButton.keepDataAspectRatio() self.assertTrue(self.plot.isKeepDataAspectRatio()) self.plot.keepDataAspectRatioButton.dontKeepDataAspectRatio() self.assertFalse(self.plot.isKeepDataAspectRatio()) def testToolYAxisOrigin(self): self.plot.toolBar() self.plot.yAxisInvertedButton.setYAxisUpward() self.assertFalse(self.plot.getYAxis().isInverted()) self.plot.yAxisInvertedButton.setYAxisDownward() self.assertTrue(self.plot.getYAxis().isInverted())
# remove restored data from info dict for key in ["complex fft", "original x"]: del info[key] # plot the original data self.plot.addCurve(x1, y1, legend=legend1, info=info) self.plot.resetZoom() app = qt.QApplication([]) sys.excepthook = qt.exceptionHandler plotwin = PlotWindow(control=True) toolbar = qt.QToolBar("My toolbar") plotwin.addToolBar(toolbar) myaction = FftAction(plotwin) toolbar.addAction(myaction) # x range: 0 -- 10 (1000 points) x = numpy.arange(1000) * 0.01 twopi = 2 * numpy.pi # Sum of sine functions with frequencies 3, 20 and 42 Hz y1 = numpy.sin(twopi * 3 * x) + 1.5 * numpy.sin(twopi * 20 * x) + 2 * numpy.sin(twopi * 42 * x) # Cosine with frequency 7 Hz and phase pi / 3 y2 = numpy.cos(twopi * 7 * (x - numpy.pi / 3)) # 5 periods of square wave, amplitude 2
class TestCurvesROIWidget(TestCaseQt): """Basic test for CurvesROIWidget""" def setUp(self): super(TestCurvesROIWidget, self).setUp() self.plot = PlotWindow() self.plot.show() self.qWaitForWindowExposed(self.plot) self.widget = self.plot.getCurvesRoiDockWidget() self.widget.show() self.qWaitForWindowExposed(self.widget) def tearDown(self): self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() del self.plot self.widget.setAttribute(qt.Qt.WA_DeleteOnClose) self.widget.close() del self.widget super(TestCurvesROIWidget, self).tearDown() def testWithCurves(self): """Plot with curves: test all ROI widget buttons""" for offset in range(2): self.plot.addCurve(numpy.arange(1000), offset + numpy.random.random(1000), legend=str(offset)) # Add two ROI self.mouseClick(self.widget.roiWidget.addButton, qt.Qt.LeftButton) self.qWait(200) self.mouseClick(self.widget.roiWidget.addButton, qt.Qt.LeftButton) self.qWait(200) # Change active curve self.plot.setActiveCurve(str(1)) # Delete a ROI self.mouseClick(self.widget.roiWidget.delButton, qt.Qt.LeftButton) self.qWait(200) with temp_dir() as tmpDir: self.tmpFile = os.path.join(tmpDir, 'test.ini') # Save ROIs self.widget.roiWidget.save(self.tmpFile) self.assertTrue(os.path.isfile(self.tmpFile)) self.assertTrue(len(self.widget.getRois()) is 2) # Reset ROIs self.mouseClick(self.widget.roiWidget.resetButton, qt.Qt.LeftButton) self.qWait(200) rois = self.widget.getRois() self.assertTrue(len(rois) is 1) print(rois) roiID = list(rois.keys())[0] self.assertTrue(rois[roiID].getName() == 'ICR') # Load ROIs self.widget.roiWidget.load(self.tmpFile) self.assertTrue(len(self.widget.getRois()) is 2) del self.tmpFile def testMiddleMarker(self): """Test with middle marker enabled""" self.widget.roiWidget.roiTable.setMiddleROIMarkerFlag(True) # Add a ROI self.mouseClick(self.widget.roiWidget.addButton, qt.Qt.LeftButton) for roiID in self.widget.roiWidget.roiTable._markersHandler._roiMarkerHandlers: handler = self.widget.roiWidget.roiTable._markersHandler._roiMarkerHandlers[roiID] assert handler.getMarker('min') xleftMarker = handler.getMarker('min').getXPosition() xMiddleMarker = handler.getMarker('middle').getXPosition() xRightMarker = handler.getMarker('max').getXPosition() thValue = xleftMarker + (xRightMarker - xleftMarker) / 2. self.assertAlmostEqual(xMiddleMarker, thValue) def testAreaCalculation(self): """Test result of area calculation""" x = numpy.arange(100.) y = numpy.arange(100.) # Add two curves self.plot.addCurve(x, y, legend="positive") self.plot.addCurve(-x, y, legend="negative") # Make sure there is an active curve and it is the positive one self.plot.setActiveCurve("positive") # Add two ROIs roi_neg = CurvesROIWidget.ROI(name='negative', fromdata=-20, todata=-10, type_='X') roi_pos = CurvesROIWidget.ROI(name='positive', fromdata=10, todata=20, type_='X') self.widget.roiWidget.setRois((roi_pos, roi_neg)) posCurve = self.plot.getCurve('positive') negCurve = self.plot.getCurve('negative') self.assertEqual(roi_pos.computeRawAndNetArea(posCurve), (numpy.trapz(y=[10, 20], x=[10, 20]), 0.0)) self.assertEqual(roi_pos.computeRawAndNetArea(negCurve), (0.0, 0.0)) self.assertEqual(roi_neg.computeRawAndNetArea(posCurve), ((0.0), 0.0)) self.assertEqual(roi_neg.computeRawAndNetArea(negCurve), ((-150.0), 0.0)) def testCountsCalculation(self): """Test result of count calculation""" x = numpy.arange(100.) y = numpy.arange(100.) # Add two curves self.plot.addCurve(x, y, legend="positive") self.plot.addCurve(-x, y, legend="negative") # Make sure there is an active curve and it is the positive one self.plot.setActiveCurve("positive") # Add two ROIs roi_neg = CurvesROIWidget.ROI(name='negative', fromdata=-20, todata=-10, type_='X') roi_pos = CurvesROIWidget.ROI(name='positive', fromdata=10, todata=20, type_='X') self.widget.roiWidget.setRois((roi_pos, roi_neg)) posCurve = self.plot.getCurve('positive') negCurve = self.plot.getCurve('negative') self.assertEqual(roi_pos.computeRawAndNetCounts(posCurve), (y[10:21].sum(), 0.0)) self.assertEqual(roi_pos.computeRawAndNetCounts(negCurve), (0.0, 0.0)) self.assertEqual(roi_neg.computeRawAndNetCounts(posCurve), ((0.0), 0.0)) self.assertEqual(roi_neg.computeRawAndNetCounts(negCurve), (y[10:21].sum(), 0.0)) def testDeferedInit(self): """Test behavior of the deferedInit""" x = numpy.arange(100.) y = numpy.arange(100.) self.plot.addCurve(x=x, y=y, legend="name", replace="True") roisDefs = OrderedDict([ ["range1", OrderedDict([["from", 20], ["to", 200], ["type", "energy"]])], ["range2", OrderedDict([["from", 300], ["to", 500], ["type", "energy"]])] ]) roiWidget = self.plot.getCurvesRoiDockWidget().roiWidget self.plot.getCurvesRoiDockWidget().setRois(roisDefs) self.assertTrue(len(roiWidget.getRois()) is len(roisDefs)) self.plot.getCurvesRoiDockWidget().setVisible(True) self.assertTrue(len(roiWidget.getRois()) is len(roisDefs)) def testDictCompatibility(self): """Test that ROI api is valid with dict and not information is lost""" roiDict = {'from': 20, 'to': 200, 'type': 'energy', 'comment': 'no', 'name': 'myROI', 'calibration': [1, 2, 3]} roi = CurvesROIWidget.ROI._fromDict(roiDict) self.assertTrue(roi.toDict() == roiDict) def testShowAllROI(self): """Test the show allROI action""" x = numpy.arange(100.) y = numpy.arange(100.) self.plot.addCurve(x=x, y=y, legend="name", replace="True") roisDefsDict = { "range1": {"from": 20, "to": 200,"type": "energy"}, "range2": {"from": 300, "to": 500, "type": "energy"} } roisDefsObj = ( CurvesROIWidget.ROI(name='range3', fromdata=20, todata=200, type_='energy'), CurvesROIWidget.ROI(name='range4', fromdata=300, todata=500, type_='energy') ) self.widget.roiWidget.showAllMarkers(True) roiWidget = self.plot.getCurvesRoiDockWidget().roiWidget roiWidget.setRois(roisDefsDict) self.assertTrue(len(self.plot._getAllMarkers()) is 2*3) markersHandler = self.widget.roiWidget.roiTable._markersHandler roiWidget.showAllMarkers(True) ICRROI = markersHandler.getVisibleRois() self.assertTrue(len(ICRROI) is 2) roiWidget.showAllMarkers(False) ICRROI = markersHandler.getVisibleRois() self.assertTrue(len(ICRROI) is 1) roiWidget.setRois(roisDefsObj) self.qapp.processEvents() self.assertTrue(len(self.plot._getAllMarkers()) is 2*3) markersHandler = self.widget.roiWidget.roiTable._markersHandler roiWidget.showAllMarkers(True) ICRROI = markersHandler.getVisibleRois() self.assertTrue(len(ICRROI) is 2) roiWidget.showAllMarkers(False) ICRROI = markersHandler.getVisibleRois() self.assertTrue(len(ICRROI) is 1) def testRoiEdition(self): """Make sure if the ROI object is edited the ROITable will be updated """ roi = CurvesROIWidget.ROI(name='linear', fromdata=0, todata=5) self.widget.roiWidget.setRois((roi, )) x = (0, 1, 1, 2, 2, 3) y = (1, 1, 2, 2, 1, 1) self.plot.addCurve(x=x, y=y, legend='linearCurve') self.plot.setActiveCurve(legend='linearCurve') self.widget.calculateROIs() roiTable = self.widget.roiWidget.roiTable indexesColumns = CurvesROIWidget.ROITable.COLUMNS_INDEX itemRawCounts = roiTable.item(0, indexesColumns['Raw Counts']) itemNetCounts = roiTable.item(0, indexesColumns['Net Counts']) self.assertTrue(itemRawCounts.text() == '8.0') self.assertTrue(itemNetCounts.text() == '2.0') itemRawArea = roiTable.item(0, indexesColumns['Raw Area']) itemNetArea = roiTable.item(0, indexesColumns['Net Area']) self.assertTrue(itemRawArea.text() == '4.0') self.assertTrue(itemNetArea.text() == '1.0') roi.setTo(2) itemRawArea = roiTable.item(0, indexesColumns['Raw Area']) self.assertTrue(itemRawArea.text() == '3.0') roi.setFrom(1) itemRawArea = roiTable.item(0, indexesColumns['Raw Area']) self.assertTrue(itemRawArea.text() == '2.0') def testRemoveActiveROI(self): """Test widget behavior when removing the active ROI""" roi = CurvesROIWidget.ROI(name='linear', fromdata=0, todata=5) self.widget.roiWidget.setRois((roi,)) self.widget.roiWidget.roiTable.setActiveRoi(None) self.assertTrue(len(self.widget.roiWidget.roiTable.selectedItems()) is 0) self.widget.roiWidget.setRois((roi,)) self.plot.setActiveCurve(legend='linearCurve') self.widget.calculateROIs() def testEmitCurrentROI(self): """Test behavior of the CurvesROIWidget.sigROISignal""" roi = CurvesROIWidget.ROI(name='linear', fromdata=0, todata=5) self.widget.roiWidget.setRois((roi,)) signalListener = SignalListener() self.widget.roiWidget.sigROISignal.connect(signalListener.partial()) self.widget.show() self.qapp.processEvents() self.assertTrue(signalListener.callCount() is 0) self.assertTrue(self.widget.roiWidget.roiTable.activeRoi is roi) roi.setFrom(0.0) self.qapp.processEvents() self.assertTrue(signalListener.callCount() is 0) roi.setFrom(0.3) self.qapp.processEvents() self.assertTrue(signalListener.callCount() is 1)
def setUp(self): super(TestPlotWindow, self).setUp() self.plot = PlotWindow() self.plot.show() self.qWaitForWindowExposed(self.plot)
class TestPositionInfo(TestCaseQt): """Tests for PositionInfo widget.""" def setUp(self): super(TestPositionInfo, self).setUp() self.plot = PlotWindow() self.plot.show() self.qWaitForWindowExposed(self.plot) self.mouseMove(self.plot, pos=(1, 1)) self.qapp.processEvents() self.qWait(100) def tearDown(self): self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() del self.plot super(TestPositionInfo, self).tearDown() def _test(self, positionWidget, converterNames, **kwargs): """General test of PositionInfo. - Add it to a toolbar and - Move mouse around the center of the PlotWindow. """ toolBar = qt.QToolBar() self.plot.addToolBar(qt.Qt.BottomToolBarArea, toolBar) toolBar.addWidget(positionWidget) converters = positionWidget.getConverters() self.assertEqual(len(converters), len(converterNames)) for index, name in enumerate(converterNames): self.assertEqual(converters[index][0], name) with TestLogging(PlotTools.__name__, **kwargs): # Move mouse to center self.mouseMove(self.plot) self.qapp.processEvents() self.qWait(100) def testDefaultConverters(self): """Test PositionInfo with default converters""" positionWidget = PlotTools.PositionInfo(plot=self.plot) self._test(positionWidget, ('X', 'Y')) def testCustomConverters(self): """Test PositionInfo with custom converters""" converters = [ ('Coords', lambda x, y: (int(x), int(y))), ('Radius', lambda x, y: numpy.sqrt(x * x + y * y)), ('Angle', lambda x, y: numpy.degrees(numpy.arctan2(y, x))) ] positionWidget = PlotTools.PositionInfo(plot=self.plot, converters=converters) self._test(positionWidget, ('Coords', 'Radius', 'Angle')) def testFailingConverters(self): """Test PositionInfo with failing custom converters""" def raiseException(x, y): raise RuntimeError() positionWidget = PlotTools.PositionInfo( plot=self.plot, converters=[('Exception', raiseException)]) self._test(positionWidget, ['Exception'], error=2)
# Add 1 to all values in the y array # and assign the result to a new array y1 y1 = y0 + 1.0 # Set the active curve data with the shifted y values activeCurve.setData(x0, y1) # creating QApplication is mandatory in order to use qt widget app = qt.QApplication([]) sys.excepthook = qt.exceptionHandler # create a PlotWindow plotwin = PlotWindow() # Add a new toolbar toolbar = qt.QToolBar("My toolbar") plotwin.addToolBar(toolbar) # Get a reference to the PlotWindow's menu bar, add a menu menubar = plotwin.menuBar() actions_menu = menubar.addMenu("Custom actions") # Initialize our action, give it plotwin as a parameter myaction = ShiftUpAction(plotwin) # Add action to the menubar and toolbar toolbar.addAction(myaction) actions_menu.addAction(myaction) # Plot a couple of curves with synthetic data x = [0, 1, 2, 3, 4, 5, 6]
def createWidget(self, parent): plot = PlotWindow(parent) plot.setAutoReplot(False) return plot
class QXTube(qt.QWidget): sigQXTubeSignal = qt.pyqtSignal(object) def __init__(self, parent=None, initdict = None): qt.QWidget.__init__(self, parent) self.l = qt.QVBoxLayout(self) self.l.setContentsMargins(0, 0, 0, 0) self.l.setSpacing(0) self.tubeWidget = TubeWidget(self, initdict = initdict) self.setParameters = self.tubeWidget.setParameters self.getParameters = self.tubeWidget.getParameters label = qt.QLabel(self) hbox = qt.QWidget(self) hboxl = qt.QHBoxLayout(hbox) hboxl.setContentsMargins(0, 0, 0, 0) hboxl.setSpacing(0) self.plotButton = qt.QPushButton(hbox) self.plotButton.setText("Plot Continuum") self.exportButton = qt.QPushButton(hbox) self.exportButton.setText("Export to Fit") #grid.addWidget(self.plotButton, 7, 1) #grid.addWidget(self.exportButton, 7, 3) hboxl.addWidget(self.plotButton) hboxl.addWidget(self.exportButton) self.l.addWidget(self.tubeWidget) f = label.font() f.setItalic(1) label.setFont(f) label.setAlignment(qt.Qt.AlignRight) label.setText("H. Ebel, X-Ray Spectrometry 28 (1999) 255-266 ") self.l.addWidget(label) self.l.addWidget(hbox) self.graph = PlotWindow(self, colormap=False, yInverted=False, aspectRatio=False, control=False, position=False, roi=False, mask=False, fit=False) self.pluginsToolButton = PluginsToolButton(plot=self.graph) self.graph.toolBar().addWidget(self.pluginsToolButton) self.graph.getInteractiveModeToolBar().getZoomModeAction().setVisible(False) self.graph.getInteractiveModeToolBar().getPanModeAction().setVisible(False) self.l.addWidget(self.graph) self.graph.setGraphXLabel("Energy (keV)") self.graph.setGraphYLabel("photons/sr/mA/keV/s") self.plotButton.clicked.connect(self.plot) self.exportButton.clicked.connect(self._export) def plot(self): d = self.tubeWidget.getParameters() transmission = d["transmission"] anode = d["anode"] anodedensity = d["anodedensity"] anodethickness = d["anodethickness"] voltage = d["voltage"] wele = d["window"] wdensity = d["windowdensity"] wthickness = d["windowthickness"] fele = d["filter1"] fdensity = d["filter1density"] fthickness = d["filter1thickness"] filterlist =[[fele, fdensity, fthickness]] alphae = d["alphae"] alphax = d["alphax"] delta = d["deltaplotting"] e = numpy.arange(1, voltage, delta) if __name__ == "__main__": continuumR = XRayTubeEbel.continuumEbel([anode, anodedensity, anodethickness], voltage, e, [wele, wdensity, wthickness], alphae=alphae, alphax=alphax, transmission=0, targetthickness=anodethickness, filterlist=filterlist) continuumT = XRayTubeEbel.continuumEbel([anode, anodedensity, anodethickness], voltage, e, [wele, wdensity, wthickness], alphae=alphae, alphax=alphax, transmission=1, targetthickness=anodethickness, filterlist=filterlist) self.graph.addCurve(e, continuumR, "continuumR") self.graph.addCurve(e, continuumT, "continuumT") else: continuum = XRayTubeEbel.continuumEbel([anode, anodedensity, anodethickness], voltage, e, [wele, wdensity, wthickness], alphae=alphae, alphax=alphax, transmission=transmission, targetthickness=anodethickness, filterlist=filterlist) self.graph.addCurve(e, continuum, "continuum") self.graph.setActiveCurve("continuum") self.graph.resetZoom() def _export(self): d = self.tubeWidget.getParameters() transmission = d["transmission"] anode = d["anode"] anodedensity = d["anodedensity"] anodethickness = d["anodethickness"] voltage = d["voltage"] wele = d["window"] wdensity = d["windowdensity"] wthickness = d["windowthickness"] fele = d["filter1"] fdensity = d["filter1density"] fthickness = d["filter1thickness"] filterlist =[[fele, fdensity, fthickness]] alphae = d["alphae"] alphax = d["alphax"] delta = d["deltaplotting"] e = numpy.arange(1, voltage, delta) d["event"] = "TubeUpdated" d["energyplot"] = e d["continuum"] = XRayTubeEbel.continuumEbel([anode, anodedensity, anodethickness], voltage, e, [wele, wdensity, wthickness], alphae=alphae, alphax=alphax, transmission=transmission, targetthickness=anodethickness, filterlist=filterlist) fllines = XRayTubeEbel.characteristicEbel([anode, anodedensity, anodethickness], voltage, [wele, wdensity, wthickness], alphae=alphae, alphax=alphax, transmission=transmission, targetthickness=anodethickness, filterlist=filterlist) d["characteristic"] = fllines fsum = 0.0 for l in fllines: _logger.debug("%s %.4f %.3e", l[2], l[0], l[1]) fsum += l[1] _logger.debug("%s", fsum) energy, energyweight, energyscatter = XRayTubeEbel.generateLists( [anode, anodedensity, anodethickness], voltage, window=[wele, wdensity, wthickness], alphae=alphae, alphax=alphax, transmission=transmission, targetthickness=anodethickness, filterlist=filterlist) d["energylist"] = energy d["weightlist"] = energyweight d["scatterlist"] = energyscatter d["flaglist"] = numpy.ones(len(energy)) self.sigQXTubeSignal.emit(d)
class TestScatterProfileToolBar(TestCaseQt, ParametricTestCase): """Tests for ScatterProfileToolBar class""" def setUp(self): super(TestScatterProfileToolBar, self).setUp() self.plot = PlotWindow() self.profile = profile.ScatterProfileToolBar(plot=self.plot) self.plot.addToolBar(self.profile) self.plot.show() self.qWaitForWindowExposed(self.plot) def tearDown(self): del self.profile self.qapp.processEvents() self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() del self.plot super(TestScatterProfileToolBar, self).tearDown() def testNoProfile(self): """Test ScatterProfileToolBar without profile""" self.assertEqual(self.profile.getPlotWidget(), self.plot) # Add a scatter plot self.plot.addScatter(x=(0., 1., 1., 0.), y=(0., 0., 1., 1.), value=(0., 1., 2., 3.)) self.plot.resetZoom(dataMargins=(.1, .1, .1, .1)) self.qapp.processEvents() # Check that there is no profile self.assertIsNone(self.profile.getProfileValues()) self.assertIsNone(self.profile.getProfilePoints()) def testHorizontalProfile(self): """Test ScatterProfileToolBar horizontal profile""" nPoints = 8 self.profile.setNPoints(nPoints) self.assertEqual(self.profile.getNPoints(), nPoints) # Add a scatter plot self.plot.addScatter(x=(0., 1., 1., 0.), y=(0., 0., 1., 1.), value=(0., 1., 2., 3.)) self.plot.resetZoom(dataMargins=(.1, .1, .1, .1)) self.qapp.processEvents() # Activate Horizontal profile hlineAction = self.profile.actions()[0] hlineAction.trigger() self.qapp.processEvents() # Set a ROI profile roi = roi_items.HorizontalLineROI() roi.setPosition(0.5) self.profile._getRoiManager().addRoi(roi) # Wait for async interpolator init for _ in range(20): self.qWait(200) if not self.profile.hasPendingOperations(): break self.qapp.processEvents() self.assertIsNotNone(self.profile.getProfileValues()) points = self.profile.getProfilePoints() self.assertEqual(len(points), nPoints) # Check that profile has same limits than Plot xLimits = self.plot.getXAxis().getLimits() self.assertEqual(points[0, 0], xLimits[0]) self.assertEqual(points[-1, 0], xLimits[1]) # Clear the profile clearAction = self.profile.actions()[-1] clearAction.trigger() self.qapp.processEvents() self.assertIsNone(self.profile.getProfileValues()) self.assertIsNone(self.profile.getProfilePoints()) self.assertEqual(self.profile.getProfileTitle(), '') def testVerticalProfile(self): """Test ScatterProfileToolBar vertical profile""" nPoints = 8 self.profile.setNPoints(nPoints) self.assertEqual(self.profile.getNPoints(), nPoints) # Add a scatter plot self.plot.addScatter(x=(0., 1., 1., 0.), y=(0., 0., 1., 1.), value=(0., 1., 2., 3.)) self.plot.resetZoom(dataMargins=(.1, .1, .1, .1)) self.qapp.processEvents() # Activate vertical profile vlineAction = self.profile.actions()[1] vlineAction.trigger() self.qapp.processEvents() # Set a ROI profile roi = roi_items.VerticalLineROI() roi.setPosition(0.5) self.profile._getRoiManager().addRoi(roi) # Wait for async interpolator init for _ in range(10): self.qWait(200) if not self.profile.hasPendingOperations(): break self.assertIsNotNone(self.profile.getProfileValues()) points = self.profile.getProfilePoints() self.assertEqual(len(points), nPoints) # Check that profile has same limits than Plot yLimits = self.plot.getYAxis().getLimits() self.assertEqual(points[0, 1], yLimits[0]) self.assertEqual(points[-1, 1], yLimits[1]) # Check that profile limits are updated when changing limits self.plot.getYAxis().setLimits(yLimits[0] + 1, yLimits[1] + 10) self.qapp.processEvents() yLimits = self.plot.getYAxis().getLimits() points = self.profile.getProfilePoints() self.assertEqual(points[0, 1], yLimits[0]) self.assertEqual(points[-1, 1], yLimits[1]) # Clear the plot self.plot.clear() self.qapp.processEvents() self.assertIsNone(self.profile.getProfileValues()) self.assertIsNone(self.profile.getProfilePoints()) def testLineProfile(self): """Test ScatterProfileToolBar line profile""" nPoints = 8 self.profile.setNPoints(nPoints) self.assertEqual(self.profile.getNPoints(), nPoints) # Activate line profile lineAction = self.profile.actions()[2] lineAction.trigger() self.qapp.processEvents() # Add a scatter plot self.plot.addScatter(x=(0., 1., 1., 0.), y=(0., 0., 1., 1.), value=(0., 1., 2., 3.)) self.plot.resetZoom(dataMargins=(.1, .1, .1, .1)) self.qapp.processEvents() # Set a ROI profile roi = roi_items.LineROI() roi.setEndPoints(numpy.array([0., 0.]), numpy.array([1., 1.])) self.profile._getRoiManager().addRoi(roi) # Wait for async interpolator init for _ in range(10): self.qWait(200) if not self.profile.hasPendingOperations(): break self.assertIsNotNone(self.profile.getProfileValues()) points = self.profile.getProfilePoints() self.assertEqual(len(points), nPoints)
class TestCurvesROIWidget(TestCaseQt): """Basic test for CurvesROIWidget""" def setUp(self): super(TestCurvesROIWidget, self).setUp() self.plot = PlotWindow() self.plot.show() self.qWaitForWindowExposed(self.plot) self.widget = self.plot.getCurvesRoiDockWidget() self.widget.show() self.qWaitForWindowExposed(self.widget) def tearDown(self): self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() del self.plot self.widget.setAttribute(qt.Qt.WA_DeleteOnClose) self.widget.close() del self.widget super(TestCurvesROIWidget, self).tearDown() def testWithCurves(self): """Plot with curves: test all ROI widget buttons""" for offset in range(2): self.plot.addCurve(numpy.arange(1000), offset + numpy.random.random(1000), legend=str(offset)) # Add two ROI self.mouseClick(self.widget.roiWidget.addButton, qt.Qt.LeftButton) self.qWait(200) self.mouseClick(self.widget.roiWidget.addButton, qt.Qt.LeftButton) self.qWait(200) # Change active curve self.plot.setActiveCurve(str(1)) # Delete a ROI self.mouseClick(self.widget.roiWidget.delButton, qt.Qt.LeftButton) self.qWait(200) with temp_dir() as tmpDir: self.tmpFile = os.path.join(tmpDir, 'test.ini') # Save ROIs self.widget.roiWidget.save(self.tmpFile) self.assertTrue(os.path.isfile(self.tmpFile)) self.assertTrue(len(self.widget.getRois()) is 2) # Reset ROIs self.mouseClick(self.widget.roiWidget.resetButton, qt.Qt.LeftButton) self.qWait(200) rois = self.widget.getRois() self.assertTrue(len(rois) is 1) print(rois) roiID = list(rois.keys())[0] self.assertTrue(rois[roiID].getName() == 'ICR') # Load ROIs self.widget.roiWidget.load(self.tmpFile) self.assertTrue(len(self.widget.getRois()) is 2) del self.tmpFile def testMiddleMarker(self): """Test with middle marker enabled""" self.widget.roiWidget.roiTable.setMiddleROIMarkerFlag(True) # Add a ROI self.mouseClick(self.widget.roiWidget.addButton, qt.Qt.LeftButton) for roiID in self.widget.roiWidget.roiTable._markersHandler._roiMarkerHandlers: handler = self.widget.roiWidget.roiTable._markersHandler._roiMarkerHandlers[ roiID] assert handler.getMarker('min') xleftMarker = handler.getMarker('min').getXPosition() xMiddleMarker = handler.getMarker('middle').getXPosition() xRightMarker = handler.getMarker('max').getXPosition() thValue = xleftMarker + (xRightMarker - xleftMarker) / 2. self.assertAlmostEqual(xMiddleMarker, thValue) def testAreaCalculation(self): """Test result of area calculation""" x = numpy.arange(100.) y = numpy.arange(100.) # Add two curves self.plot.addCurve(x, y, legend="positive") self.plot.addCurve(-x, y, legend="negative") # Make sure there is an active curve and it is the positive one self.plot.setActiveCurve("positive") # Add two ROIs roi_neg = CurvesROIWidget.ROI(name='negative', fromdata=-20, todata=-10, type_='X') roi_pos = CurvesROIWidget.ROI(name='positive', fromdata=10, todata=20, type_='X') self.widget.roiWidget.setRois((roi_pos, roi_neg)) posCurve = self.plot.getCurve('positive') negCurve = self.plot.getCurve('negative') self.assertEqual(roi_pos.computeRawAndNetArea(posCurve), (numpy.trapz(y=[10, 20], x=[10, 20]), 0.0)) self.assertEqual(roi_pos.computeRawAndNetArea(negCurve), (0.0, 0.0)) self.assertEqual(roi_neg.computeRawAndNetArea(posCurve), ((0.0), 0.0)) self.assertEqual(roi_neg.computeRawAndNetArea(negCurve), ((-150.0), 0.0)) def testCountsCalculation(self): """Test result of count calculation""" x = numpy.arange(100.) y = numpy.arange(100.) # Add two curves self.plot.addCurve(x, y, legend="positive") self.plot.addCurve(-x, y, legend="negative") # Make sure there is an active curve and it is the positive one self.plot.setActiveCurve("positive") # Add two ROIs roi_neg = CurvesROIWidget.ROI(name='negative', fromdata=-20, todata=-10, type_='X') roi_pos = CurvesROIWidget.ROI(name='positive', fromdata=10, todata=20, type_='X') self.widget.roiWidget.setRois((roi_pos, roi_neg)) posCurve = self.plot.getCurve('positive') negCurve = self.plot.getCurve('negative') self.assertEqual(roi_pos.computeRawAndNetCounts(posCurve), (y[10:21].sum(), 0.0)) self.assertEqual(roi_pos.computeRawAndNetCounts(negCurve), (0.0, 0.0)) self.assertEqual(roi_neg.computeRawAndNetCounts(posCurve), ((0.0), 0.0)) self.assertEqual(roi_neg.computeRawAndNetCounts(negCurve), (y[10:21].sum(), 0.0)) def testDeferedInit(self): """Test behavior of the deferedInit""" x = numpy.arange(100.) y = numpy.arange(100.) self.plot.addCurve(x=x, y=y, legend="name", replace="True") roisDefs = OrderedDict([[ "range1", OrderedDict([["from", 20], ["to", 200], ["type", "energy"]]) ], [ "range2", OrderedDict([["from", 300], ["to", 500], ["type", "energy"]]) ]]) roiWidget = self.plot.getCurvesRoiDockWidget().roiWidget self.plot.getCurvesRoiDockWidget().setRois(roisDefs) self.assertTrue(len(roiWidget.getRois()) is len(roisDefs)) self.plot.getCurvesRoiDockWidget().setVisible(True) self.assertTrue(len(roiWidget.getRois()) is len(roisDefs)) def testDictCompatibility(self): """Test that ROI api is valid with dict and not information is lost""" roiDict = { 'from': 20, 'to': 200, 'type': 'energy', 'comment': 'no', 'name': 'myROI', 'calibration': [1, 2, 3] } roi = CurvesROIWidget.ROI._fromDict(roiDict) self.assertTrue(roi.toDict() == roiDict) def testShowAllROI(self): """Test the show allROI action""" x = numpy.arange(100.) y = numpy.arange(100.) self.plot.addCurve(x=x, y=y, legend="name", replace="True") roisDefsDict = { "range1": { "from": 20, "to": 200, "type": "energy" }, "range2": { "from": 300, "to": 500, "type": "energy" } } roisDefsObj = (CurvesROIWidget.ROI(name='range3', fromdata=20, todata=200, type_='energy'), CurvesROIWidget.ROI(name='range4', fromdata=300, todata=500, type_='energy')) self.widget.roiWidget.showAllMarkers(True) roiWidget = self.plot.getCurvesRoiDockWidget().roiWidget roiWidget.setRois(roisDefsDict) self.assertTrue(len(self.plot._getAllMarkers()) is 2 * 3) markersHandler = self.widget.roiWidget.roiTable._markersHandler roiWidget.showAllMarkers(True) ICRROI = markersHandler.getVisibleRois() self.assertTrue(len(ICRROI) is 2) roiWidget.showAllMarkers(False) ICRROI = markersHandler.getVisibleRois() self.assertTrue(len(ICRROI) is 1) roiWidget.setRois(roisDefsObj) self.qapp.processEvents() self.assertTrue(len(self.plot._getAllMarkers()) is 2 * 3) markersHandler = self.widget.roiWidget.roiTable._markersHandler roiWidget.showAllMarkers(True) ICRROI = markersHandler.getVisibleRois() self.assertTrue(len(ICRROI) is 2) roiWidget.showAllMarkers(False) ICRROI = markersHandler.getVisibleRois() self.assertTrue(len(ICRROI) is 1) def testRoiEdition(self): """Make sure if the ROI object is edited the ROITable will be updated """ roi = CurvesROIWidget.ROI(name='linear', fromdata=0, todata=5) self.widget.roiWidget.setRois((roi, )) x = (0, 1, 1, 2, 2, 3) y = (1, 1, 2, 2, 1, 1) self.plot.addCurve(x=x, y=y, legend='linearCurve') self.plot.setActiveCurve(legend='linearCurve') self.widget.calculateROIs() roiTable = self.widget.roiWidget.roiTable indexesColumns = CurvesROIWidget.ROITable.COLUMNS_INDEX itemRawCounts = roiTable.item(0, indexesColumns['Raw Counts']) itemNetCounts = roiTable.item(0, indexesColumns['Net Counts']) self.assertTrue(itemRawCounts.text() == '8.0') self.assertTrue(itemNetCounts.text() == '2.0') itemRawArea = roiTable.item(0, indexesColumns['Raw Area']) itemNetArea = roiTable.item(0, indexesColumns['Net Area']) self.assertTrue(itemRawArea.text() == '4.0') self.assertTrue(itemNetArea.text() == '1.0') roi.setTo(2) itemRawArea = roiTable.item(0, indexesColumns['Raw Area']) self.assertTrue(itemRawArea.text() == '3.0') roi.setFrom(1) itemRawArea = roiTable.item(0, indexesColumns['Raw Area']) self.assertTrue(itemRawArea.text() == '2.0') def testRemoveActiveROI(self): """Test widget behavior when removing the active ROI""" roi = CurvesROIWidget.ROI(name='linear', fromdata=0, todata=5) self.widget.roiWidget.setRois((roi, )) self.widget.roiWidget.roiTable.setActiveRoi(None) self.assertTrue( len(self.widget.roiWidget.roiTable.selectedItems()) is 0) self.widget.roiWidget.setRois((roi, )) self.plot.setActiveCurve(legend='linearCurve') self.widget.calculateROIs() def testEmitCurrentROI(self): """Test behavior of the CurvesROIWidget.sigROISignal""" roi = CurvesROIWidget.ROI(name='linear', fromdata=0, todata=5) self.widget.roiWidget.setRois((roi, )) signalListener = SignalListener() self.widget.roiWidget.sigROISignal.connect(signalListener.partial()) self.widget.show() self.qapp.processEvents() self.assertTrue(signalListener.callCount() is 0) self.assertTrue(self.widget.roiWidget.roiTable.activeRoi is roi) roi.setFrom(0.0) self.qapp.processEvents() self.assertTrue(signalListener.callCount() is 0) roi.setFrom(0.3) self.qapp.processEvents() self.assertTrue(signalListener.callCount() is 1)
class TestCurveLegendsWidget(TestCaseQt, ParametricTestCase): """Tests for CurveLegendsWidget class""" def setUp(self): super(TestCurveLegendsWidget, self).setUp() self.plot = PlotWindow() self.legends = CurveLegendsWidget.CurveLegendsWidget() self.legends.setPlotWidget(self.plot) dock = qt.QDockWidget() dock.setWindowTitle('Curve Legends') dock.setWidget(self.legends) self.plot.addTabbedDockWidget(dock) self.plot.show() self.qWaitForWindowExposed(self.plot) def tearDown(self): del self.legends self.qapp.processEvents() self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() del self.plot super(TestCurveLegendsWidget, self).tearDown() def _assertNbLegends(self, count): """Check the number of legends in the CurveLegendsWidget""" children = self.legends.findChildren(CurveLegendsWidget._LegendWidget) self.assertEqual(len(children), count) def testAddRemoveCurves(self): """Test CurveLegendsWidget while adding/removing curves""" self.plot.addCurve((0, 1), (1, 2), legend='a') self._assertNbLegends(1) self.plot.addCurve((0, 1), (2, 3), legend='b') self._assertNbLegends(2) # Detached/attach self.legends.setPlotWidget(None) self._assertNbLegends(0) self.legends.setPlotWidget(self.plot) self._assertNbLegends(2) self.plot.clear() self._assertNbLegends(0) def testUpdateCurves(self): """Test CurveLegendsWidget while updating curves """ self.plot.addCurve((0, 1), (1, 2), legend='a') self._assertNbLegends(1) self.plot.addCurve((0, 1), (2, 3), legend='b') self._assertNbLegends(2) # Activate curve self.plot.setActiveCurve('a') self.qapp.processEvents() self.plot.setActiveCurve('b') self.qapp.processEvents() # Change curve style curve = self.plot.getCurve('a') curve.setLineWidth(2) for linestyle in (':', '', '--', '-'): with self.subTest(linestyle=linestyle): curve.setLineStyle(linestyle) self.qapp.processEvents() self.qWait(1000) for symbol in ('o', 'd', '', 's'): with self.subTest(symbol=symbol): curve.setSymbol(symbol) self.qapp.processEvents() self.qWait(1000)
class TestProfileToolBar(TestCaseQt, ParametricTestCase): """Tests for ProfileToolBar widget.""" def setUp(self): super(TestProfileToolBar, self).setUp() profileWindow = PlotWindow() self.plot = PlotWindow() self.toolBar = Profile.ProfileToolBar( plot=self.plot, profileWindow=profileWindow) self.plot.addToolBar(self.toolBar) self.plot.show() self.qWaitForWindowExposed(self.plot) profileWindow.show() self.qWaitForWindowExposed(profileWindow) self.mouseMove(self.plot) # Move to center self.qapp.processEvents() def tearDown(self): self.qapp.processEvents() self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() del self.plot del self.toolBar super(TestProfileToolBar, self).tearDown() def testAlignedProfile(self): """Test horizontal and vertical profile, without and with image""" # Use Plot backend widget to submit mouse events widget = self.plot.getWidgetHandle() for method in ('sum', 'mean'): with self.subTest(method=method): # 2 positions to use for mouse events pos1 = widget.width() * 0.4, widget.height() * 0.4 pos2 = widget.width() * 0.6, widget.height() * 0.6 for action in (self.toolBar.hLineAction, self.toolBar.vLineAction): with self.subTest(mode=action.text()): # Trigger tool button for mode toolButton = getQToolButtonFromAction(action) self.assertIsNot(toolButton, None) self.mouseMove(toolButton) self.mouseClick(toolButton, qt.Qt.LeftButton) # Without image self.mouseMove(widget, pos=pos1) self.mouseClick(widget, qt.Qt.LeftButton, pos=pos1) # with image self.plot.addImage( numpy.arange(100 * 100).reshape(100, -1)) self.mousePress(widget, qt.Qt.LeftButton, pos=pos1) self.mouseMove(widget, pos=pos2) self.mouseRelease(widget, qt.Qt.LeftButton, pos=pos2) self.mouseMove(widget) self.mouseClick(widget, qt.Qt.LeftButton) def testDiagonalProfile(self): """Test diagonal profile, without and with image""" # Use Plot backend widget to submit mouse events widget = self.plot.getWidgetHandle() for method in ('sum', 'mean'): with self.subTest(method=method): self.toolBar.setProfileMethod(method) # 2 positions to use for mouse events pos1 = widget.width() * 0.4, widget.height() * 0.4 pos2 = widget.width() * 0.6, widget.height() * 0.6 for image in (False, True): with self.subTest(image=image): if image: self.plot.addImage( numpy.arange(100 * 100).reshape(100, -1)) # Trigger tool button for diagonal profile mode toolButton = getQToolButtonFromAction( self.toolBar.lineAction) self.assertIsNot(toolButton, None) self.mouseMove(toolButton) self.mouseClick(toolButton, qt.Qt.LeftButton) self.toolBar.lineWidthSpinBox.setValue(3) # draw profile line self.mouseMove(widget, pos=pos1) self.mousePress(widget, qt.Qt.LeftButton, pos=pos1) self.mouseMove(widget, pos=pos2) self.mouseRelease(widget, qt.Qt.LeftButton, pos=pos2) if image is True: profileCurve = self.toolBar.getProfilePlot().getAllCurves()[0] if method == 'sum': self.assertTrue(profileCurve.getData()[1].max() > 10000) elif method == 'mean': self.assertTrue(profileCurve.getData()[1].max() < 10000) self.plot.clear()
class TestScatterProfileToolBar(TestCaseQt, ParametricTestCase): """Tests for ScatterProfileToolBar class""" def setUp(self): super(TestScatterProfileToolBar, self).setUp() self.plot = PlotWindow() self.profile = profile.ScatterProfileToolBar(plot=self.plot) self.plot.addToolBar(self.profile) self.plot.show() self.qWaitForWindowExposed(self.plot) def tearDown(self): del self.profile self.qapp.processEvents() self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() del self.plot super(TestScatterProfileToolBar, self).tearDown() def testNoProfile(self): """Test ScatterProfileToolBar without profile""" self.assertEqual(self.profile.getPlotWidget(), self.plot) # Add a scatter plot self.plot.addScatter( x=(0., 1., 1., 0.), y=(0., 0., 1., 1.), value=(0., 1., 2., 3.)) self.plot.resetZoom(dataMargins=(.1, .1, .1, .1)) self.qapp.processEvents() # Check that there is no profile self.assertIsNone(self.profile.getProfileValues()) self.assertIsNone(self.profile.getProfilePoints()) def testHorizontalProfile(self): """Test ScatterProfileToolBar horizontal profile""" nPoints = 8 self.profile.setNPoints(nPoints) self.assertEqual(self.profile.getNPoints(), nPoints) # Add a scatter plot self.plot.addScatter( x=(0., 1., 1., 0.), y=(0., 0., 1., 1.), value=(0., 1., 2., 3.)) self.plot.resetZoom(dataMargins=(.1, .1, .1, .1)) self.qapp.processEvents() # Activate Horizontal profile hlineAction = self.profile.actions()[0] hlineAction.trigger() self.qapp.processEvents() # Set a ROI profile roi = roi_items.HorizontalLineROI() roi.setPosition(0.5) self.profile._getRoiManager().addRoi(roi) # Wait for async interpolator init for _ in range(20): self.qWait(200) if not self.profile.hasPendingOperations(): break self.assertIsNotNone(self.profile.getProfileValues()) points = self.profile.getProfilePoints() self.assertEqual(len(points), nPoints) # Check that profile has same limits than Plot xLimits = self.plot.getXAxis().getLimits() self.assertEqual(points[0, 0], xLimits[0]) self.assertEqual(points[-1, 0], xLimits[1]) # Clear the profile clearAction = self.profile.actions()[-1] clearAction.trigger() self.qapp.processEvents() self.assertIsNone(self.profile.getProfileValues()) self.assertIsNone(self.profile.getProfilePoints()) self.assertEqual(self.profile.getProfileTitle(), '') def testVerticalProfile(self): """Test ScatterProfileToolBar vertical profile""" nPoints = 8 self.profile.setNPoints(nPoints) self.assertEqual(self.profile.getNPoints(), nPoints) # Add a scatter plot self.plot.addScatter( x=(0., 1., 1., 0.), y=(0., 0., 1., 1.), value=(0., 1., 2., 3.)) self.plot.resetZoom(dataMargins=(.1, .1, .1, .1)) self.qapp.processEvents() # Activate vertical profile vlineAction = self.profile.actions()[1] vlineAction.trigger() self.qapp.processEvents() # Set a ROI profile roi = roi_items.VerticalLineROI() roi.setPosition(0.5) self.profile._getRoiManager().addRoi(roi) # Wait for async interpolator init for _ in range(10): self.qWait(200) if not self.profile.hasPendingOperations(): break self.assertIsNotNone(self.profile.getProfileValues()) points = self.profile.getProfilePoints() self.assertEqual(len(points), nPoints) # Check that profile has same limits than Plot yLimits = self.plot.getYAxis().getLimits() self.assertEqual(points[0, 1], yLimits[0]) self.assertEqual(points[-1, 1], yLimits[1]) # Check that profile limits are updated when changing limits self.plot.getYAxis().setLimits(yLimits[0] + 1, yLimits[1] + 10) self.qapp.processEvents() yLimits = self.plot.getYAxis().getLimits() points = self.profile.getProfilePoints() self.assertEqual(points[0, 1], yLimits[0]) self.assertEqual(points[-1, 1], yLimits[1]) # Clear the plot self.plot.clear() self.qapp.processEvents() self.assertIsNone(self.profile.getProfileValues()) self.assertIsNone(self.profile.getProfilePoints()) def testLineProfile(self): """Test ScatterProfileToolBar line profile""" nPoints = 8 self.profile.setNPoints(nPoints) self.assertEqual(self.profile.getNPoints(), nPoints) # Activate line profile lineAction = self.profile.actions()[2] lineAction.trigger() self.qapp.processEvents() # Add a scatter plot self.plot.addScatter( x=(0., 1., 1., 0.), y=(0., 0., 1., 1.), value=(0., 1., 2., 3.)) self.plot.resetZoom(dataMargins=(.1, .1, .1, .1)) self.qapp.processEvents() # Set a ROI profile roi = roi_items.LineROI() roi.setEndPoints(numpy.array([0., 0.]), numpy.array([1., 1.])) self.profile._getRoiManager().addRoi(roi) # Wait for async interpolator init for _ in range(10): self.qWait(200) if not self.profile.hasPendingOperations(): break self.assertIsNotNone(self.profile.getProfileValues()) points = self.profile.getProfilePoints() self.assertEqual(len(points), nPoints)
class TestRegionOfInterestManager(TestCaseQt, ParametricTestCase): """Tests for RegionOfInterestManager class""" def setUp(self): super(TestRegionOfInterestManager, self).setUp() self.plot = PlotWindow() self.roiTableWidget = roi.RegionOfInterestTableWidget() dock = qt.QDockWidget() dock.setWidget(self.roiTableWidget) self.plot.addDockWidget(qt.Qt.BottomDockWidgetArea, dock) self.plot.show() self.qWaitForWindowExposed(self.plot) def tearDown(self): del self.roiTableWidget self.qapp.processEvents() self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) self.plot.close() del self.plot super(TestRegionOfInterestManager, self).tearDown() def test(self): """Test ROI of different shapes""" tests = ( # shape, points=[list of (x, y), list of (x, y)] (roi_items.PointROI, numpy.array(([(10., 15.)], [(20., 25.)]))), (roi_items.RectangleROI, numpy.array((((1., 10.), (11., 20.)), ((2., 3.), (12., 13.))))), (roi_items.PolygonROI, numpy.array((((0., 1.), (0., 10.), (10., 0.)), ((5., 6.), (5., 16.), (15., 6.))))), (roi_items.LineROI, numpy.array((((10., 20.), (10., 30.)), ((30., 40.), (30., 50.))))), (roi_items.HorizontalLineROI, numpy.array((((10., 20.), (10., 30.)), ((30., 40.), (30., 50.))))), (roi_items.VerticalLineROI, numpy.array((((10., 20.), (10., 30.)), ((30., 40.), (30., 50.))))), ) for roiClass, points in tests: with self.subTest(roiClass=roiClass): manager = roi.RegionOfInterestManager(self.plot) self.roiTableWidget.setRegionOfInterestManager(manager) manager.start(roiClass) self.assertEqual(manager.getRois(), ()) finishListener = SignalListener() manager.sigInteractiveModeFinished.connect(finishListener) changedListener = SignalListener() manager.sigRoiChanged.connect(changedListener) # Add a point manager.createRoi(roiClass, points[0]) self.qapp.processEvents() self.assertTrue(len(manager.getRois()), 1) self.assertEqual(changedListener.callCount(), 1) # Remove it manager.removeRoi(manager.getRois()[0]) self.assertEqual(manager.getRois(), ()) self.assertEqual(changedListener.callCount(), 2) # Add two point manager.createRoi(roiClass, points[0]) self.qapp.processEvents() manager.createRoi(roiClass, points[1]) self.qapp.processEvents() self.assertTrue(len(manager.getRois()), 2) self.assertEqual(changedListener.callCount(), 4) # Reset it result = manager.clear() self.assertTrue(result) self.assertEqual(manager.getRois(), ()) self.assertEqual(changedListener.callCount(), 5) changedListener.clear() # Add two point manager.createRoi(roiClass, points[0]) self.qapp.processEvents() manager.createRoi(roiClass, points[1]) self.qapp.processEvents() self.assertTrue(len(manager.getRois()), 2) self.assertEqual(changedListener.callCount(), 2) # stop result = manager.stop() self.assertTrue(result) self.assertTrue(len(manager.getRois()), 1) self.qapp.processEvents() self.assertEqual(finishListener.callCount(), 1) manager.clear() def testRoiDisplay(self): rois = [] # Line item = roi_items.LineROI() startPoint = numpy.array([1, 2]) endPoint = numpy.array([3, 4]) item.setEndPoints(startPoint, endPoint) rois.append(item) # Horizontal line item = roi_items.HorizontalLineROI() item.setPosition(15) rois.append(item) # Vertical line item = roi_items.VerticalLineROI() item.setPosition(15) rois.append(item) # Point item = roi_items.PointROI() point = numpy.array([1, 2]) item.setPosition(point) rois.append(item) # Rectangle item = roi_items.RectangleROI() origin = numpy.array([0, 0]) size = numpy.array([10, 20]) item.setGeometry(origin=origin, size=size) rois.append(item) # Polygon item = roi_items.PolygonROI() points = numpy.array([[10, 10], [12, 10], [50, 1]]) item.setPoints(points) rois.append(item) # Degenerated polygon: No points item = roi_items.PolygonROI() points = numpy.empty((0, 2)) item.setPoints(points) rois.append(item) # Degenerated polygon: A single point item = roi_items.PolygonROI() points = numpy.array([[5, 10]]) item.setPoints(points) rois.append(item) # Degenerated arc: it's a point item = roi_items.ArcROI() center = numpy.array([10, 20]) innerRadius, outerRadius, startAngle, endAngle = 0, 0, 0, 0 item.setGeometry(center, innerRadius, outerRadius, startAngle, endAngle) rois.append(item) # Degenerated arc: it's a line item = roi_items.ArcROI() center = numpy.array([10, 20]) innerRadius, outerRadius, startAngle, endAngle = 0, 100, numpy.pi, numpy.pi item.setGeometry(center, innerRadius, outerRadius, startAngle, endAngle) rois.append(item) # Special arc: it's a donut item = roi_items.ArcROI() center = numpy.array([10, 20]) innerRadius, outerRadius, startAngle, endAngle = 1, 100, numpy.pi, 3 * numpy.pi item.setGeometry(center, innerRadius, outerRadius, startAngle, endAngle) rois.append(item) # Arc item = roi_items.ArcROI() center = numpy.array([10, 20]) innerRadius, outerRadius, startAngle, endAngle = 1, 100, numpy.pi * 0.5, numpy.pi item.setGeometry(center, innerRadius, outerRadius, startAngle, endAngle) rois.append(item) manager = roi.RegionOfInterestManager(self.plot) self.roiTableWidget.setRegionOfInterestManager(manager) for item in rois: with self.subTest(roi=str(item)): manager.addRoi(item) self.qapp.processEvents() item.setEditable(True) self.qapp.processEvents() item.setEditable(False) self.qapp.processEvents() manager.removeRoi(item) self.qapp.processEvents() def testMaxROI(self): """Test Max ROI""" origin1 = numpy.array([1., 10.]) size1 = numpy.array([10., 10.]) origin2 = numpy.array([2., 3.]) size2 = numpy.array([10., 10.]) manager = roi.InteractiveRegionOfInterestManager(self.plot) self.roiTableWidget.setRegionOfInterestManager(manager) self.assertEqual(manager.getRois(), ()) changedListener = SignalListener() manager.sigRoiChanged.connect(changedListener) # Add two point item = roi_items.RectangleROI() item.setGeometry(origin=origin1, size=size1) manager.addRoi(item) item = roi_items.RectangleROI() item.setGeometry(origin=origin2, size=size2) manager.addRoi(item) self.qapp.processEvents() self.assertEqual(changedListener.callCount(), 2) self.assertEqual(len(manager.getRois()), 2) # Try to set max ROI to 1 while there is 2 ROIs with self.assertRaises(ValueError): manager.setMaxRois(1) manager.clear() self.assertEqual(len(manager.getRois()), 0) self.assertEqual(changedListener.callCount(), 3) # Set max limit to 1 manager.setMaxRois(1) # Add a point item = roi_items.RectangleROI() item.setGeometry(origin=origin1, size=size1) manager.addRoi(item) self.qapp.processEvents() self.assertEqual(changedListener.callCount(), 4) # Add a 2nd point while max ROI is 1 item = roi_items.RectangleROI() item.setGeometry(origin=origin1, size=size1) manager.addRoi(item) self.qapp.processEvents() self.assertEqual(changedListener.callCount(), 6) self.assertEqual(len(manager.getRois()), 1) def testChangeInteractionMode(self): """Test change of interaction mode""" manager = roi.RegionOfInterestManager(self.plot) self.roiTableWidget.setRegionOfInterestManager(manager) manager.start(roi_items.PointROI) interactiveModeToolBar = self.plot.getInteractiveModeToolBar() panAction = interactiveModeToolBar.getPanModeAction() for roiClass in manager.getSupportedRoiClasses(): with self.subTest(roiClass=roiClass): # Change to pan mode panAction.trigger() # Change to interactive ROI mode action = manager.getInteractionModeAction(roiClass) action.trigger() self.assertEqual(roiClass, manager.getCurrentInteractionModeRoiClass()) manager.clear()