Page 1 of 1

P3Speller Application using BCPy2000

Posted: 18 Jul 2011, 15:40
by salterd

We are trying to develop a BCI2000 application through which you play the game Concentration using the P300 signal. I have a lot of experience using Python and would like to make this application using the BCPy2000 framework.

I would like to use the same source and signal-processing module that we have used successfully for the default P3Speller application so as to not have to re-write code. However, I cannot find any way that I could connect the output of the P3SignalProcessing module with that of my own Python application. I have run through the BCPy2000 tutorial and I've searched through the BCI2000 source code, but I did not find any clear answers.

Is there a way to connect the modules as I've described, or is this a dead end? If there is a way, where do I start?

Thank you in advance,

Re: P3Speller Application using BCPy2000

Posted: 20 Jul 2011, 18:28
by jhill
There is no specific support for the P3SignalProcessing and P3Speller modules in the Python framework as it stands. But there are no dead ends: there's a way to do anything, if you program it. The required Python programming is probably not too complicated in either case.

What you're describing requires you to emulate one side of what I'll informally call the "P3 protocol", which is a combination of control signals and states sent by the P3TemporalFilter, through the LinearClassifier filter on the SignalProcessing side, and received by the P3SpellerTask on the Application side. (Disclaimer: I do not know much about the P3 protocol except what can be gleaned from those three wiki pages. I presume there is one StimulusCode value per row and one value per column, and that the P3SpellerTask, i.e. the application you are replacing, is responsible for comparing control signal values across members of the same group of StimulusCodes—e.g. across all rows, or across all columns. )

In Python terms, control signals are received in the form of numpy.matrix objects (each row is a channel, each column is an "element", usually a time-sample or frequency bin), as an input argument to your Process() method. This matrix is also accessible from outside Process() — for example, from the interactive PythonApp shell—as self.in_signal . If you're connecting a Python application to the existing P3SignalProcessing.exe then this matrix will presumably be 1 x 1, so this:

Code: Select all

class BciApplication(BciGenericApplication):
    def Process(self,  sig):
        x = sig[0,0]
        stimulusCodeRes = self.states['StimulusCodeRes']
will give you a scalar x that contains almost everything P3SignalProcessing has to tell you on any one particular signal packet. I say "almost", because the P3TemporalFilter page also lists "states used for output"—so your application will also be interested in the StimulusCodeRes state value, which it reads in the last line of the code sample above. The P3 protocol also involves two-way communication, via the "states used for input" listed on that same wiki page: my reading of that is that your application will also need to assign self.states['StimulusCode'] at the relevant times (to flag what the P3TemporalFilter should average with what) and also, when recording training/calibration data, it will need to assign self.states['StimulusType'] .

Hope this helps, --jez