Hi,
I'm using OpenViBE (with an OpenBCI Cyton board) to try to build a neurofeedback system, starting from the neurofeedback example.
I want to add a feature I've seen in a commercial system. It's a kind of noise gate. When the trainee is moving around, clenching jaw muscles, etc., a large and noisy signal is produced. At this point, the system shuts down the reward signal, and leaves it shut down until it's been quiet again for some period (such as 1 second). Then it goes back to normal operation.
I figured that I could create a gate signal that would be 0 or 1 using a Simple DSP with this expression:
(x > -100 && x < 100) ? 1 : 0
Then I just multiply the reward signal by that. Seems to work. But the gate signal sometimes bounces rapidly between 0 and 1. I don't know how to add the time delay so it stays at 0 for awhile. Any suggestions?
Thanks,
Dave
One-shot / debounce / timer box?
-
- Posts: 775
- Joined: Tue Dec 04, 2012 3:53 pm
- Location: INRIA Rennes, FRANCE
Re: One-shot / debounce / timer box?
HI Dave, thats indeed a bit of a puzzle you have there!
Without implementing an actual delay box or such, what I imagine could be done is something like this,
1) Change your gate signal to (-1,1) and then to a stimulation stream using the Sign Change Detector box.
2) Delay the 'toggle on' stimulation with Lua Stimulator box (you'll find a delay example in box-tutorials/lua) while passing the 'Toggle off' immediately
3) Use the stimulus outputs of the Lua Stimulator to control Stream Switch box which will send data to the display only when the gate is not activated.
I have a feeling it might work, but I havent tried it -- let us know how it goes. One problem with it might be that with this design the display will get a noncontinuous stream.
Cheers,
Jussi
Without implementing an actual delay box or such, what I imagine could be done is something like this,
1) Change your gate signal to (-1,1) and then to a stimulation stream using the Sign Change Detector box.
2) Delay the 'toggle on' stimulation with Lua Stimulator box (you'll find a delay example in box-tutorials/lua) while passing the 'Toggle off' immediately
3) Use the stimulus outputs of the Lua Stimulator to control Stream Switch box which will send data to the display only when the gate is not activated.
I have a feeling it might work, but I havent tried it -- let us know how it goes. One problem with it might be that with this design the display will get a noncontinuous stream.
Cheers,
Jussi
Re: One-shot / debounce / timer box?
Hi Jussi, thanks for the response!
Yesterday I started working with the Python box as a possible solution using pure signal processing. What you're suggesting sounds simpler, I just need to first learn more about how stimulations fit into the overall architecture (have not worked with them yet). If I find a good solution, I'll post it here.
Best,
Dave
Yesterday I started working with the Python box as a possible solution using pure signal processing. What you're suggesting sounds simpler, I just need to first learn more about how stimulations fit into the overall architecture (have not worked with them yet). If I find a good solution, I'll post it here.
Best,
Dave
Re: One-shot / debounce / timer box?
Here's what I've come up with. I couldn't figure out how to use a stimulation stream for this; once the gate is closed, if the signal again exceeds the limits, I need the recovery timer to reset itself (i.e. the gate can only re-open after the signal has been within limits for the full recovery time). Anyway, this seems to do the trick.
I've made no attempt to optimize the performance.
Cheers,
Dave
I've made no attempt to optimize the performance.
Cheers,
Dave
Code: Select all
import numpy
from datetime import datetime, timedelta
class MyOVBox(OVBox):
def __init__(self):
OVBox.__init__(self)
self.signalHeader = None
self.timeLastOutside = None # per-channel
self.gateOpen = None # states also per-channel
def initialize(self):
self.minSignal = float(self.setting['minimum signal'])
self.maxSignal = float(self.setting['maximum signal'])
self.recoveryTime = float(self.setting['recovery time (milliseconds)']) / 1000.0
def process(self):
for iInput, chunks in enumerate(self.input):
for iChunk, chunk in enumerate(chunks):
if type(chunk) == OVSignalHeader:
self.signalHeader = chunks.pop()
outputHeader = OVSignalHeader(
self.signalHeader.startTime,
self.signalHeader.endTime,
self.signalHeader.dimensionSizes,
self.signalHeader.dimensionLabels,
self.signalHeader.samplingRate)
#print self.signalHeader.dimensionSizes
#print self.signalHeader.dimensionLabels
self.output[iInput].append(outputHeader)
self.nSamples = self.signalHeader.dimensionSizes[1]
self.nChannels = self.signalHeader.dimensionSizes[0]
print 'nChannels = %d, nSamples = %d' % (self.nChannels, self.nSamples)
if not self.timeLastOutside:
# time each channel was last outside range, init to -1 second
self.timeLastOutside = [-1] * self.nChannels
if not self.gateOpen:
# all gates initially open
self.gateOpen = [True] * self.nChannels
elif type(chunk) == OVSignalBuffer:
chunks.pop()
#print 'OVSignalBuffer start %s end %s' % (chunk.startTime, chunk.endTime)
buffer = numpy.array(chunk).reshape(tuple(self.signalHeader.dimensionSizes))
buffer.flags.writeable = True
#print buffer[0,0]
#print buffer[1,0]
tick = (chunk.endTime - chunk.startTime) / self.nSamples
for iChannel in range(self.nChannels):
open = self.gateOpen[iChannel]
for iSample in range(self.nSamples):
sample = buffer[iChannel, iSample]
outside = sample > self.maxSignal or sample < self.minSignal
sampleTime = chunk.startTime + (tick * iSample)
if open:
# todo make this optional - clamp output to an open signal
buffer[iChannel, iSample] = 1.0
if outside:
open = False
#print 'iChannel %d: out of range value = %f, sample = %s, time = %s' % \
# (iChannel, sample, iSample, sampleTime)
self.timeLastOutside[iChannel] = sampleTime
else:
# todo allow value other than 0 to be configured for closed gate
buffer[iChannel, iSample] = 0.0
if outside:
self.timeLastOutside[iChannel] = sampleTime
else:
if sampleTime > self.timeLastOutside[iChannel] + self.recoveryTime:
open = True
self.gateOpen[iChannel] = open
#print 'iChannel = %d, gate open = %s, timeLastOutside = %f' % \
# (iChannel, open, self.timeLastOutside[iChannel])
outChunk = OVSignalBuffer(chunk.startTime, chunk.endTime, buffer.flatten().tolist())
self.output[iInput].append(outChunk)
elif type(chunk) == OVSignalEnd:
self.output[iInput].append(chunks.pop())
box = MyOVBox()
-
- Posts: 775
- Joined: Tue Dec 04, 2012 3:53 pm
- Location: INRIA Rennes, FRANCE
Re: One-shot / debounce / timer box?
Hi Dave, thanks for posting your solution! Hopefully it will help other people who are trying to develop signal gate -like functionality.
Cheers,
Jussi
Cheers,
Jussi