Exemple #1
0
    def __init__(self, *args, **kwargs):

        self.mapToH5 = mapToH5()
        # Data model
        self.headermodel = QStandardItemModel()

        # Selection model
        self.selectionmodel = QItemSelectionModel(self.headermodel)

        self.PCA_widget = FactorizationWidget(self.headermodel,
                                              self.selectionmodel)
        self.NMF_widget = FactorizationWidget(self.headermodel,
                                              self.selectionmodel)

        # update headers list when a tab window is closed
        self.headermodel.rowsRemoved.connect(
            partial(self.PCA_widget.setHeader, 'spectra'))
        self.headermodel.rowsRemoved.connect(
            partial(self.NMF_widget.setHeader, 'volume'))

        # Setup tabviews and update map selection
        self.imageview = TabView(self.headermodel, self.selectionmodel,
                                 MapView, 'image')

        self.stages = {
            "MapToH5": GUILayout(self.mapToH5),
            "Image View": GUILayout(self.imageview),
            "PCA": GUILayout(self.PCA_widget),
            "NMF": GUILayout(self.NMF_widget)
        }
        super(BSISB, self).__init__(*args, **kwargs)
Exemple #2
0
    def __init__(self):
        self.workflow = Workflow()

        self.headermodel = QStandardItemModel()
        # self.alignmenttabview = TabView(self.headermodel)
        self.rawtabview = TabView(self.headermodel,
                                  widgetcls=RAWViewer,
                                  field='primary')
        self.recontabs = QTabWidget()

        self.workfloweditor = WorkflowEditor(self.workflow)
        self.workfloweditor.setHidden(True)

        self.tomotoolbar = TomoToolbar()
        self.tomotoolbar.sigSliceReconstruction.connect(self.sliceReconstruct)
        self.tomotoolbar.sigFullReconstruction.connect(self.fullReconstruction)

        self.stages = {
            'Alignment':
            GUILayout(QLabel('Alignment'),
                      right=self.workfloweditor,
                      top=self.tomotoolbar),
            'Preprocess':
            GUILayout(self.rawtabview,
                      right=self.workfloweditor,
                      top=self.tomotoolbar),
            'Reconstruct':
            GUILayout(self.recontabs,
                      top=self.tomotoolbar,
                      right=self.workfloweditor),
        }
        super(TomographyPlugin, self).__init__()
    def __init__(self, headermodel):
        super(SAXSMultiViewerPlugin, self).__init__()

        self.leftTabView = TabView()
        self.leftTabView.setWidgetClass(SAXSViewerPlugin)
        self.leftTabView.setModel(headermodel)
        self.rightTabView = TabView()
        self.rightTabView.setWidgetClass(SAXSViewerPlugin)
        self.rightTabView.setModel(headermodel)

        self.addWidget(self.leftTabView)
        self.addWidget(self.rightTabView)
Exemple #4
0
    def __init__(self, headermodel, selectionmodel):
        super(SAXSMultiViewerPlugin, self).__init__()

        self.leftTabView = TabView()
        self.leftTabView.setWidgetClass(SAXSViewerPluginBase)
        self.leftTabView.setHeaderModel(headermodel)
        self.leftTabView.setSelectionModel(selectionmodel)
        self.rightTabView = TabView()
        self.rightTabView.setWidgetClass(SAXSViewerPluginBase)
        self.rightTabView.setHeaderModel(headermodel)

        self.addWidget(self.leftTabView)
        self.addWidget(self.rightTabView)
Exemple #5
0
    def __init__(self, *args, **kwargs):

        # Data model
        self.headermodel = QStandardItemModel()
        self.toolbar = QToolBar()

        # plot widget
        self.reduceWidget = QWidget()
        self.plot = pg.PlotWidget()
        self.layout = QGridLayout()
        self.reduceWidget.setLayout(self.layout)
        self.layout.addWidget(self.plot)
        x = np.random.random(20)
        y = np.random.random(20)
        self.plot.plot(x, y)

        # table widget
        self.tableWidget = QWidget()
        self.table = QTableWidget()
        self.layout2 = QGridLayout()
        self.tableWidget.setLayout(self.layout2)
        self.layout2.addWidget(self.table)
        self.table.setRowCount(len(x))
        self.table.setColumnCount(2)
        for i in range(0, len(x)):
            self.table.setItem(i, 0, QTableWidgetItem(str(round(x[i], 3))))
            self.table.setItem(i, 1, QTableWidgetItem(str(round(y[i], 3))))

        # Selection model
        self.selectionmodel = QItemSelectionModel(self.headermodel)

        # Setup TabViews
        self.rawview = TabView(self.headermodel, self.selectionmodel,
                               widgets.EFIViewerPlugin, 'primary')

        self.reduceview = TabView(self.headermodel, self.selectionmodel,
                                  self.reduceWidget)

        self.metadataview = MetadataView(self.headermodel, self.selectionmodel)

        self.stages = {
            'View':
            GUILayout(self.rawview, top=self.toolbar, right=self.metadataview),
            'Reduce':
            GUILayout(self.reduceWidget,
                      top=self.toolbar,
                      right=self.tableWidget)
            # 'View': GUILayout(QLabel('View'))
        }
        super(EFIPlugin, self).__init__(*args, **kwargs)
Exemple #6
0
    def __init__(self):
        #Define workflows
        self.my_workflow = MyWorkflow()
        #self.my_workflow_editor = WorkflowEditor(self.my_workflow)
        # Define a GUILayout
        # GUILayouts must provide a center widget
        #self.container_widget = QWidget()
        self.split_widget = CatalogAndAnalysisSplitWidget()
        layout = QVBoxLayout()  # what kind of layout
        self.button = QPushButton("push this")
        #layout.addWidget(self.split_widget) # add things to the layout one by one
        #layout.addWidget(self.button)
        #self.container_widget.setLayout(layout) # apply layout to the basic widget
        bottom_widget = QLabel('bottom')
        left_widget = QLabel('left')
        leftbottom_widget = QLabel('left bottom')
        right_widget = QLabel('right')

        self.model = QStandardItemModel()
        self.selectionmodel = QItemSelectionModel(self.model)
        stream = 'primary'
        field = 'img'
        self.test_tab_view = TabView(self.model,
                                     self.selectionmodel,
                                     widgetcls=MyImageView,
                                     stream=stream,
                                     field=field)

        self.parameter_view = ParameterTree()
        for operation in self.my_workflow.operations:
            parameter_dict = operation.as_parameter()
            for list_parameter in parameter_dict:
                parameter = Parameter.create(**list_parameter)
                self.parameter_view.addParameters(parameter)
        stage_layout = GUILayout(
            center=self.split_widget,
            #left=left_widget,
            #right=right_widget,
            #leftbottom = leftbottom_widget,
            bottom=self.button,
        )
        second_stage_layout = GUILayout(center=self.test_tab_view,
                                        righttop=self.parameter_view)
        #workflow_stage = GUILayout(center=self.test_tab_view, righttop=self.my_workflow_editor)
        #self.button.clicked.connect(self.update_label)
        #self.button.clicked.connect(self.show_message)
        self.button.clicked.connect(self.run_workflow)
        self.stages = {
            'catalogviewer and fft': stage_layout,
            'Something Else': second_stage_layout,
            #'testing workflow editor': workflow_stage,
        }

        super(MyGUIPlugin, self).__init__()
Exemple #7
0
class SAXSMultiViewerPlugin(QSplitter, QWidgetPlugin):
    def __init__(self, headermodel, selectionmodel):
        super(SAXSMultiViewerPlugin, self).__init__()

        self.leftTabView = TabView()
        self.leftTabView.setWidgetClass(SAXSViewerPluginBase)
        self.leftTabView.setHeaderModel(headermodel)
        self.leftTabView.setSelectionModel(selectionmodel)
        self.rightTabView = TabView()
        self.rightTabView.setWidgetClass(SAXSViewerPluginBase)
        self.rightTabView.setHeaderModel(headermodel)

        self.addWidget(self.leftTabView)
        self.addWidget(self.rightTabView)

    def __getattr__(self, attr):  ## implicitly wrap methods from leftViewer
        if hasattr(self.plotwidget, attr):
            m = getattr(self.leftViewer, attr)
            if hasattr(m, '__call__'):
                return m
        raise NameError(attr)
Exemple #8
0
    def __init__(self):
        # Data model
        self.catalogModel = QStandardItemModel()

        # Selection model
        self.selectionmodel = QItemSelectionModel(self.catalogModel)

        # Setup TabViews
        self.rawview = TabView(self.catalogModel,
                               self.selectionmodel,
                               widgets.NCEMViewerPlugin,
                               'primary',
                               field='raw')

        self.fftview = TabView(self.catalogModel,
                               self.selectionmodel,
                               widgets.FFTViewerPlugin,
                               'primary',
                               field='raw')

        #self.fourDview = TabView(self.headermodel, self.selectionmodel, widgets.FourDImageView, 'primary')

        self.metadataview = MetadataView(self.catalogModel,
                                         self.selectionmodel,
                                         excludedkeys=('uid', 'descriptor',
                                                       'data'))

        # self.toolbar = widgets.NCEMToolbar(self.catalogModel, self.selectionmodel)

        self.stages = {
            'View':
            GUILayout(self.rawview,
                      right=self.metadataview),  # top=self.toolbar, )),
            # 'View': GUILayout(self.rawview, top=self.toolbar),
            # '4D STEM': GUILayout(self.fourDview, ),
            'FFT View': GUILayout(self.fftview, )
        }
        super(NCEMPlugin, self).__init__()
Exemple #9
0
class SAXSPlugin(GUIPlugin):
    name = 'SAXS'

    def __init__(self):
        # Late imports required due to plugin system
        from xicam.SAXS.calibration import CalibrationPanel
        from xicam.SAXS.widgets.SAXSViewerPlugin import SAXSCalibrationViewer, SAXSMaskingViewer, SAXSReductionViewer
        from xicam.SAXS.widgets.SAXSToolbar import SAXSToolbarRaw, SAXSToolbarMask, SAXSToolbarReduce
        from xicam.SAXS.widgets.XPCSToolbar import XPCSToolBar

        self.derivedDataModel = DerivedDataModel()
        self.catalogModel = QStandardItemModel()

        # Data model
        self.catalogModel = QStandardItemModel()
        self.selectionmodel = QItemSelectionModel(self.catalogModel)

        # Initialize workflows
        self.maskingworkflow = MaskingWorkflow()
        self.simulateworkflow = SimulateWorkflow()
        self.displayworkflow = DisplayWorkflow()
        self.reduceworkflow = ReduceWorkflow()
        self.roiworkflow = ROIWorkflow()

        # Grab the calibration plugin
        self.calibrationsettings = pluginmanager.get_plugin_by_name('xicam.SAXS.calibration',
                                                                    'SettingsPlugin')

        # Setup TabViews
        # FIXME -- rework how fields propagate to displays (i.e. each image has its own detector, switching
        # between tabs updates the detector combobbox correctly)
        field = "fccd_image"
        self.calibrationtabview = TabView(self.catalogModel, widgetcls=SAXSCalibrationViewer,
                                          stream='primary', field=field,
                                          selectionmodel=self.selectionmodel,
                                          bindings=[(self.calibrationsettings.sigGeometryChanged, 'setGeometry')],
                                          geometry=self.getAI)
        self.masktabview = TabView(self.catalogModel, widgetcls=SAXSMaskingViewer, selectionmodel=self.selectionmodel,
                                   stream='primary', field=field,
                                   bindings=[('sigTimeChangeFinished', self.indexChanged),
                                             (self.calibrationsettings.sigGeometryChanged, 'setGeometry')],
                                   geometry=self.getAI)
        self.reducetabview = TabView(self.catalogModel, widgetcls=SAXSReductionViewer,
                                     selectionmodel=self.selectionmodel,
                                     stream='primary', field=field,
                                     bindings=[('sigTimeChangeFinished', self.indexChanged),
                                               (self.calibrationsettings.sigGeometryChanged, 'setGeometry')],
                                     geometry=self.getAI)
        self.comparemultiview = QLabel("COMING SOON!")  # SAXSMultiViewerPlugin(self.catalogModel, self.selectionmodel)

        # Setup correlation views
        self.correlationView = TabView(self.catalogModel, widgetcls=SAXSReductionViewer,
                                       selectionmodel=self.selectionmodel,
                                       stream='primary', field=field)
        self.twoTimeProcessor = TwoTimeParameterTree(processor=self.processTwoTime)
        self.twoTimeToolBar = XPCSToolBar(headermodel=self.catalogModel,
                                          selectionmodel=self.selectionmodel,
                                          view=self.correlationView.currentWidget,
                                          workflow=self.roiworkflow,
                                          index=0)
        self.oneTimeProcessor = OneTimeParameterTree(processor=self.processOneTime)
        self.oneTimeToolBar = XPCSToolBar(view=self.correlationView.currentWidget,
                                          workflow=self.roiworkflow,
                                          index=0)

        # Setup toolbars
        self.rawtoolbar = SAXSToolbarRaw(self.catalogModel, self.selectionmodel)
        self.masktoolbar = SAXSToolbarMask(self.catalogModel, self.selectionmodel)
        self.reducetoolbar = SAXSToolbarReduce(self.catalogModel, self.selectionmodel,
                                               view=self.reducetabview.currentWidget, workflow=self.reduceworkflow)
        self.reducetabview.kwargs['toolbar'] = self.reducetoolbar
        self.reducetoolbar.sigDeviceChanged.connect(self.deviceChanged)

        # Setup calibration widgets
        self.calibrationsettings.setModels(self.catalogModel, self.calibrationtabview.selectionmodel)
        self.calibrationpanel = CalibrationPanel(self.catalogModel, self.calibrationtabview.selectionmodel)
        self.calibrationpanel.sigDoCalibrateWorkflow.connect(self.doCalibrateWorkflow)
        self.calibrationsettings.sigGeometryChanged.connect(self.doSimulateWorkflow)

        # Setup masking widgets
        self.maskeditor = WorkflowEditor(self.maskingworkflow)
        self.maskeditor.sigWorkflowChanged.connect(self.doMaskingWorkflow)

        # Setup reduction widgets
        self.displayeditor = WorkflowEditor(self.displayworkflow)
        self.reduceeditor = WorkflowEditor(self.reduceworkflow)
        self.reduceplot = DerivedDataWidget(self.derivedDataModel)
        self.reducetoolbar.sigDoWorkflow.connect(self.doReduceWorkflow)
        self.reduceeditor.sigWorkflowChanged.connect(self.doReduceWorkflow)
        self.displayeditor.sigWorkflowChanged.connect(self.doDisplayWorkflow)
        self.reducetabview.currentChanged.connect(self.catalogChanged)

        # Setup correlation widgets
        self.correlationResults = DerivedDataWidget(self.derivedDataModel)

        self.stages = {
            'Calibrate': GUILayout(self.calibrationtabview,
                                   right=self.calibrationsettings.widget,
                                   rightbottom=self.calibrationpanel,
                                   top=self.rawtoolbar),
            'Mask': GUILayout(self.masktabview,
                              right=self.maskeditor,
                              top=self.masktoolbar),
            'Reduce': GUILayout(self.reducetabview,
                                bottom=self.reduceplot, right=self.reduceeditor, righttop=self.displayeditor,
                                top=self.reducetoolbar),
            'Compare': GUILayout(self.comparemultiview, top=self.reducetoolbar, bottom=self.reduceplot,
                                 right=self.reduceeditor),
            'Correlate': {
                '2-Time Correlation': GUILayout(self.correlationView,
                                                top=self.twoTimeToolBar,
                                                rightbottom=self.twoTimeProcessor,
                                                bottom=self.correlationResults),
                '1-Time Correlation': GUILayout(self.correlationView,
                                                top=self.oneTimeToolBar,
                                                rightbottom=self.oneTimeProcessor,
                                                bottom=self.correlationResults)
            }
        }

        super(SAXSPlugin, self).__init__()

        # Start visualizations
        self.displayworkflow.visualize(self.reduceplot, imageview=lambda: self.reducetabview.currentWidget(),
                                       toolbar=self.reducetoolbar)

    def getAI(self):
        """ Convenience method to get current field's AI """
        device = self.reducetoolbar.detectorcombobox.currentText()
        ai = self.calibrationsettings.AI(device)
        return ai

    def indexChanged(self):
        if not self.reduceplot.toolbar.multiplot.isChecked():
            self.doReduceWorkflow()

    def catalogChanged(self):
        # TODO: both catalogChanged and deviceChanged will fire, redundantly, when the first image is opened
        self.doReduceWorkflow()
        self.doDisplayWorkflow()

    def deviceChanged(self, device_name):
        self.doReduceWorkflow()
        self.doDisplayWorkflow()

    def currentCatalog(self):
        return self.catalogModel.itemFromIndex(self.selectionmodel.currentIndex()).data(Qt.UserRole)

    def schema(self):
        saxs_schema = {
            "techniques": [
                {
                    "technique": "scattering",
                    "configuration": {
                        "geometry": "transmission",
                        "detector_model": "fastccd",
                    },
                    "data_mapping": {
                        # "incoming_energy": [
                        #    "baseline",
                        #    "E"
                        # ]
                        "data_image": [
                            "primary",
                            "fccd_image"
                        ],
                        "dark_image": [
                            "dark",
                            "fccd_image"
                        ]
                    },
                    "version": 0
                },
            ]}

        return saxs_schema

    def appendCatalog(self, catalog: BlueskyRun, **kwargs):
        catalog.metadata.update(self.schema())

        displayName = ""
        if 'sample_name' in catalog.metadata['start']:
            displayName = catalog.metadata['start']['sample_name']
        elif 'scan_id' in catalog.metadata['start']:
            displayName = f"Scan: {catalog.metadata['start']['scan_id']}"
        else:
            displayName = f"UID: {catalog.metadata['start']['uid']}"

        item = CheckableItem(displayName)
        item.setData(displayName, Qt.DisplayRole)
        item.setData(catalog, Qt.UserRole)
        self.catalogModel.appendRow(item)
        self.catalogModel.dataChanged.emit(item.index(), item.index())

    def checkDataShape(self, data):
        """Checks the shape of the data and gets the first frame if able to."""
        if data.shape[0] > 1:
            msg.notifyMessage("Looks like you did not open a single data frame. "
                              "Automated calibration only works with single frame data.")
            return None
        else:
            return data[0]

    @threads.method()
    def doCalibrateWorkflow(self, workflow: Workflow):
        data = self.calibrationtabview.currentWidget().image
        data = self.checkDataShape(data)
        if data is None: return
        device = self.rawtoolbar.detectorcombobox.currentText()
        ai = self.calibrationsettings.AI(device)
        # ai.detector = detectors.Pilatus2M()
        calibrant = self.calibrationpanel.parameter['Calibrant Material']

        def setAI(result):
            self.calibrationsettings.setAI(result['ai'].value, device)
            self.doMaskingWorkflow()

        workflow.execute(None, data=data, ai=ai, calibrant=calibrant, callback_slot=setAI, threadkey='calibrate')

    @threads.method()
    def doSimulateWorkflow(self, *_):
        # TEMPORARY HACK for demonstration
        # if self.reducetabview.currentWidget():
        #     threads.invoke_in_main_thread(self.reducetabview.currentWidget().setTransform)

        if not self.calibrationtabview.currentWidget(): return
        data = self.calibrationtabview.currentWidget().image
        data = self.checkDataShape(data)
        if data is None: return
        device = self.rawtoolbar.detectorcombobox.currentText()
        ai = self.calibrationsettings.AI(device)
        if not ai: return
        calibrant = self.calibrationpanel.parameter['Calibrant Material']
        outputwidget = self.calibrationtabview.currentWidget()

        def showSimulatedCalibrant(result=None):
            outputwidget.setCalibrantImage(result['data'].value)

        self.simulateworkflow.execute(None, data=data, ai=ai, calibrant=calibrant, callback_slot=showSimulatedCalibrant,
                                      threadkey='simulate')

    @threads.method()
    def doMaskingWorkflow(self, workflow=None):
        if not self.masktabview.currentWidget(): return
        if not self.checkPolygonsSet(self.maskingworkflow):
            data = self.masktabview.currentWidget().image
            device = self.masktoolbar.detectorcombobox.currentText()
            ai = self.calibrationsettings.AI(device)
            outputwidget = self.masktabview.currentWidget()

            def showMask(result=None):
                if result:
                    outputwidget.setMaskImage(result['mask'].value)
                else:
                    outputwidget.setMaskImage(None)
                self.doDisplayWorkflow()
                self.doReduceWorkflow()

            if not workflow: workflow = self.maskingworkflow
            workflow.execute(None, data=data, ai=ai, callback_slot=showMask, threadkey='masking')

    # disabled
    @threads.method()
    def doDisplayWorkflow(self):
        return
        if not self.reducetabview.currentWidget(): return
        currentwidget = self.reducetabview.currentWidget()
        data = currentwidget.image
        data = [data[currentwidget.timeIndex(currentwidget.timeline)[0]]]
        device = self.reducetoolbar.detectorcombobox.currentText()
        ai = self.calibrationsettings.AI(device)
        if not ai: return
        mask = self.maskingworkflow.lastresult[0]['mask'].value if self.maskingworkflow.lastresult else None
        outputwidget = currentwidget

        def showDisplay(*results):
            outputwidget.setResults(results)

        self.displayworkflow.execute(None, data=data, ai=ai, mask=mask, callback_slot=showDisplay, threadkey='display')

    @threads.method()
    def doReduceWorkflow(self):
        return
        if not self.reducetabview.currentWidget(): return
        multimode = self.reducetoolbar.multiplot.isChecked()
        currentItem = self.catalogModel.itemFromIndex(self.selectionmodel.currentIndex())
        # FIXME -- hardcoded stream
        stream = "primary"
        data = currentItem.data(Qt.UserRole)
        field = self.reducetoolbar.detectorcombobox.currentText()
        if not field: return
        eventStream = getattr(currentItem.data(Qt.UserRole), stream).to_dask()[
            self.reducetoolbar.detectorcombobox.currentText()]
        if eventStream.ndim > 3:
            eventStream = eventStream[0]
        data = MetaXArray(eventStream)
        if not multimode:
            currentwidget = self.reducetabview.currentWidget()
            data = [data[currentwidget.timeIndex(currentwidget.timeLine)[0]]]
        device = self.reducetoolbar.detectorcombobox.currentText()
        ai = self.calibrationsettings.AI(device)
        if not ai: return
        ai = [ai] * len(data)
        mask = [self.maskingworkflow.lastresult[0]['mask'].value if self.maskingworkflow.lastresult else None] * len(
            data)

        def showReduce(*results):
            # FIXME -- Better way to get the hints from the results
            parentItem = CheckableItem("Scattering Reduction")
            for result in results:
                hints = next(iter(result.items()))[-1].parent.hints
                for hint in hints:
                    item = CheckableItem(hint.name)
                    item.setData(hint, Qt.UserRole)
                    parentItem.appendRow(item)
            self.derivedDataModel.appendRow(parentItem)

        self.reduceworkflow.execute_all(None, data=data, ai=ai, mask=mask, callback_slot=showReduce, threadkey='reduce')

    def checkPolygonsSet(self, workflow: Workflow):
        """
        Check for any unset polygonmask processes; start masking mode if found

        Parameters
        ----------
        workflow: Workflow

        Returns
        -------
        bool
            True if unset polygonmask process is found

        """
        pluginmaskclass = pluginmanager.get_plugin_by_name('Polygon Mask', 'ProcessingPlugin')
        for process in workflow.processes:
            if isinstance(process, pluginmaskclass):
                if process.polygon.value is None:
                    self.startPolygonMasking(process)
                    return True
        return False

    def startPolygonMasking(self, process):
        self.setEnabledOuterWidgets(False)

        # Start drawing mode
        viewer = self.masktabview.currentWidget()  # type: SAXSViewerPluginBase
        viewer.imageItem.setDrawKernel(kernel=np.array([[0]]), mask=None, center=(0, 0), mode='add')
        viewer.imageItem.drawMode = self.drawEvent
        viewer.maskROI.clearPoints()

        # Setup other signals
        process.parameter.child('Finish Mask').sigActivated.connect(partial(self.finishMask, process))
        process.parameter.child('Clear Selection').sigActivated.connect(self.clearMask)

    def setEnabledOuterWidgets(self, enabled):
        # Disable other widgets
        mainwindow = self.masktabview.window()
        for dockwidget in mainwindow.findChildren(QDockWidget):
            dockwidget.setEnabled(enabled)
        mainwindow.rightwidget.setEnabled(True)
        self.maskeditor.workflowview.setEnabled(enabled)
        self.masktabview.tabBar().setEnabled(enabled)
        mainwindow.menuBar().setEnabled(enabled)
        mainwindow.pluginmodewidget.setEnabled(enabled)

    def clearMask(self):
        viewer = self.masktabview.currentWidget()  # type: SAXSViewerPluginBase
        viewer.maskROI.clearPoints()

    def finishMask(self, process, sender):
        viewer = self.masktabview.currentWidget()  # type: SAXSViewerPluginBase
        process.polygon.value = np.array([list(handle['pos']) for handle in viewer.maskROI.handles])
        self.setEnabledOuterWidgets(True)

        # End drawing mode
        viewer.imageItem.drawKernel = None
        viewer.maskROI.clearPoints()
        process.parameter.clearChildren()

        # Redo workflow with polygon
        self.doMaskingWorkflow()

    def drawEvent(self, kernel, imgdata, mask, ss, ts, event):
        viewer = self.masktabview.currentWidget()  # type: SAXSViewerPluginBase
        viewer.maskROI.addFreeHandle(viewer.view.vb.mapSceneToView(event.scenePos()))
        if len(viewer.maskROI.handles) > 1:
            viewer.maskROI.addSegment(viewer.maskROI.handles[-2]['item'], viewer.maskROI.handles[-1]['item'])

    def processOneTime(self):
        self.process(self.oneTimeProcessor, self.correlationView.currentWidget(),
                     finished_slot=self.updateDerivedDataModel)

    def processTwoTime(self):
        self.process(self.twoTimeProcessor, self.correlationView.currentWidget(),
                     finished_slot=self.updateDerivedDataModel)

    def process(self, processor: CorrelationParameterTree, widget, **kwargs):
        if processor:
            roiFuture = self.roiworkflow.execute(data=self.correlationView.currentWidget().image[0],
                                                 image=self.correlationView.currentWidget().imageItem)  # Pass in single frame for data shape
            roiResult = roiFuture.result()
            label = roiResult[-1]["roi"]
            if label is None:
                msg.notifyMessage("Please define an ROI using the toolbar before running correlation.")
                return

            workflow = processor.workflow
            # FIXME -- don't grab first match
            technique = \
                [technique for technique in self.schema()['techniques'] if technique['technique'] == 'scattering'][0]
            stream, field = technique['data_mapping']['data_image']
            # TODO: the compute() takes a long time..., do we need to do this here? If so, show a progress bar...
            # Trim the data frames
            catalog = self.currentCatalog()
            data = [getattr(catalog, stream).to_dask()[field][0].where(
                DataArray(label, dims=["dim_1", "dim_2"]), drop=True).compute()]
            # Trim the dark images
            msg.notifyMessage("Skipping dark correction...")
            darks = [None] * len(data)
            dark_stream, dark_field = technique['data_mapping']['dark_image']
            if stream in catalog:
                darks = [getattr(catalog, dark_stream).to_dask()[dark_field][0].where(
                    DataArray(label, dims=["dim_1", "dim_2"]), drop=True).compute()]
            else:
                msg.notifyMessage(f"No dark stream named \"{dark_stream}\" for current catalog. No dark correction.")
            label = label.compress(np.any(label, axis=0), axis=1).compress(np.any(label, axis=1), axis=0)
            labels = [label] * len(data)  # TODO: update for multiple ROIs
            numLevels = [1] * len(data)

            numBufs = []
            for i in range(len(data)):
                shape = data[i].shape[0]
                # multi_tau_corr requires num_bufs to be even
                if shape % 2:
                    shape += 1
                numBufs.append(shape)

            if kwargs.get('finished_slot'):
                finishedSlot = kwargs['finished_slot']
            else:
                finishedSlot = self.updateDerivedDataModel

            # workflow_pickle = pickle.dumps(workflow)
            workflow.execute_all(None,
                                 # data=data,
                                 images=data,
                                 darks=darks,
                                 labels=labels,
                                 finished_slot=partial(finishedSlot,
                                                       workflow=workflow))
                                                       # workflow_pickle=workflow_pickle))

    def updateDerivedDataModel(self, workflow, **kwargs):
        parentItem = CheckableItem(workflow.name)
        for hint in workflow.hints:
            item = CheckableItem(hint.name)
            item.setData(hint, Qt.UserRole)
            item.setCheckable(True)
            parentItem.appendRow(item)
        self.derivedDataModel.appendRow(parentItem)
