Skip to content

Conversation

@banchan86
Copy link
Contributor

@banchan86 banchan86 commented Mar 22, 2025

Partially addresses bonsai-rx/roadmap#15

Progress

100/100 Bonsai.Reactive operators reviewed
The examples have been updated with the VisualizerWindow from Bonsai 2.9.0
Click on operator link for online preview - some might not be up yet till I update the demo branch.:

Operators covered with examples

Operator Category Basic Example Application Examples Alternatives
Accumulate Quantitative Sum
Average Quantitative Signal Smoothing
Count Quantitative ElementIndex
Min Quantitative
Max Quantitative
Scan Quantitative Accumulate
Sum Quantitative Accumulate
CombineLatest Combine Video Synchronization WithLatestFrom
Concat Combine Stimulus Composition Merge
OnErrorResumeNext
Merge Combine Input Aggregation Zip
CombineLatest
WithLatestFrom
Concat
WithLatestFrom Combine Video Synchronization
Background Subtraction
CombineLatest
Zip Combine Combine Processing Results
Combine Related Events
Sample Preloaded Sequences
WithLatestFrom
CombineLatest
Gate Dynamic Filter GateInterval
WindowTrigger
BufferTrigger
Sample Dynamic Filter SampleInterval
Zip
SkipUntil Dynamic Filter Start Video Recording SubscribeWhen
SubscribeWhen Dynamic Filter SkipUntil
TakeUntil Dynamic Filter Stop Video Recording
Condition Filter
Distinct Filter DistinctUntilChanged
DistinctUntilChanged Filter Signal State Transitions
First Filter Take
FirstOrDefault
FirstOrDefault Filter Take
Last Filter TakeLast
LastOrDefault
LastOrDefault Filter TakeLast
Slice Filter Deinterleave Video Frames GateInterval
Skip Filter Discard Startup Elements Slice
SkipLast Filter Delay
SkipWhile Filter SkipUntil
Condition
Take Filter First
TakeLast Filter Last
TakeWhile Filter TakeUntil
Condition
Timer Element Generation
Range Element Generation
CreateTimestamped Temporal *
Delay Temporal DelaySubscription
DelaySubscription Temporal Delay
GateInterval Temporal SampleInterval
Slice
Gate
SampleInterval Temporal GateInterval
Slice
Sample
Throttle Temporal *
TimeInterval Temporal
Timestamp Temporal Record Data Timestamps
Repeat Loop RepeatCount
RepeatCount Loop Repeat
ToArray Collections Collect Input Data ToList
ToList Collections ToArray
ToDictionary Collections ToLookup
ToLookup Collections ToDictionary
AsyncSubject Subject Other Subjects
BehaviorSubject Subject Other Subjects
PublishSubject Subject Other Subjects
ReplaySubject Subject Other Subjects
BufferCount Group BufferTime
WindowCount
BufferTime Group BufferCount
WindowTime
WindowCount Group WindowTime
BufferCount
WindowTime Group WindowCount
BufferTime
BufferTrigger Dynamic Group WindowTrigger
WindowTrigger Dynamic Group BufferTrigger
Window
Window Dynamic Group WindowTrigger
Amb Dynamic Switch Switch
Switch Dynamic Switch Amb
Dematerialize Logging
ElementIndex Logging
IgnoreElements Logging
IsEmpty Logging
Materialize Logging
Retry Exception RetryCount
RetryCount Exception Retry
Timeout Exception
Catch Dynamic Exception Retry
OnErrorResumeNext
OnErrorResumeNext Dynamic Exception Concat
Catch
SequenceEqual Dynamic Exception
Prepend Element Insertion Append
Append Element Insertion Prepend
DistinctBy Key Filtering *
DistinctUntilChangedBy Key Filtering *
GroupBy Key Filtering *
MaxBy Key Filtering *
MinBy Key Filtering *
OrderBy Key Sorting *
OrderByDescending Key Sorting *
ThenBy Key Sorting *
ThenByDescending Key Sorting *
CreateObservable Higher-Order SelectMany
SelectMany Higher-Order CreateObservable
Visualizer Sinks
Sink Sinks

