def test_hit_testing_occurs_same_as_draw_order(self):
     # draw order occurs from 0 -> n
     # setup
     with TestContext.create_memory_context() as test_context:
         document_controller = test_context.create_document_controller()
         document_model = document_controller.document_model
         display_panel = document_controller.selected_display_panel
         data_item = DataItem.DataItem(numpy.zeros((10, 10)))
         document_model.append_data_item(data_item)
         display_item = document_model.get_display_item_for_data_item(
             data_item)
         display_panel.set_display_panel_display_item(display_item)
         header_height = display_panel.header_canvas_item.header_height
         display_panel.root_container.layout_immediate(
             (1000 + header_height, 1000))
         # run test
         rect_region1 = Graphics.RectangleGraphic()
         rect_region1.bounds = (0.2, 0.2), (0.4, 0.4)
         rect_region2 = Graphics.RectangleGraphic()
         rect_region2.bounds = (0.4, 0.4), (0.4, 0.4)
         display_item.add_graphic(rect_region1)
         display_item.add_graphic(rect_region2)
         display_item = document_model.get_display_item_for_data_item(
             data_item)
         display_panel.display_canvas_item.simulate_click((500, 500))
         self.assertEqual(display_item.graphic_selection.indexes, set(
             (1, )))
 def test_specific_parts_take_priority_when_another_selected(self):
     # setup
     with TestContext.create_memory_context() as test_context:
         document_controller = test_context.create_document_controller()
         document_model = document_controller.document_model
         display_panel = document_controller.selected_display_panel
         data_item = DataItem.DataItem(numpy.zeros((10, 10)))
         document_model.append_data_item(data_item)
         display_item = document_model.get_display_item_for_data_item(
             data_item)
         display_panel.set_display_panel_display_item(display_item)
         header_height = display_panel.header_canvas_item.header_height
         display_panel.root_container.layout_immediate(
             (1000 + header_height, 1000))
         # run test
         rect_region1 = Graphics.RectangleGraphic()
         rect_region1.bounds = (0.2, 0.2), (0.4, 0.4)
         rect_region2 = Graphics.RectangleGraphic()
         rect_region2.bounds = (0.4, 0.4), (0.4, 0.4)
         display_item.add_graphic(rect_region1)
         display_item.add_graphic(rect_region2)
         display_item = document_model.get_display_item_for_data_item(
             data_item)
         # clicking on line should select it
         display_panel.display_canvas_item.simulate_click((700, 700))
         self.assertEqual(display_item.graphic_selection.indexes, set(
             (1, )))
         display_panel.display_canvas_item.simulate_click((600, 200))
         self.assertEqual(display_item.graphic_selection.indexes, set(
             (0, )))
Beispiel #3
0
    def test_target_region_stream_stops_updates_when_region_deselected(self):
        target_display_item_stream = HistogramPanel.TargetDisplayItemStream(
            self.document_controller).add_ref()
        target_region_stream = HistogramPanel.TargetRegionStream(
            target_display_item_stream).add_ref()
        try:
            count = 0

            def new_region(graphic: Graphics.Graphic) -> None:
                nonlocal count
                count += 1

            with contextlib.closing(
                    target_region_stream.value_stream.listen(
                        new_region)) as listener:
                rect_region = Graphics.RectangleGraphic()
                rect_region.bounds = (0.2, 0.2), (0.2, 0.2)
                self.display_item.add_graphic(rect_region)
                self.display_item.graphic_selection.set(0)  # count 1
                rect_region.bounds = (0.2, 0.2), (0.2, 0.2)  # count 2
                self.display_item.graphic_selection.clear()  # count 2
                count0 = count
                rect_region.bounds = (0.2, 0.2), (0.2, 0.2)  # count 2
                rect_region.bounds = (0.2, 0.2), (0.2, 0.2)  # count 2
                rect_region.bounds = (0.2, 0.2), (0.2, 0.2)  # count 2
                self.assertEqual(count0, count)

        finally:
            target_region_stream.remove_ref()
            target_display_item_stream.remove_ref()
 def test_histogram_updates_when_crop_region_changes(self):
     data = numpy.zeros((100, 100))
     data[20:40, 20:40] = 1
     data[40:60, 40:60] = 2
     self.display_item.data_item.set_data(data)
     self.histogram_panel._statistics_widget._statistics_func_value_model._run_until_complete(
     )
     stats1_text = self.histogram_panel._statistics_widget._stats1_property.value
     stats2_text = self.histogram_panel._statistics_widget._stats2_property.value
     rect_region = Graphics.RectangleGraphic()
     rect_region.bounds = (0.2, 0.2), (0.2, 0.2)
     self.display_item.add_graphic(rect_region)
     self.display_item.graphic_selection.set(0)
     self.histogram_panel._statistics_widget._statistics_func_value_model._run_until_complete(
     )
     stats1_new_text = self.histogram_panel._statistics_widget._stats1_property.value
     stats2_new_text = self.histogram_panel._statistics_widget._stats2_property.value
     self.assertNotEqual(stats1_text, stats1_new_text)
     self.assertNotEqual(stats2_text, stats2_new_text)
     rect_region.bounds = (0.4, 0.4), (0.2, 0.2)
     self.histogram_panel._statistics_widget._statistics_func_value_model._run_until_complete(
     )
     self.assertNotEqual(
         stats1_new_text,
         self.histogram_panel._statistics_widget._stats1_property.value)
     self.assertNotEqual(
         stats2_new_text,
         self.histogram_panel._statistics_widget._stats2_property.value)
