Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…into stephaniebrandl-lsl

conflicts resolved
  • Loading branch information
BenjaminBlankertz committed Jul 12, 2016
2 parents cebd8f8 + b9ee3e0 commit ebc7612
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 113 deletions.
12 changes: 5 additions & 7 deletions online/acquisition/bbci_acquire_lsl.m
Original file line number Diff line number Diff line change
Expand Up @@ -139,17 +139,15 @@
end
output= {state};
% close condition needs the 'state' structure.
elseif isequal(varargin{1}, 'close'),
if length(varargin)==1,
error('Please use ''close'' option with ''state'' variable as second argument: bbci_lsl_acquire(close, state)');
end
elseif isequal(varargin{1}, 'close') && istruct(varargin{2}),
elseif isequal(varargin{1}, 'close') && length(varargin)==1
error('Please use ''close'' option with ''state'' variable as second argument: bbci_lsl_acquire(close, state)');
elseif isequal(varargin{1}, 'close') && isstruct(varargin{2}),
% close inlets and libraries
state = varargin{2};
state.inlet.x.delete();
state.inlet.mrk.delete();
state.lib.delete();
output= {};
%state.lib.delete();
output= {state};

elseif length(varargin)~=1,
error('Except for INIT/CLOSE case, only one input argument expected');
Expand Down
26 changes: 26 additions & 0 deletions online/acquisition/utils/lsl_test_script.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
run = true;
last_mrk = '';

state_acquire= bbci_acquire_lsl('init');
cnt = zeros(64, 100);
mrk = zeros(1, 100);

step = 1;

while state_acquire.running
[cnt_new, cntTime, mrkTime, mrkDesc, state_acquire]= bbci_acquire_lsl(state_acquire);

if not(isempty(mrkDesc))
fprintf('RECEIVED %s\n', mrkDesc{1});
fprintf('TIME %f \n', mrkTime);
end

% fprintf('Data %s at %f \n', cnt_new, cntTime);
% fprintf('step %f \n', step)
% last_mrk = mrkDesc;
% last_mrkTime = mrkTime;
%
% cnt(:,step) = cnt_new;
step = step + 1;
end
display('Streams broke off')
3 changes: 2 additions & 1 deletion online/apply_functions/bbci_apply_queryMarker.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
% 02-2011 Benjamin Blankertz

% return if there is no quit marker
if isempty(mrkDesc),

if nargin<3 || isempty(mrkDesc)
marker_out= [];
return
end
Expand Down
2 changes: 1 addition & 1 deletion online/bbci_load.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
BC= bbci.calibrate;

% fullfile does not work for CELL, so we use strcat here:
if ~isempty(BC.folder), % if empty, assume absolute paths
if ~isempty(BC.folder) && ~fileutil_isAbsolutePath(BC.file),
data.filename= strcat(BC.folder, filesep, BC.file);
else
data.filename = BC.file;
Expand Down
1 change: 1 addition & 0 deletions online/calibration/bbci_calibrate_ERPSpeller.m
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@
if iscell(BC_result.rejected_clab), %% that means rejected_clab is not NaN
cidx= find(ismember(BC_result.clab, BC_result.rejected_clab));
BC_result.clab(cidx)= [];
BC_result.cfy_clab(cidx)= [];
end
end
else
Expand Down
66 changes: 33 additions & 33 deletions online/demos/demo_bbcionline_test_acquire_lsl.m
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
% DEMO_BBCIONLINE_APPLY_LSL_STREAMING
% this is just for testing / demonstrating the streaming of EEG data using
% lsl

% set up dummy classifier
C= struct('b', 0);
C.w= randn(8*2, 1); % 2 log-bandpower feature per channel

% setup the bbci variable to define the online processing chain
bbci= struct;
bbci.source.acquire_fcn= @bbci_acquire_lsl;

% define the dummy electrode setting
clab = {'AF5' 'AF3' 'AF1' 'AFz' 'AF2' 'AF4' 'AF6' ...
'F5' 'F3', 'F1' 'Fz' 'F2' 'F4' 'F6' ...
'FC7' 'FC5'};

bbci.signal.clab = clab;
% provide clab and markerstreamname to lsl acquire function
bbci.source.acquire_param = {'clab', clab, 'markerstreamname', 'MyMarkerStream'};

bbci.feature.proc= {@proc_variance, @proc_logarithm};
bbci.feature.ival= [-500 0];

bbci.classifier.C= C;

% specify file locations and logging
% bbci.log.output= 'screen&file';
% bbci.log.file= fullfile(BTB.DataDir, 'tmp\log');
bbci.source.record_signals = 0;
bbci.source.record_basename = fullfile(BTB.DataDir,'tmp\lsl_test');
bbci.quit_condition.running_time = 170;
bbci_apply(bbci);
% DEMO_BBCIONLINE_APPLY_LSL_STREAMING
% this is just for testing / demonstrating the streaming of EEG data using
% lsl

% set up dummy classifier
C= struct('b', 0);
C.w= randn(8*2, 1); % 2 log-bandpower feature per channel

% setup the bbci variable to define the online processing chain
bbci= struct;
bbci.source.acquire_fcn= @bbci_acquire_lsl;

% define the dummy electrode setting
clab = {'AF5' 'AF3' 'AF1' 'AFz' 'AF2' 'AF4' 'AF6' ...
'F5' 'F3', 'F1' 'Fz' 'F2' 'F4' 'F6' ...
'FC7' 'FC5'};

bbci.signal.clab = clab;
% provide clab and markerstreamname to lsl acquire function
bbci.source.acquire_param = {'clab', clab, 'markerstreamname', 'MyMarkerStream'};

bbci.feature.proc= {@proc_variance, @proc_logarithm};
bbci.feature.ival= [-500 0];

bbci.classifier.C= C;

% specify file locations and logging
% bbci.log.output= 'screen&file';
% bbci.log.file= fullfile(BTB.DataDir, 'tmp\log');
bbci.source.record_signals = 0;
bbci.source.record_basename = fullfile(BTB.DataDir,'tmp\lsl_test');
bbci.quit_condition.running_time = 170;
bbci_apply(bbci);
138 changes: 71 additions & 67 deletions online/utils/trigger/bbci_trigger_lsl.m
Original file line number Diff line number Diff line change
@@ -1,67 +1,71 @@
function bbci_trigger_lsl(value, varargin)
%BBCI_TRIGGER_LSL Sends triggers using LabStreaminglayer
% Sends trigger using the marker stream outlet defined in the
% labstreaminglayer
%
% value trigger value, numeric or 'init' or 'close' case
% varargin the argument given bbci_trigger: BTB.Acq.TriggerParam{:}.
% In any case it should contain an LSL stream outlet of the
% marker stream.

% NOTE: The case that bbci.trigger.param{:} contains the lsl
% stream is not enough because we dont have access to bbci struct
% in this function in order to close the connection.


global BTB

if ischar(value) && strcmp(value, 'init'),
if ~isdir('liblsl-Matlab')
error('LSL Toolbox is not on the path. add it via addpath(genpath(''path_to_LSL/liblsl-Matlab''))')
end
% open LSL library to check for marker stream
lib = lsl_loadlib();
mrks = lsl_resolve_byprop(lib, 'name', 'MyMarkerStream', 1, 1);
% if there is no marker stream, then open one and save it in global BTB
% structure.
if isempty(mrks)
source_id = ['sourceID' num2str(randi(50000))];
mrk_info = lsl_streaminfo(lib,'MyMarkerStream','Markers',1,1,'cf_string',source_id);
% get the lsl stream outlet and save it as well as the lsl info object in BTB struct
BTB.Acq.TriggerParam = {lsl_outlet(mrk_info), mrk_info};
BTB.Acq.TriggerFcn = @bbci_trigger_lsl;
fprintf(['Started LSL marker stream with source id ' source_id '\n']);
else
% if there is a stream it has to be closed because otherwise the
% acquire function might connect to the wrong stream.
error(['There is a markerstream with ID ' BTB.Acq.LSLsourceID ' on the network, use bbci_trigger_lsl(''close'') first!']);
end
elseif ischar(value) && strcmp(value, 'close'),
% try to close LSL marker stream
try
BTB.Acq.TriggerParam{1}.delete();
BTB.Acq.TriggerParam{2}.delete();

catch
warning('There is no BTB struct or no LSL Markerstream with name MyMarkerStream to close.');
end

elseif isnumeric(value)
% hack to meet the format of the lsl marker stream and mimic the pp
% marker format: 'S <markervalue>'
marker = cat(2, 'S ', num2str(value));
% In case someone only sets bbci.trigger.fcn = @bbci_trigger_lsl
if isempty(varargin),
error('LSL marker stream was not set up correcty. Set BTB.Acq.TriggerFcn = @bbci_trigger_lsl and use ''bbci_trigger(''init'')'' ');
end
% push sample to marker stream outlet
try
varargin{1}.push_sample({marker});
catch
error('LSL marker stream was not set up correcty. First use ''bbci_trigger(''init'')'', then ''bbci_trigger(value)''');
end
else
warning('The trigger has to be numeric or ''init'' or ''close'' : no trigger was sent')
end
end

