<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.bci2000.org/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jhuggins</id>
	<title>BCI2000 Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://www.bci2000.org/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jhuggins"/>
	<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php/Special:Contributions/Jhuggins"/>
	<updated>2026-06-09T08:47:41Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=User_Reference:Normalizer&amp;diff=4916</id>
		<title>User Reference:Normalizer</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=User_Reference:Normalizer&amp;diff=4916"/>
		<updated>2009-03-03T04:54:54Z</updated>

		<summary type="html">&lt;p&gt;Jhuggins: /* Adaptation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Function==&lt;br /&gt;
===Normalizing Transform===&lt;br /&gt;
The Normalizer applies a linear transformation to its input signal.&lt;br /&gt;
For each channel (index denoted with &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;), an offset value is subtracted, and the result multiplied with a gain value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\textrm{output}_i=(\textrm{input}_i-\textrm{NormalizerOffset}_i)\times \textrm{NormalizerGain}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adaptation===&lt;br /&gt;
From the past statistics of its input, the Normalizer estimates offset and gain values adaptively to make its output signal&lt;br /&gt;
*zero mean, and&lt;br /&gt;
*unit variance.&lt;br /&gt;
The Normalizer uses &#039;&#039;data buffers&#039;&#039; to accumulate its past input according to user-defined rules.&lt;br /&gt;
These rules are called &#039;&#039;buffer conditions&#039;&#039; because they are given in terms of boolean expressions.&lt;br /&gt;
Each data buffer is associated with such a boolean expression. Whenever an expression evaluates to &#039;&#039;true&#039;&#039;, the current input will be appended to the associated buffer.&lt;br /&gt;
Whenever it comes to updating offset and gain values, the Normalizer will use the content of its buffers to estimate data mean and variance. The offset will then be set to the data mean, and the gain to the inverse square root of the data variance, i.e., the inverse of the data standard deviation.&lt;br /&gt;
&lt;br /&gt;
One may suggest that the adaptation time may affect the accuracy of the cursor movement in mu rhythm experiments. However, the following reference shows that computing the normalization parameters either during or at the end of the trials leaded to similar results. Hence, in the current version of bci2000, adaptation is accomplished at the end of each trial and using a Moving Average Algorithm.&lt;br /&gt;
&lt;br /&gt;
Ramoser H, Wolpaw JR, Pfurtscheller G, &amp;quot;EEG-based communication: evaluation of alternative signal prediction methods&amp;quot;. Biomed Tech (Berl); 42(9) : 226-33,  Sep, 1997.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Abstract&#039;&#039;&#039;-Individuals can learn to control the amplitude of EEG activity in specific frequency bands over sensorimotor cortex and use it to move a cursor to a target on a computer screen. For one-dimensional (i.e., vertical) cursor movement, a linear equation translates the EEG activity into cursor movement. To translate an individual&#039;s EEG control into cursor control as effectively as possible, the intercept in this equation, which determines whether upward or downward movement occurs, should be set so that top and bottom targets are equally accessible. The present study compares alternative methods for using an individual&#039;s previous performance to select the intercept for subsequent trials. In offline analyses, five different intercept selection methods were applied to EEG data collected while trained subjects were moving the cursor to targets at the top or bottom edge of the screen. In the first two methods-moving average, and weighted sum-a single intercept was selected for the entire 1-2 sec period of each trial. In the other three methods-blocked moving average, blocked weighted sum, and blocked recursive sum (a variation of the weighted sum)-an intercept was selected for each 200-ms segment of the trial. The results from these methods were compared in regard to their balance between upward and downward movements and their consistency of performance across trials. For all subjects combined, the five methods performed similarly. However, performance across subjects was more consistent for the moving average, blocked moving average, and blocked recursive sum methods than for the weighted sum and blocked weighted sum methods. Due to its consistent performance and its computational simplicity, the moving average method, using the five most recent pairs of top and bottom trials, appears to be the method of choice.&lt;br /&gt;
&lt;br /&gt;
===Adaptation Rationale===&lt;br /&gt;
It may appear crude to use the total data variance for the adaptation -- why not use linear regression on data labels (target codes) to separate into user controlled (task determined) and noise variance? User controlled variance would then correspond to target separation on the feedback screen, which is what we want to normalize in the first place.&lt;br /&gt;
&lt;br /&gt;
However, a closer look reveals that the &#039;&#039;relative size&#039;&#039; of user controlled variance, and noise variance is crucial. When that &amp;quot;signal&amp;quot; variance is small compared to noise variance, we would be ill advised to use it in normalization -- this would only lead to enlarged noise, and an erratically moving cursor on the feedback screen.&lt;br /&gt;
In this case, we rather want to normalize by noise variance, to keep the cursor well-behaved. At the same time, total variance approaches noise variance in this limit because signal variance is small.&lt;br /&gt;
&lt;br /&gt;
On the other end of the spectrum, we have a signal variance that is large compared to noise variance. Here, we clearly want normalization by signal variance. However, the total variance will be dominated by signal variance. Thus, in the limit of high signal-to-noise ratio, total variance again is the quantity by which we want to normalize.&lt;br /&gt;
&lt;br /&gt;
Thus, no matter whether signal-to-noise ratio is high or low, total data variance is a good choice for normalization.&lt;br /&gt;
&lt;br /&gt;
===Typical Use===&lt;br /&gt;
Typically, the Normalizer&#039;s input is the output of a classifier, which it transforms into a zero mean/unit variance control signal which is then transmitted to an application module.&lt;br /&gt;
Using the zero mean/unit variance property, an application module can then relate quantities such as window size, screen update rate, cursor speed, and trial duration.&lt;br /&gt;
&lt;br /&gt;
==Parameters==&lt;br /&gt;
For each channel of the Normalizer&#039;s input signal, adaptation is treated independently.&lt;br /&gt;
Offsets, Gains, and Adaptation kind are represented as list parameters, with each entry in the list corresponding to a signal channel.&lt;br /&gt;
Buffer configuration is done in matrix form, with columns corresponding to signal channels, and rows corresponding to multiple buffers.&lt;br /&gt;
&lt;br /&gt;
===NormalizerOffsets, NormalizerGains=== &lt;br /&gt;
Lists of offset and gain values, with entries corresponding to signal channels. These values will be updated depending on the channel&#039;s adaptation configuration in the Adaptation parameter.&lt;br /&gt;
===Adaptation===&lt;br /&gt;
A list of values that determines adaptation strategy individually for each channel. Possible values are&lt;br /&gt;
*0 for no adaptation,&lt;br /&gt;
*1 for adjusting offsets to zero mean,&lt;br /&gt;
*2 for additionally adjusting gains to unit variance.&lt;br /&gt;
===BufferConditions===&lt;br /&gt;
A matrix consisting of [[User Reference:Expression Syntax|boolean expressions]].&lt;br /&gt;
Expressions may involve [[BCI2000 Glossary#State|state variables]] and the components of the Normalizer&#039;s input signal.&lt;br /&gt;
*Each matrix entry represents a data buffer which is a ring buffer of length &#039;&#039;BufferLength.&#039;&#039; Whenever a buffer&#039;s expression evaluates to &#039;&#039;true,&#039;&#039; the current value of the input signal will be put into the buffer (overwriting its oldest data once the buffer is filled).&lt;br /&gt;
*Columns correspond to control signal channels. Buffers in a certain column will buffer data from the corresponding signal channel, and will be used in adaptation of that channel only.&lt;br /&gt;
*Within columns, the order of buffers does not affect computation.&lt;br /&gt;
*Empty expressions do not have any effect on the computation. Thus, it is possible to have a different number of buffers for different channels.&lt;br /&gt;
*A buffer to store data for the first target, and during feedback only, should have an expression such as &amp;lt;code&amp;gt;(Feedback)&amp;amp;&amp;amp;(TargetCode==1)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===BufferLength===&lt;br /&gt;
The maximum length of each data buffer.&lt;br /&gt;
*The length is specified in data blocks if given as a raw number, and in seconds if given as a number followed by the character &amp;quot;s&amp;quot;.&lt;br /&gt;
*All data buffers have the same capacity.&lt;br /&gt;
*Once a data buffer is filled, its older entries will be replaced with new data (ring buffer).&lt;br /&gt;
*In previous versions of BCI2000, buffer lengths were specified in terms of &amp;quot;past trials&amp;quot;. However, this would enforce the notion of a &amp;quot;trial&amp;quot;, and not generalize to continuous adaptation.&lt;br /&gt;
===UpdateTrigger===&lt;br /&gt;
A [[User Reference:Expression Syntax|boolean expression]] that triggers adaptation when changing to &#039;&#039;true&#039;&#039; from &#039;&#039;false&#039;&#039;.&lt;br /&gt;
Generally, continuous adaptation within trials is not desired. Rather, one wants adaptation to occur at the end of a trial. This is achieved with &#039;&#039;UpdateTrigger&#039;&#039; expressions such as &amp;lt;code&amp;gt;Feedback==0&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;TargetCode==0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For continuous adaptation, specify an empty string in the &#039;&#039;UpdateTrigger&#039;&#039; parameter.&lt;br /&gt;
&lt;br /&gt;
==States==&lt;br /&gt;
Buffer condition expressions, and the UpdateTrigger expression may involve any [[BCI2000 Glossary#State|state]] present in the system. Expressions are checked for syntactical correctness and whether referred-to states are present during the [[Technical Reference:States of Operation|Preflight Phase]].&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
===Trial-based 1D Feedback Task with 3 Targets===&lt;br /&gt;
*Only data from the feedback phase should enter into the adaptation.&lt;br /&gt;
*To make sure that targets contribute equally to the adaptation, we use a single buffer for each target. We use a 3-rows-by-1-column BufferConditions (see below).  Depending on which control signal should be adapted on, these conditions need to be entered in the first, second, or third column of the matrix (corresponding to x, y, and z direction when used with the [[User Reference:CursorTask|CursorTask]] application module).&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==1)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==2)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==3)&lt;br /&gt;
*We want to use data from three previous trials of each target. &lt;br /&gt;
*Feedback duration is 2 seconds. We set the buffer length to the equivalent of three feedback durations:&lt;br /&gt;
  BufferLength= 6s&lt;br /&gt;
*Adaptation should happen at the end of each trial, when feedback is finished. &amp;lt;p /&amp;gt;We set UpdateTrigger to an expression that changes to &#039;&#039;true&#039;&#039; when feedback ends:&lt;br /&gt;
  UpdateTrigger= (Feedback==0)&lt;br /&gt;
*To achieve continuous movement in, say, the x direction we need a constant normalizer output on that channel. To be consistent with the [[User Reference:CursorTask#FeedbackDuration|task module&#039;s FeedbackDuration parameter]], this output should be constant +2 in order for the cursor to cross the entire screen during a trial, and +1 when cursor movement begins at the screen&#039;s center. This corresponds to the following settings for the channel in question:&lt;br /&gt;
 Adaptation= 0&lt;br /&gt;
 NormalizerOffset= -1&lt;br /&gt;
 NormalizerGain= 1 or 2, respectively.&lt;br /&gt;
&lt;br /&gt;
===Trial-based 2D Feedback Task with 4 Targets===&lt;br /&gt;
*Leaving everything else as in the previous example, we now have two dimensions corresponding to left-right (channel 1) and up-down (channel 2).&lt;br /&gt;
:Target positions are as indicated below:&lt;br /&gt;
  ---------------------------&lt;br /&gt;
  |          ##1##          |&lt;br /&gt;
  |#                       #|&lt;br /&gt;
  |2                       3|&lt;br /&gt;
  |#                       #|&lt;br /&gt;
  |          ##4##          |&lt;br /&gt;
  ---------------------------&lt;br /&gt;
:We use data from targets 1 and 4 to adjust channel 2, and targets 2 and 3 to adjust channel 1. Accordingly, the BufferConditions matrix is&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==2) (Feedback)&amp;amp;&amp;amp;(TargetCode==1)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==3) (Feedback)&amp;amp;&amp;amp;(TargetCode==4)&lt;br /&gt;
&lt;br /&gt;
===Continuous 1D Control without pre-defined Targets===&lt;br /&gt;
*For this example, we know that, over a period of 10 minutes, all output values will occur with approximately equal frequency, or at least have a symmetric distribution around zero. This matches the combination of BCI2000 and Dasher or other &amp;quot;devices&amp;quot; expecting statistically balanced input.&lt;br /&gt;
:The BufferConditions matrix will have a single entry containing a constant expression:&lt;br /&gt;
 1&lt;br /&gt;
:This way, data will always be buffered.&lt;br /&gt;
*There are no trials. We want a continuous adaptation to the values of the last 10 minutes.&lt;br /&gt;
:We set the BufferLength parameter to &amp;lt;code&amp;gt;600s&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;(10*60)s&amp;lt;/code&amp;gt;.&lt;br /&gt;
:For continuous adaptation, we enter an &#039;&#039;empty string&#039;&#039; (not a constant 0 expression) for UpdateTrigger.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
[[User Reference:Expression Syntax]], [[BCI2000 Glossary#Control Signal]], [[User Reference:LinearClassifier]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Filters]][[Category:Signal Processing]]&lt;/div&gt;</summary>
		<author><name>Jhuggins</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=User_Reference:Normalizer&amp;diff=4915</id>
		<title>User Reference:Normalizer</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=User_Reference:Normalizer&amp;diff=4915"/>
		<updated>2009-03-03T04:54:30Z</updated>

		<summary type="html">&lt;p&gt;Jhuggins: /* Adaptation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Function==&lt;br /&gt;
===Normalizing Transform===&lt;br /&gt;
The Normalizer applies a linear transformation to its input signal.&lt;br /&gt;
For each channel (index denoted with &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;), an offset value is subtracted, and the result multiplied with a gain value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\textrm{output}_i=(\textrm{input}_i-\textrm{NormalizerOffset}_i)\times \textrm{NormalizerGain}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adaptation===&lt;br /&gt;
From the past statistics of its input, the Normalizer estimates offset and gain values adaptively to make its output signal&lt;br /&gt;
*zero mean, and&lt;br /&gt;
*unit variance.&lt;br /&gt;
The Normalizer uses &#039;&#039;data buffers&#039;&#039; to accumulate its past input according to user-defined rules.&lt;br /&gt;
These rules are called &#039;&#039;buffer conditions&#039;&#039; because they are given in terms of boolean expressions.&lt;br /&gt;
Each data buffer is associated with such a boolean expression. Whenever an expression evaluates to &#039;&#039;true&#039;&#039;, the current input will be appended to the associated buffer.&lt;br /&gt;
Whenever it comes to updating offset and gain values, the Normalizer will use the content of its buffers to estimate data mean and variance. The offset will then be set to the data mean, and the gain to the inverse square root of the data variance, i.e., the inverse of the data standard deviation.&lt;br /&gt;
&lt;br /&gt;
One may suggest that the adaptation time may affect the accuracy of the cursor movement in mu rhythm experiments. However, the following reference shows that computing the normalization parameters either during or at the end of the trials leaded to similar results. Hence, in the current version of bci2000, adaptation is accomplished at the end of each trial and using a Moving Average Algorithm.&lt;br /&gt;
&lt;br /&gt;
Ramoser H, Wolpaw JR, Pfurtscheller G, &amp;quot;EEG-based communication: evaluation of alternative signal prediction methods&amp;quot;. Biomed Tech (Berl); 42(9) : 226-33,  Sep, 1997.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;&#039;&#039;Abstract&#039;&#039;&#039;&#039;&#039;&#039;&#039;-Individuals can learn to control the amplitude of EEG activity in specific frequency bands over sensorimotor cortex and use it to move a cursor to a target on a computer screen. For one-dimensional (i.e., vertical) cursor movement, a linear equation translates the EEG activity into cursor movement. To translate an individual&#039;s EEG control into cursor control as effectively as possible, the intercept in this equation, which determines whether upward or downward movement occurs, should be set so that top and bottom targets are equally accessible. The present study compares alternative methods for using an individual&#039;s previous performance to select the intercept for subsequent trials. In offline analyses, five different intercept selection methods were applied to EEG data collected while trained subjects were moving the cursor to targets at the top or bottom edge of the screen. In the first two methods-moving average, and weighted sum-a single intercept was selected for the entire 1-2 sec period of each trial. In the other three methods-blocked moving average, blocked weighted sum, and blocked recursive sum (a variation of the weighted sum)-an intercept was selected for each 200-ms segment of the trial. The results from these methods were compared in regard to their balance between upward and downward movements and their consistency of performance across trials. For all subjects combined, the five methods performed similarly. However, performance across subjects was more consistent for the moving average, blocked moving average, and blocked recursive sum methods than for the weighted sum and blocked weighted sum methods. Due to its consistent performance and its computational simplicity, the moving average method, using the five most recent pairs of top and bottom trials, appears to be the method of choice.&lt;br /&gt;
&lt;br /&gt;
===Adaptation Rationale===&lt;br /&gt;
It may appear crude to use the total data variance for the adaptation -- why not use linear regression on data labels (target codes) to separate into user controlled (task determined) and noise variance? User controlled variance would then correspond to target separation on the feedback screen, which is what we want to normalize in the first place.&lt;br /&gt;
&lt;br /&gt;
However, a closer look reveals that the &#039;&#039;relative size&#039;&#039; of user controlled variance, and noise variance is crucial. When that &amp;quot;signal&amp;quot; variance is small compared to noise variance, we would be ill advised to use it in normalization -- this would only lead to enlarged noise, and an erratically moving cursor on the feedback screen.&lt;br /&gt;
In this case, we rather want to normalize by noise variance, to keep the cursor well-behaved. At the same time, total variance approaches noise variance in this limit because signal variance is small.&lt;br /&gt;
&lt;br /&gt;
On the other end of the spectrum, we have a signal variance that is large compared to noise variance. Here, we clearly want normalization by signal variance. However, the total variance will be dominated by signal variance. Thus, in the limit of high signal-to-noise ratio, total variance again is the quantity by which we want to normalize.&lt;br /&gt;
&lt;br /&gt;
Thus, no matter whether signal-to-noise ratio is high or low, total data variance is a good choice for normalization.&lt;br /&gt;
&lt;br /&gt;
===Typical Use===&lt;br /&gt;
Typically, the Normalizer&#039;s input is the output of a classifier, which it transforms into a zero mean/unit variance control signal which is then transmitted to an application module.&lt;br /&gt;
Using the zero mean/unit variance property, an application module can then relate quantities such as window size, screen update rate, cursor speed, and trial duration.&lt;br /&gt;
&lt;br /&gt;
==Parameters==&lt;br /&gt;
For each channel of the Normalizer&#039;s input signal, adaptation is treated independently.&lt;br /&gt;
Offsets, Gains, and Adaptation kind are represented as list parameters, with each entry in the list corresponding to a signal channel.&lt;br /&gt;
Buffer configuration is done in matrix form, with columns corresponding to signal channels, and rows corresponding to multiple buffers.&lt;br /&gt;
&lt;br /&gt;
===NormalizerOffsets, NormalizerGains=== &lt;br /&gt;
Lists of offset and gain values, with entries corresponding to signal channels. These values will be updated depending on the channel&#039;s adaptation configuration in the Adaptation parameter.&lt;br /&gt;
===Adaptation===&lt;br /&gt;
A list of values that determines adaptation strategy individually for each channel. Possible values are&lt;br /&gt;
*0 for no adaptation,&lt;br /&gt;
*1 for adjusting offsets to zero mean,&lt;br /&gt;
*2 for additionally adjusting gains to unit variance.&lt;br /&gt;
===BufferConditions===&lt;br /&gt;
A matrix consisting of [[User Reference:Expression Syntax|boolean expressions]].&lt;br /&gt;
Expressions may involve [[BCI2000 Glossary#State|state variables]] and the components of the Normalizer&#039;s input signal.&lt;br /&gt;
*Each matrix entry represents a data buffer which is a ring buffer of length &#039;&#039;BufferLength.&#039;&#039; Whenever a buffer&#039;s expression evaluates to &#039;&#039;true,&#039;&#039; the current value of the input signal will be put into the buffer (overwriting its oldest data once the buffer is filled).&lt;br /&gt;
*Columns correspond to control signal channels. Buffers in a certain column will buffer data from the corresponding signal channel, and will be used in adaptation of that channel only.&lt;br /&gt;
*Within columns, the order of buffers does not affect computation.&lt;br /&gt;
*Empty expressions do not have any effect on the computation. Thus, it is possible to have a different number of buffers for different channels.&lt;br /&gt;
*A buffer to store data for the first target, and during feedback only, should have an expression such as &amp;lt;code&amp;gt;(Feedback)&amp;amp;&amp;amp;(TargetCode==1)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===BufferLength===&lt;br /&gt;
The maximum length of each data buffer.&lt;br /&gt;
*The length is specified in data blocks if given as a raw number, and in seconds if given as a number followed by the character &amp;quot;s&amp;quot;.&lt;br /&gt;
*All data buffers have the same capacity.&lt;br /&gt;
*Once a data buffer is filled, its older entries will be replaced with new data (ring buffer).&lt;br /&gt;
*In previous versions of BCI2000, buffer lengths were specified in terms of &amp;quot;past trials&amp;quot;. However, this would enforce the notion of a &amp;quot;trial&amp;quot;, and not generalize to continuous adaptation.&lt;br /&gt;
===UpdateTrigger===&lt;br /&gt;
A [[User Reference:Expression Syntax|boolean expression]] that triggers adaptation when changing to &#039;&#039;true&#039;&#039; from &#039;&#039;false&#039;&#039;.&lt;br /&gt;
Generally, continuous adaptation within trials is not desired. Rather, one wants adaptation to occur at the end of a trial. This is achieved with &#039;&#039;UpdateTrigger&#039;&#039; expressions such as &amp;lt;code&amp;gt;Feedback==0&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;TargetCode==0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For continuous adaptation, specify an empty string in the &#039;&#039;UpdateTrigger&#039;&#039; parameter.&lt;br /&gt;
&lt;br /&gt;
==States==&lt;br /&gt;
Buffer condition expressions, and the UpdateTrigger expression may involve any [[BCI2000 Glossary#State|state]] present in the system. Expressions are checked for syntactical correctness and whether referred-to states are present during the [[Technical Reference:States of Operation|Preflight Phase]].&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
===Trial-based 1D Feedback Task with 3 Targets===&lt;br /&gt;
*Only data from the feedback phase should enter into the adaptation.&lt;br /&gt;
*To make sure that targets contribute equally to the adaptation, we use a single buffer for each target. We use a 3-rows-by-1-column BufferConditions (see below).  Depending on which control signal should be adapted on, these conditions need to be entered in the first, second, or third column of the matrix (corresponding to x, y, and z direction when used with the [[User Reference:CursorTask|CursorTask]] application module).&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==1)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==2)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==3)&lt;br /&gt;
*We want to use data from three previous trials of each target. &lt;br /&gt;
*Feedback duration is 2 seconds. We set the buffer length to the equivalent of three feedback durations:&lt;br /&gt;
  BufferLength= 6s&lt;br /&gt;
*Adaptation should happen at the end of each trial, when feedback is finished. &amp;lt;p /&amp;gt;We set UpdateTrigger to an expression that changes to &#039;&#039;true&#039;&#039; when feedback ends:&lt;br /&gt;
  UpdateTrigger= (Feedback==0)&lt;br /&gt;
*To achieve continuous movement in, say, the x direction we need a constant normalizer output on that channel. To be consistent with the [[User Reference:CursorTask#FeedbackDuration|task module&#039;s FeedbackDuration parameter]], this output should be constant +2 in order for the cursor to cross the entire screen during a trial, and +1 when cursor movement begins at the screen&#039;s center. This corresponds to the following settings for the channel in question:&lt;br /&gt;
 Adaptation= 0&lt;br /&gt;
 NormalizerOffset= -1&lt;br /&gt;
 NormalizerGain= 1 or 2, respectively.&lt;br /&gt;
&lt;br /&gt;
===Trial-based 2D Feedback Task with 4 Targets===&lt;br /&gt;
*Leaving everything else as in the previous example, we now have two dimensions corresponding to left-right (channel 1) and up-down (channel 2).&lt;br /&gt;
:Target positions are as indicated below:&lt;br /&gt;
  ---------------------------&lt;br /&gt;
  |          ##1##          |&lt;br /&gt;
  |#                       #|&lt;br /&gt;
  |2                       3|&lt;br /&gt;
  |#                       #|&lt;br /&gt;
  |          ##4##          |&lt;br /&gt;
  ---------------------------&lt;br /&gt;
:We use data from targets 1 and 4 to adjust channel 2, and targets 2 and 3 to adjust channel 1. Accordingly, the BufferConditions matrix is&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==2) (Feedback)&amp;amp;&amp;amp;(TargetCode==1)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==3) (Feedback)&amp;amp;&amp;amp;(TargetCode==4)&lt;br /&gt;
&lt;br /&gt;
===Continuous 1D Control without pre-defined Targets===&lt;br /&gt;
*For this example, we know that, over a period of 10 minutes, all output values will occur with approximately equal frequency, or at least have a symmetric distribution around zero. This matches the combination of BCI2000 and Dasher or other &amp;quot;devices&amp;quot; expecting statistically balanced input.&lt;br /&gt;
:The BufferConditions matrix will have a single entry containing a constant expression:&lt;br /&gt;
 1&lt;br /&gt;
:This way, data will always be buffered.&lt;br /&gt;
*There are no trials. We want a continuous adaptation to the values of the last 10 minutes.&lt;br /&gt;
:We set the BufferLength parameter to &amp;lt;code&amp;gt;600s&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;(10*60)s&amp;lt;/code&amp;gt;.&lt;br /&gt;
:For continuous adaptation, we enter an &#039;&#039;empty string&#039;&#039; (not a constant 0 expression) for UpdateTrigger.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
[[User Reference:Expression Syntax]], [[BCI2000 Glossary#Control Signal]], [[User Reference:LinearClassifier]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Filters]][[Category:Signal Processing]]&lt;/div&gt;</summary>
		<author><name>Jhuggins</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=User_Reference:Normalizer&amp;diff=4914</id>
		<title>User Reference:Normalizer</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=User_Reference:Normalizer&amp;diff=4914"/>
		<updated>2009-03-03T04:54:12Z</updated>

		<summary type="html">&lt;p&gt;Jhuggins: /* Adaptation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Function==&lt;br /&gt;
===Normalizing Transform===&lt;br /&gt;
The Normalizer applies a linear transformation to its input signal.&lt;br /&gt;
For each channel (index denoted with &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;), an offset value is subtracted, and the result multiplied with a gain value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\textrm{output}_i=(\textrm{input}_i-\textrm{NormalizerOffset}_i)\times \textrm{NormalizerGain}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adaptation===&lt;br /&gt;
From the past statistics of its input, the Normalizer estimates offset and gain values adaptively to make its output signal&lt;br /&gt;
*zero mean, and&lt;br /&gt;
*unit variance.&lt;br /&gt;
The Normalizer uses &#039;&#039;data buffers&#039;&#039; to accumulate its past input according to user-defined rules.&lt;br /&gt;
These rules are called &#039;&#039;buffer conditions&#039;&#039; because they are given in terms of boolean expressions.&lt;br /&gt;
Each data buffer is associated with such a boolean expression. Whenever an expression evaluates to &#039;&#039;true&#039;&#039;, the current input will be appended to the associated buffer.&lt;br /&gt;
Whenever it comes to updating offset and gain values, the Normalizer will use the content of its buffers to estimate data mean and variance. The offset will then be set to the data mean, and the gain to the inverse square root of the data variance, i.e., the inverse of the data standard deviation.&lt;br /&gt;
&lt;br /&gt;
One may suggest that the adaptation time may affect the accuracy of the cursor movement in mu rhythm experiments. However, the following reference shows that computing the normalization parameters either during or at the end of the trials leaded to similar results. Hence, in the current version of bci2000, adaptation is accomplished at the end of each trial and using a Moving Average Algorithm.&lt;br /&gt;
&lt;br /&gt;
Ramoser H, Wolpaw JR, Pfurtscheller G, &amp;quot;EEG-based communication: evaluation of alternative signal prediction methods&amp;quot;. Biomed Tech (Berl); 42(9) : 226-33,  Sep, 1997.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Abstract&#039;&#039;&#039;&#039;&#039;-Individuals can learn to control the amplitude of EEG activity in specific frequency bands over sensorimotor cortex and use it to move a cursor to a target on a computer screen. For one-dimensional (i.e., vertical) cursor movement, a linear equation translates the EEG activity into cursor movement. To translate an individual&#039;s EEG control into cursor control as effectively as possible, the intercept in this equation, which determines whether upward or downward movement occurs, should be set so that top and bottom targets are equally accessible. The present study compares alternative methods for using an individual&#039;s previous performance to select the intercept for subsequent trials. In offline analyses, five different intercept selection methods were applied to EEG data collected while trained subjects were moving the cursor to targets at the top or bottom edge of the screen. In the first two methods-moving average, and weighted sum-a single intercept was selected for the entire 1-2 sec period of each trial. In the other three methods-blocked moving average, blocked weighted sum, and blocked recursive sum (a variation of the weighted sum)-an intercept was selected for each 200-ms segment of the trial. The results from these methods were compared in regard to their balance between upward and downward movements and their consistency of performance across trials. For all subjects combined, the five methods performed similarly. However, performance across subjects was more consistent for the moving average, blocked moving average, and blocked recursive sum methods than for the weighted sum and blocked weighted sum methods. Due to its consistent performance and its computational simplicity, the moving average method, using the five most recent pairs of top and bottom trials, appears to be the method of choice.&lt;br /&gt;
&lt;br /&gt;
===Adaptation Rationale===&lt;br /&gt;
It may appear crude to use the total data variance for the adaptation -- why not use linear regression on data labels (target codes) to separate into user controlled (task determined) and noise variance? User controlled variance would then correspond to target separation on the feedback screen, which is what we want to normalize in the first place.&lt;br /&gt;
&lt;br /&gt;
However, a closer look reveals that the &#039;&#039;relative size&#039;&#039; of user controlled variance, and noise variance is crucial. When that &amp;quot;signal&amp;quot; variance is small compared to noise variance, we would be ill advised to use it in normalization -- this would only lead to enlarged noise, and an erratically moving cursor on the feedback screen.&lt;br /&gt;
In this case, we rather want to normalize by noise variance, to keep the cursor well-behaved. At the same time, total variance approaches noise variance in this limit because signal variance is small.&lt;br /&gt;
&lt;br /&gt;
On the other end of the spectrum, we have a signal variance that is large compared to noise variance. Here, we clearly want normalization by signal variance. However, the total variance will be dominated by signal variance. Thus, in the limit of high signal-to-noise ratio, total variance again is the quantity by which we want to normalize.&lt;br /&gt;
&lt;br /&gt;
Thus, no matter whether signal-to-noise ratio is high or low, total data variance is a good choice for normalization.&lt;br /&gt;
&lt;br /&gt;
===Typical Use===&lt;br /&gt;
Typically, the Normalizer&#039;s input is the output of a classifier, which it transforms into a zero mean/unit variance control signal which is then transmitted to an application module.&lt;br /&gt;
Using the zero mean/unit variance property, an application module can then relate quantities such as window size, screen update rate, cursor speed, and trial duration.&lt;br /&gt;
&lt;br /&gt;
==Parameters==&lt;br /&gt;
For each channel of the Normalizer&#039;s input signal, adaptation is treated independently.&lt;br /&gt;
Offsets, Gains, and Adaptation kind are represented as list parameters, with each entry in the list corresponding to a signal channel.&lt;br /&gt;
Buffer configuration is done in matrix form, with columns corresponding to signal channels, and rows corresponding to multiple buffers.&lt;br /&gt;
&lt;br /&gt;
===NormalizerOffsets, NormalizerGains=== &lt;br /&gt;
Lists of offset and gain values, with entries corresponding to signal channels. These values will be updated depending on the channel&#039;s adaptation configuration in the Adaptation parameter.&lt;br /&gt;
===Adaptation===&lt;br /&gt;
A list of values that determines adaptation strategy individually for each channel. Possible values are&lt;br /&gt;
*0 for no adaptation,&lt;br /&gt;
*1 for adjusting offsets to zero mean,&lt;br /&gt;
*2 for additionally adjusting gains to unit variance.&lt;br /&gt;
===BufferConditions===&lt;br /&gt;
A matrix consisting of [[User Reference:Expression Syntax|boolean expressions]].&lt;br /&gt;
Expressions may involve [[BCI2000 Glossary#State|state variables]] and the components of the Normalizer&#039;s input signal.&lt;br /&gt;
*Each matrix entry represents a data buffer which is a ring buffer of length &#039;&#039;BufferLength.&#039;&#039; Whenever a buffer&#039;s expression evaluates to &#039;&#039;true,&#039;&#039; the current value of the input signal will be put into the buffer (overwriting its oldest data once the buffer is filled).&lt;br /&gt;
*Columns correspond to control signal channels. Buffers in a certain column will buffer data from the corresponding signal channel, and will be used in adaptation of that channel only.&lt;br /&gt;
*Within columns, the order of buffers does not affect computation.&lt;br /&gt;
*Empty expressions do not have any effect on the computation. Thus, it is possible to have a different number of buffers for different channels.&lt;br /&gt;
*A buffer to store data for the first target, and during feedback only, should have an expression such as &amp;lt;code&amp;gt;(Feedback)&amp;amp;&amp;amp;(TargetCode==1)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===BufferLength===&lt;br /&gt;
The maximum length of each data buffer.&lt;br /&gt;
*The length is specified in data blocks if given as a raw number, and in seconds if given as a number followed by the character &amp;quot;s&amp;quot;.&lt;br /&gt;
*All data buffers have the same capacity.&lt;br /&gt;
*Once a data buffer is filled, its older entries will be replaced with new data (ring buffer).&lt;br /&gt;
*In previous versions of BCI2000, buffer lengths were specified in terms of &amp;quot;past trials&amp;quot;. However, this would enforce the notion of a &amp;quot;trial&amp;quot;, and not generalize to continuous adaptation.&lt;br /&gt;
===UpdateTrigger===&lt;br /&gt;
A [[User Reference:Expression Syntax|boolean expression]] that triggers adaptation when changing to &#039;&#039;true&#039;&#039; from &#039;&#039;false&#039;&#039;.&lt;br /&gt;
Generally, continuous adaptation within trials is not desired. Rather, one wants adaptation to occur at the end of a trial. This is achieved with &#039;&#039;UpdateTrigger&#039;&#039; expressions such as &amp;lt;code&amp;gt;Feedback==0&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;TargetCode==0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For continuous adaptation, specify an empty string in the &#039;&#039;UpdateTrigger&#039;&#039; parameter.&lt;br /&gt;
&lt;br /&gt;
==States==&lt;br /&gt;
Buffer condition expressions, and the UpdateTrigger expression may involve any [[BCI2000 Glossary#State|state]] present in the system. Expressions are checked for syntactical correctness and whether referred-to states are present during the [[Technical Reference:States of Operation|Preflight Phase]].&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
===Trial-based 1D Feedback Task with 3 Targets===&lt;br /&gt;
*Only data from the feedback phase should enter into the adaptation.&lt;br /&gt;
*To make sure that targets contribute equally to the adaptation, we use a single buffer for each target. We use a 3-rows-by-1-column BufferConditions (see below).  Depending on which control signal should be adapted on, these conditions need to be entered in the first, second, or third column of the matrix (corresponding to x, y, and z direction when used with the [[User Reference:CursorTask|CursorTask]] application module).&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==1)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==2)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==3)&lt;br /&gt;
*We want to use data from three previous trials of each target. &lt;br /&gt;
*Feedback duration is 2 seconds. We set the buffer length to the equivalent of three feedback durations:&lt;br /&gt;
  BufferLength= 6s&lt;br /&gt;
*Adaptation should happen at the end of each trial, when feedback is finished. &amp;lt;p /&amp;gt;We set UpdateTrigger to an expression that changes to &#039;&#039;true&#039;&#039; when feedback ends:&lt;br /&gt;
  UpdateTrigger= (Feedback==0)&lt;br /&gt;
*To achieve continuous movement in, say, the x direction we need a constant normalizer output on that channel. To be consistent with the [[User Reference:CursorTask#FeedbackDuration|task module&#039;s FeedbackDuration parameter]], this output should be constant +2 in order for the cursor to cross the entire screen during a trial, and +1 when cursor movement begins at the screen&#039;s center. This corresponds to the following settings for the channel in question:&lt;br /&gt;
 Adaptation= 0&lt;br /&gt;
 NormalizerOffset= -1&lt;br /&gt;
 NormalizerGain= 1 or 2, respectively.&lt;br /&gt;
&lt;br /&gt;
===Trial-based 2D Feedback Task with 4 Targets===&lt;br /&gt;
*Leaving everything else as in the previous example, we now have two dimensions corresponding to left-right (channel 1) and up-down (channel 2).&lt;br /&gt;
:Target positions are as indicated below:&lt;br /&gt;
  ---------------------------&lt;br /&gt;
  |          ##1##          |&lt;br /&gt;
  |#                       #|&lt;br /&gt;
  |2                       3|&lt;br /&gt;
  |#                       #|&lt;br /&gt;
  |          ##4##          |&lt;br /&gt;
  ---------------------------&lt;br /&gt;
:We use data from targets 1 and 4 to adjust channel 2, and targets 2 and 3 to adjust channel 1. Accordingly, the BufferConditions matrix is&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==2) (Feedback)&amp;amp;&amp;amp;(TargetCode==1)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==3) (Feedback)&amp;amp;&amp;amp;(TargetCode==4)&lt;br /&gt;
&lt;br /&gt;
===Continuous 1D Control without pre-defined Targets===&lt;br /&gt;
*For this example, we know that, over a period of 10 minutes, all output values will occur with approximately equal frequency, or at least have a symmetric distribution around zero. This matches the combination of BCI2000 and Dasher or other &amp;quot;devices&amp;quot; expecting statistically balanced input.&lt;br /&gt;
:The BufferConditions matrix will have a single entry containing a constant expression:&lt;br /&gt;
 1&lt;br /&gt;
:This way, data will always be buffered.&lt;br /&gt;
*There are no trials. We want a continuous adaptation to the values of the last 10 minutes.&lt;br /&gt;
:We set the BufferLength parameter to &amp;lt;code&amp;gt;600s&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;(10*60)s&amp;lt;/code&amp;gt;.&lt;br /&gt;
:For continuous adaptation, we enter an &#039;&#039;empty string&#039;&#039; (not a constant 0 expression) for UpdateTrigger.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
[[User Reference:Expression Syntax]], [[BCI2000 Glossary#Control Signal]], [[User Reference:LinearClassifier]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Filters]][[Category:Signal Processing]]&lt;/div&gt;</summary>
		<author><name>Jhuggins</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=User_Reference:Normalizer&amp;diff=4913</id>
		<title>User Reference:Normalizer</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=User_Reference:Normalizer&amp;diff=4913"/>
		<updated>2009-03-03T04:53:21Z</updated>

		<summary type="html">&lt;p&gt;Jhuggins: /* Adaptation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Function==&lt;br /&gt;
===Normalizing Transform===&lt;br /&gt;
The Normalizer applies a linear transformation to its input signal.&lt;br /&gt;
For each channel (index denoted with &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;), an offset value is subtracted, and the result multiplied with a gain value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\textrm{output}_i=(\textrm{input}_i-\textrm{NormalizerOffset}_i)\times \textrm{NormalizerGain}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adaptation===&lt;br /&gt;
From the past statistics of its input, the Normalizer estimates offset and gain values adaptively to make its output signal&lt;br /&gt;
*zero mean, and&lt;br /&gt;
*unit variance.&lt;br /&gt;
The Normalizer uses &#039;&#039;data buffers&#039;&#039; to accumulate its past input according to user-defined rules.&lt;br /&gt;
These rules are called &#039;&#039;buffer conditions&#039;&#039; because they are given in terms of boolean expressions.&lt;br /&gt;
Each data buffer is associated with such a boolean expression. Whenever an expression evaluates to &#039;&#039;true&#039;&#039;, the current input will be appended to the associated buffer.&lt;br /&gt;
Whenever it comes to updating offset and gain values, the Normalizer will use the content of its buffers to estimate data mean and variance. The offset will then be set to the data mean, and the gain to the inverse square root of the data variance, i.e., the inverse of the data standard deviation.&lt;br /&gt;
&lt;br /&gt;
One may suggest that the adaptation time may affect the accuracy of the cursor movement in mu rhythm experiments. However, the following reference shows that computing the normalization parameters either during or at the end of the trials leaded to similar results. Hence, in the current version of bci2000, adaptation is accomplished at the end of each trial and using a Moving Average Algorithm.&lt;br /&gt;
&lt;br /&gt;
Ramoser H, Wolpaw JR, Pfurtscheller G, &amp;quot;EEG-based communication: evaluation of alternative signal prediction methods&amp;quot;. Biomed Tech (Berl); 42(9) : 226-33,  Sep, 1997.&lt;br /&gt;
&lt;br /&gt;
Individuals can learn to control the amplitude of EEG activity in specific frequency bands over sensorimotor cortex and use it to move a cursor to a target on a computer screen. For one-dimensional (i.e., vertical) cursor movement, a linear equation translates the EEG activity into cursor movement. To translate an individual&#039;s EEG control into cursor control as effectively as possible, the intercept in this equation, which determines whether upward or downward movement occurs, should be set so that top and bottom targets are equally accessible. The present study compares alternative methods for using an individual&#039;s previous performance to select the intercept for subsequent trials. In offline analyses, five different intercept selection methods were applied to EEG data collected while trained subjects were moving the cursor to targets at the top or bottom edge of the screen. In the first two methods-moving average, and weighted sum-a single intercept was selected for the entire 1-2 sec period of each trial. In the other three methods-blocked moving average, blocked weighted sum, and blocked recursive sum (a variation of the weighted sum)-an intercept was selected for each 200-ms segment of the trial. The results from these methods were compared in regard to their balance between upward and downward movements and their consistency of performance across trials. For all subjects combined, the five methods performed similarly. However, performance across subjects was more consistent for the moving average, blocked moving average, and blocked recursive sum methods than for the weighted sum and blocked weighted sum methods. Due to its consistent performance and its computational simplicity, the moving average method, using the five most recent pairs of top and bottom trials, appears to be the method of choice.&lt;br /&gt;
&lt;br /&gt;
===Adaptation Rationale===&lt;br /&gt;
It may appear crude to use the total data variance for the adaptation -- why not use linear regression on data labels (target codes) to separate into user controlled (task determined) and noise variance? User controlled variance would then correspond to target separation on the feedback screen, which is what we want to normalize in the first place.&lt;br /&gt;
&lt;br /&gt;
However, a closer look reveals that the &#039;&#039;relative size&#039;&#039; of user controlled variance, and noise variance is crucial. When that &amp;quot;signal&amp;quot; variance is small compared to noise variance, we would be ill advised to use it in normalization -- this would only lead to enlarged noise, and an erratically moving cursor on the feedback screen.&lt;br /&gt;
In this case, we rather want to normalize by noise variance, to keep the cursor well-behaved. At the same time, total variance approaches noise variance in this limit because signal variance is small.&lt;br /&gt;
&lt;br /&gt;
On the other end of the spectrum, we have a signal variance that is large compared to noise variance. Here, we clearly want normalization by signal variance. However, the total variance will be dominated by signal variance. Thus, in the limit of high signal-to-noise ratio, total variance again is the quantity by which we want to normalize.&lt;br /&gt;
&lt;br /&gt;
Thus, no matter whether signal-to-noise ratio is high or low, total data variance is a good choice for normalization.&lt;br /&gt;
&lt;br /&gt;
===Typical Use===&lt;br /&gt;
Typically, the Normalizer&#039;s input is the output of a classifier, which it transforms into a zero mean/unit variance control signal which is then transmitted to an application module.&lt;br /&gt;
Using the zero mean/unit variance property, an application module can then relate quantities such as window size, screen update rate, cursor speed, and trial duration.&lt;br /&gt;
&lt;br /&gt;
==Parameters==&lt;br /&gt;
For each channel of the Normalizer&#039;s input signal, adaptation is treated independently.&lt;br /&gt;
Offsets, Gains, and Adaptation kind are represented as list parameters, with each entry in the list corresponding to a signal channel.&lt;br /&gt;
Buffer configuration is done in matrix form, with columns corresponding to signal channels, and rows corresponding to multiple buffers.&lt;br /&gt;
&lt;br /&gt;
===NormalizerOffsets, NormalizerGains=== &lt;br /&gt;
Lists of offset and gain values, with entries corresponding to signal channels. These values will be updated depending on the channel&#039;s adaptation configuration in the Adaptation parameter.&lt;br /&gt;
===Adaptation===&lt;br /&gt;
A list of values that determines adaptation strategy individually for each channel. Possible values are&lt;br /&gt;
*0 for no adaptation,&lt;br /&gt;
*1 for adjusting offsets to zero mean,&lt;br /&gt;
*2 for additionally adjusting gains to unit variance.&lt;br /&gt;
===BufferConditions===&lt;br /&gt;
A matrix consisting of [[User Reference:Expression Syntax|boolean expressions]].&lt;br /&gt;
Expressions may involve [[BCI2000 Glossary#State|state variables]] and the components of the Normalizer&#039;s input signal.&lt;br /&gt;
*Each matrix entry represents a data buffer which is a ring buffer of length &#039;&#039;BufferLength.&#039;&#039; Whenever a buffer&#039;s expression evaluates to &#039;&#039;true,&#039;&#039; the current value of the input signal will be put into the buffer (overwriting its oldest data once the buffer is filled).&lt;br /&gt;
*Columns correspond to control signal channels. Buffers in a certain column will buffer data from the corresponding signal channel, and will be used in adaptation of that channel only.&lt;br /&gt;
*Within columns, the order of buffers does not affect computation.&lt;br /&gt;
*Empty expressions do not have any effect on the computation. Thus, it is possible to have a different number of buffers for different channels.&lt;br /&gt;
*A buffer to store data for the first target, and during feedback only, should have an expression such as &amp;lt;code&amp;gt;(Feedback)&amp;amp;&amp;amp;(TargetCode==1)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===BufferLength===&lt;br /&gt;
The maximum length of each data buffer.&lt;br /&gt;
*The length is specified in data blocks if given as a raw number, and in seconds if given as a number followed by the character &amp;quot;s&amp;quot;.&lt;br /&gt;
*All data buffers have the same capacity.&lt;br /&gt;
*Once a data buffer is filled, its older entries will be replaced with new data (ring buffer).&lt;br /&gt;
*In previous versions of BCI2000, buffer lengths were specified in terms of &amp;quot;past trials&amp;quot;. However, this would enforce the notion of a &amp;quot;trial&amp;quot;, and not generalize to continuous adaptation.&lt;br /&gt;
===UpdateTrigger===&lt;br /&gt;
A [[User Reference:Expression Syntax|boolean expression]] that triggers adaptation when changing to &#039;&#039;true&#039;&#039; from &#039;&#039;false&#039;&#039;.&lt;br /&gt;
Generally, continuous adaptation within trials is not desired. Rather, one wants adaptation to occur at the end of a trial. This is achieved with &#039;&#039;UpdateTrigger&#039;&#039; expressions such as &amp;lt;code&amp;gt;Feedback==0&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;TargetCode==0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For continuous adaptation, specify an empty string in the &#039;&#039;UpdateTrigger&#039;&#039; parameter.&lt;br /&gt;
&lt;br /&gt;
==States==&lt;br /&gt;
Buffer condition expressions, and the UpdateTrigger expression may involve any [[BCI2000 Glossary#State|state]] present in the system. Expressions are checked for syntactical correctness and whether referred-to states are present during the [[Technical Reference:States of Operation|Preflight Phase]].&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
===Trial-based 1D Feedback Task with 3 Targets===&lt;br /&gt;
*Only data from the feedback phase should enter into the adaptation.&lt;br /&gt;
*To make sure that targets contribute equally to the adaptation, we use a single buffer for each target. We use a 3-rows-by-1-column BufferConditions (see below).  Depending on which control signal should be adapted on, these conditions need to be entered in the first, second, or third column of the matrix (corresponding to x, y, and z direction when used with the [[User Reference:CursorTask|CursorTask]] application module).&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==1)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==2)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==3)&lt;br /&gt;
*We want to use data from three previous trials of each target. &lt;br /&gt;
*Feedback duration is 2 seconds. We set the buffer length to the equivalent of three feedback durations:&lt;br /&gt;
  BufferLength= 6s&lt;br /&gt;
*Adaptation should happen at the end of each trial, when feedback is finished. &amp;lt;p /&amp;gt;We set UpdateTrigger to an expression that changes to &#039;&#039;true&#039;&#039; when feedback ends:&lt;br /&gt;
  UpdateTrigger= (Feedback==0)&lt;br /&gt;
*To achieve continuous movement in, say, the x direction we need a constant normalizer output on that channel. To be consistent with the [[User Reference:CursorTask#FeedbackDuration|task module&#039;s FeedbackDuration parameter]], this output should be constant +2 in order for the cursor to cross the entire screen during a trial, and +1 when cursor movement begins at the screen&#039;s center. This corresponds to the following settings for the channel in question:&lt;br /&gt;
 Adaptation= 0&lt;br /&gt;
 NormalizerOffset= -1&lt;br /&gt;
 NormalizerGain= 1 or 2, respectively.&lt;br /&gt;
&lt;br /&gt;
===Trial-based 2D Feedback Task with 4 Targets===&lt;br /&gt;
*Leaving everything else as in the previous example, we now have two dimensions corresponding to left-right (channel 1) and up-down (channel 2).&lt;br /&gt;
:Target positions are as indicated below:&lt;br /&gt;
  ---------------------------&lt;br /&gt;
  |          ##1##          |&lt;br /&gt;
  |#                       #|&lt;br /&gt;
  |2                       3|&lt;br /&gt;
  |#                       #|&lt;br /&gt;
  |          ##4##          |&lt;br /&gt;
  ---------------------------&lt;br /&gt;
:We use data from targets 1 and 4 to adjust channel 2, and targets 2 and 3 to adjust channel 1. Accordingly, the BufferConditions matrix is&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==2) (Feedback)&amp;amp;&amp;amp;(TargetCode==1)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==3) (Feedback)&amp;amp;&amp;amp;(TargetCode==4)&lt;br /&gt;
&lt;br /&gt;
===Continuous 1D Control without pre-defined Targets===&lt;br /&gt;
*For this example, we know that, over a period of 10 minutes, all output values will occur with approximately equal frequency, or at least have a symmetric distribution around zero. This matches the combination of BCI2000 and Dasher or other &amp;quot;devices&amp;quot; expecting statistically balanced input.&lt;br /&gt;
:The BufferConditions matrix will have a single entry containing a constant expression:&lt;br /&gt;
 1&lt;br /&gt;
:This way, data will always be buffered.&lt;br /&gt;
*There are no trials. We want a continuous adaptation to the values of the last 10 minutes.&lt;br /&gt;
:We set the BufferLength parameter to &amp;lt;code&amp;gt;600s&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;(10*60)s&amp;lt;/code&amp;gt;.&lt;br /&gt;
:For continuous adaptation, we enter an &#039;&#039;empty string&#039;&#039; (not a constant 0 expression) for UpdateTrigger.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
[[User Reference:Expression Syntax]], [[BCI2000 Glossary#Control Signal]], [[User Reference:LinearClassifier]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Filters]][[Category:Signal Processing]]&lt;/div&gt;</summary>
		<author><name>Jhuggins</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=User_Reference:Normalizer&amp;diff=4912</id>
		<title>User Reference:Normalizer</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=User_Reference:Normalizer&amp;diff=4912"/>
		<updated>2009-03-03T04:52:15Z</updated>

		<summary type="html">&lt;p&gt;Jhuggins: /* Adaptation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Function==&lt;br /&gt;
===Normalizing Transform===&lt;br /&gt;
The Normalizer applies a linear transformation to its input signal.&lt;br /&gt;
For each channel (index denoted with &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;), an offset value is subtracted, and the result multiplied with a gain value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\textrm{output}_i=(\textrm{input}_i-\textrm{NormalizerOffset}_i)\times \textrm{NormalizerGain}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adaptation===&lt;br /&gt;
From the past statistics of its input, the Normalizer estimates offset and gain values adaptively to make its output signal&lt;br /&gt;
*zero mean, and&lt;br /&gt;
*unit variance.&lt;br /&gt;
The Normalizer uses &#039;&#039;data buffers&#039;&#039; to accumulate its past input according to user-defined rules.&lt;br /&gt;
These rules are called &#039;&#039;buffer conditions&#039;&#039; because they are given in terms of boolean expressions.&lt;br /&gt;
Each data buffer is associated with such a boolean expression. Whenever an expression evaluates to &#039;&#039;true&#039;&#039;, the current input will be appended to the associated buffer.&lt;br /&gt;
Whenever it comes to updating offset and gain values, the Normalizer will use the content of its buffers to estimate data mean and variance. The offset will then be set to the data mean, and the gain to the inverse square root of the data variance, i.e., the inverse of the data standard deviation.&lt;br /&gt;
&lt;br /&gt;
One may suggest that the adaptation time may affect the accuracy of the cursor movement in mu rhythm experiments. However, the following reference shows that computing the normalization parameters either during or at the end of the trials leaded to similar results. Hence, in the current version of bci2000, adaptation is accomplished at the end of each trial and using a Moving Average Algorithm.&lt;br /&gt;
&lt;br /&gt;
Ramoser H, Wolpaw JR, Pfurtscheller G,&lt;br /&gt;
&lt;br /&gt;
EEG-based communication: evaluation of alternative signal prediction methods.&lt;br /&gt;
&lt;br /&gt;
Biomed Tech (Berl). 1997 Sep;42(9):226-33.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Individuals can learn to control the amplitude of EEG activity in specific frequency bands over sensorimotor cortex and use it to move a cursor to a target on a computer screen. For one-dimensional (i.e., vertical) cursor movement, a linear equation translates the EEG activity into cursor movement. To translate an individual&#039;s EEG control into cursor control as effectively as possible, the intercept in this equation, which determines whether upward or downward movement occurs, should be set so that top and bottom targets are equally accessible. The present study compares alternative methods for using an individual&#039;s previous performance to select the intercept for subsequent trials. In offline analyses, five different intercept selection methods were applied to EEG data collected while trained subjects were moving the cursor to targets at the top or bottom edge of the screen. In the first two methods-moving average, and weighted sum-a single intercept was selected for the entire 1-2 sec period of each trial. In the other three methods-blocked moving average, blocked weighted sum, and blocked recursive sum (a variation of the weighted sum)-an intercept was selected for each 200-ms segment of the trial. The results from these methods were compared in regard to their balance between upward and downward movements and their consistency of performance across trials. For all subjects combined, the five methods performed similarly. However, performance across subjects was more consistent for the moving average, blocked moving average, and blocked recursive sum methods than for the weighted sum and blocked weighted sum methods. Due to its consistent performance and its computational simplicity, the moving average method, using the five most recent pairs of top and bottom trials, appears to be the method of choice.&lt;br /&gt;
&lt;br /&gt;
===Adaptation Rationale===&lt;br /&gt;
It may appear crude to use the total data variance for the adaptation -- why not use linear regression on data labels (target codes) to separate into user controlled (task determined) and noise variance? User controlled variance would then correspond to target separation on the feedback screen, which is what we want to normalize in the first place.&lt;br /&gt;
&lt;br /&gt;
However, a closer look reveals that the &#039;&#039;relative size&#039;&#039; of user controlled variance, and noise variance is crucial. When that &amp;quot;signal&amp;quot; variance is small compared to noise variance, we would be ill advised to use it in normalization -- this would only lead to enlarged noise, and an erratically moving cursor on the feedback screen.&lt;br /&gt;
In this case, we rather want to normalize by noise variance, to keep the cursor well-behaved. At the same time, total variance approaches noise variance in this limit because signal variance is small.&lt;br /&gt;
&lt;br /&gt;
On the other end of the spectrum, we have a signal variance that is large compared to noise variance. Here, we clearly want normalization by signal variance. However, the total variance will be dominated by signal variance. Thus, in the limit of high signal-to-noise ratio, total variance again is the quantity by which we want to normalize.&lt;br /&gt;
&lt;br /&gt;
Thus, no matter whether signal-to-noise ratio is high or low, total data variance is a good choice for normalization.&lt;br /&gt;
&lt;br /&gt;
===Typical Use===&lt;br /&gt;
Typically, the Normalizer&#039;s input is the output of a classifier, which it transforms into a zero mean/unit variance control signal which is then transmitted to an application module.&lt;br /&gt;
Using the zero mean/unit variance property, an application module can then relate quantities such as window size, screen update rate, cursor speed, and trial duration.&lt;br /&gt;
&lt;br /&gt;
==Parameters==&lt;br /&gt;
For each channel of the Normalizer&#039;s input signal, adaptation is treated independently.&lt;br /&gt;
Offsets, Gains, and Adaptation kind are represented as list parameters, with each entry in the list corresponding to a signal channel.&lt;br /&gt;
Buffer configuration is done in matrix form, with columns corresponding to signal channels, and rows corresponding to multiple buffers.&lt;br /&gt;
&lt;br /&gt;
===NormalizerOffsets, NormalizerGains=== &lt;br /&gt;
Lists of offset and gain values, with entries corresponding to signal channels. These values will be updated depending on the channel&#039;s adaptation configuration in the Adaptation parameter.&lt;br /&gt;
===Adaptation===&lt;br /&gt;
A list of values that determines adaptation strategy individually for each channel. Possible values are&lt;br /&gt;
*0 for no adaptation,&lt;br /&gt;
*1 for adjusting offsets to zero mean,&lt;br /&gt;
*2 for additionally adjusting gains to unit variance.&lt;br /&gt;
===BufferConditions===&lt;br /&gt;
A matrix consisting of [[User Reference:Expression Syntax|boolean expressions]].&lt;br /&gt;
Expressions may involve [[BCI2000 Glossary#State|state variables]] and the components of the Normalizer&#039;s input signal.&lt;br /&gt;
*Each matrix entry represents a data buffer which is a ring buffer of length &#039;&#039;BufferLength.&#039;&#039; Whenever a buffer&#039;s expression evaluates to &#039;&#039;true,&#039;&#039; the current value of the input signal will be put into the buffer (overwriting its oldest data once the buffer is filled).&lt;br /&gt;
*Columns correspond to control signal channels. Buffers in a certain column will buffer data from the corresponding signal channel, and will be used in adaptation of that channel only.&lt;br /&gt;
*Within columns, the order of buffers does not affect computation.&lt;br /&gt;
*Empty expressions do not have any effect on the computation. Thus, it is possible to have a different number of buffers for different channels.&lt;br /&gt;
*A buffer to store data for the first target, and during feedback only, should have an expression such as &amp;lt;code&amp;gt;(Feedback)&amp;amp;&amp;amp;(TargetCode==1)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===BufferLength===&lt;br /&gt;
The maximum length of each data buffer.&lt;br /&gt;
*The length is specified in data blocks if given as a raw number, and in seconds if given as a number followed by the character &amp;quot;s&amp;quot;.&lt;br /&gt;
*All data buffers have the same capacity.&lt;br /&gt;
*Once a data buffer is filled, its older entries will be replaced with new data (ring buffer).&lt;br /&gt;
*In previous versions of BCI2000, buffer lengths were specified in terms of &amp;quot;past trials&amp;quot;. However, this would enforce the notion of a &amp;quot;trial&amp;quot;, and not generalize to continuous adaptation.&lt;br /&gt;
===UpdateTrigger===&lt;br /&gt;
A [[User Reference:Expression Syntax|boolean expression]] that triggers adaptation when changing to &#039;&#039;true&#039;&#039; from &#039;&#039;false&#039;&#039;.&lt;br /&gt;
Generally, continuous adaptation within trials is not desired. Rather, one wants adaptation to occur at the end of a trial. This is achieved with &#039;&#039;UpdateTrigger&#039;&#039; expressions such as &amp;lt;code&amp;gt;Feedback==0&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;TargetCode==0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For continuous adaptation, specify an empty string in the &#039;&#039;UpdateTrigger&#039;&#039; parameter.&lt;br /&gt;
&lt;br /&gt;
==States==&lt;br /&gt;
Buffer condition expressions, and the UpdateTrigger expression may involve any [[BCI2000 Glossary#State|state]] present in the system. Expressions are checked for syntactical correctness and whether referred-to states are present during the [[Technical Reference:States of Operation|Preflight Phase]].&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
===Trial-based 1D Feedback Task with 3 Targets===&lt;br /&gt;
*Only data from the feedback phase should enter into the adaptation.&lt;br /&gt;
*To make sure that targets contribute equally to the adaptation, we use a single buffer for each target. We use a 3-rows-by-1-column BufferConditions (see below).  Depending on which control signal should be adapted on, these conditions need to be entered in the first, second, or third column of the matrix (corresponding to x, y, and z direction when used with the [[User Reference:CursorTask|CursorTask]] application module).&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==1)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==2)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==3)&lt;br /&gt;
*We want to use data from three previous trials of each target. &lt;br /&gt;
*Feedback duration is 2 seconds. We set the buffer length to the equivalent of three feedback durations:&lt;br /&gt;
  BufferLength= 6s&lt;br /&gt;
*Adaptation should happen at the end of each trial, when feedback is finished. &amp;lt;p /&amp;gt;We set UpdateTrigger to an expression that changes to &#039;&#039;true&#039;&#039; when feedback ends:&lt;br /&gt;
  UpdateTrigger= (Feedback==0)&lt;br /&gt;
*To achieve continuous movement in, say, the x direction we need a constant normalizer output on that channel. To be consistent with the [[User Reference:CursorTask#FeedbackDuration|task module&#039;s FeedbackDuration parameter]], this output should be constant +2 in order for the cursor to cross the entire screen during a trial, and +1 when cursor movement begins at the screen&#039;s center. This corresponds to the following settings for the channel in question:&lt;br /&gt;
 Adaptation= 0&lt;br /&gt;
 NormalizerOffset= -1&lt;br /&gt;
 NormalizerGain= 1 or 2, respectively.&lt;br /&gt;
&lt;br /&gt;
===Trial-based 2D Feedback Task with 4 Targets===&lt;br /&gt;
*Leaving everything else as in the previous example, we now have two dimensions corresponding to left-right (channel 1) and up-down (channel 2).&lt;br /&gt;
:Target positions are as indicated below:&lt;br /&gt;
  ---------------------------&lt;br /&gt;
  |          ##1##          |&lt;br /&gt;
  |#                       #|&lt;br /&gt;
  |2                       3|&lt;br /&gt;
  |#                       #|&lt;br /&gt;
  |          ##4##          |&lt;br /&gt;
  ---------------------------&lt;br /&gt;
:We use data from targets 1 and 4 to adjust channel 2, and targets 2 and 3 to adjust channel 1. Accordingly, the BufferConditions matrix is&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==2) (Feedback)&amp;amp;&amp;amp;(TargetCode==1)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==3) (Feedback)&amp;amp;&amp;amp;(TargetCode==4)&lt;br /&gt;
&lt;br /&gt;
===Continuous 1D Control without pre-defined Targets===&lt;br /&gt;
*For this example, we know that, over a period of 10 minutes, all output values will occur with approximately equal frequency, or at least have a symmetric distribution around zero. This matches the combination of BCI2000 and Dasher or other &amp;quot;devices&amp;quot; expecting statistically balanced input.&lt;br /&gt;
:The BufferConditions matrix will have a single entry containing a constant expression:&lt;br /&gt;
 1&lt;br /&gt;
:This way, data will always be buffered.&lt;br /&gt;
*There are no trials. We want a continuous adaptation to the values of the last 10 minutes.&lt;br /&gt;
:We set the BufferLength parameter to &amp;lt;code&amp;gt;600s&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;(10*60)s&amp;lt;/code&amp;gt;.&lt;br /&gt;
:For continuous adaptation, we enter an &#039;&#039;empty string&#039;&#039; (not a constant 0 expression) for UpdateTrigger.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
[[User Reference:Expression Syntax]], [[BCI2000 Glossary#Control Signal]], [[User Reference:LinearClassifier]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Filters]][[Category:Signal Processing]]&lt;/div&gt;</summary>
		<author><name>Jhuggins</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=User_Reference:Normalizer&amp;diff=4911</id>
		<title>User Reference:Normalizer</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=User_Reference:Normalizer&amp;diff=4911"/>
		<updated>2009-03-03T04:51:50Z</updated>

		<summary type="html">&lt;p&gt;Jhuggins: /* Adaptation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Function==&lt;br /&gt;
===Normalizing Transform===&lt;br /&gt;
The Normalizer applies a linear transformation to its input signal.&lt;br /&gt;
For each channel (index denoted with &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;), an offset value is subtracted, and the result multiplied with a gain value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\textrm{output}_i=(\textrm{input}_i-\textrm{NormalizerOffset}_i)\times \textrm{NormalizerGain}_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adaptation===&lt;br /&gt;
From the past statistics of its input, the Normalizer estimates offset and gain values adaptively to make its output signal&lt;br /&gt;
*zero mean, and&lt;br /&gt;
*unit variance.&lt;br /&gt;
The Normalizer uses &#039;&#039;data buffers&#039;&#039; to accumulate its past input according to user-defined rules.&lt;br /&gt;
These rules are called &#039;&#039;buffer conditions&#039;&#039; because they are given in terms of boolean expressions.&lt;br /&gt;
Each data buffer is associated with such a boolean expression. Whenever an expression evaluates to &#039;&#039;true&#039;&#039;, the current input will be appended to the associated buffer.&lt;br /&gt;
Whenever it comes to updating offset and gain values, the Normalizer will use the content of its buffers to estimate data mean and variance. The offset will then be set to the data mean, and the gain to the inverse square root of the data variance, i.e., the inverse of the data standard deviation.&lt;br /&gt;
&lt;br /&gt;
One may suggest that the adaptation time may affect the accuracy of the cursor movement in mu rhythm experiments. However, the following reference shows that computing the normalization parameters either during or at the end of the trials leaded to similar results. Hence, in the current version of bci2000, adaptation is accomplished at the end of each trial and using a Moving Average Algorithm.&lt;br /&gt;
&lt;br /&gt;
Ramoser H, Wolpaw JR, Pfurtscheller G,&lt;br /&gt;
EEG-based communication: evaluation of alternative signal prediction methods.&lt;br /&gt;
Biomed Tech (Berl). 1997 Sep;42(9):226-33.&lt;br /&gt;
&lt;br /&gt;
Individuals can learn to control the amplitude of EEG activity in specific frequency bands over sensorimotor cortex and use it to move a cursor to a target on a computer screen. For one-dimensional (i.e., vertical) cursor movement, a linear equation translates the EEG activity into cursor movement. To translate an individual&#039;s EEG control into cursor control as effectively as possible, the intercept in this equation, which determines whether upward or downward movement occurs, should be set so that top and bottom targets are equally accessible. The present study compares alternative methods for using an individual&#039;s previous performance to select the intercept for subsequent trials. In offline analyses, five different intercept selection methods were applied to EEG data collected while trained subjects were moving the cursor to targets at the top or bottom edge of the screen. In the first two methods-moving average, and weighted sum-a single intercept was selected for the entire 1-2 sec period of each trial. In the other three methods-blocked moving average, blocked weighted sum, and blocked recursive sum (a variation of the weighted sum)-an intercept was selected for each 200-ms segment of the trial. The results from these methods were compared in regard to their balance between upward and downward movements and their consistency of performance across trials. For all subjects combined, the five methods performed similarly. However, performance across subjects was more consistent for the moving average, blocked moving average, and blocked recursive sum methods than for the weighted sum and blocked weighted sum methods. Due to its consistent performance and its computational simplicity, the moving average method, using the five most recent pairs of top and bottom trials, appears to be the method of choice.&lt;br /&gt;
&lt;br /&gt;
===Adaptation Rationale===&lt;br /&gt;
It may appear crude to use the total data variance for the adaptation -- why not use linear regression on data labels (target codes) to separate into user controlled (task determined) and noise variance? User controlled variance would then correspond to target separation on the feedback screen, which is what we want to normalize in the first place.&lt;br /&gt;
&lt;br /&gt;
However, a closer look reveals that the &#039;&#039;relative size&#039;&#039; of user controlled variance, and noise variance is crucial. When that &amp;quot;signal&amp;quot; variance is small compared to noise variance, we would be ill advised to use it in normalization -- this would only lead to enlarged noise, and an erratically moving cursor on the feedback screen.&lt;br /&gt;
In this case, we rather want to normalize by noise variance, to keep the cursor well-behaved. At the same time, total variance approaches noise variance in this limit because signal variance is small.&lt;br /&gt;
&lt;br /&gt;
On the other end of the spectrum, we have a signal variance that is large compared to noise variance. Here, we clearly want normalization by signal variance. However, the total variance will be dominated by signal variance. Thus, in the limit of high signal-to-noise ratio, total variance again is the quantity by which we want to normalize.&lt;br /&gt;
&lt;br /&gt;
Thus, no matter whether signal-to-noise ratio is high or low, total data variance is a good choice for normalization.&lt;br /&gt;
&lt;br /&gt;
===Typical Use===&lt;br /&gt;
Typically, the Normalizer&#039;s input is the output of a classifier, which it transforms into a zero mean/unit variance control signal which is then transmitted to an application module.&lt;br /&gt;
Using the zero mean/unit variance property, an application module can then relate quantities such as window size, screen update rate, cursor speed, and trial duration.&lt;br /&gt;
&lt;br /&gt;
==Parameters==&lt;br /&gt;
For each channel of the Normalizer&#039;s input signal, adaptation is treated independently.&lt;br /&gt;
Offsets, Gains, and Adaptation kind are represented as list parameters, with each entry in the list corresponding to a signal channel.&lt;br /&gt;
Buffer configuration is done in matrix form, with columns corresponding to signal channels, and rows corresponding to multiple buffers.&lt;br /&gt;
&lt;br /&gt;
===NormalizerOffsets, NormalizerGains=== &lt;br /&gt;
Lists of offset and gain values, with entries corresponding to signal channels. These values will be updated depending on the channel&#039;s adaptation configuration in the Adaptation parameter.&lt;br /&gt;
===Adaptation===&lt;br /&gt;
A list of values that determines adaptation strategy individually for each channel. Possible values are&lt;br /&gt;
*0 for no adaptation,&lt;br /&gt;
*1 for adjusting offsets to zero mean,&lt;br /&gt;
*2 for additionally adjusting gains to unit variance.&lt;br /&gt;
===BufferConditions===&lt;br /&gt;
A matrix consisting of [[User Reference:Expression Syntax|boolean expressions]].&lt;br /&gt;
Expressions may involve [[BCI2000 Glossary#State|state variables]] and the components of the Normalizer&#039;s input signal.&lt;br /&gt;
*Each matrix entry represents a data buffer which is a ring buffer of length &#039;&#039;BufferLength.&#039;&#039; Whenever a buffer&#039;s expression evaluates to &#039;&#039;true,&#039;&#039; the current value of the input signal will be put into the buffer (overwriting its oldest data once the buffer is filled).&lt;br /&gt;
*Columns correspond to control signal channels. Buffers in a certain column will buffer data from the corresponding signal channel, and will be used in adaptation of that channel only.&lt;br /&gt;
*Within columns, the order of buffers does not affect computation.&lt;br /&gt;
*Empty expressions do not have any effect on the computation. Thus, it is possible to have a different number of buffers for different channels.&lt;br /&gt;
*A buffer to store data for the first target, and during feedback only, should have an expression such as &amp;lt;code&amp;gt;(Feedback)&amp;amp;&amp;amp;(TargetCode==1)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===BufferLength===&lt;br /&gt;
The maximum length of each data buffer.&lt;br /&gt;
*The length is specified in data blocks if given as a raw number, and in seconds if given as a number followed by the character &amp;quot;s&amp;quot;.&lt;br /&gt;
*All data buffers have the same capacity.&lt;br /&gt;
*Once a data buffer is filled, its older entries will be replaced with new data (ring buffer).&lt;br /&gt;
*In previous versions of BCI2000, buffer lengths were specified in terms of &amp;quot;past trials&amp;quot;. However, this would enforce the notion of a &amp;quot;trial&amp;quot;, and not generalize to continuous adaptation.&lt;br /&gt;
===UpdateTrigger===&lt;br /&gt;
A [[User Reference:Expression Syntax|boolean expression]] that triggers adaptation when changing to &#039;&#039;true&#039;&#039; from &#039;&#039;false&#039;&#039;.&lt;br /&gt;
Generally, continuous adaptation within trials is not desired. Rather, one wants adaptation to occur at the end of a trial. This is achieved with &#039;&#039;UpdateTrigger&#039;&#039; expressions such as &amp;lt;code&amp;gt;Feedback==0&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;TargetCode==0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For continuous adaptation, specify an empty string in the &#039;&#039;UpdateTrigger&#039;&#039; parameter.&lt;br /&gt;
&lt;br /&gt;
==States==&lt;br /&gt;
Buffer condition expressions, and the UpdateTrigger expression may involve any [[BCI2000 Glossary#State|state]] present in the system. Expressions are checked for syntactical correctness and whether referred-to states are present during the [[Technical Reference:States of Operation|Preflight Phase]].&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
===Trial-based 1D Feedback Task with 3 Targets===&lt;br /&gt;
*Only data from the feedback phase should enter into the adaptation.&lt;br /&gt;
*To make sure that targets contribute equally to the adaptation, we use a single buffer for each target. We use a 3-rows-by-1-column BufferConditions (see below).  Depending on which control signal should be adapted on, these conditions need to be entered in the first, second, or third column of the matrix (corresponding to x, y, and z direction when used with the [[User Reference:CursorTask|CursorTask]] application module).&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==1)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==2)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==3)&lt;br /&gt;
*We want to use data from three previous trials of each target. &lt;br /&gt;
*Feedback duration is 2 seconds. We set the buffer length to the equivalent of three feedback durations:&lt;br /&gt;
  BufferLength= 6s&lt;br /&gt;
*Adaptation should happen at the end of each trial, when feedback is finished. &amp;lt;p /&amp;gt;We set UpdateTrigger to an expression that changes to &#039;&#039;true&#039;&#039; when feedback ends:&lt;br /&gt;
  UpdateTrigger= (Feedback==0)&lt;br /&gt;
*To achieve continuous movement in, say, the x direction we need a constant normalizer output on that channel. To be consistent with the [[User Reference:CursorTask#FeedbackDuration|task module&#039;s FeedbackDuration parameter]], this output should be constant +2 in order for the cursor to cross the entire screen during a trial, and +1 when cursor movement begins at the screen&#039;s center. This corresponds to the following settings for the channel in question:&lt;br /&gt;
 Adaptation= 0&lt;br /&gt;
 NormalizerOffset= -1&lt;br /&gt;
 NormalizerGain= 1 or 2, respectively.&lt;br /&gt;
&lt;br /&gt;
===Trial-based 2D Feedback Task with 4 Targets===&lt;br /&gt;
*Leaving everything else as in the previous example, we now have two dimensions corresponding to left-right (channel 1) and up-down (channel 2).&lt;br /&gt;
:Target positions are as indicated below:&lt;br /&gt;
  ---------------------------&lt;br /&gt;
  |          ##1##          |&lt;br /&gt;
  |#                       #|&lt;br /&gt;
  |2                       3|&lt;br /&gt;
  |#                       #|&lt;br /&gt;
  |          ##4##          |&lt;br /&gt;
  ---------------------------&lt;br /&gt;
:We use data from targets 1 and 4 to adjust channel 2, and targets 2 and 3 to adjust channel 1. Accordingly, the BufferConditions matrix is&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==2) (Feedback)&amp;amp;&amp;amp;(TargetCode==1)&lt;br /&gt;
 (Feedback)&amp;amp;&amp;amp;(TargetCode==3) (Feedback)&amp;amp;&amp;amp;(TargetCode==4)&lt;br /&gt;
&lt;br /&gt;
===Continuous 1D Control without pre-defined Targets===&lt;br /&gt;
*For this example, we know that, over a period of 10 minutes, all output values will occur with approximately equal frequency, or at least have a symmetric distribution around zero. This matches the combination of BCI2000 and Dasher or other &amp;quot;devices&amp;quot; expecting statistically balanced input.&lt;br /&gt;
:The BufferConditions matrix will have a single entry containing a constant expression:&lt;br /&gt;
 1&lt;br /&gt;
:This way, data will always be buffered.&lt;br /&gt;
*There are no trials. We want a continuous adaptation to the values of the last 10 minutes.&lt;br /&gt;
:We set the BufferLength parameter to &amp;lt;code&amp;gt;600s&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;(10*60)s&amp;lt;/code&amp;gt;.&lt;br /&gt;
:For continuous adaptation, we enter an &#039;&#039;empty string&#039;&#039; (not a constant 0 expression) for UpdateTrigger.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
[[User Reference:Expression Syntax]], [[BCI2000 Glossary#Control Signal]], [[User Reference:LinearClassifier]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Filters]][[Category:Signal Processing]]&lt;/div&gt;</summary>
		<author><name>Jhuggins</name></author>
	</entry>
	<entry>
		<id>https://www.bci2000.org/mediawiki/index.php?title=User_Reference:SpatialFilter&amp;diff=4899</id>
		<title>User Reference:SpatialFilter</title>
		<link rel="alternate" type="text/html" href="https://www.bci2000.org/mediawiki/index.php?title=User_Reference:SpatialFilter&amp;diff=4899"/>
		<updated>2009-02-02T13:47:45Z</updated>

		<summary type="html">&lt;p&gt;Jhuggins: /* SpatialFilterType */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Function==&lt;br /&gt;