Exemple #10
0
class TomographyPlugin(GUIPlugin):
    name = 'Tomography'
    sigLog = Signal(int, str, str, np.ndarray)
    slice = 0
    multislice = 1
    preview3d = 2
    fullrecon = 3

    def __init__(self):
        self.workflow = Workflow()

        self.headermodel = QStandardItemModel()
        # self.alignmenttabview = TabView(self.headermodel)
        self.rawtabview = TabView(self.headermodel,
                                  widgetcls=RAWViewer,
                                  field='primary')
        self.recontabs = QTabWidget()

        self.workfloweditor = WorkflowEditor(self.workflow)
        self.workfloweditor.setHidden(True)

        self.tomotoolbar = TomoToolbar()
        self.tomotoolbar.sigSliceReconstruction.connect(self.sliceReconstruct)
        self.tomotoolbar.sigFullReconstruction.connect(self.fullReconstruction)

        self.stages = {
            'Alignment':
            GUILayout(QLabel('Alignment'),
                      right=self.workfloweditor,
                      top=self.tomotoolbar),
            'Preprocess':
            GUILayout(self.rawtabview,
                      right=self.workfloweditor,
                      top=self.tomotoolbar),
            'Reconstruct':
            GUILayout(self.recontabs,
                      top=self.tomotoolbar,
                      right=self.workfloweditor),
        }
        super(TomographyPlugin, self).__init__()

    def appendHeader(self, header: NonDBHeader, **kwargs):
        item = QStandardItem(header.startdoc.get('sample_name', '????'))
        item.header = header
        self.headermodel.appendRow(item)
        self.headermodel.dataChanged.emit(QModelIndex(), QModelIndex())

    def sliceReconstruct(self):
        currentitem = self.headermodel.item(self.rawtabview.currentIndex())
        if not currentitem:
            msg.showMessage(
                'Error: You must open files before reconstructing.')
        try:
            msg.showBusy()
            msg.showMessage('Running slice reconstruction...', level=msg.INFO)
            path = self.headermodel.item(
                self.rawtabview.currentIndex()).header.startdoc['path']
            self.workflow.execute(
                None,
                path=path,
                threadkey='slicereconstruct',
                callback_slot=partial(self.showReconstruction,
                                      mode=self.slice),
                except_slot=self.exceptionCallback)
        except Exception as ex:
            msg.logError(ex)
            msg.showReady()
            msg.clearMessage()

    def fullReconstruction(self):
        volumeviewer = VolumeViewer()
        self.recontabs.addTab(volumeviewer, '????')

        currentitem = self.headermodel.item(self.rawtabview.currentIndex())
        if not currentitem:
            msg.showMessage(
                'Error: You must open files before reconstructing.')
        try:
            msg.showBusy()
            msg.showMessage('Running slice reconstruction...', level=msg.INFO)
            currentheader = self.headermodel.item(
                self.rawtabview.currentIndex()).header
            readprocess = self.workflow.processes[
                0]  # hopefully! TODO: require a readprocess first
            readprocess.path.value = currentheader.startdoc['path']

            numofsinograms = currentheader.meta_array('primary').shape[1]

            executor = DaskExecutor()
            client = distributed.Client()

            def chunkiterator(workflow):
                for i in range(0, int(numofsinograms),
                               int(readprocess.chunksize.value)):
                    readprocess.sinoindex.value = i
                    yield executor.execute(workflow)

            _reconthread = QThreadFutureIterator(
                chunkiterator,
                self.workflow,
                callback_slot=partial(self.showReconstruction,
                                      mode=self.fullrecon),
                except_slot=self.exceptionCallback)
            _reconthread.start()
        except Exception as ex:
            msg.logError(ex)
            msg.showReady()
            msg.clearMessage()

    def exceptionCallback(self, ex):
        msg.notifyMessage("Reconstruction failed;\n see log for error")
        msg.showMessage("Reconstruction failed; see log for error")
        msg.logError(ex)
        msg.showReady()

    def showReconstruction(self, result, mode):
        print('result:', result)
        if mode == self.slice:
            sliceviewer = SliceViewer()
            sliceviewer.setImage(list(result.values())[0].value.squeeze())
            self.recontabs.addTab(sliceviewer, '????')

        if mode == self.fullrecon:
            self.recontabs.widget(self.recontabs.count() - 1).appendData(
                list(result.values())[0].value[::4, ::4, ::4])
        msg.showReady()
