-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal for VisualizationWidgets
class organization
#239
Comments
More details about the controllers: The controller class above should be a different class on its own (inherting from As a very rough draft this how I envision a companion controller class to a VisualizationWidget to look like: class VisualizationWidgetController(widgets.Box):
def __init__(self, neuro_data_type, controller_kwargs):
super().__init__()
# Definite all the widgets of the controllers
initialize_control_widgets()
# Call the abstract method that makes all the values available all the top level
make_root_levels_available()
def initialize_control_widgets(self):
"""
All the widgets and their interactions should be defined and initialized here
"""
self.dropdown_widget = widgets.Dropdown(value=value, options=options description="description")
self.float_text_widget = widgets.FloatText(0.0, step=0.1, description="start (s)")
# Set interactions as observers between them (in case one widget values modify the options of another)
self.dropdown_widget.observe(self.upddate_float_text_widget, names="value")
self.float_text_widget.observe(self.update_dropdown_widget, names="value")
# This could be a general method of a general Controller abstract class as its logic should be common to all
def make_root_levels_available(self):
"""
The role of this function is make all the values of the widgets available as top level attrbiutes. This should
improve to readability when interacting with this calss as it avoids having to access attributes inside HBox or
VBox which are hidden in a list as children.
"""
pass
def update_dropdown_widget(self):
pass
def upddate_float_text_widget(self):
pass The canvas widget can be either a |
VisualizationWidgets
class organization
Thanks for the formal writeup and figures, this looks great! A couple notes from our discussion yesterday:
to which I'd also like to adjust the terminology of a general
def extract_data(self, neurodata, field: str, selection: Union[slice, Tuple[slice]]):
# Define how to select data from from a field of the neurodata object
# E.g., self.data = .... # the current data block
def process_data(self, **kwargs): # can be whatever Visualization specific arguments are needed/set by controllers
self.data_to_plot = some_processing(self.data, **kwargs) and some |
Another thing important to note here is we're not proposing a massive refactor of all widgets at the current time, just a more structured guideline for the creation of new widgets (which we will implement in the two current major PRs #232 and #230) which can be incorporated into the documentation for future development as well. |
See #241 for implementation of much of this design... Another aspect I found very useful in practice was breaking up each step of your proposed workflow into separate |
Overall I found this design very helpful over several cases of generalizing/extending parent/child visualizations (and controllers, too!). Not only does it make it easier to code this up, it makes it more readable, more scalable, and once I get around to it, more testable. |
This is a draft / work in progress. As we are finishing #232 and I am switching to work in other projects I wanted to write my thoughts of what could be a general schema or abstract class for the visualization widgets in the library. Two preliminary points:
Proposal
My claim is that is useful to think about visualization widgets as coordination classes in charge composition, layout and interaction between controllers, data and plotting. The idea can be sumarized in the following diagram:
In brief, the role of the
VisualizationWidget
is to coordinate the interaction between aControllerClass
, aCanvasClass
and the data extracted and processed from the neurodata types (i.e. a TimeSeries or a DynamicTable). A minor role of theVisualizationWidget
is to define the layout between the controllers and the canvas (usually done with Box mechanism). The most important responsability of theVisualizationWidget
is to define the interactions between the data and the canvass which is done with the jupyter widgets observer mechanism. Furthermore, I think we should aim to isolate the definition of the interactions (i.e. establishing them) from theircomputational and rendering actions. Their definitions are done in theVisualizationWidget
class and their actions are done separately and called with a dedicated method to reduce coupling between these two functionalities. See the following diagram:In more detail, the methods
update_data
(in charge of extracting and processing data according to the controller state) andupdate_canvas
(in charge of building the plot and updating theCanvasWidget
) are attached with the observer mechanism to the controller class (this is the definition of the interaction mentioned above) and they implement their actions with external functions (composition) for the sake of keeping the coupling of the code low. That is, for eachVisualizationWidget
instance there should be a separate stand alone function that is in charge of processing the data to make it plot-ready (i.e. extract the data from the units table and build a firing rate histogram) and a separate stand alone function that is in charge of buidling a plot (i.e. get a series of spikes and produce an histogram). The idea is that these functions should be called inside ofupdate_data
andupdate_plot
respectively (their point of contact) but they can be analized, tested and benchmarked on their own keeping the coupling low and the code organized.A bare-bones pseudocode-like implementation is shown now to drive the point home and hopefully make the idea clearer in case I missed something:
The text was updated successfully, but these errors were encountered: