예제 #1
0
 def test_execute_synchronous_no_links_not_enough_kwargs(
         self, sum_op, square_op, negative_op):
     # TODO -- expect exception
     workflow = Workflow()
     workflow.add_operations(sum_op, square_op, negative_op)
     results = workflow.execute_synchronous(n1=2, n2=5)
     assert results == ({"negative": -49}, )
예제 #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__()
예제 #3
0
    def __init__(self):

        # Set up an invert operation
        @OperationPlugin
        @output_names('inverted_data')
        def invert(data: np.ndarray = None) -> np.ndarray:
            if issubclass(data.dtype.type, np.integer):
                max = np.iinfo(data.dtype).max
            else:
                max = np.finfo(data.dtype).max
            return max - data

        # Set up our workflow
        workflow = Workflow()
        workflow.add_operation(invert)
        workflow_editor = WorkflowEditor(workflow)

        # Set up a GUI layout
        center_widget = QLabel("test")
        sample_stage_layout = GUILayout(center_widget)

        # Set up stages
        stages = {
            "Sample Stage": GUILayout(center_widget, right=workflow_editor)
        }
        self.stages = stages
        super(SamplePlugin, self).__init__()
예제 #4
0
 def test_execute_no_links_diff_input_names(self, sum_op, square_op, negative_op):
     # do the input names have to match in this case (more than one entry op)
     operations = [sum_op, square_op, negative_op]
     workflow = Workflow(name="test", operations=operations)
     results = workflow.execute(n1=3, n2=-3, n=10, num=33).result()
     assert len(results) == 3
     assert {"sum": 0} in results
     assert {"square": 100} in results
     assert {"negative": -33} in results
예제 #5
0
def custom_parameter_workflow(custom_parameter_op):
    from xicam.core.execution.workflow import Workflow

    wf = Workflow()

    custom_parameter_op = custom_parameter_op()

    wf.add_operation(custom_parameter_op)
    return wf
    def test_execute_operation_no_default_no_value(self, sum_op):
        # not sure how to test this....
        def handle_exception(exception):
            with pytest.raises(TypeError):
                raise exception

        workflow = Workflow()
        workflow.add_operation(sum_op)
        results = workflow.execute(except_slot=handle_exception).result()
        print(results)
예제 #7
0
    def test_execute_operation_default_input_value(self):
        @operation
        @output_names("doubled")
        def double_op(x=10):
            return x * 2

        workflow = Workflow()
        workflow.add_operation(double_op)
        results = workflow.execute().result()
        assert results == ({"doubled": 20}, )
    def test_no_output_names(self):
        @operation
        def my_func(a1, a2):
            return a1, a2

        op = my_func()
        w = Workflow()
        w.add_operations(op)
        result = w.execute_synchronous(a1=1, a2=2)
        assert result == ({"my_func": 1}, )
 def test_end_node(self, double_and_triple_op, sum_op, square_op):
     workflow = Workflow()
     workflow.add_operations(double_and_triple_op, sum_op, square_op)
     workflow.add_link(sum_op, square_op, "sum", "n")
     workflow.add_link(square_op, double_and_triple_op, "square", "n")
     result = workflow.execute_synchronous(n1=1, n2=2)
     assert result == ({"double": 18, "triple": 27}, )
 def test_execute_synchronous(self, sum_op, square_op, negative_op):
     workflow = Workflow()
     workflow.add_operations(sum_op, square_op, negative_op)
     workflow.add_link(sum_op, square_op, "sum", "n")
     workflow.add_link(square_op, negative_op, "square", "num")
     results = workflow.execute_synchronous(n1=2, n2=5)
     assert results == ({"negative": -49}, )
    def test_one_output_name(self):
        @operation
        @output_names("return_val")
        def my_func(a1, a2):
            return a1, a2

        op = my_func()
        workflow = Workflow()
        workflow.add_operations(op)
        result = workflow.execute_synchronous(a1=1, a2=2)
        assert result == ({"return_val": 1}, )
예제 #12
0
 def test_execute_synchronous_no_links(self, sum_op, square_op, negative_op):
     workflow = Workflow()
     workflow.add_operations(sum_op, square_op, negative_op)
     # n1, n2 -- inputs to sum_op;
     # n -- input to square_op
     # num -- input to negative_op
     results = workflow.execute_synchronous(n1=2, n2=5, n=10, num=50)
     assert len(results) == 3
     assert {"sum": 7} in results
     assert {"square": 100} in results
     assert {"negative": -50} in results
 def test_start_node(self, double_and_triple_op, sum_op, square_op):
     workflow = Workflow()
     workflow.add_operations(double_and_triple_op, sum_op, square_op)
     workflow.add_link(double_and_triple_op, sum_op, "double", "n1")
     workflow.add_link(double_and_triple_op, sum_op, "triple", "n2")
     workflow.add_link(sum_op, square_op, "sum", "n")
     result = workflow.execute_synchronous(n=1)
     assert result == ({"square": 25}, )
