Commit 263f0197 authored by Jozef Legeny's avatar Jozef Legeny

openvibe-scenarios/bci/ssvep:

merged branch wip-jlegeny -r 2583:2848 resulting in following changes:
+ added scenarios for the SSVEP paradigm
+ added monitoring, configuration, acquisition, training and online-testing scenarios
+ added various helper lua scripts
+ added folders destined to contain generated files
+ added an example EEG signal recording for SSVEP training



git-svn-id: svn://scm.gforge.inria.fr/svn/openvibe@2849 c330d7e9-fc0c-0410-a5b3-fd85c6f5aa8f
parent ec06edc1
<OpenViBE-SettingsOverride>
<SettingValue>${Path_Samples}/bci/ssvep/scripts/configuration-experiment-settings.lua</SettingValue>
<SettingValue>100,0,0</SettingValue>
<SettingValue>0,0,0</SettingValue>
<SettingValue>20;15;12</SettingValue>
<SettingValue>0.5</SettingValue>
<SettingValue>0.1</SettingValue>
<SettingValue>0.250</SettingValue>
</OpenViBE-SettingsOverride>
<OpenViBE-SettingsOverride>
<SettingValue>${Path_Samples}/bci/ssvep/scripts/training-acquisition-controller.lua</SettingValue>
<SettingValue>0 2 3 1 2 1 0 3 1 2 3 0 2 0 3 1 0 3 1 2 3 0 1 2 1 3 2 0 3 2 0 1 </SettingValue>
<SettingValue>7.000000</SettingValue>
<SettingValue>4.000000</SettingValue>
<SettingValue>1.000000</SettingValue>
<SettingValue>0.3;0.3</SettingValue>
<SettingValue>(0.0;0.0);(0.0;0.5);(-0.5;0.0);(0.5;0.0)</SettingValue>
</OpenViBE-SettingsOverride>
\ No newline at end of file
dofile("../share/openvibe-plugins/stimulation/lua-stimulator-stim-codes.lua")
flip_count = 0
switched_flip_count = 0
flips = {}
function initialize(box)
flip_count = box:get_input_count()
for i = 1, flip_count do
flips[i] = false
end
end
function uninitialize(box)
end
function process(box)
while switched_flip_count < flip_count do
for i = 1, flip_count do
if box:get_stimulation_count(i) > 0 then
box:remove_stimulation(i, 1)
if not flips[i] then
switched_flip_count = switched_flip_count + 1
flips[i] = true
io.write("Flip ", i, " of ", flip_count, " switched\n")
end
end
end
box:sleep()
end
box:send_stimulation(1, OVTK_StimulationId_Label_00, box:get_current_time())
end
dofile("../share/openvibe-plugins/stimulation/lua-stimulator-stim-codes.lua")
targets = {}
non_targets = {}
sent_stimulation = 0
function initialize(box)
-- read the parameters of the box
s_targets = box:get_setting(2)
for t in s_targets:gmatch("%d+") do
targets[t + 0] = true
end
s_non_targets = box:get_setting(3)
for t in s_non_targets:gmatch("%d+") do
non_targets[t + 0] = true
end
sent_stimulation = _G[box:get_setting(4)]
end
function uninitialize(box)
end
function process(box)
finished = false
while not finished do
time = box:get_current_time()
while box:get_stimulation_count(1) > 0 do
s_code, s_date, s_duration = box:get_stimulation(1, 1)
box:remove_stimulation(1, 1)
if s_code >= OVTK_StimulationId_Label_00 and s_code <= OVTK_StimulationId_Label_1F then
received_stimulation = s_code - OVTK_StimulationId_Label_00
if targets[received_stimulation] ~= nil then
box:send_stimulation(1, sent_stimulation, time)
elseif non_targets[received_stimulation] ~= nil then
box:send_stimulation(2, sent_stimulation, time)
end
elseif s_code == OVTK_StimulationId_ExperimentStop then
finished = true
end
end
box:sleep()
end
end
dofile("../share/openvibe-plugins/stimulation/lua-stimulator-stim-codes.lua")
stimulation_frequencies = {}
frequency_count = 0
target_light_color = {}
target_dark_color = {}
training_target_size = {}
training_targets_positions = {}
processing_epoch_duration = nil
processing_epoch_interval = nil
processing_frequency_tolerance = nil
function initialize(box)
for value in box:get_setting(2):gmatch("%d+") do
table.insert(target_light_color, value)
end
for value in box:get_setting(3):gmatch("%d+") do
table.insert(target_dark_color, value)
end
for value in box:get_setting(4):gmatch("%d+[.]?%d*") do
table.insert(stimulation_frequencies, value)
frequency_count = frequency_count + 1
end
processing_epoch_duration = box:get_setting(5)
processing_epoch_interval = box:get_setting(6)
processing_frequency_tolerance = box:get_setting(7)
end
function uninitialize(box)
end
function process(box)
while box:get_stimulation_count(1) == 0 do
box:sleep()
end
box:log("Info", box:get_config("Writing additional configuration to '${CustomConfigurationPrefix${OperatingSystem}}-ssvep-demo${CustomConfigurationSuffix${OperatingSystem}}'"))
cfg_file = io.open(box:get_config("${CustomConfigurationPrefix${OperatingSystem}}-ssvep-demo${CustomConfigurationSuffix${OperatingSystem}}"), "a")
cfg_file:write("SSVEP_TargetLightColourRed = ", target_light_color[1] / 100, "\n")
cfg_file:write("SSVEP_TargetLightColourGreen = ", target_light_color[2] / 100, "\n")
cfg_file:write("SSVEP_TargetLightColourBlue = ", target_light_color[3] / 100, "\n")
cfg_file:write("SSVEP_TargetDarkColourRed = ", target_dark_color[1] / 100, "\n")
cfg_file:write("SSVEP_TargetDarkColourGreen = ", target_dark_color[2] / 100, "\n")
cfg_file:write("SSVEP_TargetDarkColourBlue = ", target_dark_color[3] / 100, "\n")
for i=1,frequency_count do
cfg_file:write("SSVEP_Frequency_", i, " = ", string.format("%g", stimulation_frequencies[i]), "\n")
end
cfg_file:close()
-- create configuration files for temporal filters
for i=1,frequency_count do
box:log("Info", string.format("Writing file '../share/openvibe-scenarios/bci/ssvep/configuration/temporal-filter-freq-%d.cfg'", i))
cfg_file = io.open(string.format("../share/openvibe-scenarios/bci/ssvep/configuration/temporal-filter-freq-%d.cfg", i), "w")
cfg_file:write("<OpenViBE-SettingsOverride>\n")
cfg_file:write("<SettingValue>Butterworth</SettingValue>\n")
cfg_file:write("<SettingValue>Band pass</SettingValue>\n")
cfg_file:write("<SettingValue>4</SettingValue>\n")
cfg_file:write(string.format("<SettingValue>%g</SettingValue>\n", stimulation_frequencies[i] - processing_frequency_tolerance))
cfg_file:write(string.format("<SettingValue>%g</SettingValue>\n", stimulation_frequencies[i] + processing_frequency_tolerance))
cfg_file:write("<SettingValue>0.500000</SettingValue>\n")
cfg_file:write("</OpenViBE-SettingsOverride>\n")
cfg_file:close()
end
-- create configuration file for time based epoching
box:log("Info", "Writing file '../share/openvibe-scenarios/bci/ssvep/configuration/time-based-epoching.cfg'")
cfg_file = io.open("../share/openvibe-scenarios/bci/ssvep/configuration/time-based-epoching.cfg", "w")
cfg_file:write("<OpenViBE-SettingsOverride>\n")
cfg_file:write(string.format("<SettingValue>%g</SettingValue>\n", processing_epoch_duration))
cfg_file:write(string.format("<SettingValue>%g</SettingValue>\n", processing_epoch_interval))
cfg_file:write("</OpenViBE-SettingsOverride>\n")
cfg_file:close()
-- notify the scenario that the configuration process is complete
box:send_stimulation(1, OVTK_StimulationId_TrainCompleted, box:get_current_time() + 0.2, 0)
end
dofile("../share/openvibe-plugins/stimulation/lua-stimulator-stim-codes.lua")
vrpn_host = nil
vrpn_port = nil
screen_refresh_rate = nil
function initialize(box)
screen_refresh_rate = box:get_setting(2)
end
function uninitialize(box)
end
function process(box)
box:log("Info", box:get_config("Generating '${CustomConfigurationPrefix${OperatingSystem}}-ssvep-demo${CustomConfigurationSuffix${OperatingSystem}}'"))
cfg_file = io.open(box:get_config("${CustomConfigurationPrefix${OperatingSystem}}-ssvep-demo${CustomConfigurationSuffix${OperatingSystem}}"), "w")
cfg_file:write("# This file was automatically generated!\n\n")
cfg_file:write("# If you want to change the SSVEP configuration\n")
cfg_file:write("# please use the provided ssvep-configuration scenario.\n")
cfg_file:write("SSVEP_ScreenRefreshRate = ", screen_refresh_rate, "\n")
cfg_file:close()
box:send_stimulation(1, OVTK_StimulationId_TrainCompleted, box:get_current_time() + 0.2, 0)
end
buffer = {}
function initialize(box)
end
function uninitialize(box)
end
-- This script receives stimulations and lets pass only every other one
-- for each stimulation code
-- Useful to remove "key up" events of keyboard stimulator
function process(box)
while (true) do
for index = 1, box:get_stimulation_count(1) do
stimulation = box:get_stimulation(1, index)
if buffer[stimulation] == nil then
box:send_stimulation(1, stimulation, box:get_current_time(), 0)
buffer[stimulation] = 1
else
buffer[stimulation] = nil
end
box:remove_stimulation(1, 1)
end
box:sleep()
end
end
dofile("../share/openvibe-plugins/stimulation/lua-stimulator-stim-codes.lua")
class_count = 0
function initialize(box)
class_count = box:get_setting(2)
end
function uninitialize(box)
end
function process(box)
local finished = false
while not finished do
time = box:get_current_time()
while box:get_stimulation_count(1) > 0 do
local decision = 0
local decided = false
-- check each input
for i = 1, class_count do
-- if the frequency is considered as stimulated
if (box:get_stimulation(i, 1) - OVTK_StimulationId_Label_00 == 1) then
if not decided then
decision = i
decided = true
else
decision = 0
end
end
box:remove_stimulation(i, 1)
end
if decision ~= 0 then
box:send_stimulation(1, OVTK_StimulationId_Label_00 + decision - 1, box:get_current_time() + 0.01, 0)
end
end
box:sleep()
end
end
dofile("../share/openvibe-plugins/stimulation/lua-stimulator-stim-codes.lua")
sequence = {}
flickeringDelay = nil
function initialize(box)
s_sequence = box:get_setting(2)
io.write(string.format("Target Sequence : [%s]\n", s_sequence))
for target in s_sequence:gmatch("%d+") do
table.insert(sequence, target)
end
end
function uninitialize(box)
end
function process(box)
-- while targets are available, send a stimulation with new target
-- position for each request
while true do
if box:get_stimulation_count(1) > 0 then
identifier, date, duration = box:get_stimulation(1, 1)
if identifier == OVTK_StimulationId_Target then
current_time = box:get_current_time() + 1
-- if no targets are available, quit the game
if # sequence == 0 then
box:send_stimulation(1, OVTK_StimulationId_ExperimentStop, current_time, 0)
break
end
next_target = sequence[1]
table.remove(sequence, 1)
box:send_stimulation(1, OVTK_StimulationId_Label_00 + next_target , current_time, 0)
end
box:remove_stimulation(1, 1)
end
box:sleep()
end
end
delay = 1
function initialize(box)
s_delay = box:get_setting(2);
io.write(string.format("Delay : [%s]\n", s_delay))
if (s_delay:find("^%d+$") ~= nil) then
delay = tonumber(s_delay)
else
io.write("[ERROR] The parameter should be a numeric value\n")
end
end
function uninitialize(box)
end
function process(box)
box:send_stimulation(1, 0x00008001, delay, 0)
end
dofile("../share/openvibe-plugins/stimulation/lua-stimulator-stim-codes.lua")
sequence = {}
number_of_cycles = 0
stimulation_duration = nil
break_duration = nil
flickering_delay = nil
target_width = nil
target_height = nil
target_positions = {}
number_of_targets = {}
stimulationLabels = {
0x00008100,
0x00008101,
0x00008102,
0x00008103,
0x00008104,
0x00008105,
0x00008106,
0x00008107
}
function initialize(box)
-- load the goal sequence
s_sequence = box:get_setting(2)
for target in s_sequence:gmatch("%d+") do
table.insert(sequence, target)
number_of_cycles = number_of_cycles + 1
end
box:log("Info", string.format("Number of goals in sequence: [%d]", number_of_cycles))
-- get the duration of a stimulation sequence
s_stimulation_duration = box:get_setting(3)
if (s_stimulation_duration:find("^%d+[.]?%d*$") ~= nil) then
stimulation_duration = tonumber(s_stimulation_duration)
box:log("Info", string.format("Stimulation Duration : [%g]", stimulation_duration))
else
box:log("Error", "The parameter 'stimulation duration' must be a numeric value\n")
error()
end
-- get the duration of a break between stimulations
s_break_duration = box:get_setting(4)
if (s_break_duration:find("^%d+[.]?%d*$") ~= nil) then
break_duration = tonumber(s_break_duration)
box:log("Info", string.format("Break Duration : [%s]", s_break_duration))
else
box:log("Error", "The parameter 'break duration' must be a numeric value\n")
error()
end
-- get the delay between the appearance of the marker and the start of flickering
s_flickering_delay = box:get_setting(5)
if (s_flickering_delay:find("^%d+[.]?%d*$") ~= nil) then
flickering_delay = tonumber(s_flickering_delay)
box:log("Info", string.format("Flickering Delay : [%s]", s_flickering_delay))
else
box:log("Error", "The parameter 'flickering delay' must be a numeric value\n")
error()
end
-- get the target size
s_targetSize = box:get_setting(6)
s_width, s_height = s_targetSize:match("^(%d+[.]?%d*);(%d+[.]?%d*)$")
target_width = tonumber(s_width)
target_height = tonumber(s_height)
if s_width ~= nil and s_height ~= nil then
box:log("Info", string.format("Target dimensions : width = %g, height = %g", target_width, target_height))
else
box:log("Error", "The parameter 'target size' must be in format float;float")
error()
end
-- get the targets' positions
s_targetPositions = box:get_setting(7)
number_of_targets = 0
for s_target_x, s_target_y in s_targetPositions:gmatch("(-?%d+[.]?%d*);(-?%d+[.]?%d*)") do
box:log("Info", string.format("Target %d : x = %g y = %g", number_of_targets, tonumber(s_target_x), tonumber(s_target_y)))
table.insert(target_positions, {tonumber(s_target_x), tonumber(s_target_y)})
number_of_targets = number_of_targets + 1
end
-- create the configuration file for the stimulation-based-epoching
-- this file is used during classifier training only
cfg_file = io.open("../share/openvibe-scenarios/bci/ssvep/configuration/stimulation-based-epoching.cfg", "w")
cfg_file:write("<OpenViBE-SettingsOverride>\n")
cfg_file:write(" <SettingValue>", stimulation_duration, "</SettingValue>\n")
cfg_file:write(" <SettingValue>", flickering_delay, "</SettingValue>\n")
cfg_file:write(" <SettingValue>OVTK_StimulationId_Target</SettingValue>\n")
cfg_file:write("</OpenViBE-SettingsOverride>\n")
cfg_file:close()
-- create the configuration file for the training program
cfg_file = io.open(box:get_config("${CustomConfigurationPrefix${OperatingSystem}}-ssvep-demo-training${CustomConfigurationSuffix${OperatingSystem}}"), "w")
cfg_file:write("# This file was automatically generated!\n\n")
cfg_file:write("# If you want to change the SSVEP trainer configuration\n")
cfg_file:write("# please use the box settings in the training scenario.\n\n")
cfg_file:write("SSVEP_TargetCount = ", number_of_targets, "\n")
cfg_file:write("SSVEP_TargetWidth = ", target_width, "\n")
cfg_file:write("SSVEP_TargetHeight = ", target_height, "\n")
for target_index, position in ipairs(target_positions) do
cfg_file:write("SSVEP_Target_X_", target_index - 1, " = ", position[1], "\n")
cfg_file:write("SSVEP_Target_Y_", target_index - 1, " = ", position[2], "\n")
end
cfg_file:close()
end
function uninitialize(box)
end
function process(box)
while box:get_stimulation_count(1) == 0 do
box:sleep()
end
current_time = box:get_current_time() + 1
box:send_stimulation(1, OVTK_StimulationId_ExperimentStart, current_time, 0)
current_time = current_time + 2
for i,target in ipairs(sequence) do
box:log("Info", string.format("Goal no %d is %d at %d", i, target, current_time))
-- mark goal
box:send_stimulation(2, OVTK_StimulationId_LabelStart + target, current_time, 0)
-- wait for Flickering_delay seconds
current_time = current_time + flickering_delay
-- start flickering
box:send_stimulation(1, OVTK_StimulationId_VisualStimulationStart, current_time, 0)
-- wait for Stimulation_duration seconds
current_time = current_time + stimulation_duration
-- unmark goal and stop flickering
box:send_stimulation(1, OVTK_StimulationId_VisualStimulationStop, current_time, 0)
-- wait for Break_duration seconds
current_time = current_time + break_duration
end
box:send_stimulation(1, OVTK_StimulationId_ExperimentStop, current_time, 0)
box:sleep()
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment