Skip to content

Add page that describes hardware configuration & data acquisition #186

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

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions articles/getting-started/onix-bonsai.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
---
uid: onix-bonsai
title: Configure Hardware and Stream Data
---

> [!TIP]
> This page provides a description of how workflows involving OpenEphys.Onix1 work. When it comes to
> writing your own workflows, starting from [example workflows](xref:hardware) for your hardware
> might be easier and faster than writing a workflow from scratch.

## Construct Top-level Configuration Chain

Every workflow in Bonsai that is meant to work with ONIX hardware should contain a hardware
configuration chain in its first row. This hardware configuration chain comprises of the following
steps:
1) Creating a ONI context (an object that is capable of reading to and writing from ONIX hardware)
2) Writing properties to hardware
3) Starting acquisition

### Create a context

An ONI context contains information about the device driver and index where the hardware which
enables it to read from and write to hardware. To create a context, place a
<xref:OpenEphys.Onix1.CreateContext> into the workflow. The context's device driver and index can be
set by the user by editing CreateContext's properties. The Driver property is typically set to
"riffa" which is the name of the PCIe device used by ONIX, and the Index property is typically set
to 0 though [using multiple ONIX systems on a single PC](#multiple-onix-systems) requires changing this value.

::: workflow
![/workflows/operators/CreateContext.bonsai workflow](../../workflows/operators/CreateContext.bonsai)
:::

The context generated by CreateContext when the workflow starts is a [data
element](xref:data-elements) named <xref:OpenEphys.Onix1.ContextTask>.

### Configure hardware

Hardware configuration is performed when ContextTask passes through a [configuration
operator](xref:configure). A configuration operator allows the user to set the values that are
written to hardware by editing its properties. There are two types of configuration operators:
multi-device configuration operators and single-device configuration operators. Single-device
configuration operators allow configuration of a single device contained by a headstage, miniscope,
or breakout board whereas multi-device configuration operators allow configuration of all devices
contained by a headstage, miniscope, or breakout board. We recommend using multi-device
configuration operators for concision and ease-of-use, though single-device operators can be helpful
in more advanced workflows that require writing to hardware while the workflow is running.

Any number of configuration operators can be chained following a CreateContext operator. If you use
only multi-device configuration operators, you'll probably have between one and three total
configuration operators: one for the breakout board and one for each port that is connected to a
headstage or miniscope.

::: workflow
![/workflows/getting-started/configure.bonsai workflow](../../workflows/getting-started/configure.bonsai)
:::

### Start acquisition

The data acquisition process is started when ContextTask passes through
<xref:OpenEphys.Onix1.StartAcquisition>. StartAcquisition allows the user to set parameters that are
related to data acquisition such as ReadSize and WriteSize. Setting the ReadSize property for a
particular workflow is a balancing act of minimizing latency of data from hardware to software while
not letting the ONIX system's hardware buffer accumulate data to maximum capacity.

<!-- TODO: Need a separate tutorial or guide on this -->

::: workflow
![/workflows/getting-started/start-acquisition.bonsai workflow](../../workflows/getting-started/start-acquisition.bonsai)
:::

## Acquire Data

Streaming data into Bonsai requires a <xref:dataio>.

### Set up data I/O operators

Streaming data from the configured hardware/devices requires placing a data I/O operator and setting
its DeviceName property for every device from which you would like to stream. Setting its DeviceName
tells the operator from which device to stream data. In these docs, setting the DeviceName is
referred to as linking the data I/O operator to a device. The value of each DeviceName property in
the workflow must correspond to a device in the configuration chain. Take this workflow for example:

::: workflow
![/images/analog-input.bonsai workflow](../../images/analog-input.bonsai)
:::

The DeviceName property of the AnalogInput operator is set to "BreakoutBoard/AnalogIO". This links
the operator to the AnalogIO device on the Breakout Board meaning that the AnalogInput operator will
streams data from that device.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: streams -> stream


### Visualize & save data

Each OpenEphys.Onix1 data I/O operator produces a data frame whose members might contain multiple
disparate data types. Select the data from the frame you want to save by following the
[member-selection section](xref:visualize-data#select-data-members) of the Visualize Data page.

To save data, place a writer operator (such as <xref:Bonsai.Dsp.MatrixWriter>,
<xref:Bonsai.IO.CsvWriter>, or <xref:Bonsai.Vision.VideoWriter>) downstream/to the right of the operator
that is producing data you want to save. For example:

::: workflow
![/workflows/getting-started/writer-example.bonsai workflow](../../workflows/getting-started/writer-example.bonsai)
:::

> [!TIP]
> - The recommended writer operator for saving particular data is used in the example workflow in
> the [hardware guide](xref:hardware) for your hardware.
> - Each hardware guide has a Python script to load and view data. You can use this is to load and
> view data from the example workflow or as a starting point for loading data from your own workflow.

<!-- For high data rates, use <xref:Bonsai.Dsp.MatrixWriter>. For lower data rates or files that store
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the comment about when to use each data writer is helpful, even if reductive. In fact, it could warrant a separate section on Writing Data, same as you did for Visualize Data. This could also include how to know what type of data a node produces (by either checking the reference or by using the text visualizer or whatever the actual method is).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, we should have a section like "visualize data" for "write data". that would be a good spot to plug a solution for issue #165

human-readable data, use <xref:Bonsai.IO.CsvWriter>. For videos, use <xref:Bonsai.Vision.Writer> -->
<!-- Not sure sure the above comment is too reductive and maybe should just not be mentioned. -->

Read the [relevant sections](xref:visualize-data#select-visualizers) of the Visualize Data page
to visualize this data.

## Use Multiple Instances of Identical Hardware

### Multiple Headstages/Miniscopes

Linking the data I/O operator to devices when using two identical headstages or miniscopes involves
an additional step: aliasing the multi-device configuration operator. Suppose you want to stream
orientation data from two Headstage64s through the Bno055Data operator. By default, the
ConfigureHeadstage64 operators are both named "Headstage64". This causes their devices to also have
identical names, "Headstage64/Bno055". The two headstages and their devices must be disambiguated. The
solution is to alias one or both headstages by editing their Name property.

::: workflow
![/images/bno055-data-alias.bonsai workflow](../../images/bno055-data-alias.bonsai)
:::

In this workflow, each ConfigureHeadstage64 operator previously named "Headstage64" has been
suffixed by the port to which the headstage is plugged. Now, the names "Headstage64A/Bno055" and
"Headstage64B/Bno055" can be used when setting the DeviceName property in each Bno055Data operator.

### Multiple ONIX Systems

If a second ONIX system is used on the same computer, a second configuration chain operator is
required. In this case, the Index property of the configuration chain that corresponds to the second
system should be set to 1.

::: workflow
![/workflows/getting-started/multiple-breakout.bonsai workflow](../../workflows/getting-started/multiple-breakout.bonsai)
:::
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
---
uid: initialize-onicontext
title: Initialize the ONI Context
uid: script-workflow
title: Bonsai Workflow Editor
---

The [CreateContext](xref:OpenEphys.Onix1.CreateContext) operator initializes the acquisition context, and it should be the first operator you add to your workflow as it provides access to the hardware device table for all other configuration operators. There are several different ways to find this operator and add it to the workflow:
Scripting in Bonsai involves placing nodes onto the workflow editor. This page describes how to do
that using <xref:OpenEphys.Onix1.CreateContext> as an example.

1. From the Bonsai editor, navigate to the toolbox on the left side of the screen and expand the **Source** section. Next, expand the **OpenEphys.Onix1** section, and find the `CreateContext` line. The operator can then be added by either double-clicking it, or dragging and dropping the operator into the workflow.

Expand Down
10 changes: 5 additions & 5 deletions articles/getting-started/visualize-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ produced by an operator. They are opened by double-clicking the corresponding no

Read below for more details about how to visualize data.

## Selecting operator data members for visualization
## Select data member(s)

Some operators, such as [ONIX data I/O operators](xref:dataio), require selecting members from their output to visualize
their data:
Expand All @@ -28,7 +28,7 @@ member from the data frame produced by the data I/O operator.
> the data in a meaningful capacity. This is true for [ONIX data I/O operators](xref:dataio) which typically produce
> [data frames](xref:data-elements).

## Selecting visualizers
## Select visualizers

Select the visualizer you would like to use for visualizing data:
1. Right-click the `MemberSelector` node labelled with the member you would like to visualize.
Expand All @@ -39,9 +39,9 @@ Select the visualizer you would like to use for visualizing data:
<source src="../../images/set-visualizer.mp4" type="video/mp4">
</video>

## Opening visualizers
## Open visualizers

Open the visualizer and check:
Open the visualizer:
1. Start the workflow.
1. If the desired visualizer is closed, double-click the `MemberSelector` node labelled with the member you would
like to visualize.
Expand All @@ -58,7 +58,7 @@ Open the visualizer and check:
> Visualizers can be selected while the workflow is running which is helpful for more quickly trying different visualizer
> options in succession if you are unsure about which one you want to use.

## Configuring visualizers
## Configure visualizers
Some visualizers, in particular those that involve plots, allow additional configuration.
Right-click the visualizer window to gain access to configuration options.

Expand Down
3 changes: 2 additions & 1 deletion articles/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
- href: getting-started/bonsai-usage.md
- href: getting-started/operator-types.md
- href: getting-started/tips-tricks.md
- href: getting-started/script-workflow.md
- href: getting-started/onix-bonsai.md
- href: getting-started/property-categories.md
- href: getting-started/initialize-oni-context.md
- href: getting-started/start-workflow.md
- href: getting-started/visualize-data.md
- href: getting-started/reference.md
Expand Down
2 changes: 1 addition & 1 deletion articles/tutorials/ephys-processing-listening.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ tutorial by visualizing the data produced.

## Configure the Hardware

Construct a [top-level hardware configuration chain](xref:initialize-onicontext):
Construct a [top-level hardware configuration chain](xref:onix-bonsai):

::: workflow
![/workflows/tutorials/ephys-process-listen/configure.bonsai workflow](../../workflows/tutorials/ephys-process-listen/configure.bonsai)
Expand Down
132 changes: 132 additions & 0 deletions images/analog-input.bonsai
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<WorkflowBuilder Version="2.8.5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:onix1="clr-namespace:OpenEphys.Onix1;assembly=OpenEphys.Onix1"
xmlns="https://bonsai-rx.org/2018/workflow">
<Workflow>
<Nodes>
<Expression xsi:type="Combinator">
<Combinator xsi:type="onix1:CreateContext">
<onix1:Driver>riffa</onix1:Driver>
<onix1:Index>0</onix1:Index>
</Combinator>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="onix1:ConfigureBreakoutBoard">
<onix1:Name>BreakoutBoard</onix1:Name>
<onix1:Heartbeat>
<onix1:DeviceName>BreakoutBoard/Heartbeat</onix1:DeviceName>
<onix1:DeviceAddress>0</onix1:DeviceAddress>
<onix1:Enable>true</onix1:Enable>
<onix1:BeatsPerSecond>100</onix1:BeatsPerSecond>
</onix1:Heartbeat>
<onix1:AnalogIO>
<onix1:DeviceName>BreakoutBoard/AnalogIO</onix1:DeviceName>
<onix1:DeviceAddress>6</onix1:DeviceAddress>
<onix1:Enable>true</onix1:Enable>
<onix1:InputRange0>TenVolts</onix1:InputRange0>
<onix1:InputRange1>TenVolts</onix1:InputRange1>
<onix1:InputRange2>TenVolts</onix1:InputRange2>
<onix1:InputRange3>TenVolts</onix1:InputRange3>
<onix1:InputRange4>TenVolts</onix1:InputRange4>
<onix1:InputRange5>TenVolts</onix1:InputRange5>
<onix1:InputRange6>TenVolts</onix1:InputRange6>
<onix1:InputRange7>TenVolts</onix1:InputRange7>
<onix1:InputRange8>TenVolts</onix1:InputRange8>
<onix1:InputRange9>TenVolts</onix1:InputRange9>
<onix1:InputRange10>TenVolts</onix1:InputRange10>
<onix1:InputRange11>TenVolts</onix1:InputRange11>
<onix1:Direction0>Input</onix1:Direction0>
<onix1:Direction1>Input</onix1:Direction1>
<onix1:Direction2>Input</onix1:Direction2>
<onix1:Direction3>Input</onix1:Direction3>
<onix1:Direction4>Input</onix1:Direction4>
<onix1:Direction5>Input</onix1:Direction5>
<onix1:Direction6>Input</onix1:Direction6>
<onix1:Direction7>Input</onix1:Direction7>
<onix1:Direction8>Input</onix1:Direction8>
<onix1:Direction9>Input</onix1:Direction9>
<onix1:Direction10>Input</onix1:Direction10>
<onix1:Direction11>Input</onix1:Direction11>
</onix1:AnalogIO>
<onix1:DigitalIO>
<onix1:DeviceName>BreakoutBoard/DigitalIO</onix1:DeviceName>
<onix1:DeviceAddress>7</onix1:DeviceAddress>
<onix1:Enable>false</onix1:Enable>
</onix1:DigitalIO>
<onix1:ClockOutput>
<onix1:DeviceName>BreakoutBoard/OutputClock</onix1:DeviceName>
<onix1:DeviceAddress>5</onix1:DeviceAddress>
<onix1:ClockGate>false</onix1:ClockGate>
<onix1:Frequency>1000000</onix1:Frequency>
<onix1:DutyCycle>50</onix1:DutyCycle>
<onix1:Delay>0</onix1:Delay>
</onix1:ClockOutput>
<onix1:HarpInput>
<onix1:DeviceName>BreakoutBoard/HarpSyncInput</onix1:DeviceName>
<onix1:DeviceAddress>12</onix1:DeviceAddress>
<onix1:Enable>false</onix1:Enable>
<onix1:Source>Breakout</onix1:Source>
</onix1:HarpInput>
<onix1:MemoryMonitor>
<onix1:DeviceName>BreakoutBoard/MemoryMonitor</onix1:DeviceName>
<onix1:DeviceAddress>10</onix1:DeviceAddress>
<onix1:Enable>false</onix1:Enable>
<onix1:SamplesPerSecond>10</onix1:SamplesPerSecond>
</onix1:MemoryMonitor>
</Combinator>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="onix1:ConfigureHeadstage64">
<onix1:Name>Headstage64</onix1:Name>
<onix1:Rhd2164>
<onix1:DeviceName>Headstage64/Rhd2164</onix1:DeviceName>
<onix1:DeviceAddress>256</onix1:DeviceAddress>
<onix1:Enable>false</onix1:Enable>
<onix1:DspCutoff>Dsp146mHz</onix1:DspCutoff>
<onix1:AnalogLowCutoff>Low100mHz</onix1:AnalogLowCutoff>
<onix1:AnalogHighCutoff>High10000Hz</onix1:AnalogHighCutoff>
</onix1:Rhd2164>
<onix1:Bno055>
<onix1:DeviceName>Headstage64/Bno055</onix1:DeviceName>
<onix1:DeviceAddress>257</onix1:DeviceAddress>
<onix1:Enable>true</onix1:Enable>
</onix1:Bno055>
<onix1:TS4231>
<onix1:DeviceName>Headstage64/TS4231V1</onix1:DeviceName>
<onix1:DeviceAddress>258</onix1:DeviceAddress>
<onix1:Enable>false</onix1:Enable>
</onix1:TS4231>
<onix1:ElectricalStimulator>
<onix1:DeviceName>Headstage64/Headstage64ElectricalStimulator</onix1:DeviceName>
<onix1:DeviceAddress>259</onix1:DeviceAddress>
</onix1:ElectricalStimulator>
<onix1:OpticalStimulator>
<onix1:DeviceName>Headstage64/Headstage64OpticalStimulator</onix1:DeviceName>
<onix1:DeviceAddress>260</onix1:DeviceAddress>
</onix1:OpticalStimulator>
<onix1:Port>PortA</onix1:Port>
<onix1:PortVoltage xsi:nil="true" />
</Combinator>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="onix1:StartAcquisition">
<onix1:ReadSize>2048</onix1:ReadSize>
<onix1:WriteSize>2048</onix1:WriteSize>
</Combinator>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="onix1:AnalogInput">
<onix1:DeviceName>BreakoutBoard/AnalogIO</onix1:DeviceName>
<onix1:BufferSize>100</onix1:BufferSize>
<onix1:DataType>S16</onix1:DataType>
</Combinator>
</Expression>
</Nodes>
<Edges>
<Edge From="0" To="1" Label="Source1" />
<Edge From="1" To="2" Label="Source1" />
<Edge From="2" To="3" Label="Source1" />
</Edges>
</Workflow>
</WorkflowBuilder>
Loading
Loading