Some improvements for cli usage
There are various different topics discussed below. I tried to summarise them here at the top level
-
access pattern to sublayers, and their consistency in terms of return values -
reconstructing a gui from a config file, i.e. functionality to dump a config to disk. #203 -
nested objects, i.e. gui/dock/widget(/sub_widget for BECFigure
) -
consistency of methods, i.e. plot and add_plot for BECFigure
Access pattern to sublayers
While exploring a bit the functionality of the widgets, I encountered that the access pattern on the top level is slightly different then for all the rest. I.E. gui.panels returns a dictionary opposed to docks, figure and the underlying widgets:
• demo [1/35] ❯❯ gui.panels
Out[1]: {'dock_1': <BECDock object at 0x118c5c910>}
• demo [2/35] ❯❯ dock = gui.panels["dock_1"]
• demo [3/35] ❯❯ dock.widget_list
Out[3]: [<BECFigure object at 0x12b537790>]
• demo [4/35] ❯❯ fig = dock.widget_list[0]
• demo [5/35] ❯❯ plot = fig.add_plot('samx','bpm4i')
• demo [6/35] ❯❯ fig.widget_list
Out[6]: [<BECWaveform object at 0x119258ed0>]
• demo [7/35] ❯❯ plot.curves
Out[7]: [<BECCurve object at 0x14e764a50>]
If there is no good reason for gui.panels to return a dictionary, I would vote for consistent access patterns with either dictionary on all levels or list for all.
It also seems like BECFigure
has the property widgets
, which returns a dictionary and widget_list
returning a list of all widgets. Overall, I think we could go through the methods and reduce the exposed rpc functions + make them consistent in between different layers.
Reconstructing a gui with widgets
Adding a functionality to save a custom build gui, and reload it after restarting the client would be desirable including configurations for the widgets. The functionality could be given by a simple function:
gui.save_gui_session(fname='./gui_config_timestamp.yaml')
exit
bec
gui.load_gui_session_from_disk(fname='./gui_config_timestamp.yaml')
If not specified, a default path could be used with a timestamp. Similar to how the config is saved upon reloading a new config. One could consider even dumping the config to disk/redis upon closing BEC to facilitate easy recovering of configured states.
Objects, nested access
I build a relatively small GUI quickly, and wondered whether the access pattern could be simplified. We could consider if we make gui an object in the client that allows better access to docks and widgets. I am not fully convinced if this makes it easier, but I feel it could help.
If I currently have a GUI with 3 docks, as in the screenshot, I have to follow the following patterns to change the scale of the 2D image plot.
Current access
dock_3 = gui.panels["dock_3"]
fig = dock_3.widget_list[0]
img = fig.widget_list[0]
img.set_vrange(vmin=0, vmax=100)
Assuming that I forgot to which variables I assigned them upon creating the gui. I know that we can stack those commands, but assuming that I do not know them by hard then I would have to follow the pattern above.
What if gui
could become and object in the CLI that can be extended dynamically, i.e. it could have dynamic objects created once for instance a dock is added.
Proposed access
In the screenshot above I could for instance have:
gui.dock_1.
gui.dock_2.
gui.dock_3.
Each automatically created automatically upon adding a dock/widget or any item to the gui, and create the object based on the name of the class. Having multiple instances of the same class could be covered by adding a running index in case the object exists.
This would mean that BECImageShow
widget would be accessible like this:
gui.bec_image_show.
The same for the SpiralProgressBar
and BECFigure
. Alternatively, one can also simply nest the access:
gui.dock_1.bec_figure.bec_image_show.
I am not 100% if this is technically possible, but we could have a discussion.
Consistency of methods
BECFigure.plot()
vs BECFigure.add_plot()
have different APIs, and should probably be the same.