Dateien hochladen nach „scenarios/scripts“
This commit is contained in:
parent
c98c71846b
commit
8f13f5f9c9
200
scenarios/scripts/p300-tactile-accumulator.lua
Normal file
200
scenarios/scripts/p300-tactile-accumulator.lua
Normal file
@ -0,0 +1,200 @@
|
||||
|
||||
function arrayMax(a)
|
||||
if #a == 0 then return nil, nil end
|
||||
local maxIdx, maxValue = 0, a[0]
|
||||
for i = 1, (#a -1 ) do
|
||||
if maxValue < a[i] then
|
||||
maxIdx, maxValue = i, a[i]
|
||||
end
|
||||
end
|
||||
return maxIdx, maxValue
|
||||
end
|
||||
|
||||
-- For handling target fifo
|
||||
|
||||
List = {}
|
||||
function List.new ()
|
||||
return {first = 0, last = -1}
|
||||
end
|
||||
|
||||
function List.pushright (list, value)
|
||||
local last = list.last + 1
|
||||
list.last = last
|
||||
list[last] = value
|
||||
end
|
||||
|
||||
function List.popleft (list)
|
||||
local first = list.first
|
||||
if first > list.last then
|
||||
error("list is empty")
|
||||
end
|
||||
local value = list[first]
|
||||
list[first] = nil -- to allow garbage collection
|
||||
list.first = first + 1
|
||||
return value
|
||||
end
|
||||
|
||||
function List.isempty (list)
|
||||
if list.first > list.last then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
row_base = _G[box:get_setting(2)]
|
||||
col_base = _G[box:get_setting(3)]
|
||||
segment_start = _G[box:get_setting(4)]
|
||||
segment_stop = _G[box:get_setting(5)]
|
||||
|
||||
-- 0 inactive, 1 segment started, 2 segment stopped (can vote)
|
||||
segment_status = 0
|
||||
|
||||
-- the idea is to push the flash states to the fifo, and when predictions arrive (with some delay), they are matched in oldest-first fashion.
|
||||
target_fifo = List.new()
|
||||
|
||||
-- box:log("Info", string.format("pop %d %d", id[1], id[2]))
|
||||
|
||||
row_votes = {}
|
||||
col_votes = {}
|
||||
|
||||
do_debug = false
|
||||
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
|
||||
end
|
||||
|
||||
function process(box)
|
||||
-- loops until box is stopped
|
||||
while box:keep_processing() do
|
||||
|
||||
-- first, parse the timeline stream
|
||||
for stimulation = 1, box:get_stimulation_count(2) do
|
||||
-- gets the received stimulation
|
||||
local identifier, date, duration = box:get_stimulation(2, 1)
|
||||
-- discards it
|
||||
box:remove_stimulation(2, 1)
|
||||
|
||||
if identifier == segment_start then
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Trial start"))
|
||||
box:log("Info", string.format("Clear votes"))
|
||||
end
|
||||
-- zero the votes
|
||||
col_votes = {}
|
||||
row_votes = {}
|
||||
target_fifo = List.new()
|
||||
-- fixme fixed 20
|
||||
for i = 0,20 do
|
||||
col_votes[i] = 0
|
||||
row_votes[i] = 0
|
||||
end
|
||||
segment_status = 1
|
||||
end
|
||||
|
||||
-- Does the identifier code a flash? if so, put into fifo
|
||||
if segment_status == 1 and identifier >= row_base and identifier <= OVTK_StimulationId_LabelEnd then
|
||||
|
||||
-- assume rows before cols
|
||||
if identifier < col_base then
|
||||
local t = {"row", identifier - row_base}
|
||||
List.pushright(target_fifo,t)
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Push row target %d", identifier - row_base ))
|
||||
end
|
||||
else
|
||||
local t = {"col", identifier - col_base}
|
||||
List.pushright(target_fifo,t)
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Push col target %d", identifier - col_base ))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
if identifier == segment_stop then
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Trial stop"))
|
||||
end
|
||||
segment_status = 2
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- then parse the classifications
|
||||
for stimulation = 1, box:get_stimulation_count(1) do
|
||||
|
||||
-- gets the received stimulation
|
||||
local identifier, date, duration = box:get_stimulation(1, 1)
|
||||
-- discards it
|
||||
box:remove_stimulation(1, 1)
|
||||
|
||||
-- Is it an in-class prediction?
|
||||
if identifier == OVTK_StimulationId_Target then
|
||||
local t = List.popleft(target_fifo)
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Pred fifo %s %d is target", t[1], t[2]))
|
||||
end
|
||||
if t[1]=="row" then
|
||||
row_votes[t[2]] = row_votes[t[2]] + 1
|
||||
else
|
||||
col_votes[t[2]] = col_votes[t[2]] + 1
|
||||
end
|
||||
end
|
||||
|
||||
if identifier == OVTK_StimulationId_NonTarget then
|
||||
local t = List.popleft(target_fifo)
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Pred fifo %s %d is nontarget", t[1], t[2]))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if segment_status == 2 and List.isempty(target_fifo) then
|
||||
-- output the vote after the segment end when we've matched all predictions
|
||||
|
||||
local maxRowIdx, maxRowValue = arrayMax(row_votes)
|
||||
local maxColIdx, maxColValue = arrayMax(col_votes)
|
||||
|
||||
if maxRowValue == 0 and maxColValue == 0 then
|
||||
box:log("Warning", string.format("Classifier predicted 'no p300' for all flashes of the trial"));
|
||||
end
|
||||
|
||||
if do_debug then
|
||||
local rowVotes = 0
|
||||
local colVotes = 0
|
||||
for ir, val in pairs(row_votes) do
|
||||
rowVotes = rowVotes + val
|
||||
end
|
||||
for ir, val in pairs(col_votes) do
|
||||
colVotes = colVotes + val
|
||||
end
|
||||
|
||||
box:log("Info", string.format("Vote [%d %d] wt [%d,%d]", maxRowIdx+row_base, maxColIdx+col_base, maxRowValue, maxColValue))
|
||||
box:log("Info", string.format(" Total [%d %d]", rowVotes, colVotes))
|
||||
end
|
||||
|
||||
|
||||
|
||||
local now = box:get_current_time()
|
||||
|
||||
box:send_stimulation(1, maxRowIdx + row_base, now, 0)
|
||||
box:send_stimulation(2, maxColIdx + col_base, now, 0)
|
||||
|
||||
segment_status = 0
|
||||
end
|
||||
|
||||
box:sleep()
|
||||
end
|
||||
end
|
||||
|
61
scenarios/scripts/p300-tactile-filter-flash.lua
Normal file
61
scenarios/scripts/p300-tactile-filter-flash.lua
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
-- Picks out 'flashes' from a stimulation stream
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
box:set_filter_mode(1);
|
||||
|
||||
state = 0
|
||||
|
||||
do_debug = false
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
end
|
||||
|
||||
-- this function is called once by the box
|
||||
function process(box)
|
||||
|
||||
-- loop until box:keep_processing() returns zero
|
||||
-- cpu will be released with a call to sleep
|
||||
-- at the end of the loop
|
||||
while box:keep_processing() do
|
||||
|
||||
-- gets current simulated time
|
||||
t = box:get_current_time()
|
||||
|
||||
-- loops on every received stimulation for a given input
|
||||
for stimulation = 1, box:get_stimulation_count(1) do
|
||||
|
||||
-- gets stimulation
|
||||
stimulation_id, stimulation_time, stimulation_duration = box:get_stimulation(1, 1)
|
||||
|
||||
if stimulation_id == OVTK_StimulationId_SegmentStart then
|
||||
state = 1
|
||||
elseif stimulation_id == OVTK_StimulationId_SegmentStop then
|
||||
state = 0
|
||||
end
|
||||
|
||||
-- If we're between 'rest start' and 'rest_stop', this specifies a target
|
||||
if state == 1 and stimulation_id >= OVTK_StimulationId_LabelStart and stimulation_id <= OVTK_StimulationId_LabelEnd then
|
||||
|
||||
box:send_stimulation(1, stimulation_id, stimulation_time, 0)
|
||||
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Push a target %d at %f (now %f)", stimulation_id, stimulation_time, t))
|
||||
end
|
||||
end
|
||||
|
||||
-- discards it
|
||||
box:remove_stimulation(1, 1)
|
||||
|
||||
end
|
||||
|
||||
-- releases cpu
|
||||
box:sleep()
|
||||
end
|
||||
end
|
61
scenarios/scripts/p300-tactile-filter-target.lua
Normal file
61
scenarios/scripts/p300-tactile-filter-target.lua
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
-- Picks out 'targets' from a stimulation stream
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
state = 0
|
||||
|
||||
box:set_filter_mode(1);
|
||||
|
||||
do_debug = false
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
end
|
||||
|
||||
-- this function is called once by the box
|
||||
function process(box)
|
||||
|
||||
-- loop until box:keep_processing() returns zero
|
||||
-- cpu will be released with a call to sleep
|
||||
-- at the end of the loop
|
||||
while box:keep_processing() do
|
||||
|
||||
-- gets current simulated time
|
||||
t = box:get_current_time()
|
||||
|
||||
-- loops on every received stimulation for a given input
|
||||
for stimulation = 1, box:get_stimulation_count(1) do
|
||||
|
||||
-- gets stimulation
|
||||
stimulation_id, stimulation_time, stimulation_duration = box:get_stimulation(1, 1)
|
||||
|
||||
if stimulation_id == OVTK_StimulationId_RestStart then
|
||||
state = 1
|
||||
elseif stimulation_id == OVTK_StimulationId_RestStop then
|
||||
state = 0
|
||||
end
|
||||
|
||||
-- If we're between 'rest start' and 'rest_stop', this specifies a target
|
||||
if state == 1 and stimulation_id >= OVTK_StimulationId_LabelStart and stimulation_id <= OVTK_StimulationId_LabelEnd then
|
||||
|
||||
box:send_stimulation(1, stimulation_id, stimulation_time, 0)
|
||||
|
||||
if do_debug then
|
||||
box:log("Info", string.format("Push a target %d at %f (now = %f)", stimulation_id, stimulation_time, t))
|
||||
end
|
||||
end
|
||||
|
||||
-- discards it
|
||||
box:remove_stimulation(1, 1)
|
||||
|
||||
end
|
||||
|
||||
-- releases cpu
|
||||
box:sleep()
|
||||
end
|
||||
end
|
21
scenarios/scripts/p300-tactile-launch.lua
Normal file
21
scenarios/scripts/p300-tactile-launch.lua
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
stim = _G[box:get_setting(2)]
|
||||
launchTime = box:get_setting(3)
|
||||
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
end
|
||||
|
||||
-- this function is called once by the box
|
||||
function process(box)
|
||||
|
||||
box:send_stimulation(1, stim, launchTime, 0)
|
||||
|
||||
end
|
138
scenarios/scripts/p300-tactile-stimulator.lua
Normal file
138
scenarios/scripts/p300-tactile-stimulator.lua
Normal file
@ -0,0 +1,138 @@
|
||||
-- This Lua script sends Stimulations to the speller visualization box for a tactile p300-System with 6 stimulators
|
||||
--
|
||||
-- Author : Tobias Baumann
|
||||
-- Date : 2021-12-06
|
||||
-- Revised: 2021-19-11
|
||||
|
||||
--This function lets the box sleep until a fixed moment
|
||||
function wait_until(box, time)
|
||||
while box:get_current_time() < time do
|
||||
box:sleep()
|
||||
end
|
||||
end
|
||||
|
||||
--This function lets the box wait for a fixed duration
|
||||
function wait_for(box, duration)
|
||||
wait_until(box, box:get_current_time() + duration)
|
||||
end
|
||||
|
||||
--this function checks, wether value already is an element of the given stim_matrix
|
||||
function is_element(matrix, value)
|
||||
for i = 1, #matrix do
|
||||
if #matrix == 0 then
|
||||
return(false)
|
||||
elseif value == matrix[i] then
|
||||
return(true)
|
||||
end
|
||||
end
|
||||
return(false)
|
||||
end
|
||||
--this function creates a sequence of stimulations by shuffeling the values of the given stim_matrix
|
||||
function create_sequence(matrix)
|
||||
math.randomseed(os.time())
|
||||
local stim_matrix = {}
|
||||
local stim_code = 0
|
||||
local i = 1
|
||||
while i <= #matrix do
|
||||
stim_code = matrix[math.random(1,#matrix)]
|
||||
if is_element(stim_matrix, stim_code) == false then
|
||||
stim_matrix[i] = stim_code
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
return(stim_matrix)
|
||||
end
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
--load stimulation codes
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
--load box settings
|
||||
row_base = _G[box:get_setting(2)]
|
||||
col_base = _G[box:get_setting(3)]
|
||||
n_rows = box:get_setting(4)
|
||||
n_repetitions = box:get_setting(5)
|
||||
flash_duration = box:get_setting(7)
|
||||
noflash_duration = box:get_setting(8)
|
||||
inter_repetition_delay = box:get_setting(9)
|
||||
inter_trial_delay = box:get_setting(10)
|
||||
send_toggle = _G[box:get_setting(11)]
|
||||
time_to_send = box:get_setting(13)
|
||||
|
||||
if box:get_setting(12) == 'true' then
|
||||
free_spelling = true
|
||||
n_trials = 1
|
||||
else
|
||||
free_spelling = false
|
||||
n_trials = box:get_setting(6)
|
||||
end
|
||||
|
||||
--Lua variables
|
||||
send = false
|
||||
experiment_end = false
|
||||
tactilo_stimcodes = {}
|
||||
for x = 1, n_rows do
|
||||
tactilo_stimcodes[x] = row_base + x - 1
|
||||
end
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
|
||||
end
|
||||
|
||||
-- this function is called once by the box
|
||||
function process(box)
|
||||
while box:keep_processing() do
|
||||
|
||||
if send and not experiment_end then
|
||||
-- iterate over the number of trials
|
||||
for trial = 1, n_trials do
|
||||
box:send_stimulation(1, OVTK_StimulationId_RestStart, box:get_current_time() , 0)
|
||||
wait_for(box, inter_trial_delay)
|
||||
box:send_stimulation(1, OVTK_StimulationId_RestStop, box:get_current_time() , 0)
|
||||
box:send_stimulation(1, OVTK_StimulationId_TrialStart ,box:get_current_time() , 0)
|
||||
|
||||
-- iterate over the number of repetitions
|
||||
for segment = 1, n_repetitions do
|
||||
tactilo_stimcodes = create_sequence(tactilo_stimcodes)
|
||||
box:send_stimulation(1, OVTK_StimulationId_SegmentStart ,box:get_current_time() , 0)
|
||||
|
||||
-- iterate over the number of tactilos
|
||||
for i = 1, #tactilo_stimcodes do
|
||||
box:send_stimulation(1, tactilo_stimcodes[i] ,box:get_current_time() , 0)
|
||||
box:send_stimulation(1, OVTK_StimulationId_VisualStimulationStart ,box:get_current_time() , 0)
|
||||
wait_for(box, flash_duration)
|
||||
box:send_stimulation(1, OVTK_StimulationId_VisualStimulationStop ,box:get_current_time() , 0)
|
||||
wait_for(box, noflash_duration)
|
||||
end
|
||||
|
||||
box:send_stimulation(1, OVTK_StimulationId_SegmentStop ,box:get_current_time() , 0)
|
||||
wait_for(box, inter_repetition_delay)
|
||||
end
|
||||
|
||||
box:send_stimulation(1, OVTK_StimulationId_TrialStop ,box:get_current_time() , 0)
|
||||
|
||||
end
|
||||
|
||||
if not free_spelling then
|
||||
-- end experiment if set to copy spelling
|
||||
box:send_stimulation(1, OVTK_StimulationId_ExperimentStop ,box:get_current_time() , 0)
|
||||
send = false
|
||||
experiment_end = true
|
||||
end
|
||||
|
||||
else if not send and not experiment_end then
|
||||
-- delay the start of the experiment by t = time_to_send
|
||||
wait_for(box, time_to_send)
|
||||
send = true
|
||||
box:send_stimulation(1, OVTK_StimulationId_ExperimentStart ,box:get_current_time() , 0)
|
||||
end
|
||||
|
||||
end
|
||||
-- releases cpu
|
||||
box:sleep()
|
||||
end
|
||||
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user