Beispiel #5
0
 async def explore_edges(self, document_controller):
     document_model = document_controller.document_model
     model_data_item = self.__model_data_item
     model_display_item = document_model.get_display_item_for_data_item(
         model_data_item)
     pick_region = Graphics.RectangleGraphic()
     pick_region.size = min(1 / 16,
                            16 / model_data_item.dimensional_shape[0]), min(
                                1 / 16,
                                16 / model_data_item.dimensional_shape[1])
     pick_region.label = _("Explore")
     model_display_item.add_graphic(pick_region)
     pick_data_item = document_model.get_pick_region_new(
         model_display_item,
         model_display_item.data_item,
         pick_region=pick_region)
     if pick_data_item:
         explore_interval = Graphics.IntervalGraphic()
         explore_interval.interval = 0.4, 0.6
         explore_interval.label = _("Explore")
         explore_interval.graphic_id = "explore"
         pick_data_item.source = model_data_item
         pick_display_item = document_model.get_display_item_for_data_item(
             pick_data_item)
         pick_display_item.add_graphic(explore_interval)
         document_controller.show_display_item(pick_display_item)
         await self.__document_model.compute_immediate(
             document_controller.event_loop,
             document_model.get_data_item_computation(pick_data_item)
         )  # need the data to make connect_explorer_interval work; so do this here. ugh.
         self.__connect_explorer_interval(document_model, pick_data_item)
 def test_specific_parts_take_priority_over_all_part(self):
     # setup
     with TestContext.create_memory_context() as test_context:
         document_controller = test_context.create_document_controller()
         document_model = document_controller.document_model
         display_panel = document_controller.selected_display_panel
         data_item = DataItem.DataItem(numpy.zeros((10, 10)))
         document_model.append_data_item(data_item)
         display_item = document_model.get_display_item_for_data_item(
             data_item)
         display_panel.set_display_panel_display_item(display_item)
         header_height = display_panel.header_canvas_item.header_height
         display_panel.root_container.layout_immediate(
             (1000 + header_height, 1000))
         # run test
         rect_region = Graphics.RectangleGraphic()
         rect_region.bounds = (0.25, 0.25), (0.5, 0.5)
         line_region = Graphics.LineGraphic()
         line_region.start = (0.5, 0.5)
         line_region.end = (0.5, 1.0)
         # draws line, then rect
         display_item.add_graphic(line_region)
         display_item.add_graphic(rect_region)
         display_item = document_model.get_display_item_for_data_item(
             data_item)
         # clicking on line should select it
         display_panel.display_canvas_item.simulate_click((500, 600))
         self.assertEqual(display_item.graphic_selection.indexes, set(
             (0, )))
Beispiel #7
0
    def test_changing_graphic_does_not_notify_display_values_change(self):
        with TestContext.create_memory_context() as test_context:
            document_model = test_context.create_document_model()
            # this is used to update the inspector
            data_item = DataItem.DataItem(numpy.zeros((4, 4)))
            document_model.append_data_item(data_item)
            display_item = document_model.get_display_item_for_data_item(
                data_item)
            graphic = Graphics.RectangleGraphic()
            display_item.add_graphic(graphic)
            display_data_channel = display_item.display_data_channels[0]

            class Observer:
                def __init__(self) -> None:
                    self.count = 0

                def next_calculated_display_values(self):
                    self.count += 1

            o = Observer()
            with contextlib.closing(
                    display_data_channel.
                    add_calculated_display_values_listener(
                        o.next_calculated_display_values)):
                display_data_channel.get_calculated_display_values()
                self.assertEqual(
                    1, o.count)  # 1 will be sent when adding the listener
                with display_item.display_item_changes():
                    graphic.bounds = ((0, 0), (1, 1))
                self.assertEqual(
                    1, o.count)  # 1 will be sent when adding the listener
 def test_changing_region_properties_change_drawn_graphic_properties(self):
     with TestContext.create_memory_context() as test_context:
         document_model = test_context.create_document_model()
         data_item = DataItem.DataItem(numpy.zeros((8, 8), numpy.uint32))
         document_model.append_data_item(data_item)
         display_item = document_model.get_display_item_for_data_item(data_item)
         regions = list()
         regions.append(Graphics.PointGraphic())
         regions.append(Graphics.RectangleGraphic())
         regions.append(Graphics.EllipseGraphic())
         regions.append(Graphics.LineGraphic())
         regions.append(Graphics.IntervalGraphic())
         regions.append(Graphics.ChannelGraphic())
         for region in regions:
             region.label = "label"
             region.is_position_locked = False
             region.is_shape_locked = False
             region.is_bounds_constrained = False
             display_item.add_graphic(region)
             drawn_graphic = display_item.graphics[-1]
             self.assertEqual(region.label, drawn_graphic.label)
             self.assertEqual(region.is_position_locked, drawn_graphic.is_position_locked)
             self.assertEqual(region.is_shape_locked, drawn_graphic.is_shape_locked)
             self.assertEqual(region.is_bounds_constrained, drawn_graphic.is_bounds_constrained)
             region.label = "label2"
             region.is_position_locked = True
             region.is_shape_locked = True
             region.is_bounds_constrained = True
             self.assertEqual(region.label, drawn_graphic.label)
             self.assertEqual(region.is_position_locked, drawn_graphic.is_position_locked)
             self.assertEqual(region.is_shape_locked, drawn_graphic.is_shape_locked)
             self.assertEqual(region.is_bounds_constrained, drawn_graphic.is_bounds_constrained)
Beispiel #9
0
 def test_selected_item_takes_priority_over_all_part(self):
     # setup
     document_model = DocumentModel.DocumentModel()
     document_controller = DocumentController.DocumentController(
         self.app.ui, document_model, workspace_id="library")
     with contextlib.closing(document_controller):
         display_panel = document_controller.selected_display_panel
         data_item = DataItem.DataItem(numpy.zeros((10, 10)))
         document_model.append_data_item(data_item)
         display_item = document_model.get_display_item_for_data_item(
             data_item)
         display_panel.set_display_panel_display_item(display_item)
         header_height = display_panel.header_canvas_item.header_height
         display_panel.root_container.layout_immediate(
             (1000 + header_height, 1000))
         # run test
         rect_region = Graphics.RectangleGraphic()
         rect_region.bounds = (0.25, 0.25), (0.5, 0.5)
         line_region = Graphics.LineGraphic()
         line_region.start = (0.0, 1.0)
         line_region.end = (0.75, 0.25)
         # draws line, then rect
         display_item.add_graphic(line_region)
         display_item.add_graphic(rect_region)
         display_item = document_model.get_display_item_for_data_item(
             data_item)
         display_panel.display_canvas_item.simulate_click((50, 950))
         self.assertEqual(display_item.graphic_selection.indexes, set(
             (0, )))
         display_panel.display_canvas_item.simulate_click((500, 500))
         self.assertEqual(display_item.graphic_selection.indexes, set(
             (0, )))
Beispiel #10
0
        def add_line_profile(data_item,
                             document_controller,
                             display_panel_id,
                             midpoint=0.5,
                             integration_width=.25):
            logging.debug("midpoint: {:.4f}".format(midpoint))
            logging.debug("width: {:.4f}".format(integration_width))

            # next, line profile through center of crop
            # please don't copy this bad example code!
            crop_region = Graphics.RectangleGraphic()
            crop_region.center = (midpoint, 0.5)
            crop_region.size = (integration_width, 1)
            crop_region.is_bounds_constrained = True
            display_specifier = DataItem.DisplaySpecifier.from_data_item(
                data_item)
            display_specifier.display.add_graphic(crop_region)
            eels_data_item = document_controller.document_model.get_projection_new(
                data_item, crop_region)
            if eels_data_item:
                eels_data_item.title = _("EELS Summed")
                document_controller.display_data_item(
                    DataItem.DisplaySpecifier.from_data_item(eels_data_item))

            document_controller.workspace_controller.display_data_item_in_display_panel(
                eels_data_item, display_panel_id)