Comments (*)

  • For Throttle, it was hard to build a basic example using just Bonsai.Core reactive operators, since it relies on an input with a variable rate, so I used KeyDown as an input.
  • CreateTimestamped was renamed from CombineTimestamp, but the accompanying doc files were not updated yet; these files were renamed. In addition, the existing example (to carry forward the timestamp) was adopted as a basic example. While it is more like an application example, I could not figure out how to generate a basic example without copying much of that workflow. In addition, a true basic example for this operator would rely on timestamps coming from a different source.
  • For the key filtering and sorting operators (like GroupBy, OrderBy), the basic examples are a little complicated because of the steps needed to set up the key/value collection. I grouped the Key and Value manipulations to somewhat hide them, as I think they're not essential for understanding how the operators work, but I am open to other suggestions on how to simplify them.

Operators without examples

Operator Category Comment
ResourceSubject Subject - Used for niche applications involving device operators?
- Unsure how to create a basic or suitable application example.
- I listed AsyncSubject as an alternative due to prior confusion.
ObserveOn
SubscribeOn
Scheduler - Unsure about how to create examples for them.
- Would Timer -> SubscribeOn (DefaultScheduler) ->
ObserveOn (NewThreadScheduler) -> Accumulate work?
CurrentThreadScheduler
DefaultScheduler
EventLoopScheduler
ImmediateScheduler
NewThreadScheduler
TaskPoolScheduler
ThreadPoolScheduler
Scheduler Objects - Unsure how to use them.
- Unsure as to when someone would use them given that they
also appear as property options for ObserveOn and SubscribeOn.
Synchronize Exception - Very niche operator used to patch custom implementations
Publish
Replay
Nested Subjects - Not sure how to use them in place of their regular subject variant.
- Can be used to unlock more complex functionality?
Defer Higher-Order - Not sure how to illustrate its behaviour with muliple subscribers
I mainly use it as my default closed-scope node

Other Thoughts/Issues

  • Haven't decided whether to add higher-order examples for operators that have a higher-order counterpart (like Concat)
  • In many cases, I think the description for the basic example closely mirrors the editor description for the operator, so I might just take those out and leave only descriptions for the application examples. I will probably leave it for one of the last edits so it can be reversed if necessary.
  • The section that follows with the class declaration code snippet, inheritance, and inherited members does not have a section heading. That makes it appear as a continuation of the examples or alternatives. I think adding a section heading is needed, but I will also probably add it as an edit near the end.
  • For collection operators (ToList, etc), I thought it would be helpful to add some references to .NET documentation for the collection, in case they need to be manipulated further. These were added to the existing summaries for each operator and do not affect the examples directly.
  • In some of the more complicated examples, I used two VisualizerWindows to illustrate the elements before and after they have been processed by the operator, I have been wondering if that might be a good general strategy to apply to all the Reactive operators, even if it adds a bit of clutter.
  • @glopesdev has also mentioned that we could consider listing the alternatives using the <seealso> tag for XML doc comments, there is an example of that in the existing documentation for the SubscribeOn operator.

@banchan86 banchan86 requested a review from glopesdev March 22, 2025 17:20
@banchan86 banchan86 added the documentation Improvements or additions to documentation label Mar 22, 2025
@banchan86 banchan86 changed the title Add usage examples for reactive quantitative operators Add usage examples for reactive operators Apr 3, 2025
@banchan86
Copy link
Contributor Author

I updated this PR with the feedback from DCM and added another batch of reactive operators (operators that "combine" sequences). As such i changed the title of this PR and also added a chart in the top level comment to document which operators were included.

Other changes that were made:

  • Switched basic types in basic examples to those from Bonsai.Core (Range/Int/Timer)
  • Separated "basic examples" from "practical application examples"
    • One point we discussed was whether to even include practical/complex examples or leave them out. As I was covering the "combine" operators however, I discovered that there was already some mention of practical applications for the operators in the overwrite articles. Distinguishing between those operators was also hard with just basic examples. Thus, I opted to include practical examples/applications for them by simply expanding on those existing notes with workflow containers.
  • Improved visualization of operators that only emit a final value by repeating the block
    • I noticed that the previous solution of using a delay node and a note to use ObjectTextVisualizer was very clunky and unintuitive.

@banchan86 banchan86 force-pushed the reactive-usage-quantitative branch from 3af2eef to 7982cd0 Compare July 15, 2025 04:17
@banchan86 banchan86 removed the request for review from glopesdev August 27, 2025 19:48
@banchan86 banchan86 marked this pull request as ready for review September 4, 2025 18:46
@banchan86 banchan86 requested a review from glopesdev September 4, 2025 18:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant