Using Scan for setting a double threshold

224 views
Skip to first unread message

Chi-Yu Lee

unread,
Dec 5, 2018, 3:32:23 PM12/5/18
to Bonsai Users
Dear Bonsai team

I am writing this to share with you the second lesson I had today
In a video-based behavioural experiment where we set a condition for the animals to enter a certain area. Something we can start from is to select an area with Crop and track the animals with Threshold > FindContours > BinaryRegionAnalysis and then set a threshold to see if this animal enter the selected area. One thing can happen is that the value in that area might value depends on the animals' subtle movement. Therefore, instead of setting one threshold to meet, one can do is to set multiple threshold for different conditions (or different states), which means that there is a one threshold for the animal in the threat zone and another threshold for the animal not being in the threat zone. Scan is a module that uses its input and output to determine the current state of the workflow. Therefore the workflow seems to be as follow.
1. Use Boolean to set a default state and send this to Scan
2. In the Scan, create two conditions. One condition is for one state. The other condition is for the other state
3. The first condition would accumulate the value whereas the other condition is the opposite of the first condition so there is a need to put a BitwiseNot. 
4. Output the conditions as value and use GreaterThan as thresholds for each of them 
5. Merge the two workflow for only one workflow output

The logic behind this is when the workflow is in the default state, it would process via the default condition. When the value of this condition pass the threshold, it would switch to the other condition and stay in that state until the condition does not anymore.
In my case, there are two states, the active state has a higher threshold to enter so only when the animals enter the threshold do the condition is satisfied. Otherwise, it would stay in the default state. When the active state returns back to the default state, it needs to cross a threshold that is higher than the baseline but lower than the high-threshold.

This is an elegant way to set two thresholds for a condition. I think it would be very useful to use Scan but I honestly think I have not understood everything in this workflow. Therefore, feel free to let me know if you have any concerns or comments.

Best Regards

Chi-Yu


Presentation1.jpg

Vincent Prevosto

unread,
Dec 19, 2018, 7:53:37 PM12/19/18
to Bonsai Users
Hi Chi-Yu,
Thanks for this tutorial.
I tried to adapt this solution to a problem I had, as it seemed fairly similar, but I couldn't replicate your example. I understand the logic, but having a workflow to work with would really make a difference.
1/ a very simple issue was that I had never used the Scan operator. I realize that's been around since v2.1, so it may sound silly, but just reminding people what is Scan and where to find it would be a good start.
2/ I don't know what is the output of your Area module (I suppose it's Source.Area, so a double). My Python transform outputs a Tuple of double, and I need both to set my threshold. So I can't simply accumulate a unique double.
3/ Nonetheless, I tried mapping my ON/OFF thresholds onto you ON/OFF conditions, but that fails. I can't accumulate booleans (the output of my thresholds), and if I output integers to accumulate, there's an error for the Condition, that says that it must have a single boolean output.
Since I fixed the issue through other means, this question is mostly out of curiosity. Let me know if you have suggestion on using Scan in this situation.

Gonçalo Lopes

unread,
Jan 3, 2019, 8:08:44 AM1/3/19
to Vincent Prevosto, Bonsai Users
Hi Vincent,

Scan allows you to store and accumulate memory across different elements of a data stream. It works by pairing the input values together with an accumulator, which is passed inside the nested workflow for some processing. The result of the nested operation is stored and becomes the accumulator for the next pass. For example, a simple general-purpose accumulator can be defined in terms of Scan:

scan.jpg

Inside Scan:

scan-nested.jpg

Basically we are selecting in each iteration the value of the accumulator and the input, and adding both together. This result will be stored, and added again with the next input. By default, the initial value of the accumulator is set to the first value of the input, but you can also set the initial value by feeding a second input to Scan, like so:

scan.jpg


Scan can work with any input type, both for the accumulator and the input. The only thing you need to ensure is that the type of the result matches the type of the accumulator which will be stored for the next pass. The result is not restricted to single numbers, so you can accumulate tuples of values, images, arrays, and everything else. For example, for tuples you can use branch and Zip inside Scan to split, accumulate, and reconstruct a pair of values that is carried across the iterations.

Maybe Chi-Yu can clarify the specific points regarding his application, but I hope this will help clarify the use of Scan.

--
You received this message because you are subscribed to the Google Groups "Bonsai Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bonsai-users...@googlegroups.com.
Visit this group at https://groups.google.com/group/bonsai-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/bonsai-users/71fc9e99-8cd6-4f8e-93c4-0f6446788cb6%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Vincent Prevosto

unread,
Jan 4, 2019, 12:23:43 PM1/4/19
to Bonsai Users
Thanks for the clarification Gonçalo. I'll play around with Scan, it looks promising for some of my workflows.
Sometimes when I read your explanations, it makes me wish there would be an additional option in the pop-up menu that appears when right-clicking on an operator in the toolbox, that would be like "try it!", and it would open a small functional workflow that makes use of that particular operator to illustrate how it works. Even though the documentation and forum are great resources, some operators are not entirely intuitive to use. Thanks for all the help, though!
Reply all
Reply to author
Forward
0 new messages