Hi,
I have been working on a finite state machine for what will eventually be a 2AFC behavior. Currently the task in bonsai looks like Go-NoGo.
I am using your Harp device to detect licks and move to success or miss for timeouts.
However, since I now want to make this into a choice behavior, I am now going to build some workflow that determines the trial type: whether left or right lick is defined as the successful choice.
For testing purposes, I'm making two kinds of trials: sine wave grating or square wave grating in bonvision. I've made a node that determines trialtype "determineTrialType" which includes a python transform where the output is either "squareTrial" or "sineTrial," for testing purposes. Then, in the "stimOn" sink in the main workflow, I use the trialType to control the externalized property square wave for the gratings stimulus.
Next, I would like to use the "squareTrial" or "sineTrial" to determine which lick port is the successful one. To do this, I have two ideas, and neither are working, but they've both revealed strange things to me. Here is where I'd like your help:
Idea 1: Have the "squareTrial" or "sineTrial" feed into the Behavior.Input node's externalized Mask property, so that for squareTrials, the lick port 0 is rewarding and the lick port 1 causes an error. And for sineTrials, the lick port 1 is rewarding and the lick port 0 causes an error. Additionally, a timeout for either case causes an error. I have this implemented in the "respWindow" grayed-out selectMany node in the main workflow. When I check it while it runs, I am successfully changing the mask property for both ports, but I have noticed unfortunately that licks from port 0 are being detected as behavior.inputs despite the mask being set to a specific port (1 or 2). For context, I only have a single IR port plugged in, to port 0. I wonder if this is happening because the other ports don't have any inputs? Is it a bug/should I reinstall harp? I don't understand this.
Idea 2: Declare an IR beam break from each port as a "leftLick" or "rightLick" at the top level of the workflow, and just manage the logic inside the response window node. I have tried this, (it is at the top level of workflow and is called in the active/enabled "respWindow" selectMany node). However, when I run this version, once a lick happens, it remains in the "licking" state permanently. Meaning, it just gets toggled on, but not back off, so in subsequent trials, once the workflow enters the responseWindow state, a lick is immediately registered without me breaking the beam. I don't know how to reset the licks when the trial repeats.
And finally, I've noticed that the trialType actually updates when the workflow leaves the stimOn sink. I don't understand why this is happening; I would like to determine the trial type before all the other states execute, and I put that piece of the workflow before the stimOn sink for that reason. Perhaps because it's a nested workflow? Or perhaps because the trialType is subscribed inside the stimOn sink?
I think that these walls may have to do with my concept of how to subscribe/multicast behaviorsubjects. It feels like they are being updated when I don't want them to be. Also, I'm not that confident that each state is being moved through in a sequence. It's not clear when the different parts of the code are actually happening.
Thanks for any advice you can provide. I attached the workflow here.
For idea 1, gray out the second "respWindow" node and the declaration of left and right licks at top level of workflow (under the finite state machine).
I'd appreciate any help you can give!
Thank you,
Daniela