예제 #14
0
    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')
예제 #15
0
    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 test_all_output_names(self):
        @operation
        @output_names('x', 'y')
        def my_func(a1, a2):
            return a1, a2

        op = my_func()
        workflow = Workflow()
        workflow.add_operations(op)
        result = workflow.execute_synchronous(a1=1, a2=2)
        print(result)
        assert result == ({'x': 1, 'y': 2}, )
예제 #17
0
    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 test_mutliple_end_nodes(double_and_triple_op, sum_op, square_op):
    workflow = Workflow()
    workflow.add_operations(double_and_triple_op, sum_op, square_op)
    workflow.add_link(sum_op, double_and_triple_op, "sum", "n")
    workflow.add_link(sum_op, square_op, "sum", "n")
    result = workflow.execute_synchronous(n1=2, n2=3)
    assert len(result) == 2
    assert {"double": 10, "triple": 15} in result
    assert {"square": 25} in result
예제 #19
0
    def __init__(self, workflow: Workflow):
        super(WorkflowEditor, self).__init__()
        self.setOrientation(Qt.Vertical)

        self.processeditor = WorkflowProcessEditor()
        self.workflowview = LinearWorkflowView(WorkflowModel(workflow))

        self.addWidget(self.processeditor)
        self.addWidget(WorkflowWidget(self.workflowview))

        self.workflowview.sigShowParameter.connect(lambda parameter: self.setParameters(parameter))

        workflow.attach(self.sigWorkflowChanged.emit)
    def __init__(self,
                 workflow: Workflow,
                 operation_filter: Callable[[OperationPlugin], bool] = None,
                 kwargs_callable: Callable[[], dict] = None,
                 execute_iterative: bool = False,
                 **kwargs):
        """
        A Workflow editor that shows each operation in insertion order. This is useful in simplistic workflows, typically
        when data passes from through a linear sequence. This order may not represent execution order when
        a workflow is programmatically composed, or when graph-based editing is supported in the future.

        Parameters
        ----------
        workflow : Workflow
            A workflow instance; may be initially empty.
        operation_filter: Callable[[OperationPlugin], bool]
            A callable that can be used to filter which operations to show in the "Add Operation" menu
        kwargs_callable: Callable[[], dict]
            A callable that gets called when auto-run is triggered. This callable is expected to generate a dict of
            kwargs that will be passed into the workflow as inputs.
        execute_iterative: bool
            Determines if the attached workflow will be executed with `.execute` or `.execute_all`. When `.execute_all`
            is used, all input args get zipped, and the workflow is executed over each arg tuple.

        """
        super(WorkflowEditor, self).__init__()
        self.workflow = workflow
        self.kwargs = kwargs
        self.kwargs_callable = kwargs_callable
        self.execute_iterative = execute_iterative
        self.setOrientation(Qt.Vertical)

        self.operationeditor = WorkflowOperationEditor()
        self.workflowview = LinearWorkflowView(WorkflowModel(workflow))

        self.addWidget(self.operationeditor)
        workflow_widget = WorkflowWidget(self.workflowview,
                                         operation_filter=operation_filter)
        self.addWidget(workflow_widget)
        workflow_widget.sigRunWorkflow.connect(self.sigRunWorkflow.emit)
        workflow_widget.sigRunWorkflow.connect(self.run_workflow)
        # Should this work internally? How would the start operations get their inputs?
        # Would the ExamplePlugin need to explicitly set the parameter value (even for hidden image)?
        # It would be nice to just have this work easily... (to ExamplePlugin's perspective)
        # workflow_widget.sigRunWorkflow.connect(self.run_workflow)
        # TODO make work for autorun...
        # OR is this the outside class's respsonsibility (see SAXSGUIPlugin.maskeditor)

        self.workflowview.sigShowParameter.connect(self.setParameters)

        workflow.attach(self.sigWorkflowChanged.emit)
예제 #21
0
    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')
