gUSBampADC - decimation, SC, granular common ground/ref...

Forum for software developers to discuss BCI2000 software development
Locked
boulay
Posts: 382
Joined: 25 Dec 2011, 21:14

gUSBampADC - decimation, SC, granular common ground/ref...

Post by boulay » 17 Jul 2012, 07:23

Before I was about to code-in bipolar derivation, Juergen dissuaded me with some logical reasoning. I'm hoping to engage in that same type of conversation regarding some other features.
(Just for completeness: hardware bipolar derivation might be superior to software bipolar derivation in the case where the monopolar signals saturate. That shouldn't be an issue for most signal types.)

Here are some other features I would like to discuss:
  • Reducing TMS artifacts requires turning off the filters. The anti-aliasing filter can only be disabled if sampling at a rate > 4800 Hz. However, this leads to huge data files. Would it be possible to sample at a high rate but decimate the data in the source module before it gets stored or passed to signal processing? Should this go in GenericADC?
    On line 610 of gUSBampADC.cpp, GT_EnableSC is commented out. Is that because it is enabled by default? (I need it)
    Can we use an intlist parameter to specify common grounds and common refs with more granularity? e.g. [1 1 1 1 1 1 1 0] would link all grounds for amp-1 and link the grounds for the first 3 banks of amp-2. Is that sufficiently intuitive?
    Per-channel bandpass and notch filters using a matrix?
There are a few other small issues I came across:
  • The wiki is outdated wrt BipolarChList. http://www.bci2000.org/wiki/index.php/U ... gUSBampADC
    The wiki says SourceChGain should be set to 1 when SignalType is float32, but defaults + "../parms/fragments/amplifiers/gUSBamp.prm" has SignalType set to float32 and SourceChGain set to 0.019.
    The AD range is +/- 250 mV and the AD resolution is 24-bit yielding 0.0298023223876953125 uV/bit. I don't know where 0.019 came from.
[Edited to disambiguate whether or not grounds are linked across devices. AFAIK they are not.]

mellinger
Posts: 1341
Joined: 12 Feb 2003, 11:06

Re: gUSBampADC - decimation, SC, granular common ground/ref.

Post by mellinger » 17 Jul 2012, 08:32

Would it be possible to sample at a high rate but decimate the data in the source module before it gets stored or passed to signal processing? Should this go in GenericADC?
In general, downsampling can lead to uneven timing, so I would not provide it in form of generic functionality within GenericADC. So you should add downsampling to the gUSBamp source module for your own purposes first.

The simplest way to implement downsampling without aliasing concerns is to have an integer ratio n between original and downsampled frequency. Then, you can replace each group of subsequent n samples simply with their mean value. This works because taking the mean is equivalent to convolution with a rectangular window, such that the signal's amplitude spectrum gets multiplied by a sinc function with its first zero at the new Nyquist frequency, and reasonable damping above that.

Other than plain integer downsampling ratios are also not advisable because they will result in variable block lengths, which are not allowed by BCI2000.

To be on the safe side, you might add a 2nd order IIR HP filter with stronger damping prior to downsampling. The SourceFilter gives you an example how to use the IIRFilter base class, and the StandaloneFilter class (src/shared/filters/StandaloneChain) gives you an easy way to use a GenericFilter descendant outside the main processing chain.
GT_EnableSC is commented out. Is that because it is enabled by default?
g.tec's documentation is not especially verbose regarding details, so I don't know whether this is enabled by default. If you need it, just enable it. However, the code should not enable it by default for all users. Adding a parameter might be a good idea.

SourceChGain does not represent physical amplifier resolution but instructs software how to translate values stored in the dat file into units of microvolts. With the gUSBamp source module, the user is able to choose integer data formats for storage, though data arrive in float format from the amplifier. By choosing SourceChGain, the user effectively decides which resolution is used for data storage. When storing floats, that factor makes no difference with regard to resolution. The wiki suggests a value of 1 to avoid unnecessary confusion, while the values in the example configuration were chosen to achieve a reasonable resolution when storing integer data.

Regards,
Juergen

griffin.milsap
Posts: 58
Joined: 08 Jun 2009, 12:42

Re: gUSBampADC - decimation, SC, granular common ground/ref.

Post by griffin.milsap » 17 Jul 2012, 10:37

Chad,

It is also worth noting that we're working on a ground-up rewrite of the g.USBamp module -- to be completed in a few months time. Many of the issues you're noting with the current module (in addition to several other small bugs) have been documented and will be fixed for the new version. If there is anything else you think belongs in this new module, let us know and we can work it in.

-Griff

boulay
Posts: 382
Joined: 25 Dec 2011, 21:14

Re: gUSBampADC - decimation, SC, granular common ground/ref.

Post by boulay » 17 Jul 2012, 22:17

To be on the safe side, you might add a 2nd order IIR HP filter with stronger damping prior to downsampling. The SourceFilter gives you an example how to use the IIRFilter base class, and the StandaloneFilter class (src/shared/filters/StandaloneChain) gives you an easy way to use a GenericFilter descendant outside the main processing chain.
Would this filter also have transients from the TMS impulse artifact? I'm trying to avoid having the TMS artifact affect evoked potentials in the EMG or EEG, meaning I need the artifact gone within 5 ms.
By choosing SourceChGain, the user effectively decides which resolution is used for data storage. When storing floats, that factor makes no difference with regard to resolution.
Would this be an issue if a user decided to load the data without using --calibrated?

When storing as int16, if I wanted to maximize range then I would divide by 7.6294, and if I wanted to maximize resolution (same resolution as sampled, but decreased range) then I would divide by 0.0298. Dividing by 0.019 sacrifices range unnecessarily to gain resolution higher than is possible by the AD. For someone like me, that learns by example and trusts the tutorial, seeing 0.019 as SourceChGain tells me that there's something I don't understand and I should just trust this magical number and never change it.

boulay
Posts: 382
Joined: 25 Dec 2011, 21:14

Re: gUSBampADC - decimation, SC, granular common ground/ref.

Post by boulay » 18 Jul 2012, 00:43

griffin.milsap wrote:If there is anything else you think belongs in this new module, let us know and we can work it in.
I'd be happy to test the new version if you wouldn't mind including me in the development.

I've attached a clip of the gusbamp GUI in Matlab in case it is useful. Obviously BCI2000's interface is quite different, but it might give you an idea about the features that gtec thinks should be user-facing.
gUSBamp_MATLAB_GUI.PNG

mellinger
Posts: 1341
Joined: 12 Feb 2003, 11:06

Re: gUSBampADC - decimation, SC, granular common ground/ref.

Post by mellinger » 18 Jul 2012, 08:40

Quote:
To be on the safe side, you might add a 2nd order IIR HP filter with stronger damping prior to downsampling. The SourceFilter gives you an example how to use the IIRFilter base class, and the StandaloneFilter class (src/shared/filters/StandaloneChain) gives you an easy way to use a GenericFilter descendant outside the main processing chain.

Would this filter also have transients from the TMS impulse artifact? I'm trying to avoid having the TMS artifact affect evoked potentials in the EMG or EEG, meaning I need the artifact gone within 5 ms.
Sorry, I meant Low Pass, not High Pass. The temporal extent of an LP's impulse response is inversely proportional to its corner frequency, and also a function of its steepness. For a 2nd order Butterworth filter with a corner frequency of 1/5 of the sampling rate, the impulse response dies out after less than 100 samples (http://www-users.cs.york.ac.uk/~fisher/ ... /trad.html). I wouldn't expect a problem there.
Quote:
By choosing SourceChGain, the user effectively decides which resolution is used for data storage. When storing floats, that factor makes no difference with regard to resolution.

Would this be an issue if a user decided to load the data without using --calibrated?
Sure, he decides to change SourceChGain between sessions, later decides to analyze across those sessions, and is not aware of the meaning of the SourceChGain parameter, although he decided to change it, then, yes, he will run into trouble.
When storing as int16, if I wanted to maximize range then I would divide by 7.6294, and if I wanted to maximize resolution (same resolution as sampled, but decreased range) then I would divide by 0.0298. Dividing by 0.019 sacrifices range unnecessarily to gain resolution higher than is possible by the AD. For someone like me, that learns by example and trusts the tutorial, seeing 0.019 as SourceChGain tells me that there's something I don't understand and I should just trust this magical number and never change it.
So it seems the guy who originally created those files made an error when computing the value. AFAIK, the new gUSBamp source module will only support float output, so SourceChGain will be fixed to 1, and the parameter files will be replaced.

Regards,
Juergen

Locked

Who is online

Users browsing this forum: No registered users and 0 guests