Beispiel #11
0
 def _create_graphic(self) -> Graphics.RectangleGraphic:
     subscan_graphic = Graphics.RectangleGraphic()
     subscan_graphic.graphic_id = "subscan"
     subscan_graphic.label = _("Subscan")
     subscan_graphic.bounds = tuple(typing.cast(Geometry.FloatRect, self.__stem_controller.subscan_region))
     subscan_graphic.rotation = self.__stem_controller.subscan_rotation
     subscan_graphic.is_bounds_constrained = True
     return subscan_graphic
Beispiel #12
0
 def test_histogram_statistics_with_zero_array(self):
     self.display_item.data_item.set_data(
         numpy.ones((10, 10), dtype=numpy.uint32))
     rect_region = Graphics.RectangleGraphic()
     rect_region.bounds = (10000, 10000), (1, 1)
     self.display_item.add_graphic(rect_region)
     self.display_item.graphic_selection.set(0)
     self.histogram_panel._histogram_widget._recompute()
Beispiel #13
0
    async def __update_subscan_region(self):
        subscan_region = self.__update_subscan_region_value
        with self.__last_data_items_lock:
            scan_data_items = self.__scan_data_items
        if subscan_region:
            # create subscan graphics for each scan data item if it doesn't exist
            if not self.__subscan_graphic_trackers:
                for scan_data_item in scan_data_items:
                    display_item = self.__document_model.get_display_item_for_data_item(
                        scan_data_item)
                    if display_item:
                        subscan_graphic = Graphics.RectangleGraphic()
                        subscan_graphic.graphic_id = "subscan"
                        subscan_graphic.label = _("Subscan")
                        subscan_graphic.bounds = subscan_region
                        subscan_graphic.is_bounds_constrained = True

                        def subscan_graphic_property_changed(
                                subscan_graphic, name):
                            if name == "bounds":
                                self.__subscan_region_value.value = subscan_graphic.bounds

                        subscan_graphic_property_changed_listener = subscan_graphic.property_changed_event.listen(
                            functools.partial(subscan_graphic_property_changed,
                                              subscan_graphic))

                        def graphic_removed(subscan_graphic):
                            self.__remove_one_subscan_graphic(subscan_graphic)
                            self.__subscan_state_model.value = SubscanState.DISABLED
                            self.__subscan_region_value.value = None

                        def display_removed(subscan_graphic):
                            self.__remove_one_subscan_graphic(subscan_graphic)

                        remove_region_graphic_event_listener = subscan_graphic.about_to_be_removed_event.listen(
                            functools.partial(graphic_removed,
                                              subscan_graphic))
                        display_about_to_be_removed_listener = display_item.about_to_be_removed_event.listen(
                            functools.partial(display_removed,
                                              subscan_graphic))
                        self.__subscan_graphic_trackers.append(
                            (subscan_graphic,
                             subscan_graphic_property_changed_listener,
                             remove_region_graphic_event_listener,
                             display_about_to_be_removed_listener))
                        display_item.add_graphic(subscan_graphic)
            # apply new value to any existing subscan graphics
            for subscan_graphic, l1, l2, l3 in self.__subscan_graphic_trackers:
                subscan_graphic.bounds = subscan_region
        else:
            # remove any graphics
            for subscan_graphic, subscan_graphic_property_changed_listener, remove_region_graphic_event_listener, display_about_to_be_removed_listener in self.__subscan_graphic_trackers:
                subscan_graphic_property_changed_listener.close()
                remove_region_graphic_event_listener.close()
                display_about_to_be_removed_listener.close()
                subscan_graphic.container.remove_graphic(subscan_graphic)
            self.__subscan_graphic_trackers = list()
Beispiel #14
0
 def test_region_mask_rect(self):
     rect_graphic = Graphics.RectangleGraphic()
     rect_graphic.bounds = (0.2, 0.2), (0.1, 0.1)
     mask = rect_graphic.get_mask((1000, 1000))
     self.assertEqual(mask.data[200, 200], 1)  # top left
     self.assertEqual(mask.data[200, 300], 1)  # bottom left
     self.assertEqual(mask.data[300, 300], 1)  # bottom right
     self.assertEqual(mask.data[300, 200], 1)  # bottom left
     self.assertEqual(mask.data[250, 200], 1)  # center top
     self.assertEqual(mask.data[300, 250], 1)  # center right
     self.assertEqual(mask.data[250, 300], 1)  # center bottom
     self.assertEqual(mask.data[200, 250], 1)  # center left