function bbci_trigger_lsl(value, varargin)
%BBCI_TRIGGER_LSL Sends triggers using LabStreaminglayer
% Sends trigger using the marker stream outlet defined in the
% labstreaminglayer
%
% value trigger value, numeric or 'init' or 'close' case
% varargin the argument given bbci_trigger: BTB.Acq.TriggerParam{:}.
% In any case it should contain an LSL stream outlet of the
% marker stream.

% NOTE: The case that bbci.trigger.param{:} contains the lsl
% stream is not enough because we dont have access to bbci struct
% in this function in order to close the connection.

% 11-2015 Jan Boelts


global BTB

if ischar(value) && strcmp(value, 'init'),
if ~isdir('liblsl-Matlab')
error('LSL Toolbox is not on the path. add it via addpath(genpath(''path_to_LSL/liblsl-Matlab''))')
end
% open LSL library to check for marker stream
lib = lsl_loadlib();
mrks = lsl_resolve_byprop(lib, 'name', 'MyMarkerStream', 1, 1);
% if there is no marker stream, then open one and save it in global BTB
% structure.
if isempty(mrks)
source_id = ['sourceID' num2str(randi(50000))];
mrk_info = lsl_streaminfo(lib,'MyMarkerStream','Markers',1,1,'cf_string',source_id);
% get the lsl stream outlet and save it as well as the lsl info object in BTB struct
BTB.Acq.TriggerParam = {lsl_outlet(mrk_info), mrk_info};
BTB.Acq.TriggerFcn = @bbci_trigger_lsl;
BTB.Acq.LSLsourceID = source_id;
fprintf(['Started LSL marker stream with source id ' source_id '\n']);
else
% if there is a stream it has to be closed because otherwise the
% acquire function might connect to the wrong stream.
error(['There is a markerstream with ID ' BTB.Acq.LSLsourceID ' on the network, use bbci_trigger(''close'') first!']);
end
elseif ischar(value) && strcmp(value, 'close'),
% try to close LSL marker stream
try
BTB.Acq.TriggerParam{1}.delete();
BTB.Acq.TriggerParam{2}.delete();

catch
warning('There is no BTB struct or no LSL Markerstream with name MyMarkerStream to close.');
end

elseif isnumeric(value)
% hack to meet the format of the lsl marker stream and mimic the pp
% marker format: 'S <markervalue>'
marker = cat(2, 'S ', num2str(value));
% In case someone only sets bbci.trigger.fcn = @bbci_trigger_lsl
if isempty(varargin),
error('LSL marker stream was not set up correcty. Set BTB.Acq.TriggerFcn = @bbci_trigger_lsl and use ''bbci_trigger(''init'')'' ');
end
% push sample to marker stream outlet
try
varargin{1}.push_sample({marker});
catch
error('LSL marker stream was not set up correcty. First use ''bbci_trigger(''init'')'', then ''bbci_trigger(value)''');
end
else
warning('The trigger has to be numeric or ''init'' or ''close'' : no trigger was sent')
end
end

>>>>>>> b9ee3e0cb00b9a0abbd586a100c6a90147bdac3f
10 changes: 6 additions & 4 deletions processing/utils/reject_varEventsAndChannels.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@

props= { 'Whiskerperc' 10 'DOUBLE[1]'
'Whiskerlength' 3 'DOUBLE[1]'
'TrialThresholdPercChannels' 0.2 'DOUBLE[1]'
'DoMultipass' 0 'BOOL'
'DoChannelMultipass' 0 'BOOL'
'DoRelVar' 0 'BOOL'
'DoUnstabChans' 1 'BOOL'
'DoSilentChans' 1 'BOOL'
Expand Down Expand Up @@ -106,11 +108,11 @@


%% first-pass trials: remove really bad trials
%% criterium: >= 20% of the channels have excessive variance
%% criterium: >= opt.TrialThresholdPercChannels (default 20%) of the channels have excessive variance
perc= stat_percentiles(V(:), [0 100] + [1 -1]*opt.Whiskerperc);
thresh= perc(2) + opt.Whiskerlength*diff(perc);
EX= ( V > thresh );
rTrials= find( mean(EX,1)>0.2 );
rTrials= find( mean(EX,1)>opt.TrialThresholdPercChannels );

V(:,rTrials)= [];
evGood(rTrials)= [];
Expand All @@ -137,7 +139,7 @@
if isempty(rC),
goon= 0;
end
goon= goon && opt.DoMultipass;
goon= goon && opt.DoChannelMultipass;
end
end

Expand Down Expand Up @@ -212,7 +214,7 @@
mrk= mrk_selectEvents(mrk, 'not', rTrials);

if opt.Verbose && ~isempty(rTrials),
fprintf('%d artifact trials removed due to variance criterion.\n', ...
fprintf('%d artifact trials detected due to variance criterion.\n', ...
numel(rTrials));
end

Expand Down

0 comments on commit ebc7612

Please sign in to comment.