The SpatialFilter computes an instantaneous linear transformation of its input. Typically, the SpatialFilter&#039;s input is the unfiltered brain signal from the source module. The linear transformation that is applied by the spatial filter is described by a transformation matrix, and applied for each sample separately, not linking data across different points in time. This linear transformation can be parameterized in three different ways as described below.&lt;br /&gt;
&lt;br /&gt;
==Parameters==&lt;br /&gt;
===SpatialFilterType===&lt;br /&gt;
This parameter defines the method that will be used to design the spatial filter. Choices are:&lt;br /&gt;
;0 None&lt;br /&gt;
:No spatial filtering is performed; the input signal is copied to the output signal, and the spatial filter matrix is ignored.&lt;br /&gt;
;1 Full Matrix&lt;br /&gt;
:The linear transformation applied to the input signal is defined by the &#039;&#039;SpatialFilter&#039;&#039; matrix parameter. This is the is also the default, and matches behavior in previous versions of BCI2000.&lt;br /&gt;
;2 Sparse Matrix&lt;br /&gt;
:The sparse matrix filter uses the &#039;&#039;SpatialFilter&#039;&#039; matrix parameter to define non-zero matrix entries. Each non-zero entry is given by an input channel, output channel, and weight for that channel.&lt;br /&gt;
;3 Common Average Reference (CAR)&lt;br /&gt;
:The common average reference spatial filter calculates the mean of all channels, and subtracts this value from the selected output channels. This filter&#039;s output channels may be defined by the &#039;&#039;SpatialFilterCAROutput&#039;&#039; parameter.&lt;br /&gt;
&lt;br /&gt;
===SpatialFilter===&lt;br /&gt;
====Full Matrix Filter Type====&lt;br /&gt;
[[Image:SpatialFilter.png|right|256px]]&lt;br /&gt;
The full matrix filter uses the SpatialFilter parameter to define the linear transformation applied to the filter&#039;s input signal. In this matrix, columns represent input channels, and rows represent output channels. Each matrix element defines a weight with which the respective input channel (column) enters into the respective output channel (row).&lt;br /&gt;
&lt;br /&gt;
If the spatial filter is an identity filter -- not modifying its input --, then the SpatialFilter matrix is a unit matrix (square matrix with ones on the main diagonal, and all other elements zero).&lt;br /&gt;
&lt;br /&gt;
In a typical EEG experiment with fixed montage, you might want &#039;&#039;column labels&#039;&#039; to reflect the respective electrode location, simplifying the task of further modifications to the spatial filter.&lt;br /&gt;
Also, specifying &#039;&#039;row labels&#039;&#039; to identify output channels allows you to use those labels in configuration of further stages of processing, such as the [[User Reference:LinearClassifier|LinearClassifier]].&lt;br /&gt;
&lt;br /&gt;
====Sparse Matrix Filter Type====&lt;br /&gt;
The sparse matrix filter uses the SpatialFilter parameter to define the relationship between input channels and output channels with a given weight. In this case, the SpatialFilter matrix must have 3 columns, and a row for each input/output relationship. The first column contains the input channel, the third column defines the weight that the input channel is multiplied by before being assigned to the output channel, which is defined in the second column.&lt;br /&gt;
&lt;br /&gt;
When specifying input channels in the first column, you may use [[User Reference:DataIOFilter#ChannelNames|channel names]]. In order to assign labels to output channels in sparse representation, use arbitrary labels in the (third) output channel column.&lt;br /&gt;
&lt;br /&gt;
See the example below for more information on how to use the sparse matrix.&lt;br /&gt;
&lt;br /&gt;
===SpatialFilterCAROutput===&lt;br /&gt;
This parameter is a list of channels that define which channels should be output from the common average reference spatial filter, and the order in which they should appear. That is, the location of the channel in this list determines the output channel position. For example, if input channels 6, 7, 10, and 12 should be passed to the output of the spatial filter as channels 3, 4, 1, and 2, then this parameter should be set to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;10 12 6 7&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Rather than numbers, channel names may be specified as defined in the [[User Reference:DataIOFilter#ChannelNames|ChannelNames]] parameter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;C3 C4 CP3 CP4 Cz&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is important to note that &#039;&#039;&#039;all&#039;&#039;&#039; channels passed to the spatial filter (typically defined in the [[User Reference:Parameters#TransmitChList|TransmitChList parameter]]) are used in the CAR calculation, but only a subset of these channels are actually output and passed to the next step in the signal processing chain.&lt;br /&gt;
&lt;br /&gt;
If this parameter is left blank, then all input channels are passed to the output, and the number of input channels equals the number of output channels.&lt;br /&gt;
&lt;br /&gt;
==States==&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
===Linked Mastoids (Full Matrix)===&lt;br /&gt;
Physical reference is to the left mastoid (A1). The right mastoid (A2) is recorded vs A1 on channel 1. All other electrodes are recorded vs A1 as well, and use the remaining channels.&lt;br /&gt;
In your spatial filter, you will want to re-reference all channels against &amp;quot;linked mastoids&amp;quot;, i.e. against the mean of A1 and A2.&lt;br /&gt;
&lt;br /&gt;
In the spatial filter matrix, you want to subtract half of the A2 channel from each of the remaining channels:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|+ Linked Mastoids&lt;br /&gt;
! &amp;amp;nbsp; !! A2  !! Fz !! Cz !! Pz !! ...&lt;br /&gt;
|-&lt;br /&gt;
! Fz&#039;&lt;br /&gt;
| -1/2 ||  1 ||  0 ||  0 || rowspan=&amp;quot;3&amp;quot; | ...&lt;br /&gt;
|-&lt;br /&gt;
! Cz&#039;&lt;br /&gt;
| -1/2 ||  0 ||  1 ||  0&lt;br /&gt;
|-&lt;br /&gt;
! Pz&#039;&lt;br /&gt;
| -1/2 ||  0 ||  0 ||  1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;nbsp; || colspan=&amp;quot;5&amp;quot; | ...&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sparse Matrix===&lt;br /&gt;
In this example, the mean of channels 1-4 are passed to output channel 1, and the negative mean of channels 10-14 are passed to output channel 2. The SpatialFilter matrix definition is given below.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|+ Sparse Matrix&lt;br /&gt;
! &amp;amp;nbsp; !! In !! Out !! Wt&lt;br /&gt;
|-&lt;br /&gt;
! 1 &lt;br /&gt;
| 1 || 1 || .25&lt;br /&gt;
|-&lt;br /&gt;
! 2 &lt;br /&gt;
| 2 || 1 || .25&lt;br /&gt;
|-&lt;br /&gt;
! 3 &lt;br /&gt;
| 3 || 1 || .25&lt;br /&gt;
|-&lt;br /&gt;
! 4 &lt;br /&gt;
| 4 || 1 || .25&lt;br /&gt;
|-&lt;br /&gt;
! 5 &lt;br /&gt;
| 10 || 2 || -.2&lt;br /&gt;
|-&lt;br /&gt;
! 6 &lt;br /&gt;
| 11 || 2 || -.2&lt;br /&gt;
|-&lt;br /&gt;
! 7 &lt;br /&gt;
| 12 || 2 || -.2&lt;br /&gt;
|-&lt;br /&gt;
! 8 &lt;br /&gt;
| 13 || 2 || -.2&lt;br /&gt;
|-&lt;br /&gt;
! 9 &lt;br /&gt;
| 14 || 2 || -.2&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This results in:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;OutCh(1) = 0.25*InCh(1) + 0.25*InCh(2) + 0.25*InCh(3) + 0.25*InCh(4)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;OutCh(2) = (-0.25)*InCh(10) + (-0.25)*InCh(11) + (-0.25)*InCh(12) + (-0.25)*InCh(13)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Large Laplacian (Sparse Matrix)===&lt;br /&gt;
In this example, the spatial filter computes Large-Laplacian filtered versions of channels &#039;&#039;C3&#039;&#039; and &#039;&#039;C4&#039;&#039; by re-referencing them to the mean of their mid-range neighbors &#039;&#039;Cz&#039;&#039;, &#039;&#039;P3/4&#039;&#039;, &#039;&#039;T7/8&#039;&#039;, and &#039;&#039;F3/4&#039;&#039;:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;C3&#039;=C3-(Cz+P3+T7+F3)/4&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;C4&#039;=C4-(Cz+P4+T8+F4)/4&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using channel names, the filter specification will be independent of the order and exact set of input channels, provided that all required channels are available and labeled correctly.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|+ Sparse Matrix&lt;br /&gt;
! &amp;amp;nbsp; !! In !! Out !! Wt&lt;br /&gt;
|-&lt;br /&gt;
! 1 &lt;br /&gt;
| C3 || C3 || 1&lt;br /&gt;
|-&lt;br /&gt;
! 2 &lt;br /&gt;
| Cz || C3 || -.25&lt;br /&gt;
|-&lt;br /&gt;
! 3 &lt;br /&gt;
| P3 || C3 || -.25&lt;br /&gt;
|-&lt;br /&gt;
! 4 &lt;br /&gt;
| T7 || C3 || -.25&lt;br /&gt;
|-&lt;br /&gt;
! 5 &lt;br /&gt;
| F3 || C3 || -.25&lt;br /&gt;
|-&lt;br /&gt;
! 6 &lt;br /&gt;
| C4 || C4 || 1&lt;br /&gt;
|-&lt;br /&gt;
! 7 &lt;br /&gt;
| Cz || C4 || -.25&lt;br /&gt;
|-&lt;br /&gt;
! 8 &lt;br /&gt;
| P4 || C4 || -.25&lt;br /&gt;
|-&lt;br /&gt;
! 9 &lt;br /&gt;
| T8 || C4 || -.25&lt;br /&gt;
|-&lt;br /&gt;
! 10 &lt;br /&gt;
| F4 || C4 || -.25&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Performance Notes==&lt;br /&gt;
Each spatial filter type uses a different algorithm to compute the linear transformation, and can therefore have implications on CPU load and performance. In the following, &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; denotes the filter&#039;s number of input channels, and &amp;lt;math&amp;gt;M \leq N&amp;lt;/math&amp;gt; denotes its number of output channels.&lt;br /&gt;
&lt;br /&gt;
===None===&lt;br /&gt;
No computations are actually done, but input data is being copied into the filter&#039;s output, resulting in a complexity &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===CAR===&lt;br /&gt;
The common-average reference has a complexity of &amp;lt;math&amp;gt;O(N+M)&amp;lt;/math&amp;gt;, providing the next best performance in most circumstances. It is possible to create a CAR using either the full-matrix or sparse matrix options; however, the CAR method only calculates the mean value once per sample, and subtracts it only from the selected output channels. In order to implement a CAR in a full-matrix, the mean must be recalculated for &#039;&#039;every&#039;&#039; output channel, which is not as efficient, particularly for high channel count systems.&lt;br /&gt;
&lt;br /&gt;
===Sparse Matrix===&lt;br /&gt;
The sparse matrix method performance is determined completely by the number of elements (rows) in the &#039;&#039;SpatialFilter&#039;&#039; matrix. In the best case, a single channel is multiplied by the weight and assigned to the specified output channel; this would take far less CPU time than the CAR method, and possibly the &amp;quot;none&amp;quot; option as well. &lt;br /&gt;
&lt;br /&gt;
In a realistic scenario, all &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; input channels will be used to calculate &amp;lt;math&amp;gt;M \leq N&amp;lt;/math&amp;gt; output channels; thus, complexity is between &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;O(N*M)&amp;lt;/math&amp;gt;, with &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt; in the worst case.&lt;br /&gt;
&lt;br /&gt;
Sparse matrix worst-case performance will be close to that of an &amp;lt;math&amp;gt;N\times N&amp;lt;/math&amp;gt; &amp;quot;full&amp;quot; spatial filter matrix. Thus, for spatial filter configurations that depend on electrode/sensor locations such as Laplacian filtering, filter definition in terms of a sparse matrix using [[User_Reference:DataIOFilter#ChannelNames|channel labels]] appears most advantageous.&lt;br /&gt;
&lt;br /&gt;
===Full Matrix===&lt;br /&gt;
Full matrix representation is the most general way to specify a spatial filter, and recommended for situations not allowed for by the remaining spatial filter types.&lt;br /&gt;
Compared to those, it is associated with a number of disadvantages:&lt;br /&gt;
*Complexity is &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt;. In situations with large sampling rates and/or a large number of channels, this may result in real-time problems due to high CPU load.&lt;br /&gt;
*[[User_Reference:DataIOFilter#ChannelNames|Channel labels]] are not preserved across the filter. Due to the filter&#039;s general nature, no relation between input and output channel names can be inferred, and all output labels must be specified manually.&lt;br /&gt;
*The filter&#039;s specification depends on the order of input channels, which makes it interdependent with the [[User Reference:Parameters#TransmitChList|&#039;&#039;TransmitChList&#039;&#039; parameter]].&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
[[User Reference:LinearClassifier]], [[User Reference:DataIOFilter#ChannelNames]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Filters]][[Category:Signal Processing]]&lt;/div&gt;</summary>
		<author><name>Jhuggins</name></author>
	</entry>
</feed>