Beispiel #15
0
 def test_region_mask_with_different_types_of_graphics(self):
     line_graphic = Graphics.LineGraphic()
     line_graphic.start = (0.25, 0.25)
     line_graphic.end = (0.75, 0.75)
     spot_graphic = Graphics.SpotGraphic()
     spot_graphic.bounds = (0.2, 0.2), (0.1, 0.1)
     ellipse_graphic = Graphics.EllipseGraphic()
     ellipse_graphic.bounds = (0.2, 0.2), (0.1, 0.1)
     rect_graphic = Graphics.RectangleGraphic()
     rect_graphic.bounds = (0.25, 0.25), (0.5, 0.5)
     point_graphic = Graphics.PointGraphic()
     point_graphic.position = (0.25, 0.25)
     wedge_graphic = Graphics.WedgeGraphic()
     line_graphic.get_mask((256, 256))
     spot_graphic.get_mask((256, 256))
     ellipse_graphic.get_mask((256, 256))
     rect_graphic.get_mask((256, 256))
     point_graphic.get_mask((256, 256))
 def __update_drift_region(self) -> None:
     assert threading.current_thread() == threading.main_thread()
     if self.__stem_controller.drift_channel_id:
         drift_data_item = self.__stem_controller.scan_context_channel_map.get(
             self.__stem_controller.drift_channel_id)
     else:
         drift_data_item = None
     # determine if a new graphic should exist and if it exists already
     if self.__stem_controller.drift_channel_id and self.__stem_controller.drift_region and drift_data_item:
         drift_display_item = self.__document_model.get_display_item_for_data_item(
             drift_data_item)
         # remove the graphic if it already exists on the wrong display item
         if self.__graphic and (not drift_display_item or not self.__graphic
                                in drift_display_item.graphics):
             self.__remove_graphic()
         # it already exists on the correct display item, update it.
         if self.__graphic:
             self.__graphic.bounds = tuple(
                 self.__stem_controller.drift_region)
             self.__graphic.rotation = self.__stem_controller.drift_rotation
         # otherwise create it if there is a display item for it
         elif drift_display_item:
             drift_graphic = Graphics.RectangleGraphic()
             drift_graphic.graphic_id = "drift"
             drift_graphic.label = _("Drift")
             drift_graphic.bounds = tuple(
                 self.__stem_controller.drift_region)
             drift_graphic.rotation = self.__stem_controller.drift_rotation
             drift_graphic.is_bounds_constrained = True
             drift_graphic.color = "#F0F"  # purple
             drift_display_item.add_graphic(drift_graphic)
             self.__graphic_display_item = drift_display_item
             self.__graphic = drift_graphic
             self.__graphic_property_changed_listener = self.__graphic.property_changed_event.listen(
                 self.__graphic_property_changed)
             self.__graphic_about_to_be_removed_listener = self.__graphic.about_to_be_removed_event.listen(
                 self.__graphic_about_to_be_removed)
         # otherwise do nothing, graphic is removed and not tracked.
     else:
         # either no drift channel_id or drift region - so remove the graphic
         if self.__graphic:
             self.__remove_graphic()
Beispiel #17
0
        def add_line_profile(
                data_item: DataItem.DataItem,
                document_controller: DocumentController.DocumentController,
                display_panel_id: str,
                midpoint: float = 0.5,
                integration_width: float = 0.25) -> None:
            logging.debug("midpoint: {:.4f}".format(midpoint))
            logging.debug("width: {:.4f}".format(integration_width))

            # next, line profile through center of crop
            # please don't copy this bad example code!
            crop_region = Graphics.RectangleGraphic()
            crop_region.center = Geometry.FloatPoint(midpoint, 0.5)
            crop_region.size = Geometry.FloatSize(integration_width, 1)
            crop_region.is_bounds_constrained = True
            display_item = document_controller.document_model.get_display_item_for_data_item(
                data_item)
            assert display_item
            display_item.add_graphic(crop_region)
            display_data_item = display_item.data_item
            assert display_data_item
            eels_data_item = document_controller.document_model.get_projection_new(
                display_item, display_data_item, crop_region)
            if eels_data_item:
                eels_data_item.title = _("EELS Summed")
                eels_display_item = document_controller.document_model.get_display_item_for_data_item(
                    eels_data_item)
                assert eels_display_item
                document_controller.show_display_item(eels_display_item)
            else:
                eels_display_item = None

            workspace_controller = document_controller.workspace_controller
            if workspace_controller and eels_display_item:
                workspace_controller.display_display_item_in_display_panel(
                    eels_display_item, display_panel_id)
