bluesky / bluesky-widgets

Components for graphical applications that interact with bluesky libraries
http://blueskyproject.io/bluesky-widgets
BSD 3-Clause "New" or "Revised" License
7 stars 22 forks source link

Consider adding a layer to remove coupling with views and BlueskyRun API #65

Open danielballan opened 3 years ago

danielballan commented 3 years ago

The view code knows about of the concept of a BlueskyRun and its particular interface and signals:

https://github.com/bluesky/bluesky-widgets/blob/434046b54ee160cdcdd7a6c8c1fc1bf7e82d575b/bluesky_widgets/_matplotlib_axes.py#L104-L105

https://github.com/bluesky/bluesky-widgets/blob/434046b54ee160cdcdd7a6c8c1fc1bf7e82d575b/bluesky_widgets/_matplotlib_axes.py#L121-L125

What if, instead, we separate the bluesky-aware aspect into a separate components, perhaps by subclassing like so:

class LineSpec:
    "Not bluesky-aware, just knows about an abstract `transform` (callable) and `data`"
    def __init__(self, update: callable, label, style=None):
        "Expected signature of update is: update() -> x: Array, y: Array"
        ...
        self.events = EmitterGroup(new_data=Event, completed=Event)

class BlueskyLineSpec(LineSpec):
    "Hooks up LineSpec's signals to BlueskyRun signals."
    def __init__(self, transform: callable, run: BlueskyRun, label, style=None):

        run.events.new_data.connect(self.events.new_data)
        run.events.completed.connect(self.events.completed)

        def update():
            return transform(data)

        super().__init__(update, label, style)

then LineSpec and the views become generic. That would extend the utility of these components at the cost of an additional layer of signaling.

danielballan commented 3 years ago

Another important consequence of this is that the bottom layer LineSpec is not bound to a single BlueskyRun, and you could generate LineSpecs joining data from multiple Runs. And of course from things that have nothing to do with BlueskyRun at all.

danielballan commented 3 years ago

Also, if transform always returns a dict of kwargs rather than an artist-specific construct (like (x, y) for lines) we can simplify the view code and reduce the artist-specific code.

h/t @tacaswell

danielballan commented 3 years ago

97 does this almost entirely. It moves the 1:1 correspondence to BlueskyRun into a classmethod. That could easily be moved off to a subclass in the future.

danielballan commented 3 years ago

@tacaswell shared this snippet of work related to matplotlib 4.0 https://gist.github.com/tacaswell/95177903175dbc28be5353b4a0e5118f. Keeping this here so I don't lose it.