Skip to content

Commit 38cadae

Browse files
committed
new stimulation method and bitAcc transfer for stimulation weight update
1 parent ab6bc2a commit 38cadae

File tree

7 files changed

+102
-36
lines changed

7 files changed

+102
-36
lines changed

bci_Process_FreeMode.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ function bci_Process_FreeMode()
6464
if isTrialEnd
6565
if bitAcc > 0
6666
bitACCs = [bitACCs,bitAcc];
67+
68+
vepstim.updateWeights(bitAcc);
6769
end
6870
% clear remote buffer
6971
if strcmp(settings.modelType,'remote')

example1.m

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
settings = struct();
1616
settings.monitorResolution = [1920,1080];
1717
settings.monitorRefreshRate = 60;
18-
settings.stimulation = 'random';
19-
settings.layout = 'keyboard';
18+
settings.stimulation = 'optimal';
19+
settings.layout = 'qwertz';
2020
settings.windowSize = 'fullscreen';
2121
settings.startWait = 0;
2222
settings.trialTime = 10;
@@ -28,6 +28,13 @@
2828
max_correlation_coef = 0.6;
2929
seq_generator(sequence_number, bit_size, max_correlation_coef);
3030

31+
settings.stimSettings.monitorRefreshRate = 60;
32+
settings.stimSettings.framesPerStimulus = 1;
33+
34+
layout.numTargets = 55.0;
35+
stimulation = feval(['stimulation_' settings.stimulation],layout.numTargets,settings.stimSettings);
36+
stimulation.setTargetSequences();
37+
3138
% initialize experiment object without TCP/IP server and debug enabled
3239
experiment = vep_experiment(screenNumber,'tcpip',false,'settings',settings,'debug',false);
3340
% Save screenshot

seq_generator.asv

Lines changed: 0 additions & 26 deletions
This file was deleted.

seq_generator.m

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
function seq_generator(sequence_number, bit_size, max_correlation_coef)
2-
3-
if ~bit_size, bit_number = 20; end
4-
if ~sequence_number, sequence_number = 20; end
5-
if ~max_correlation_coef, max_correlation_coef = 0.8; end
2+
3+
if ~bit_size, bit_number = 20; end %number of bits in one sequence
4+
if ~sequence_number, sequence_number = 200; end %number of sequences generated
5+
if ~max_correlation_coef, max_correlation_coef = 0.8; end %maximum correlation coefficient between seqs
66

77

88
randomBinaryNumbers = transpose(randi([0, 1], sequence_number, bit_size));
9-
R = corrcoef(randomBinaryNumbers);
10-
9+
R = corrcoef(randomBinaryNumbers);
1110
[row, column, ] = find(triu(R,1) > max_correlation_coef);
1211

1312
while ~isempty(row)
@@ -18,7 +17,8 @@ function seq_generator(sequence_number, bit_size, max_correlation_coef)
1817
R = corrcoef(randomBinaryNumbers);
1918
[row, column, ] = find(triu(R,1) > max_correlation_coef);
2019
end
21-
randomBinaryNumbers = transpose(randomBinaryNumbers);
22-
csvwrite('random_seq_pool.csv', randomBinaryNumbers);
20+
randomBinaryNumbers = transpose(randomBinaryNumbers);
2321