예제 #22
0
    def __init__(self, workflow: Workflow):
        super(WorkflowEditor, self).__init__()
        self.workflow = workflow
        self.setOrientation(Qt.Vertical)

        self.operationeditor = WorkflowOperationEditor()
        self.workflowview = LinearWorkflowView(WorkflowModel(workflow))

        self.addWidget(self.operationeditor)
        self.addWidget(WorkflowWidget(self.workflowview))

        self.workflowview.sigShowParameter.connect(self.setParameters)

        workflow.attach(self.sigWorkflowChanged.emit)
예제 #23
0
 def test_execute_all(self, qtbot, sum_op, square_op, negative_op):
     results = [{"negative": (1 + 2) ** 2 * -1},
                {"negative": (3 + 4) ** 2 * -1},
                {"negative": (5 + 6) ** 2 * -1}]
     def cb(*result):
         next_result = results.pop(0)
         assert result == next_result
     workflow = Workflow()
     workflow.add_operations(sum_op, square_op, negative_op)
     workflow.add_link(sum_op, square_op, "sum", "n")
     workflow.add_link(square_op, negative_op, "square", "num")
     n1_values = [1, 3, 5]
     n2_values = [2, 4, 6]
     # TODO -- we are only getting one result, should get three (3 pairs of n1/n2).
     workflow.execute_all(callback_slot=cb, n1=n1_values, n2=n2_values).result()
예제 #24
0
    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')
예제 #25
0
 def test_two_ops_to_one_op(self, negative_op, square_op, sum_op):
     workflow = Workflow()
     workflow.add_operations(negative_op, square_op, sum_op)
     workflow.add_link(negative_op, sum_op, "negative", "n1")
     workflow.add_link(square_op, sum_op, "square", "n2")
     print(workflow.get_inbound_links(sum_op))
     #from dask import visualize
     #visualize(workflow.as_dask_graph()[0], filename="/home/ihumphrey/graph")
     graph = workflow.as_dask_graph()[0]
     print(graph)
     for k, op in graph.items():
         print(k, op[0].node.name)
     from dask.threaded import get
     negative_op.filled_values.update(num=3)
     square_op.filled_values.update(n=4)
     print(get(graph, '0'))  # WHY is this an issue? Complains that sum missing required 'n2'
예제 #26
0
    def test_execute_no_links(self):
        @operation
        @output_names("doubled")
        def double_op(n):
            return n * 2

        @operation
        @output_names("tripled")
        def triple_op(n):
            return n * 3

        workflow = Workflow()
        workflow.add_operations(double_op, triple_op)
        results = workflow.execute(n=10).result()
        assert len(results) == 2
        assert {"doubled": 20} in results
        assert {"tripled": 30} in results
예제 #27
0
def test_workflow():
    from xicam.core.execution.workflow import Workflow
    from xicam.core.execution.daskexecutor import DaskExecutor
    from xicam.plugins.operationplugin import output_names

    executor = DaskExecutor()

    @operation
    @output_names("square")
    def square(a=3) -> int:
        return a**2

    @operation
    @output_names("sum")
    def my_sum(a, b=3) -> int:
        return a + b

    wf = Workflow()

    square = square()
    my_sum = my_sum()

    wf.add_operation(square)
    wf.add_operation(my_sum)
    wf.add_link(square, my_sum, "square", "a")

    assert wf.execute_synchronous(executor=executor) == [{"sum": 12}]
예제 #28
0
    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')
예제 #29
0
 def test_default(self, op, old):
     w = Workflow(operations=[op])
     result = w.execute_synchronous(executor=executor)
     corrected_images = result[0]['corrected_images']
     gains = get_default(op, 'gains')
     assert np.array_equal(corrected_images,
                           op.filled_values['images'] * gains[0])
     if TEST_CSX_TOOLS:
         w.clear_operations()
         w.add_operation(old)
         result = w.execute_synchronous(executor=executor)
         assert np.array_equal(result[0]['corrected_images'],
                               corrected_images)
예제 #30
0
 def test_execute_all(self, sum_op, square_op, negative_op):
     workflow = Workflow()
     workflow.add_operations(sum_op, square_op, negative_op)
     workflow.add_link(sum_op, square_op, "sum", "n")
     workflow.add_link(square_op, negative_op, "square", "num")
     n1_values = [1, 3, 5]
     n2_values = [2, 4, 6]
     # TODO -- we are only getting one result, should get three (3 pairs of n1/n2).
     results = list(
         workflow.execute_all(n1=n1_values, n2=n2_values).result())
     assert results == [{
         "negative": (1 + 2)**2 * -1
     }, {
         "negative": (3 + 4)**2 * -1
     }, {
         "negative": (5 + 6)**2 * -1
     }]