Harp setting behavior events as observables and calling observables only on change

221 views
Skip to first unread message

Daniela Cassataro

unread,
Apr 8, 2022, 8:07:57 PM4/8/22
to Bonsai Users
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).
idea1.pngidea2.png
I'd appreciate any help you can give! 

Thank you,

Daniela
2022-04-16_fsm-harpAttempt.bonsai

brunocruz

unread,
Apr 9, 2022, 10:57:04 AM4/9/22
to Bonsai Users
Heya,

Can you check if the logic in the attached workflow works for you? I dont have an Harp Behavior to test it right now unfortunately. The idea is very close to what you had before. Basically each trial type has an ID = -1 or 1. When the animal licks, you check which response it gave (-1 or 1) and compare it to the trial type. If they match, give reward, if not it is a wrong trial. Meanwhile, I gave the reponse ID 0 to time outs. You can make this logic as complex as you would like, but for your case it might do the trick :)

Hope it helps!,
B

2022-04-16_fsm-harpAttempt.bonsai

Daniela Cassataro

unread,
May 13, 2022, 12:07:53 AM5/13/22
to Bonsai Users
Hi Bruno,
Thank you so much. 
I got your logic to work with harp (just had to add createMessage node in), and it is going to work well with my experimental design. 
I am running into an issue, though. Maybe you can advise.

Inside "respWindow" node, we subscribeSubject from observable sequences, LeftLick/RightLick. 
Screenshot 2022-05-12 205556.jpg

The licks are multicasted from harp inputs at the IR detectors:
Screenshot 2022-05-12 205414.jpg

The lick is correctly detected on the first loop of the workflow, but on all subsequent loops, the Observable (LeftLick, for example), always gets read as in the "lick" state. As in, when I subscribeSubject to LeftLick, if there ever was a leftlick, there will always be a left lick on all future loops. 
How can I only detect whether a lick happens within the response window time period? Is it subscribeWhen? does it involve TakeUntil? Is there a subscribe "after"? or "if a lick happens right now? " As the workflow stands, it just measures whether a lick *ever* occurred.

I thought about resetting the Left/Right Lick observables after every loop, but I would like to collect the data of every time the animal licks, even if outside the response windows, (I don't want to interfere with that stream of data by resetting the observable). maybe I am still not understanding observables? 

Workflow is attached.


Thank you in advance. Appreciate all the help you've given so far.
2022-05-12_fsm-harpAttempt.bonsai
Reply all
Reply to author
Forward
0 new messages