22+
csvwrite('random_seq_pool.csv', randomBinaryNumbers);
23+
csvwrite('random_seq_weights.csv', cat(1,ones(1,sequence_number)./sequence_number,zeros(1,sequence_number)));
2424
end
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
classdef stimulation_optimal < stimulation
2+
%STIMULATION_PREDEFINED - stimulation using predefined sequences
3+
4+
properties
5+
randstream; %the random stream
6+
sequences; %sequence pool
7+
weights; %sequence weigths and occurances
8+
targetseq; %sequences assigned to targets
9+
end
10+
11+
methods
12+
function this = stimulation_optimal(numTargets,varargin)
13+
%STIMULATION_PREDEFINED - stimulation using predefined sequences
14+
% STIMULATION_PREDIFINED(numTargets,csvfile,seed)
15+
% CSVFILE - csv file with sequences
16+
% SEED - random seed used to randomly assign sequences to targets
17+
this@stimulation(numTargets,varargin{:});
18+
p = inputParser;
19+
p.StructExpand = true;
20+
p.KeepUnmatched = true;
21+
addParameter(p,'sequencePool','random_seq_pool.csv',@(x) ischar(x) && exist(x, 'file') == 2);
22+
addParameter(p,'sequenceWeights','random_seq_weights.csv',@(x) ischar(x) && exist(x, 'file') == 2);
23+
addParameter(p,'randomseed',1,@(x) helper.isint(x) && length(x) == 1);
24+
parse(p,varargin{:});
25+
26+
this.randstream = RandStream('mt19937ar','Seed',p.Results.randomseed);
27+
this.sequences = csvread(p.Results.sequencePool)';
28+
this.weights = csvread(p.Results.sequenceWeights)';
29+
end
30+
31+
function setTargetSequences(this)
32+
%SETTARGETSEQUENCES - assign random sequence of the sequence pool to each target
33+
if size(this.sequences,2) > this.numTargets
34+
% get random subset if pool has more sequences as targets
35+
% tmp_weights = this.weights(:,1)./size(this.weights,1);
36+
tmp_weights = this.weights(:,1);
37+
subset = zeros(1, this.numTargets);
38+
% subset = randsample( size(this.sequences,2), this.numTargets, false, this.weights(1,:)./size(this.weights,2));
39+
for i = 1:this.numTargets
40+
subnet_new_idx = randsample(this.randstream, size(this.sequences,2), 1, true, tmp_weights);
41+
tmp_weights(subnet_new_idx) = 0;
42+
subset(i) = subnet_new_idx;
43+
end
44+
45+
elseif size(this.sequences,2) == this.numTargets
46+
% if number of sequences equals number of targets
47+
subset = 1:this.numTargets;
48+
else
49+
error('setTargetSequences: too few sequences in sequence pool');
50+
end
51+
this.weights(subset,2) = this.weights(subset, 2) + 1;
52+
this.targetseq = this.sequences(:,subset);
53+
end
54+
55+
function updateWeights(this, bitAcc)
56+
%UPDATEWEIGHTS - update weights using newest bit prediction
57+
%accuracy
58+
this.weights(:, 1) = this.weights(:, 1) .* bitAcc;
59+
end
60+
61+
function bits = next(this,lostBits)
62+
%NEXT - returns the next bits of the sequence pool for each target
63+
%call super method
64+
next@stimulation(this,lostBits);
65+
if mod(this.stimPos-1,size(this.sequences,1))+1 == 1, this.setTargetSequences(); end
66+
bits = this.targetseq(mod(this.stimPos-1,size(this.sequences,1))+1,:);
67+
end
68+
end
69+
70+
end
71+

vepstim/vep_experiment.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,12 @@ function endTrial(this)
287287
this.stimulation.endTrial();
288288
end
289289

290+
function updateWeights(this,bitAcc)
291+
%updateWeights - update weights in stimulation using
292+
%updateWeights() function
293+
this.stimulation.updateWeights(bitAcc);
294+
end
295+
290296
function setInfoText(this,text,duration)
291297
%SETINFOTEXT - shows a info text on the screen
292298
% SETINFOTEXT(text,duration) - shows TEXT for DURATION seconds

vepstim/vep_operator.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ function console(this,text)
162162
this.send('console',text);
163163
end
164164

165+
function updateWeights(this, bitAcc)
166+
%UPDATEWEIGHTS - send bit prediction accuracy to vep_experiment and
167+
%update weights
168+
this.send('updateWeights', bitAcc);
169+
end
170+
165171
function info(this,text,varargin)
166172
%INFO - shows a info text on the screen
167173
% INFO(text) - show TEXT for 10 seconds

0 commit comments

Comments
 (0)