Use of one box to trigger another

Concerning processing components: filters, file load/save, visualizations, communication ...
karthiks
Posts: 78
Joined: Thu Sep 02, 2010 2:43 pm
Location: Université Libre de Bruxelles

Use of one box to trigger another

Post by karthiks »

Hey,

I am trying to use a pattern generator box ( I wrote it) to give some output patters. I want to use an existing classifier as the start trigger for this box. For example, if the beta power goes above this level, trigger the start of box.

How can I do this?

Regards,

Karthik
Regards,

Karthik

lbonnet
Site Admin
Posts: 417
Joined: Wed Oct 07, 2009 12:11 pm

Re: Use of one box to trigger another

Post by lbonnet »

Hi !
I am trying to use a pattern generator box ( I wrote it) to give some output patters.
Good job I guess :)
I want to use an existing classifier as the start trigger for this box. For example, if the beta power goes above this level, trigger the start of box.
OpenViBE currently includes 2 classifier, LDA and SVM. They need to be trained on some features you extracted in a first acquisition stage.
Afterward, the trained classifier processor box is used in the online stage, and outputs the class selected. This class label can be used as a trigger afterward I guess.

If you simply need a box that outputs a "trigger" stimulation when a threshold is reached, I think you can write a simple box that does the job !
This box could be very close to what the Crop box does already.

Laurent
Follow us on twitter >> openvibebci

Checkout my (old) blog for some OpenViBE tips & tricks : here !

karthiks
Posts: 78
Joined: Thu Sep 02, 2010 2:43 pm
Location: Université Libre de Bruxelles

Re: Use of one box to trigger another

Post by karthiks »

Hi Laurent,
lbonnet wrote:
I want to use an existing classifier as the start trigger for this box. For example, if the beta power goes above this level, trigger the start of box.
OpenViBE currently includes 2 classifier, LDA and SVM. They need to be trained on some features you extracted in a first acquisition stage.
Afterward, the trained classifier processor box is used in the online stage, and outputs the class selected. This class label can be used as a trigger afterward I guess.

If you simply need a box that outputs a "trigger" stimulation when a threshold is reached, I think you can write a simple box that does the job !
This box could be very close to what the Crop box does already.
So, how can I generate the trigger output? I mean to ask, what exactly in the coding docs should I be looking at? :)

Also, what should I be coding in to my pattern box so that it only starts when the trigger is received? What is the OV_TypeId of the trigger? Streamed Matrix?

Thanks,

Karthik

karthiks
Posts: 78
Joined: Thu Sep 02, 2010 2:43 pm
Location: Université Libre de Bruxelles

Re: Use of one box to trigger another

Post by karthiks »

hey,

any suggestions about the trigger coding?
Regards,

Karthik

ddvlamin
Posts: 160
Joined: Thu Aug 13, 2009 8:39 am
Location: Ghent University
Contact:

Re: Use of one box to trigger another

Post by ddvlamin »

Hi,

As lbonnet suggests, if you first build a classifier that is able to discriminate between high and low beta power then the bias term in the classifier will function as your threshold. The label that is the output of the classifier is then simply a trigger for your box to activate. So you should connect the first output of the classifier processor box to the trigger input of your box. This should be of type Stimulations just as the first label output of the classifier box. In your box you should then check (probably in the process function of your box) if a certain StimulationId is received and consequently activate or start executing the code in your box.

To work well, you will probably need to adjust the bias of the classifier in order to have a low amount of false positives (otherwise it could be that you box is activated a lot).

If this is not the answer you are looking for, maybe you can specify more details about your application so that we can have a better view on what you are trying to accomplish.

Dieter

karthiks
Posts: 78
Joined: Thu Sep 02, 2010 2:43 pm
Location: Université Libre de Bruxelles

Re: Use of one box to trigger another

Post by karthiks »

Thank you for the help.

I am unable to understand the coding of the stimulation part. As suggested by Laurent, I have tried to modify the crop box, but the problem remains in how do I say that "if the value is higher than x, send this stimulation"?

Code: Select all

if(m_vDecoders[i]->isBufferReceived())
			{
				IMatrix* l_pMatrix = m_oSignalDecoder.getOutputMatrix();
				float64* l_pBuffer = l_pMatrix->getBuffer();
				if(*l_pBuffer > m_f64Threshold)
				{
					*l_pBuffer = this->getTypeManager().getEnumerationEntryValueFromName(OV_TypeId_Stimulation,"OVTK_StimulationId_Start");
				}

				m_vEncoders[i]->encodeBuffer(i);
			}
I have gotten up to this but the output does not give stimulations (I used Stimulation listener for this). What am I doing wrong?

Any help is appreciated.
Regards,

Karthik

ddvlamin
Posts: 160
Joined: Thu Aug 13, 2009 8:39 am
Location: Ghent University
Contact:

Re: Use of one box to trigger another

Post by ddvlamin »

Hi,

I assume one of the encoders in your array m_vEncoders is a stimulation encoder? How is l_pBuffer then connected to the input of this stimulation encoder?

I looked at the code of the Clock stimulator and to generate stimulations I would expect the following code in your initialize method

Code: Select all

	
m_pStimulationEncoder=&this->getAlgorithmManager().getAlgorithm(this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationStreamEncoder));
m_pStimulationEncoder->initialize();
Somewhere in the process function I would then expect at least the following lines of code

Code: Select all


//initializes the variable that will handle the stimulation set in which you will later save the information of your stimulation (time and label) and connects it to the input of the stimulation encoder. You now just have to fill in the necessary information of the stimulation (time and label)

TParameterHandler < IStimulationSet* > ip_pStimulationSet(m_pStimulationEncoder->getInputParameter(OVP_GD_Algorithm_StimulationStreamEncoder_InputParameterId_StimulationSet));

//requests the current time
uint64 l_ui64CurrentTime=getPlayerContext().getCurrentTime();

// the label of your stimulation, this is your code
m_ui64StimulationId=this->getTypeManager().getEnumerationEntryValueFromName(OV_TypeId_Stimulation,"OVTK_StimulationId_Start");

//append the stimulation to the set with the information (label and time) you have given above
ip_pStimulationSet->appendStimulation(m_ui64StimulationId, l_ui64CurrentTime, 0);

//now call the encoder to process those stimulations so they are sent to the output of your box and thus to the next box
m_pStimulationEncoder->process(OVP_GD_Algorithm_StimulationStreamEncoder_InputTriggerId_EncodeBuffer);
It could be that some more details should be added, the code of the Clock stimulator can probably help you with that.

Hopefully this helps you to progress?

Best regards,
Dieter Devlaminck

karthiks
Posts: 78
Joined: Thu Sep 02, 2010 2:43 pm
Location: Université Libre de Bruxelles

Re: Use of one box to trigger another

Post by karthiks »

Hey Dieter,

Thank you for the effort. The code that you have linked is done using the old way of coding in OpenViBE. :(

I was trying to use the Codec Toolkit to code since it is faster but seems like I should fall back to the older coding style.

Thanks again for the help.
Regards,

Karthik

ddvlamin
Posts: 160
Joined: Thu Aug 13, 2009 8:39 am
Location: Ghent University
Contact:

Re: Use of one box to trigger another

Post by ddvlamin »

Dear Karthiks,

Ok, I'm sorry, I'm still using the old way, anyway thanks for pointing this out. I took a look at the toolkit, but I still do not understand your code. Where exactly in your code do you set the StimulationSet with the necessary information and where do you connect it to the input of the encoder algorithm? You want to tell the encoder to encode the stimulation that you have saved in your variable l_pBuffer but how does it know this? A stimulation encoder does expect a StimulationSet no?

In my opinion you will still need to request the input of the encoder

Code: Select all

IStimulationSet* l_pStimulations =  m_oStimEncoder.getInputStimulationSet();
and then insert your information (label and timing) in this object with the usual methods.

Code: Select all

setStimulationIdentifier (const OpenViBE::uint64 ui64StimulationIndex, const OpenViBE::uint64 ui64StimulationIdentifier)
setStimulationDate (const OpenViBE::uint64 ui64StimulationIndex, const OpenViBE::uint64 ui64StimulationDate)
and then call

Code: Select all

 m_oStimEncoder->encodeBuffer(i);
It should be something along those lines no? Maybe you could post the complete file?

Best regards,
Dieter

karthiks
Posts: 78
Joined: Thu Sep 02, 2010 2:43 pm
Location: Université Libre de Bruxelles

Re: Use of one box to trigger another

Post by karthiks »

Dear Dieter,

I think it may be easier and faster for me to just take a train to Ghent :p

So, the first idea worked out. I feel quite stupid for not realising it before -

Code: Select all

if(m_vDecoders[i]->isBufferReceived())
			{
				OpenViBE::Kernel::TParameterHandler <IStimulationSet*> l_oStimulationSet = m_oStimEncoder.getInputStimulationSet();
				uint64 l_ui64CurrentTime = getPlayerContext().getCurrentTime();
				IMatrix* l_pMatrix = m_oSignalDecoder.getOutputMatrix();
				float64* l_pBuffer = l_pMatrix->getBuffer();
				if(*l_pBuffer > m_f64Threshold)
				{
					uint64 l_ui32Stimulationflag = this->getTypeManager().getEnumerationEntryValueFromName(OV_TypeId_Stimulation,"OVTK_StimulationId_Start");
					l_oStimulationSet->appendStimulation(l_ui32Stimulationflag, l_ui64CurrentTime,0);
				}
				m_vEncoders[i]->encodeBuffer(i);
			}
But, the new problem now is that there is a continous stream of Stimulations even though the "if loop" is not satisfied. Any ideas for the solution?

Edit: For now, I have moved the

Code: Select all

m_vEncoders[i]->encodeBuffer(i);
in to the loop

Code: Select all

if(*l_pBuffer > m_f64Threshold)
				{
					uint64 l_ui32Stimulationflag = this->getTypeManager().getEnumerationEntryValueFromName(OV_TypeId_Stimulation,"OVTK_StimulationId_Start");
					l_oStimulationSet->appendStimulation(l_ui32Stimulationflag, l_ui64CurrentTime,0);
m_vEncoders[i]->encodeBuffer(i);
				}
I don't think that is a good solution so any help is appreciated.
Regards,

Karthik

ddvlamin
Posts: 160
Joined: Thu Aug 13, 2009 8:39 am
Location: Ghent University
Contact:

Re: Use of one box to trigger another

Post by ddvlamin »

karthiks wrote:Dear Dieter,

I think it may be easier and faster for me to just take a train to Ghent :p
Hehe, true. What research are you doing or which project are you involved in? I tried to find something on the ULB site related to brain-related research, but could not immediately find anything.
karthiks wrote:So, the first idea worked out. I feel quite stupid for not realising it before -

Code: Select all

if(m_vDecoders[i]->isBufferReceived())
			{
				OpenViBE::Kernel::TParameterHandler <IStimulationSet*> l_oStimulationSet = m_oStimEncoder.getInputStimulationSet();
				uint64 l_ui64CurrentTime = getPlayerContext().getCurrentTime();
				IMatrix* l_pMatrix = m_oSignalDecoder.getOutputMatrix();
				float64* l_pBuffer = l_pMatrix->getBuffer();
				if(*l_pBuffer > m_f64Threshold)
				{
					uint64 l_ui32Stimulationflag = this->getTypeManager().getEnumerationEntryValueFromName(OV_TypeId_Stimulation,"OVTK_StimulationId_Start");
					l_oStimulationSet->appendStimulation(l_ui32Stimulationflag, l_ui64CurrentTime,0);
				}
				m_vEncoders[i]->encodeBuffer(i);
			}
But, the new problem now is that there is a continous stream of Stimulations even though the "if loop" is not satisfied. Any ideas for the solution?
Ok, great to see that you already managed to get some stimulations at the output. Concerning the new problem, the following two ideas just came to my mind (however I'm not an expert so it's just an idea): if it still outputs stimulations while it is not in the if loop then this means the stimulations of the previous call are still saved in the input of the encoder which your variable l_oStimulationSet is pointing to. Maybe it helps to first set the stimulation count to zero each time the process function is called?

Code: Select all

l_oStimulationSet->setStimulationCount(0);
A second idea, do you mark each chunk as "ready to send" with

Code: Select all

l_rDynamicBoxContext.markOutputAsReadyToSend(...)
as this sets the chunk size to zero again till the next call to process?

Best regards,
Dieter

karthiks
Posts: 78
Joined: Thu Sep 02, 2010 2:43 pm
Location: Université Libre de Bruxelles

Re: Use of one box to trigger another

Post by karthiks »

ddvlamin wrote: Ok, great to see that you already managed to get some stimulations at the output. Concerning the new problem, the following two ideas just came to my mind (however I'm not an expert so it's just an idea): if it still outputs stimulations while it is not in the if loop then this means the stimulations of the previous call are still saved in the input of the encoder which your variable l_oStimulationSet is pointing to. Maybe it helps to first set the stimulation count to zero each time the process function is called?

Code: Select all

l_oStimulationSet->setStimulationCount(0);
This worked perfectly :D
ddvlamin wrote: A second idea, do you mark each chunk as "ready to send" with

Code: Select all

l_rDynamicBoxContext.markOutputAsReadyToSend(...)
as this sets the chunk size to zero again till the next call to process?
This was already implemented :)
ddvlamin wrote:
Hehe, true. What research are you doing or which project are you involved in? I tried to find something on the ULB site related to brain-related research, but could not immediately find anything.
I work with Prof. Cheron http://www.cheron.be/ on MINDWALKER https://mindwalker-project.eu/ :)
Regards,