Exemple #11
0
class BSISB(GUIPlugin):
    name = 'BSISB'

    def __init__(self, *args, **kwargs):

        self.mapToH5 = mapToH5()
        # Data model
        self.headermodel = QStandardItemModel()

        # Selection model
        self.selectionmodel = QItemSelectionModel(self.headermodel)

        self.PCA_widget = FactorizationWidget(self.headermodel,
                                              self.selectionmodel)
        self.NMF_widget = FactorizationWidget(self.headermodel,
                                              self.selectionmodel)

        # update headers list when a tab window is closed
        self.headermodel.rowsRemoved.connect(
            partial(self.PCA_widget.setHeader, 'spectra'))
        self.headermodel.rowsRemoved.connect(
            partial(self.NMF_widget.setHeader, 'volume'))

        # Setup tabviews and update map selection
        self.imageview = TabView(self.headermodel, self.selectionmodel,
                                 MapView, 'image')

        self.stages = {
            "MapToH5": GUILayout(self.mapToH5),
            "Image View": GUILayout(self.imageview),
            "PCA": GUILayout(self.PCA_widget),
            "NMF": GUILayout(self.NMF_widget)
        }
        super(BSISB, self).__init__(*args, **kwargs)

    def appendHeader(self, header: NonDBHeader, **kwargs):
        # init item
        item = QStandardItem(
            header.startdoc.get('sample_name', '????') + '_' +
            str(self.headermodel.rowCount()))
        item.header = header
        item.selectedPixels = None

        self.headermodel.appendRow(item)
        self.headermodel.dataChanged.emit(QModelIndex(), QModelIndex())

        # read out image shape
        imageEvent = next(header.events(fields=['image']))
        imgShape = imageEvent['imgShape']

        # get current MapView widget
        currentMapView = self.imageview.currentWidget()
        # transmit imgshape to currentMapView
        currentMapView.getImgShape(imgShape)
        # get xy coordinates of ROI selected pixels
        currentMapView.sigRoiPixels.connect(
            partial(self.appendSelection, 'pixel'))
        currentMapView.sigRoiState.connect(partial(self.appendSelection,
                                                   'ROI'))
        currentMapView.sigAutoMaskState.connect(
            partial(self.appendSelection, 'autoMask'))
        currentMapView.sigSelectMaskState.connect(
            partial(self.appendSelection, 'select'))

        self.PCA_widget.setHeader(field='spectra')
        self.NMF_widget.setHeader(field='volume')
        for i in range(4):
            self.PCA_widget.roiList[i].sigRegionChangeFinished.connect(
                self.updateROI)

    def appendSelection(self, sigCase, sigContent):
        # get current widget and append selectedPixels to item
        currentItemIdx = self.imageview.currentIndex()
        if sigCase == 'pixel':
            self.headermodel.item(currentItemIdx).selectedPixels = sigContent
        elif sigCase == 'ROI':
            self.headermodel.item(currentItemIdx).roiState = sigContent
            self.PCA_widget.updateRoiMask()
            self.NMF_widget.updateRoiMask()
        elif sigCase == 'autoMask':
            self.headermodel.item(currentItemIdx).maskState = sigContent
            self.PCA_widget.updateRoiMask()
            self.NMF_widget.updateRoiMask()
        elif sigCase == 'select':
            self.headermodel.item(currentItemIdx).selectState = sigContent
            self.PCA_widget.updateRoiMask()
            self.NMF_widget.updateRoiMask()

    def updateROI(self, roi):
        if self.selectionmodel.hasSelection():
            selectMapIdx = self.selectionmodel.selectedIndexes()[0].row()
        else:
            selectMapIdx = 0
        self.imageview.widget(selectMapIdx).roiMove(roi)

    def updateTab(self, tabIdx):
        if tabIdx >= 0:
            self.selectionmodel.select(self.headermodel.index(tabIdx, 0),
                                       QItemSelectionModel.ClearAndSelect)
    def __init__(self):
        # Late imports required due to plugin system
        from xicam.SAXS.calibration import CalibrationPanel
        from xicam.SAXS.widgets.SAXSMultiViewer import SAXSMultiViewerPlugin
        from xicam.SAXS.widgets.SAXSViewerPlugin import SAXSViewerPluginBase, SAXSCalibrationViewer, SAXSMaskingViewer, \
            SAXSReductionViewer
        from xicam.SAXS.widgets.SAXSToolbar import SAXSToolbar
        from xicam.SAXS.widgets.SAXSSpectra import SAXSSpectra

        # Data model
        self.headermodel = QStandardItemModel()
        self.selectionmodel = QItemSelectionModel(self.headermodel)

        # Initialize workflows
        self.maskingworkflow = MaskingWorkflow()
        self.simulateworkflow = SimulateWorkflow()
        self.displayworkflow = DisplayWorkflow()
        self.reduceworkflow = ReduceWorkflow()

        # Grab the calibration plugin
        self.calibrationsettings = pluginmanager.getPluginByName(
            'xicam.SAXS.calibration', 'SettingsPlugin').plugin_object
        print(
            pluginmanager.getPluginByName('xicam.SAXS.calibration',
                                          'SettingsPlugin').path)

        # Setup TabViews
        self.calibrationtabview = TabView(
            self.headermodel,
            widgetcls=SAXSCalibrationViewer,
            selectionmodel=self.selectionmodel,
            bindings=[(self.calibrationsettings.sigGeometryChanged,
                       'setGeometry')],
            geometry=self.getAI)
        self.masktabview = TabView(
            self.headermodel,
            widgetcls=SAXSMaskingViewer,
            selectionmodel=self.selectionmodel,
            bindings=[('sigTimeChangeFinished', self.indexChanged),
                      (self.calibrationsettings.sigGeometryChanged,
                       'setGeometry')],
            geometry=self.getAI)
        self.reducetabview = TabView(
            self.headermodel,
            widgetcls=SAXSReductionViewer,
            selectionmodel=self.selectionmodel,
            bindings=[('sigTimeChangeFinished', self.indexChanged),
                      (self.calibrationsettings.sigGeometryChanged,
                       'setGeometry')],
            geometry=self.getAI)
        self.comparemultiview = SAXSMultiViewerPlugin(self.headermodel,
                                                      self.selectionmodel)

        # self.tabviewsynchronizer = TabViewSynchronizer(
        #     [self.calibrationtabview, self.masktabview, self.reducetabview, self.comparemultiview.leftTabView])

        # Setup toolbars
        self.toolbar = SAXSToolbar(self.headermodel, self.selectionmodel)
        self.calibrationtabview.kwargs['toolbar'] = self.toolbar
        self.reducetabview.kwargs['toolbar'] = self.toolbar

        # Setup calibration widgets
        self.calibrationsettings.setModels(
            self.headermodel, self.calibrationtabview.selectionmodel)
        self.calibrationpanel = CalibrationPanel(
            self.headermodel, self.calibrationtabview.selectionmodel)
        self.calibrationpanel.sigDoCalibrateWorkflow.connect(
            self.doCalibrateWorkflow)
        self.calibrationsettings.sigGeometryChanged.connect(
            self.doSimulateWorkflow)

        # Setup masking widgets
        self.maskeditor = WorkflowEditor(self.maskingworkflow)
        self.maskeditor.sigWorkflowChanged.connect(self.doMaskingWorkflow)

        # Setup reduction widgets
        self.displayeditor = WorkflowEditor(self.displayworkflow)
        self.reduceeditor = WorkflowEditor(self.reduceworkflow)
        self.reduceplot = SAXSSpectra(self.reduceworkflow, self.toolbar)
        self.toolbar.sigDoWorkflow.connect(partial(self.doReduceWorkflow))
        self.reduceeditor.sigWorkflowChanged.connect(self.doReduceWorkflow)
        self.displayeditor.sigWorkflowChanged.connect(self.doDisplayWorkflow)
        self.reducetabview.currentChanged.connect(self.headerChanged)
        self.reducetabview.currentChanged.connect(self.headerChanged)

        # Setup more bindings
        self.calibrationsettings.sigSimulateCalibrant.connect(
            partial(self.doSimulateWorkflow))

        self.stages = {
            'Calibrate':
            GUILayout(
                self.calibrationtabview,
                # pluginmanager.getPluginByName('SAXSViewerPlugin', 'WidgetPlugin').plugin_object()
                right=self.calibrationsettings.widget,
                rightbottom=self.calibrationpanel,
                top=self.toolbar),
            'Mask':
            GUILayout(self.masktabview,
                      right=self.maskeditor,
                      top=self.toolbar),
            'Reduce':
            GUILayout(self.reducetabview,
                      bottom=self.reduceplot,
                      right=self.reduceeditor,
                      righttop=self.displayeditor,
                      top=self.toolbar),
            'Compare':
            GUILayout(self.comparemultiview,
                      top=self.toolbar,
                      bottom=self.reduceplot,
                      right=self.reduceeditor)
        }
        super(SAXSPlugin, self).__init__()

        # Start visualizations
        self.displayworkflow.visualize(
            self.reduceplot,
            imageview=lambda: self.reducetabview.currentWidget(),
            toolbar=self.toolbar)
Exemple #13
0
class XPCS(GUIPlugin):
    name = 'XPCS'

    def __init__(self):
        self.catalog = BlueskyInMemoryCatalog()

        # XPCS data model
        self.resultsModel = QStandardItemModel()

        # Input (raw) data model
        self.headerModel = QStandardItemModel()
        self.selectionModel = QItemSelectionModel(self.headerModel)

        # Widgets
        self.calibrationSettings = pluginmanager.getPluginByName(
            'xicam.SAXS.calibration', 'SettingsPlugin').plugin_object

        # Setup TabViews
        self.rawTabView = TabView(
            self.headerModel,
            widgetcls=XPCSViewerPlugin,
            selectionmodel=self.selectionModel,
            bindings=[(self.calibrationSettings.sigGeometryChanged,
                       'setGeometry')],
            geometry=self.getAI)

        # Setup correlation views
        self.twoTimeView = TwoTimeView()
        self.twoTimeFileSelection = FileSelectionView(self.headerModel,
                                                      self.selectionModel)
        self.twoTimeProcessor = TwoTimeProcessor()
        self.twoTimeToolBar = QToolBar()
        self.twoTimeToolBar.addAction(QIcon(static.path('icons/run.png')),
                                      'Process', self.processTwoTime)
        self.twoTimeToolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)

        self.oneTimeView = OneTimeView()
        self.oneTimeFileSelection = FileSelectionView(self.headerModel,
                                                      self.selectionModel)
        self.oneTimeProcessor = OneTimeProcessor()
        self.oneTimeToolBar = QToolBar()
        self.oneTimeToolBar.addAction(QIcon(static.path('icons/run.png')),
                                      'Process', self.processOneTime)
        self.oneTimeToolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)

        # self.placeholder = QLabel('correlation parameters')

        self.stages = {
            'Raw':
            GUILayout(self.rawTabView, right=self.calibrationSettings.widget),
            '2-Time Correlation':
            GUILayout(
                self.twoTimeView,
                top=self.twoTimeToolBar,
                right=self.twoTimeFileSelection,
                rightbottom=self.twoTimeProcessor,
            ),
            # bottom=self.placeholder),
            '1-Time Correlation':
            GUILayout(
                self.oneTimeView,
                top=self.oneTimeToolBar,
                right=self.oneTimeFileSelection,
                rightbottom=self.oneTimeProcessor,
            )
            # bottom=self.placeholder)
        }

        # TODO -- improve result caching
        self._results = []

        super(XPCS, self).__init__()

    def appendHeader(self, header: NonDBHeader, **kwargs):
        item = QStandardItem(header.startdoc.get('sample_name', '????'))
        item.header = header
        self.headerModel.appendRow(item)
        self.selectionModel.reset()
        self.selectionModel.setCurrentIndex(
            self.headerModel.index(self.headerModel.rowCount() - 1, 0),
            QItemSelectionModel.Rows)
        self.headerModel.dataChanged.emit(QModelIndex(), QModelIndex())

        # Load any reduced (processed) data
        reduced = False
        for descriptor in header.descriptordocs:
            if descriptor['name'] == 'reduced':
                reduced = True
                break
        paths = header.startdoc.get('paths')
        for path in paths:
            if reduced:
                startItem = QStandardItem(
                    header.startdoc.get('sample_name', '??'))
                eventlist = header.eventdocs
                for event in eventlist:
                    eventItem = QStandardItem(event['data']['name'])
                    eventItem.setData(event, Qt.UserRole)
                    eventItem.setCheckable(True)
                    startItem.appendRow(eventItem)
                # TODO -- properly add to view (one-time or 2-time, etc.)
                self.oneTimeView.model.invisibleRootItem().appendRow(startItem)

    def getAI(self):
        return None

    def currentheader(self):
        return self.headerModel.itemFromIndex(
            self.selectionModel.currentIndex()).header

    def currentheaders(self):
        selected_indices = self.selectionModel.selectedIndexes()
        headers = []
        for model_index in selected_indices:
            headers.append(self.headerModel.itemFromIndex(model_index).header)
        return headers

    def processOneTime(self):
        self.process(self.oneTimeProcessor,
                     callback_slot=partial(
                         self.saveResult,
                         fileSelectionView=self.oneTimeFileSelection),
                     finished_slot=partial(self.createDocument,
                                           view=self.oneTimeView))

    def processTwoTime(self):
        self.process(self.twoTimeProcessor,
                     callback_slot=partial(
                         self.saveResult,
                         fileSelectionView=self.twoTimeFileSelection),
                     finished_slot=partial(self.createDocument,
                                           view=self.twoTimeView))

    def process(self, processor: XPCSProcessor, **kwargs):
        if processor:
            workflow = processor.workflow

            data = [header.meta_array() for header in self.currentheaders()]
            currentWidget = self.rawTabView.currentWidget()
            rois = [
                item for item in currentWidget.view.items
                if isinstance(item, BetterROI)
            ]
            labels = [currentWidget.poly_mask()] * len(data)
            numLevels = [1] * len(data)

            numBufs = []
            for i, _ in enumerate(data):
                shape = data[i].shape[0]
                # multi_tau_corr requires num_bufs to be even
                if shape % 2:
                    shape += 1
                numBufs.append(shape)

            if kwargs.get('callback_slot'):
                callbackSlot = kwargs['callback_slot']
            else:
                callbackSlot = self.saveResult
            if kwargs.get('finished_slot'):
                finishedSlot = kwargs['finished_slot']
            else:
                finishedSlot = self.createDocument

            workflowPickle = pickle.dumps(workflow)
            workflow.execute_all(None,
                                 data=data,
                                 labels=labels,
                                 num_levels=numLevels,
                                 num_bufs=numBufs,
                                 callback_slot=callbackSlot,
                                 finished_slot=partial(
                                     finishedSlot,
                                     header=self.currentheader(),
                                     roi=repr(rois[0]),
                                     workflow=workflowPickle))
            # TODO -- should header be passed to callback_slot
            # (callback slot handle can handle multiple data items in data list)

    def saveResult(self, result, fileSelectionView=None):
        if fileSelectionView:
            data = dict()
            if not fileSelectionView.correlationName.displayText():
                data[
                    'name'] = fileSelectionView.correlationName.placeholderText(
                    )
            else:
                data['name'] = fileSelectionView.correlationName.displayText()
            data['result'] = result

            self._results.append(data)

    def createDocument(self, view: CorrelationView, header, roi, workflow):
        self.catalog.upsert(self._createDocument,
                            (self._results, header, roi, workflow), {})
        # TODO -- make sure that this works for multiple selected series to process
        key = list(self.catalog)[-1]

        parentItem = QStandardItem(self._results[-1]['name'])
        for name, doc in self.catalog[key].read_canonical():
            if name == 'event':
                resultsModel = view.model
                # item = QStandardItem(doc['data']['name'])  # TODO -- make sure passed data['name'] is unique in model -> CHECK HERE
                item = QStandardItem(doc['data']['name'])
                item.setData(doc, Qt.UserRole)
                item.setCheckable(True)
                parentItem.appendRow(item)
                selectionModel = view.selectionModel
                selectionModel.reset()
                selectionModel.setCurrentIndex(
                    resultsModel.index(resultsModel.rowCount() - 1, 0),
                    QItemSelectionModel.Rows)
                selectionModel.select(selectionModel.currentIndex(),
                                      QItemSelectionModel.SelectCurrent)
        resultsModel.appendRow(parentItem)
        self._results = []

    def _createDocument(self, results, header, roi, workflow):
        timestamp = time.time()

        run_bundle = event_model.compose_run()
        yield 'start', run_bundle.start_doc

        # TODO -- make sure workflow pickles, or try dill / cloudpickle
        source = 'Xi-cam'

        peek_result = results[0]['result']
        g2_shape = peek_result['g2'].value.shape[0]
        # TODO -- make sure g2_err is calculated and added to internal process documents
        import numpy as np
        g2_err = np.zeros(g2_shape)
        g2_err_shape = g2_shape
        lag_steps_shape = peek_result['lag_steps'].value.shape[0]
        workflow = []
        workflow_shape = len(workflow)

        reduced_data_keys = {
            'g2': {
                'source': source,
                'dtype': 'number',
                'shape': [g2_shape]
            },
            'g2_err': {
                'source': source,
                'dtype': 'number',
                'shape': [g2_err_shape]
            },
            'lag_steps': {
                'source': source,
                'dtype': 'number',
                'shape': [lag_steps_shape]
            },
            'fit_curve': {
                'source': source,
                'dtype': 'number',
                'shape': [lag_steps_shape]
            },
            'name': {
                'source': source,
                'dtype': 'string',
                'shape': []
            },  # todo -- shape
            'workflow': {
                'source': source,
                'dtype': 'string',
                'shape': [workflow_shape]
            }
        }
        reduced_stream_name = 'reduced'
        reduced_stream_bundle = run_bundle.compose_descriptor(
            data_keys=reduced_data_keys, name=reduced_stream_name)
        yield 'descriptor', reduced_stream_bundle.descriptor_doc

        # todo -- peek frame shape
        frame_data_keys = {
            'frame': {
                'source': source,
                'dtype': 'number',
                'shape': []
            }
        }
        frame_stream_name = 'primary'
        frame_stream_bundle = run_bundle.compose_descriptor(
            data_keys=frame_data_keys, name=frame_stream_name)
        yield 'descriptor', frame_stream_bundle.descriptor_doc

        # todo -- store only paths? store the image data itself (memory...)
        # frames = header.startdoc['paths']
        frames = []
        for frame in frames:
            yield 'event', frame_stream_bundle.compose_event(
                data={frame}, timestamps={timestamp})

        for result in results:
            yield 'event', reduced_stream_bundle.compose_event(
                data={
                    'g2': result['result']['g2'].value,
                    'g2_err': g2_err,
                    'lag_steps': result['result']['lag_steps'].value,
                    'fit_curve': result['result']['fit_curve'].value,
                    'name': roi,  # TODO update to roi
                    'workflow': workflow
                },
                timestamps={
                    'g2': timestamp,
                    'g2_err': timestamp,
                    'lag_steps': timestamp,
                    'fit_curve': timestamp,
                    'name': timestamp,
                    'workflow': workflow
                })

        yield 'stop', run_bundle.compose_stop()
class SAXSPlugin(GUIPlugin):
    name = 'SAXS'

    def __init__(self):
        # Late imports required due to plugin system
        from xicam.SAXS.calibration import CalibrationPanel
        from xicam.SAXS.widgets.SAXSMultiViewer import SAXSMultiViewerPlugin
        from xicam.SAXS.widgets.SAXSViewerPlugin import SAXSViewerPluginBase, SAXSCalibrationViewer, SAXSMaskingViewer, \
            SAXSReductionViewer
        from xicam.SAXS.widgets.SAXSToolbar import SAXSToolbar
        from xicam.SAXS.widgets.SAXSSpectra import SAXSSpectra

        # Data model
        self.headermodel = QStandardItemModel()
        self.selectionmodel = QItemSelectionModel(self.headermodel)

        # Initialize workflows
        self.maskingworkflow = MaskingWorkflow()
        self.simulateworkflow = SimulateWorkflow()
        self.displayworkflow = DisplayWorkflow()
        self.reduceworkflow = ReduceWorkflow()

        # Grab the calibration plugin
        self.calibrationsettings = pluginmanager.getPluginByName(
            'xicam.SAXS.calibration', 'SettingsPlugin').plugin_object
        print(
            pluginmanager.getPluginByName('xicam.SAXS.calibration',
                                          'SettingsPlugin').path)

        # Setup TabViews
        self.calibrationtabview = TabView(
            self.headermodel,
            widgetcls=SAXSCalibrationViewer,
            selectionmodel=self.selectionmodel,
            bindings=[(self.calibrationsettings.sigGeometryChanged,
                       'setGeometry')],
            geometry=self.getAI)
        self.masktabview = TabView(
            self.headermodel,
            widgetcls=SAXSMaskingViewer,
            selectionmodel=self.selectionmodel,
            bindings=[('sigTimeChangeFinished', self.indexChanged),
                      (self.calibrationsettings.sigGeometryChanged,
                       'setGeometry')],
            geometry=self.getAI)
        self.reducetabview = TabView(
            self.headermodel,
            widgetcls=SAXSReductionViewer,
            selectionmodel=self.selectionmodel,
            bindings=[('sigTimeChangeFinished', self.indexChanged),
                      (self.calibrationsettings.sigGeometryChanged,
                       'setGeometry')],
            geometry=self.getAI)
        self.comparemultiview = SAXSMultiViewerPlugin(self.headermodel,
                                                      self.selectionmodel)

        # self.tabviewsynchronizer = TabViewSynchronizer(
        #     [self.calibrationtabview, self.masktabview, self.reducetabview, self.comparemultiview.leftTabView])

        # Setup toolbars
        self.toolbar = SAXSToolbar(self.headermodel, self.selectionmodel)
        self.calibrationtabview.kwargs['toolbar'] = self.toolbar
        self.reducetabview.kwargs['toolbar'] = self.toolbar

        # Setup calibration widgets
        self.calibrationsettings.setModels(
            self.headermodel, self.calibrationtabview.selectionmodel)
        self.calibrationpanel = CalibrationPanel(
            self.headermodel, self.calibrationtabview.selectionmodel)
        self.calibrationpanel.sigDoCalibrateWorkflow.connect(
            self.doCalibrateWorkflow)
        self.calibrationsettings.sigGeometryChanged.connect(
            self.doSimulateWorkflow)

        # Setup masking widgets
        self.maskeditor = WorkflowEditor(self.maskingworkflow)
        self.maskeditor.sigWorkflowChanged.connect(self.doMaskingWorkflow)

        # Setup reduction widgets
        self.displayeditor = WorkflowEditor(self.displayworkflow)
        self.reduceeditor = WorkflowEditor(self.reduceworkflow)
        self.reduceplot = SAXSSpectra(self.reduceworkflow, self.toolbar)
        self.toolbar.sigDoWorkflow.connect(partial(self.doReduceWorkflow))
        self.reduceeditor.sigWorkflowChanged.connect(self.doReduceWorkflow)
        self.displayeditor.sigWorkflowChanged.connect(self.doDisplayWorkflow)
        self.reducetabview.currentChanged.connect(self.headerChanged)
        self.reducetabview.currentChanged.connect(self.headerChanged)

        # Setup more bindings
        self.calibrationsettings.sigSimulateCalibrant.connect(
            partial(self.doSimulateWorkflow))

        self.stages = {
            'Calibrate':
            GUILayout(
                self.calibrationtabview,
                # pluginmanager.getPluginByName('SAXSViewerPlugin', 'WidgetPlugin').plugin_object()
                right=self.calibrationsettings.widget,
                rightbottom=self.calibrationpanel,
                top=self.toolbar),
            'Mask':
            GUILayout(self.masktabview,
                      right=self.maskeditor,
                      top=self.toolbar),
            'Reduce':
            GUILayout(self.reducetabview,
                      bottom=self.reduceplot,
                      right=self.reduceeditor,
                      righttop=self.displayeditor,
                      top=self.toolbar),
            'Compare':
            GUILayout(self.comparemultiview,
                      top=self.toolbar,
                      bottom=self.reduceplot,
                      right=self.reduceeditor)
        }
        super(SAXSPlugin, self).__init__()

        # Start visualizations
        self.displayworkflow.visualize(
            self.reduceplot,
            imageview=lambda: self.reducetabview.currentWidget(),
            toolbar=self.toolbar)

    # def experimentChanged(self):
    #     self.doReduceWorkflow(self.reduceworkflow)

    def getAI(self):
        """ Convenience method to get current field's AI """
        device = self.toolbar.detectorcombobox.currentText()
        ai = self.calibrationsettings.AI(device)
        return ai

    def indexChanged(self):
        if not self.reduceplot.toolbar.multiplot.isChecked():
            self.doReduceWorkflow(self.reduceworkflow)

    def headerChanged(self):
        self.toolbar.updatedetectorcombobox(None, None)
        self.doReduceWorkflow()
        self.doDisplayWorkflow()

    def appendHeader(self, header: NonDBHeader, **kwargs):
        item = QStandardItem(header.startdoc.get('sample_name', '????'))
        item.header = header
        self.headermodel.appendRow(item)
        self.selectionmodel.setCurrentIndex(
            self.headermodel.index(self.headermodel.rowCount() - 1, 0),
            QItemSelectionModel.Rows)
        self.headermodel.dataChanged.emit(QModelIndex(), QModelIndex())

    def doCalibrateWorkflow(self, workflow: Workflow):
        data = self.calibrationtabview.currentWidget().header.meta_array()[0]
        device = self.toolbar.detectorcombobox.currentText()
        ai = self.calibrationsettings.AI(device)
        # ai.detector = detectors.Pilatus2M()
        calibrant = self.calibrationpanel.parameter['Calibrant Material']

        def setAI(result):
            self.calibrationsettings.setAI(result['ai'].value, device)
            self.doMaskingWorkflow()

        workflow.execute(None,
                         data=data,
                         ai=ai,
                         calibrant=calibrant,
                         callback_slot=setAI,
                         threadkey='calibrate')

    def doSimulateWorkflow(self):
        # TEMPORARY HACK for demonstration
        #self.reducetabview.currentWidget().setTransform()

        if not self.calibrationtabview.currentWidget(): return
        data = self.calibrationtabview.currentWidget().header.meta_array()[0]
        device = self.toolbar.detectorcombobox.currentText()
        ai = self.calibrationsettings.AI(device)
        calibrant = self.calibrationpanel.parameter['Calibrant Material']
        outputwidget = self.calibrationtabview.currentWidget()

        def showSimulatedCalibrant(result=None):
            outputwidget.setCalibrantImage(result['data'].value)

        self.simulateworkflow.execute(None,
                                      data=data,
                                      ai=ai,
                                      calibrant=calibrant,
                                      callback_slot=showSimulatedCalibrant,
                                      threadkey='simulate')

    def doMaskingWorkflow(self, workflow=None):
        if not self.masktabview.currentWidget(): return
        if not self.checkPolygonsSet(self.maskingworkflow):
            data = self.masktabview.currentWidget().header.meta_array()[0]
            device = self.toolbar.detectorcombobox.currentText()
            ai = self.calibrationsettings.AI(device)
            outputwidget = self.masktabview.currentWidget()

            def showMask(result=None):
                if result:
                    outputwidget.setMaskImage(result['mask'].value)
                else:
                    outputwidget.setMaskImage(None)
                self.doDisplayWorkflow()
                self.doReduceWorkflow()

            if not workflow: workflow = self.maskingworkflow
            workflow.execute(None,
                             data=data,
                             ai=ai,
                             callback_slot=showMask,
                             threadkey='masking')

    def doDisplayWorkflow(self):
        if not self.reducetabview.currentWidget(): return
        currentwidget = self.reducetabview.currentWidget()
        data = currentwidget.header.meta_array()[currentwidget.timeIndex(
            currentwidget.timeLine)[0]]
        device = self.toolbar.detectorcombobox.currentText()
        ai = self.calibrationsettings.AI(device)
        mask = self.maskingworkflow.lastresult[0][
            'mask'].value if self.maskingworkflow.lastresult else None
        outputwidget = currentwidget

        def showDisplay(*results):
            outputwidget.setResults(results)

        self.displayworkflow.execute(None,
                                     data=data,
                                     ai=ai,
                                     mask=mask,
                                     callback_slot=showDisplay,
                                     threadkey='display')

    def doReduceWorkflow(self):
        if not self.reducetabview.currentWidget(): return
        multimode = self.reduceplot.toolbar.multiplot.isChecked()
        currentwidget = self.reducetabview.currentWidget()
        data = currentwidget.header.meta_array()
        if not multimode:
            data = [data[currentwidget.timeIndex(currentwidget.timeLine)[0]]]
        device = self.toolbar.detectorcombobox.currentText()
        ai = self.calibrationsettings.AI(device)
        ai = [ai] * len(data)
        mask = [
            self.maskingworkflow.lastresult[0]['mask'].value
            if self.maskingworkflow.lastresult else None
        ] * len(data)
        outputwidget = self.reduceplot

        # outputwidget.clear_all()

        def showReduce(*results):
            self.reduceplot.plot_mode(results)
            pass

        self.reduceworkflow.execute_all(None,
                                        data=data,
                                        ai=ai,
                                        mask=mask,
                                        callback_slot=showReduce,
                                        threadkey='reduce')

    def checkPolygonsSet(self, workflow: Workflow):
        """
        Check for any unset polygonmask processes; start masking mode if found

        Parameters
        ----------
        workflow: Workflow

        Returns
        -------
        bool
            True if unset polygonmask process is found

        """
        pluginmaskclass = pluginmanager.getPluginByName(
            'Polygon Mask', 'ProcessingPlugin')
        for process in workflow.processes:
            if isinstance(process, pluginmaskclass.plugin_object):
                if process.polygon.value is None:
                    self.startPolygonMasking(process)
                    return True
        return False

    def startPolygonMasking(self, process):
        self.setEnabledOuterWidgets(False)

        # Start drawing mode
        viewer = self.masktabview.currentWidget()  # type: SAXSViewerPluginBase
        viewer.imageItem.setDrawKernel(kernel=np.array([[0]]),
                                       mask=None,
                                       center=(0, 0),
                                       mode='add')
        viewer.imageItem.drawMode = self.drawEvent
        viewer.maskROI.clearPoints()

        # Setup other signals
        process.parameter.child('Finish Mask').sigActivated.connect(
            partial(self.finishMask, process))
        process.parameter.child('Clear Selection').sigActivated.connect(
            self.clearMask)

    def setEnabledOuterWidgets(self, enabled):
        # Disable other widgets
        mainwindow = self.masktabview.window()
        for dockwidget in mainwindow.findChildren(QDockWidget):
            dockwidget.setEnabled(enabled)
        mainwindow.rightwidget.setEnabled(True)
        self.maskeditor.workflowview.setEnabled(enabled)
        self.masktabview.tabBar().setEnabled(enabled)
        mainwindow.menuBar().setEnabled(enabled)
        mainwindow.pluginmodewidget.setEnabled(enabled)

    def clearMask(self):
        viewer = self.masktabview.currentWidget()  # type: SAXSViewerPluginBase
        viewer.maskROI.clearPoints()

    def finishMask(self, process, sender):
        viewer = self.masktabview.currentWidget()  # type: SAXSViewerPluginBase
        process.polygon.value = np.array(
            [list(handle['pos']) for handle in viewer.maskROI.handles])
        self.setEnabledOuterWidgets(True)

        # End drawing mode
        viewer.imageItem.drawKernel = None
        viewer.maskROI.clearPoints()
        process.parameter.clearChildren()

        # Redo workflow with polygon
        self.doMaskingWorkflow()

    def drawEvent(self, kernel, imgdata, mask, ss, ts, event):
        viewer = self.masktabview.currentWidget()  # type: SAXSViewerPluginBase
        viewer.maskROI.addFreeHandle(
            viewer.view.vb.mapSceneToView(event.scenePos()))
        if len(viewer.maskROI.handles) > 1:
            viewer.maskROI.addSegment(viewer.maskROI.handles[-2]['item'],
                                      viewer.maskROI.handles[-1]['item'])
Exemple #15
0
    def __init__(self):
        # Data model
        self.headermodel = QStandardItemModel()

        # Initialize workflows
        self.maskingworkflow = MaskingWorkflow()
        self.simulateworkflow = SimulateWorkflow()
        self.displayworkflow = DisplayWorkflow()
        self.reduceworkflow = ReduceWorkflow()

        # Setup TabViews
        self.calibrationtabview = TabView(self.headermodel,
                                          pluginmanager.getPluginByName('SAXSViewerPlugin',
                                                                        'WidgetPlugin').plugin_object,
                                          'primary')
        self.masktabview = TabView(self.headermodel,
                                   pluginmanager.getPluginByName('SAXSViewerPlugin', 'WidgetPlugin').plugin_object,
                                   'primary')
        self.reducetabview = TabView(self.headermodel,
                                     pluginmanager.getPluginByName('SAXSViewerPlugin', 'WidgetPlugin').plugin_object,
                                     'primary', bindings=[('sigTimeChangeFinished', self.indexChanged)])
        self.comparemultiview = SAXSMultiViewerPlugin(self.headermodel)

        self.tabviewsynchronizer = TabViewSynchronizer(
            [self.calibrationtabview, self.masktabview, self.reducetabview, self.comparemultiview.leftTabView])

        # Setup toolbars
        self.calibrationtoolbar = SAXSToolbar(self.calibrationtabview, workflow=self.reduceworkflow)
        self.reducetoolbar = SAXSToolbar(self.reducetabview, workflow=self.reduceworkflow)
        self.calibrationtabview.kwargs['toolbar'] = self.calibrationtoolbar
        self.reducetabview.kwargs['toolbar'] = self.reducetoolbar

        # Setup calibration widgets
        self.calibrationsettings = pluginmanager.getPluginByName('DeviceProfiles', 'SettingsPlugin').plugin_object
        self.calibrationsettings.setModels(self.headermodel, self.calibrationtabview.selectionmodel)
        self.calibrationpanel = CalibrationPanel()
        self.calibrationpanel.setModels(self.headermodel, self.calibrationtabview.selectionmodel)
        self.calibrationpanel.sigDoCalibrateWorkflow.connect(self.doCalibrateWorkflow)

        # Setup masking widgets
        self.maskeditor = WorkflowEditor(self.maskingworkflow)
        self.maskeditor.sigWorkflowChanged.connect(self.doMaskingWorkflow)

        # Setup reduction widgets
        self.displayeditor = WorkflowEditor(self.displayworkflow)
        self.reduceworkflow.attach(partial(self.doReduceWorkflow, self.reduceworkflow))
        self.reduceeditor = WorkflowEditor(self.reduceworkflow)
        self.reduceplot = SAXSSpectra(self.reduceworkflow, self.reducetoolbar)
        self.reducetoolbar.sigDoWorkflow.connect(partial(self.doReduceWorkflow, self.reduceworkflow))
        self.reduceeditor.sigWorkflowChanged.connect(self.doReduceWorkflow)
        self.displayeditor.sigWorkflowChanged.connect(self.doDisplayWorkflow)
        self.reducetabview.currentChanged.connect(partial(self.doReduceWorkflow, self.reduceworkflow))
        self.reducetabview.currentChanged.connect(partial(self.doDisplayWorkflow, self.displayworkflow))

        # Setup more bindings
        self.calibrationsettings.sigSimulateCalibrant.connect(partial(self.doSimulateWorkflow, self.simulateworkflow))

        self.stages = {
            'Calibrate': GUILayout(self.calibrationtabview,
                                   # pluginmanager.getPluginByName('SAXSViewerPlugin', 'WidgetPlugin').plugin_object()
                                   right=self.calibrationsettings.widget,
                                   rightbottom=self.calibrationpanel,
                                   top=self.calibrationtoolbar),
            'Mask': GUILayout(self.masktabview,
                              right=self.maskeditor),
            'Reduce': GUILayout(self.reducetabview,
                                bottom=self.reduceplot, right=self.reduceeditor, righttop=self.displayeditor,
                                top=self.reducetoolbar),
            'Compare': GUILayout(self.comparemultiview, top=self.reducetoolbar, bottom=self.reduceplot,
                                 right=self.reduceeditor)
        }
        super(SAXSPlugin, self).__init__()
Exemple #16
0
class SAXSPlugin(GUIPlugin):
    name = 'SAXS'
    sigLog = Signal(int, str, str, np.ndarray)

    def __init__(self):
        # Data model
        self.headermodel = QStandardItemModel()

        # Initialize workflows
        self.maskingworkflow = MaskingWorkflow()
        self.simulateworkflow = SimulateWorkflow()
        self.displayworkflow = DisplayWorkflow()
        self.reduceworkflow = ReduceWorkflow()

        # Setup TabViews
        self.calibrationtabview = TabView(self.headermodel,
                                          pluginmanager.getPluginByName('SAXSViewerPlugin',
                                                                        'WidgetPlugin').plugin_object,
                                          'primary')
        self.masktabview = TabView(self.headermodel,
                                   pluginmanager.getPluginByName('SAXSViewerPlugin', 'WidgetPlugin').plugin_object,
                                   'primary')
        self.reducetabview = TabView(self.headermodel,
                                     pluginmanager.getPluginByName('SAXSViewerPlugin', 'WidgetPlugin').plugin_object,
                                     'primary', bindings=[('sigTimeChangeFinished', self.indexChanged)])
        self.comparemultiview = SAXSMultiViewerPlugin(self.headermodel)

        self.tabviewsynchronizer = TabViewSynchronizer(
            [self.calibrationtabview, self.masktabview, self.reducetabview, self.comparemultiview.leftTabView])

        # Setup toolbars
        self.calibrationtoolbar = SAXSToolbar(self.calibrationtabview, workflow=self.reduceworkflow)
        self.reducetoolbar = SAXSToolbar(self.reducetabview, workflow=self.reduceworkflow)
        self.calibrationtabview.kwargs['toolbar'] = self.calibrationtoolbar
        self.reducetabview.kwargs['toolbar'] = self.reducetoolbar

        # Setup calibration widgets
        self.calibrationsettings = pluginmanager.getPluginByName('DeviceProfiles', 'SettingsPlugin').plugin_object
        self.calibrationsettings.setModels(self.headermodel, self.calibrationtabview.selectionmodel)
        self.calibrationpanel = CalibrationPanel()
        self.calibrationpanel.setModels(self.headermodel, self.calibrationtabview.selectionmodel)
        self.calibrationpanel.sigDoCalibrateWorkflow.connect(self.doCalibrateWorkflow)

        # Setup masking widgets
        self.maskeditor = WorkflowEditor(self.maskingworkflow)
        self.maskeditor.sigWorkflowChanged.connect(self.doMaskingWorkflow)

        # Setup reduction widgets
        self.displayeditor = WorkflowEditor(self.displayworkflow)
        self.reduceworkflow.attach(partial(self.doReduceWorkflow, self.reduceworkflow))
        self.reduceeditor = WorkflowEditor(self.reduceworkflow)
        self.reduceplot = SAXSSpectra(self.reduceworkflow, self.reducetoolbar)
        self.reducetoolbar.sigDoWorkflow.connect(partial(self.doReduceWorkflow, self.reduceworkflow))
        self.reduceeditor.sigWorkflowChanged.connect(self.doReduceWorkflow)
        self.displayeditor.sigWorkflowChanged.connect(self.doDisplayWorkflow)
        self.reducetabview.currentChanged.connect(partial(self.doReduceWorkflow, self.reduceworkflow))
        self.reducetabview.currentChanged.connect(partial(self.doDisplayWorkflow, self.displayworkflow))

        # Setup more bindings
        self.calibrationsettings.sigSimulateCalibrant.connect(partial(self.doSimulateWorkflow, self.simulateworkflow))

        self.stages = {
            'Calibrate': GUILayout(self.calibrationtabview,
                                   # pluginmanager.getPluginByName('SAXSViewerPlugin', 'WidgetPlugin').plugin_object()
                                   right=self.calibrationsettings.widget,
                                   rightbottom=self.calibrationpanel,
                                   top=self.calibrationtoolbar),
            'Mask': GUILayout(self.masktabview,
                              right=self.maskeditor),
            'Reduce': GUILayout(self.reducetabview,
                                bottom=self.reduceplot, right=self.reduceeditor, righttop=self.displayeditor,
                                top=self.reducetoolbar),
            'Compare': GUILayout(self.comparemultiview, top=self.reducetoolbar, bottom=self.reduceplot,
                                 right=self.reduceeditor)
        }
        super(SAXSPlugin, self).__init__()

    def experimentChanged(self):
        self.doReduceWorkflow(self.reduceworkflow)

    def indexChanged(self):
        if not self.reduceplot.toolbar.multiplot.isChecked():
            self.doReduceWorkflow(self.reduceworkflow)

    def appendHeader(self, header: NonDBHeader, **kwargs):
        item = QStandardItem(header.startdoc.get('sample_name', '????'))
        item.header = header
        self.headermodel.appendRow(item)
        self.headermodel.dataChanged.emit(QModelIndex(), QModelIndex())

    def doCalibrateWorkflow(self, workflow: Workflow):
        data = self.calibrationtabview.currentWidget().header.meta_array('primary')[0]
        device = self.calibrationpanel.parameter['Device']
        ai = self.calibrationsettings.AI('pilatus2M')
        ai.detector = detectors.Pilatus2M()
        c = calibrant.ALL_CALIBRANTS('AgBh')

        def setAI(result):
            self.calibrationsettings.setAI(result['ai'].value, device)
            self.doMaskingWorkflow(self.maskingworkflow)

        workflow.execute(None, data=data, ai=ai, calibrant=c, callback_slot=setAI, threadkey='calibrate')

    def doSimulateWorkflow(self, workflow: Workflow):
        data = self.calibrationtabview.currentWidget().header.meta_array('primary')[0]
        ai = self.calibrationsettings.AI('pilatus2M')
        ai.detector = detectors.Pilatus2M()
        calibrant = self.calibrationpanel.parameter['Calibrant Material']
        outputwidget = self.calibrationtabview.currentWidget()

        def showSimulatedCalibrant(result=None):
            outputwidget.setCalibrantImage(result['data'].value)

        workflow.execute(None, data=data, ai=ai, calibrant=calibrant, callback_slot=showSimulatedCalibrant,
                         threadkey='simulate')

    def doMaskingWorkflow(self, workflow: Workflow):
        if not self.checkPolygonsSet(workflow):
            data = self.calibrationtabview.currentWidget().header.meta_array('primary')[0]
            ai = self.calibrationsettings.AI('pilatus2M')
            ai.detector = detectors.Pilatus2M()
            outputwidget = self.masktabview.currentWidget()

            def showMask(result=None):
                if result:
                    outputwidget.setMaskImage(result['mask'].value)
                else:
                    outputwidget.setMaskImage(None)
                self.doDisplayWorkflow(self.displayworkflow)
                self.doReduceWorkflow(self.reduceworkflow)

            workflow.execute(None, data=data, ai=ai, callback_slot=showMask, threadkey='masking')

    def doDisplayWorkflow(self, workflow: Workflow):
        currentwidget = self.reducetabview.currentWidget()
        data = currentwidget.header.meta_array('primary')[currentwidget.timeIndex(currentwidget.timeLine)[0]]
        ai = self.calibrationsettings.AI('pilatus2M')
        ai.detector = detectors.Pilatus2M()
        mask = self.maskingworkflow.lastresult[0]['mask'].value if self.maskingworkflow.lastresult else None
        outputwidget = currentwidget

        def showDisplay(*results):
            outputwidget.setResults(results)

        workflow.execute(None, data=data, ai=ai, mask=mask, callback_slot=showDisplay, threadkey='display')

    def doReduceWorkflow(self, workflow: Workflow):
        multimode = self.reduceplot.toolbar.multiplot.isChecked()
        currentwidget = self.reducetabview.currentWidget()
        data = currentwidget.header.meta_array('primary')
        if not multimode:
            data = [data[currentwidget.timeIndex(currentwidget.timeLine)[0]]]
        ai = self.calibrationsettings.AI('pilatus2M')
        ai.detector = detectors.Pilatus2M()
        ai = [ai] * len(data)
        mask = [self.maskingworkflow.lastresult[0]['mask'].value if self.maskingworkflow.lastresult else None] * len(
            data)
        outputwidget = self.reduceplot
        outputwidget.clear()

        def showReduce(*results):
            outputwidget.appendResult(results)

        workflow.execute_all(None, data=data, ai=ai, mask=mask, callback_slot=showReduce, threadkey='reduce')

    def checkPolygonsSet(self, workflow: Workflow):
        """
        Check for any unset polygonmask processes; start masking mode if found

        Parameters
        ----------
        workflow: Workflow

        Returns
        -------
        bool
            True if unset polygonmask process is found

        """
        pluginmaskclass = pluginmanager.getPluginByName('Polygon Mask', 'ProcessingPlugin')
        for process in workflow.processes:
            if isinstance(process, pluginmaskclass.plugin_object):
                if process.polygon.value is None:
                    self.startPolygonMasking(process)
                    return True
        return False

    def startPolygonMasking(self, process):
        self.setEnabledOuterWidgets(False)

        # Start drawing mode
        viewer = self.masktabview.currentWidget()  # type: SAXSViewerPlugin
        viewer.imageItem.setDrawKernel(kernel=np.array([[0]]), mask=None, center=(0, 0), mode='add')
        viewer.imageItem.drawMode = self.drawEvent
        viewer.maskROI.clearPoints()

        # Setup other signals
        process.parameter.child('Finish Mask').sigActivated.connect(partial(self.finishMask, process))
        process.parameter.child('Clear Selection').sigActivated.connect(self.clearMask)

    def setEnabledOuterWidgets(self, enabled):
        # Disable other widgets
        mainwindow = self.masktabview.window()
        for dockwidget in mainwindow.findChildren(QDockWidget):
            dockwidget.setEnabled(enabled)
        mainwindow.rightwidget.setEnabled(True)
        self.maskeditor.workflowview.setEnabled(enabled)
        self.masktabview.tabBar().setEnabled(enabled)
        mainwindow.menuBar().setEnabled(enabled)
        mainwindow.pluginmodewidget.setEnabled(enabled)

    def clearMask(self):
        viewer = self.masktabview.currentWidget()  # type: SAXSViewerPlugin
        viewer.maskROI.clearPoints()

    def finishMask(self, process, sender):
        viewer = self.masktabview.currentWidget()  # type: SAXSViewerPlugin
        process.polygon.value = np.array([list(handle['pos']) for handle in viewer.maskROI.handles])
        self.setEnabledOuterWidgets(True)

        # End drawing mode
        viewer.imageItem.drawKernel = None
        viewer.maskROI.clearPoints()
        process.parameter.clearChildren()

        # Redo workflow with polygon
        self.doMaskingWorkflow(process._workflow)

    def drawEvent(self, kernel, imgdata, mask, ss, ts, event):
        viewer = self.masktabview.currentWidget()  # type: SAXSViewerPlugin
        viewer.maskROI.addFreeHandle(viewer.view.vb.mapSceneToView(event.scenePos()))
        if len(viewer.maskROI.handles) > 1:
            viewer.maskROI.addSegment(viewer.maskROI.handles[-2]['item'], viewer.maskROI.handles[-1]['item'])
Exemple #17
0
    def __init__(self):
        # Late imports required due to plugin system
        from xicam.SAXS.calibration import CalibrationPanel
        from xicam.SAXS.widgets.SAXSViewerPlugin import SAXSCalibrationViewer, SAXSMaskingViewer, SAXSReductionViewer
        from xicam.SAXS.widgets.SAXSToolbar import SAXSToolbarRaw, SAXSToolbarMask, SAXSToolbarReduce
        from xicam.SAXS.widgets.XPCSToolbar import XPCSToolBar

        self.derivedDataModel = DerivedDataModel()
        self.catalogModel = QStandardItemModel()

        # Data model
        self.catalogModel = QStandardItemModel()
        self.selectionmodel = QItemSelectionModel(self.catalogModel)

        # Initialize workflows
        self.maskingworkflow = MaskingWorkflow()
        self.simulateworkflow = SimulateWorkflow()
        self.displayworkflow = DisplayWorkflow()
        self.reduceworkflow = ReduceWorkflow()
        self.roiworkflow = ROIWorkflow()

        # Grab the calibration plugin
        self.calibrationsettings = pluginmanager.get_plugin_by_name('xicam.SAXS.calibration',
                                                                    'SettingsPlugin')

        # Setup TabViews
        # FIXME -- rework how fields propagate to displays (i.e. each image has its own detector, switching
        # between tabs updates the detector combobbox correctly)
        field = "fccd_image"
        self.calibrationtabview = TabView(self.catalogModel, widgetcls=SAXSCalibrationViewer,
                                          stream='primary', field=field,
                                          selectionmodel=self.selectionmodel,
                                          bindings=[(self.calibrationsettings.sigGeometryChanged, 'setGeometry')],
                                          geometry=self.getAI)
        self.masktabview = TabView(self.catalogModel, widgetcls=SAXSMaskingViewer, selectionmodel=self.selectionmodel,
                                   stream='primary', field=field,
                                   bindings=[('sigTimeChangeFinished', self.indexChanged),
                                             (self.calibrationsettings.sigGeometryChanged, 'setGeometry')],
                                   geometry=self.getAI)
        self.reducetabview = TabView(self.catalogModel, widgetcls=SAXSReductionViewer,
                                     selectionmodel=self.selectionmodel,
                                     stream='primary', field=field,
                                     bindings=[('sigTimeChangeFinished', self.indexChanged),
                                               (self.calibrationsettings.sigGeometryChanged, 'setGeometry')],
                                     geometry=self.getAI)
        self.comparemultiview = QLabel("COMING SOON!")  # SAXSMultiViewerPlugin(self.catalogModel, self.selectionmodel)

        # Setup correlation views
        self.correlationView = TabView(self.catalogModel, widgetcls=SAXSReductionViewer,
                                       selectionmodel=self.selectionmodel,
                                       stream='primary', field=field)
        self.twoTimeProcessor = TwoTimeParameterTree(processor=self.processTwoTime)
        self.twoTimeToolBar = XPCSToolBar(headermodel=self.catalogModel,
                                          selectionmodel=self.selectionmodel,
                                          view=self.correlationView.currentWidget,
                                          workflow=self.roiworkflow,
                                          index=0)
        self.oneTimeProcessor = OneTimeParameterTree(processor=self.processOneTime)
        self.oneTimeToolBar = XPCSToolBar(view=self.correlationView.currentWidget,
                                          workflow=self.roiworkflow,
                                          index=0)

        # Setup toolbars
        self.rawtoolbar = SAXSToolbarRaw(self.catalogModel, self.selectionmodel)
        self.masktoolbar = SAXSToolbarMask(self.catalogModel, self.selectionmodel)
        self.reducetoolbar = SAXSToolbarReduce(self.catalogModel, self.selectionmodel,
                                               view=self.reducetabview.currentWidget, workflow=self.reduceworkflow)
        self.reducetabview.kwargs['toolbar'] = self.reducetoolbar
        self.reducetoolbar.sigDeviceChanged.connect(self.deviceChanged)

        # Setup calibration widgets
        self.calibrationsettings.setModels(self.catalogModel, self.calibrationtabview.selectionmodel)
        self.calibrationpanel = CalibrationPanel(self.catalogModel, self.calibrationtabview.selectionmodel)
        self.calibrationpanel.sigDoCalibrateWorkflow.connect(self.doCalibrateWorkflow)
        self.calibrationsettings.sigGeometryChanged.connect(self.doSimulateWorkflow)

        # Setup masking widgets
        self.maskeditor = WorkflowEditor(self.maskingworkflow)
        self.maskeditor.sigWorkflowChanged.connect(self.doMaskingWorkflow)

        # Setup reduction widgets
        self.displayeditor = WorkflowEditor(self.displayworkflow)
        self.reduceeditor = WorkflowEditor(self.reduceworkflow)
        self.reduceplot = DerivedDataWidget(self.derivedDataModel)
        self.reducetoolbar.sigDoWorkflow.connect(self.doReduceWorkflow)
        self.reduceeditor.sigWorkflowChanged.connect(self.doReduceWorkflow)
        self.displayeditor.sigWorkflowChanged.connect(self.doDisplayWorkflow)
        self.reducetabview.currentChanged.connect(self.catalogChanged)

        # Setup correlation widgets
        self.correlationResults = DerivedDataWidget(self.derivedDataModel)

        self.stages = {
            'Calibrate': GUILayout(self.calibrationtabview,
                                   right=self.calibrationsettings.widget,
                                   rightbottom=self.calibrationpanel,
                                   top=self.rawtoolbar),
            'Mask': GUILayout(self.masktabview,
                              right=self.maskeditor,
                              top=self.masktoolbar),
            'Reduce': GUILayout(self.reducetabview,
                                bottom=self.reduceplot, right=self.reduceeditor, righttop=self.displayeditor,
                                top=self.reducetoolbar),
            'Compare': GUILayout(self.comparemultiview, top=self.reducetoolbar, bottom=self.reduceplot,
                                 right=self.reduceeditor),
            'Correlate': {
                '2-Time Correlation': GUILayout(self.correlationView,
                                                top=self.twoTimeToolBar,
                                                rightbottom=self.twoTimeProcessor,
                                                bottom=self.correlationResults),
                '1-Time Correlation': GUILayout(self.correlationView,
                                                top=self.oneTimeToolBar,
                                                rightbottom=self.oneTimeProcessor,
                                                bottom=self.correlationResults)
            }
        }

        super(SAXSPlugin, self).__init__()

        # Start visualizations
        self.displayworkflow.visualize(self.reduceplot, imageview=lambda: self.reducetabview.currentWidget(),
                                       toolbar=self.reducetoolbar)
Exemple #18
0
    def __init__(self):
        self.catalog = BlueskyInMemoryCatalog()

        # XPCS data model
        self.resultsModel = QStandardItemModel()

        # Input (raw) data model
        self.headerModel = QStandardItemModel()
        self.selectionModel = QItemSelectionModel(self.headerModel)

        # Widgets
        self.calibrationSettings = pluginmanager.getPluginByName(
            'xicam.SAXS.calibration', 'SettingsPlugin').plugin_object

        # Setup TabViews
        self.rawTabView = TabView(
            self.headerModel,
            widgetcls=XPCSViewerPlugin,
            selectionmodel=self.selectionModel,
            bindings=[(self.calibrationSettings.sigGeometryChanged,
                       'setGeometry')],
            geometry=self.getAI)

        # Setup correlation views
        self.twoTimeView = TwoTimeView()
        self.twoTimeFileSelection = FileSelectionView(self.headerModel,
                                                      self.selectionModel)
        self.twoTimeProcessor = TwoTimeProcessor()
        self.twoTimeToolBar = QToolBar()
        self.twoTimeToolBar.addAction(QIcon(static.path('icons/run.png')),
                                      'Process', self.processTwoTime)
        self.twoTimeToolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)

        self.oneTimeView = OneTimeView()
        self.oneTimeFileSelection = FileSelectionView(self.headerModel,
                                                      self.selectionModel)
        self.oneTimeProcessor = OneTimeProcessor()
        self.oneTimeToolBar = QToolBar()
        self.oneTimeToolBar.addAction(QIcon(static.path('icons/run.png')),
                                      'Process', self.processOneTime)
        self.oneTimeToolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)

        # self.placeholder = QLabel('correlation parameters')

        self.stages = {
            'Raw':
            GUILayout(self.rawTabView, right=self.calibrationSettings.widget),
            '2-Time Correlation':
            GUILayout(
                self.twoTimeView,
                top=self.twoTimeToolBar,
                right=self.twoTimeFileSelection,
                rightbottom=self.twoTimeProcessor,
            ),
            # bottom=self.placeholder),
            '1-Time Correlation':
            GUILayout(
                self.oneTimeView,
                top=self.oneTimeToolBar,
                right=self.oneTimeFileSelection,
                rightbottom=self.oneTimeProcessor,
            )
            # bottom=self.placeholder)
        }

        # TODO -- improve result caching
        self._results = []

        super(XPCS, self).__init__()