async def pick_new_edge(document_controller, model_data_item, edge) -> None:
    """Set up a new edge pick from the model data item and the given edge.

    The library will have the following new components and connections:
        - a pick region on the model data item
        - a pick data item with a fit/signal connected to the edge data structure
        - a background subtraction computation with model data item, and edge intervals as inputs
        - a background data item, computed by the background subtraction computation
        - a subtracted data item, computed by the background subtraction computation
        - a eels line plot with pick, background, and subtracted data items as components
        - an edge reference, owned by eels line plot, with reference to edge
        - the edge reference is used to recognize the eels line plot as associated with the referenced edge
    """
    document_model = document_controller.document_model
    model_display_item = document_model.get_display_item_for_data_item(model_data_item)
    pick_region = Graphics.RectangleGraphic()
    pick_region.size = min(1 / 16, 16 / model_data_item.dimensional_shape[0]), min(1 / 16, 16 / model_data_item.dimensional_shape[1])
    pick_region.label = "{} {}".format(_("Pick"), str(edge.electron_shell))
    model_display_item.add_graphic(pick_region)

    # set up the computation for this edge.
    eels_data_item = DataItem.DataItem()
    document_model.append_data_item(eels_data_item)
    eels_data_item.title = "{} EELS Data of {}".format(pick_region.label, model_data_item.title)
    eels_data_item.source = pick_region
    eels_display_item = document_model.get_display_item_for_data_item(eels_data_item)
    eels_display_item.display_type = "line_plot"
    eels_display_item.display_layers = [
        {"label": "Signal", "data_index": 0, "data_row": 2, "fill_color": "#0F0"},
        {"label": "Background", "data_index": 0, "data_row": 1, "fill_color": "rgba(255, 0, 0, 0.3)"},
        {"label": "Data", "data_index": 0, "data_row": 0, "fill_color": "#1E90FF"},
    ]
    eels_display_item.set_display_property("legend_position", "top-right")
    fit_region = Graphics.IntervalGraphic()
    fit_region.label = _("Fit")
    fit_region.graphic_id = "fit"
    fit_region.interval = edge.fit_interval
    eels_display_item.add_graphic(fit_region)
    signal_region = Graphics.IntervalGraphic()
    signal_region.label = _("Signal")
    signal_region.graphic_id = "signal"
    signal_region.interval = edge.signal_interval
    eels_display_item.add_graphic(signal_region)
    document_model.append_connection(Connection.PropertyConnection(edge.data_structure, "fit_interval", fit_region, "interval", parent=eels_data_item))
    document_model.append_connection(Connection.PropertyConnection(edge.data_structure, "signal_interval", signal_region, "interval", parent=eels_data_item))

    computation = document_model.create_computation()
    computation.create_object("eels_xdata", document_model.get_object_specifier(model_data_item, "xdata"))
    computation.create_object("region", document_model.get_object_specifier(pick_region))
    computation.create_input("fit_interval", document_model.get_object_specifier(edge.data_structure), "fit_interval")
    computation.create_input("signal_interval", document_model.get_object_specifier(edge.data_structure), "signal_interval")
    computation.processing_id = "eels.background_subtraction11"
    computation.create_result("data", document_model.get_object_specifier(eels_data_item))
    document_model.append_computation(computation)

    # the eels item will need the initial computation results to display properly (view to intervals)
    await document_model.compute_immediate(document_controller.event_loop, computation)

    # ensure computation is deleted when eels is deleted
    computation.source = eels_data_item

    # create an elemental_mapping_edge_ref data structure, owned by the eels data item, with a referenced
    # object pointing to the edge. used for recognizing the eels data item as such.
    data_structure = document_model.create_data_structure(structure_type="elemental_mapping_edge_ref", source=eels_data_item)
    data_structure.set_referenced_object("spectrum_image", model_data_item)
    data_structure.set_referenced_object("edge", edge.data_structure)
    data_structure.set_referenced_object("data", eels_data_item)
    data_structure.set_referenced_object("pick_region", pick_region)
    document_model.append_data_structure(data_structure)

    # display it
    eels_display_item.view_to_intervals(eels_data_item.xdata, [edge.data_structure.fit_interval, edge.data_structure.signal_interval])
    document_controller.show_display_item(eels_display_item)