-
Notifications
You must be signed in to change notification settings - Fork 5
Add Headstage64 GUIs #459
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
base: main
Are you sure you want to change the base?
Add Headstage64 GUIs #459
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code review was performed during a live demonstration via verbal notes.
Before finalizing the edits to this PR, I have an outstanding question at the bottom that I need some help answering before moving forward. This comment also serves as a general update on the status of the PR so that when the review comes it is easier to see the status of the GUI elements, as well as to provide context for the question. Current StatusThe current status of this PR is the following; all configuration properties have been removed from the Side note @jonnew: after our discussion this morning, I actually think that we no longer need the GUIs are functionally complete, I will be stress testing them today to make sure I haven't missed any obvious issues, but here is how they look: Headstage64 GUII have most of these changes as local commits, as there is some back and forth I want to clean up before requesting a review. Additionally, I will need to bring this branch up to date with main before we could merge it. Outstanding QuestionThe question that we need to answer now, before moving forward, is whether or not the stimulus sequence parameters should be packaged into a single Whichever method is used, they will both be written in real-time during acquisition so that the stimulus sequence can be updated on the fly. Stimulus Sequence object![]() Pros:
Cons:
Individual parameters![]() Pros:
Cons:
Final ThoughtsGiven that we do not know when bonsai-rx/bonsai#2370 will be approved and merged into a release version of Bonsai, it is probably prudent to leave the parameters as individual parameters and not worry about packing them into a |
I need to think about this, but one thing: Once you move this to the configure node, those will be not externalizable anyways, whether or not they are packed into a |
Ah, that's right. I was thinking about it from the context of the device node, but anything in the headstage node will not be externalizable until the property mapper is added |
@aacuevas @jonnew Update based on discussion during our meeting today: what does it look like if we were to implement this PR using individual parameters (i.e., copying the behavior from the original Exploring Individual ParametersStarting from the current main branch, and only implementing this for the View from the Bonsai editor for the
Passing Parameters to/from the GUIHere there are two options:
Option 2 is the option I went with, as it keeps the construction argument list short once all 12 parameters are implemented. Following the pattern of option 2, it is fairly easy to pass the In the ElectricalStimulatorSequenceDialog = new(configureNode.ElectricalStimulator); In the configureNode.ElectricalStimulator = editorDialog.ElectricalStimulatorSequenceDialog.ElectricalStimulator; Serializing / Deserializing the Stimulus SequenceThis is the only point where I think that keeping the individual properties runs into a hard issue to solve. Previously, when I was using The main work for serializing/deserializing is done by the There is support for serializing collections, but this would require manually pulling out the individual properties and adding them to a Externalizing ParametersSimilar to the issue of serializing above, once we have the ability to externalize nested parameters there is a question of usage for externalizing the stimulus parameters. If the user only needs to externalize and manipulate a single property then the individual parameters make this very easy, but if they wanted to cycle between two totally different sequences they would have to externalize and update all twelve parameters individually. The Maintaining real-time updatesIndividual Properties readonly BehaviorSubject<double> phaseOneCurrent = new(0);
public double PhaseOneCurrent
{
get => phaseOneCurrent.Value;
set => phaseOneCurrent.OnNext(value);
}
// [...]
phaseOneCurrent.SubscribeSafe(observer, value => device.WriteRegister(Headstage64ElectricalStimulator.CURRENT1, uAToCode(value))) Stimulus Sequence If we want to use the Final ThoughtsWe can port over the individual properties to the If we wanted to use the |
Based on our meeting this morning, we will probably implement the stimulator sequence as individual parameters in the If we do go with individual parameters, this also means that I will need to remove the ability to save the stimulus sequence as a file. Originally, I was following the pattern we started with If this is the route we want to go, I can finalize this PR and rebase so that the updates can be reviewed. |
4b8af2d
to
bb9470b
Compare
Requested changes were implemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we have to think about another way of dealing with configuration operators that don't need a GUI and what to do with them in the context of the GUI for the aggregate (headstage) configuration operator. There is a lot of lines of code and files added to this comment that, at the end of the day, actually are there to precisely nothing. I think we need to rethink about this and what were are trying to achieve with the GUI.
[Category(DevicesCategory)] | ||
[TypeConverter(typeof(SingleDeviceFactoryConverter))] | ||
[Description("Specifies the configuration for the TS4231 device in the headstage-64.")] | ||
[Editor("OpenEphys.Onix1.Design.TS4231V1Editor, OpenEphys.Onix1.Design", typeof(UITypeEditor))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This attribute, and the creation of 3 design files (TS4231V1Dialog.cs, TS4231V1Dialog.Designer.cs, and TS4231V1Editor.cs) were added to do... nothing. This seems very wrong to me. Same story for Bno055. I realize that in the Bno055 case, we've been using this pattern for a while and I'm just noticing it now, but something seems wrong here. This is a lot of boilerplate to generate a blank canvas and redundant properties pane. I think that these design files should be removed and the solution will need to come from another direction. Perhaps a generic DefaultDialog.cs et al.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original intent was to build the framework for all of the dialogs, using a common GUI (GenericDeviceDialog
) at its base. Then, when we wanted to create a custom UI for a specific device, we would stop inheriting from GenericDeviceDialog
and already have everything in place to load and save the GUI data.
I definitely understand what you mean about there being a lot of files added that don't seem to do a lot, so I tested an implementation where I removed all of the boilerplate files, and instead created a GenericDeviceEditor
that all of them can point to. This keeps the functionality of adding a tab for each device in the headstage GUI, but it still shows the same redundant editor so we can discuss if that is useful or not.
I also wanted to say that there is not a GUI for ConfigureHeadstage64ElectricalStimulator
because at one point we discussed whether or not there should be GUIs attached to the device nodes or only the headstage nodes, to prompt users to use the headstage nodes in all cases. I am not sure why I added the dialog to the Bno055
node, so I will need to go through and make sure we are consistent with whichever direction we want to go; adding GUIs to all device nodes, or removing them.
[Description("Controls a headstage-64 onboard electrical stimulus sequencer.")] | ||
public class Headstage64ElectricalStimulatorTrigger : Sink<bool> | ||
{ | ||
readonly BehaviorSubject<bool> enable = new(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a completely backwards incompatible change, correct?
- If a saved workflow has values here, they will be ignored
- If a saved workflow exposed these as externalized properties, it will have a compiler error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Category(DevicesCategory)] | ||
[TypeConverter(typeof(SingleDeviceFactoryConverter))] | ||
[Description("Specifies the configuration for the Rhd2164 device in the headstage-64.")] | ||
[Editor("OpenEphys.Onix1.Design.Rhd2164Editor, OpenEphys.Onix1.Design", typeof(UITypeEditor))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment on line 71.
[Category(DevicesCategory)] | ||
[TypeConverter(typeof(SingleDeviceFactoryConverter))] | ||
[Description("Specifies the configuration for the Bno055 device in the headstage-64.")] | ||
[Editor("OpenEphys.Onix1.Design.Bno055Editor, OpenEphys.Onix1.Design", typeof(UITypeEditor))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment on line 71.
/// Initializes a copy instance of the <see cref="ConfigureTS4231V1"/> class with the given values. | ||
/// </summary> | ||
/// <param name="configureTS4231V1">Existing configuration settings.</param> | ||
public ConfigureTS4231V1(ConfigureTS4231V1 configureTS4231V1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This addition seems like a reversal of needs to me. You have created a copy constructor so you can use a GUI that appears to add no functionality over the default property pane for the sake of having a tab in the headstage. This is backwards I think.
This PR is ready for review again, but it is not ready to merge. To be specific, we are still deciding whether or not keep the tabs for devices that do not have a custom UI yet. In the current iteration (as of ac8e445) the boilerplate files have been removed and only a single generic dialog remains, which all devices can then utilize to be rendered as a separate tab in a headstage GUI. Another topic to discuss is where GUIs should exist; should they only apply to the headstage configure nodes? Or should they be attached to the device configure nodes as well? To retain the full functionality, we might need to split the editor into two different files, since the same editor cannot be attached to a class and a property. For more details, see the implementation in ee3607d, where the HS64 electrical/optical stimulators are given two editors. Once these topics (and any others that come up) are finalized, I can finish the implementation and then clean up the history prior to merging. |
6931790
to
f1c6e9c
Compare
0dcf143
to
b4d910c
Compare
@jonnew This PR is ready for a final review, the history has been cleaned so that files are not added and then removed |
- In preparation of using the same base class for Headstage64 optical/electrical stimulators
- Created new StimulusSequence Dialogs for Electrical/Optical Stimulator, used GenericDialogs for other devices without existing dialogs - Moved all properties from the Trigger node to the Configure node, but kept the same real-time functionality
- Allow inherited dialogs to render in designer - Refactor dialog initialization to streamline child form properties and enhance readability - Use reflection to copy properties automatically
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my comments.
This PR adds GUIs for the electrical and optical stimulators on the
Headstage64
.