Karthik

ddvlamin
Posts: 160
Joined: Thu Aug 13, 2009 8:39 am
Location: Ghent University
Contact:

Re: Use of one box to trigger another

Post by ddvlamin »

Ok, glad it works.

Shame on me, I didn't know of this project, it is missing on my list of European BCI projects :) It seems a quite large and ambitious project. Do you already have a working brain-controlled exoskeleton or is this planned as a demo for the end of the project?

I assume you are also working with the ANT amplifiers as Dr. Zanow is a partner in this project?

Best,
Dieter

karthiks
Posts: 78
Joined: Thu Sep 02, 2010 2:43 pm
Location: Université Libre de Bruxelles

Re: Use of one box to trigger another

Post by karthiks »

ddvlamin wrote:Ok, glad it works.

Shame on me, I didn't know of this project, it is missing on my list of European BCI projects :) It seems a quite large and ambitious project. Do you already have a working brain-controlled exoskeleton or is this planned as a demo for the end of the project?

I assume you are also working with the ANT amplifiers as Dr. Zanow is a partner in this project?

Best,
Dieter
Heh, shame on us that we are not so known :)

We are progressing towards the exoskeleton and most probably at the end of project, there should be a demo.

Yea, we are working with ANT amplifiers. We also have a Emotiv cap but it is not so useful for motor imagery tasks.
Last edited by karthiks on Tue Oct 18, 2011 3:10 pm, edited 1 time in total.
Regards,

Karthik

karthiks
Posts: 78
Joined: Thu Sep 02, 2010 2:43 pm
Location: Université Libre de Bruxelles

Re: Use of one box to trigger another

Post by karthiks »

Hey Dieter,

One last question, if we have an algorithm that generates our results at different points in the algorithm. for ex. we need x, y and z but they are calculated at different points in the algorithm. How do we pass them as output?

I am using a StreamedMatrixEncoder here.
Regards,

Karthik

Post Reply