这是我用于实验的脚本。
对象听到 3 种不同的音调,每种音调代表不同的奖励金额。所以当音 1 出现时,没有奖励,而当音 2 和 3 出现并且对象触发 时photobeam(pb_broken)
,将给予奖励。
问题是,有时物体在没有听到音调的情况下获得奖励,因为它们靠近光束,从而触发它,并导致它释放奖励。
我想防止这种情况发生,但我不知道该怎么做。这是我的选择:
- 如果在音调之前触发了光束 1(有 2 个光束),则跳过该音调,并继续进行实验(不要再次播放该音调,并在原本应该出现的时候继续下一个音调)
- 如果在奖励音(2 和 3)之前触发光束 1,则跳过音(如上)
- 如果 pb 1 坏了,则将音调延迟 1 秒,从而将所有内容延迟 1 秒,但仍以 1200 秒结束。这将是理想的情况。
这是我的代码:
clear all;
%%
% Set-up DAQ with an output and input session
global outputSession; % this will control the feeders
outputSession = daq.createSession('ni');
outputSession.addDigitalChannel('Dev2', 'Port1/Line0:1', 'OutputOnly');
outputSession.outputSingleScan([0 0]); % set everything to 0 to start
global inputSession; % this reads from the photobeams
inputSession = daq.createSession('ni');
inputSession.addDigitalChannel('Dev2', 'Port1/Line5:6', 'InputOnly');
global leverSession; % read from levers: note, scan returns 1 if not pressed, empty if pressed!
leverSession = daq.createSession('ni');
leverSession.addDigitalChannel('Dev2', 'Port1/Line2', 'InputOnly');
%% intitialize variables, draw status figure etc.
global target_rewarded; % needs to be global so functions can reset it
target_rewarded = [0 0]; % no targets (receptacles) armed to start
% track times and IDs of photobeam breaks
EventLogSize = 10000;
eventLog.pb_broken_time = nan(EventLogSize,1);
eventLog.pb_broken_id = nan(EventLogSize,1);
pb_counter = 1;
% times and IDs of feeders
eventLog.reward_time = nan(500,1);
eventLog.reward_id = nan(500,1);
reward_counter = 1;
eventLog.mistake_time = nan(500,1);
eventLog.mistake_id = nan(500,1);
mistake_counter = 1;
%%% generate trial start times %%%
sound_on = 0;
trial_count = 1;
%%% generate trial list %%%
trial_block = [1 1 2 2 3 3]; % permute block and repeat
eventLog.trial_list = [];
for iBlock = 1:50
eventLog.trial_list = cat(2,eventLog.trial_list,trial_block(randperm(length(trial_block))));
end
%%% SET UP TIMES OF CUE (TONE) ONSET HERE
maxTrials = 500;
mean_ITI = 20;
SD_ITI = 3;
eventLog.trial_times = mean_ITI.*ones(maxTrials,1);
trial_SD = SD_ITI.*randn(maxTrials,1);
eventLog.trial_times = eventLog.trial_times + trial_SD;
eventLog.trial_times = cumsum(eventLog.trial_times);
%%% set up sounds %%%
outputID = 10; % which sound connection on computer to use
duration = 7; % in seconds
samplesPerSecond = 22050; % the bit rate of the tone
tvec = 0:1/samplesPerSecond:duration;
% 1: 2kHz tone, on/off at 10Hz
s1 = sin(2*pi*2000*tvec);
s1 = s1.*square(2*pi*10*tvec);
s1 = 0.2.*s1;
% 2: white noise
s2 = rand(size(tvec));
s2 = 0.2*((s2.*2)-1);
% 4: 8kHz tone, sinewave amplitude-modulated at 2Hz
s3 = sin(2*pi*8000*tvec);
modl = 0.5*(sin(2*pi*2*tvec)+1);
s3 = s3.*modl;
s3 = 0.5.*s3;
tone1 = audioplayer(s1, samplesPerSecond, 16, outputID);
set(tone1,'StopFcn',@reset_rewards); % set it up so that if the tone ends, rewards are reset
tone2 = audioplayer(s2, samplesPerSecond, 16, outputID);
set(tone2,'StopFcn',@reset_rewards); % set it up so that if the tone ends, rewards are reset
tone3 = audioplayer(s3, samplesPerSecond, 16, outputID);
set(tone3,'StopFcn',@reset_rewards); % set it up so that if the tone ends, rewards are reset
sound_timer = [];
%%% tone-to-pellet mapping
tone_to_pellets = [0 2 5];
correct_pb = 1; % which photobeam is rewarded
correct_feeder = 2; % which feeder to use
%%% initialize main timer and photobeam status %%%
start_timer = tic; % call as t_elapsed = toc(start_timer);
t_elapsed = 0;
max_time = 1200; % in seconds
pb_broken = [];
previous_broken = 0;
%%% make task window %%%
fs = 18;
f1_handle = figure(1);
t_handle = title('Task starting...'); set(t_handle,'FontSize',fs);
status_handle = text(0,0.8,sprintf('Correct trials %d, Incorrect trials %d',reward_counter-1,mistake_counter-1)); set(status_handle,'FontSize',fs);
axis off;
%% run task
while t_elapsed < max_time
% update figure text,time
set(t_handle,'String',sprintf('t %.2f, pb %d, target %s',t_elapsed,pb_broken,num2str(target_rewarded)));
drawnow;
t_elapsed = toc(start_timer);
% check if any photobeams are broken
pb_broken = pb_scan(inputSession);
n_broken = numel(pb_broken);
if n_broken > 0 % do something potentially
% check
if n_broken > 1
disp('WARNING: multiple photobeams broken');
pb_broken = pb_broken(1);
end
if pb_broken == previous_broken % no change, do nothing
continue;
end
% log this: it's a new photobeam break
eventLog.pb_broken_time(pb_counter) = t_elapsed;
eventLog.pb_broken_id(pb_counter) = pb_broken;
pb_counter = pb_counter + 1;
disp(sprintf('*** Photobeam %d broken ***',pb_broken));
if any(target_rewarded > 0) % reward active, maybe dispense pellet
if pb_broken == correct_pb
disp('*** CORRECT POKE ***');
switch eventLog.trial_list(trial_count-1) % check what trial it is
case 1
disp(sprintf('Dispensed %d pellets',tone_to_pellets(1)));
dispensePellets(correct_feeder,tone_to_pellets(1));
stop(tone1);
case 2
disp(sprintf('Dispensed %d pellets',tone_to_pellets(2)));
dispensePellets(correct_feeder,tone_to_pellets(2));
stop(tone2);
case 3
disp(sprintf('Dispensed %d pellets',tone_to_pellets(3)));
dispensePellets(correct_feeder,tone_to_pellets(3));
stop(tone3);
end
target_rewarded = [0 0];
eventLog.reward_time(reward_counter) = t_elapsed;
eventLog.reward_id(reward_counter) = tone_to_pellets(eventLog.trial_list(trial_count-1));
reward_counter = reward_counter + 1;
disp(sprintf('Logged %d pellets rewarded',tone_to_pellets(eventLog.trial_list(trial_count-1))));
set(status_handle,'String',sprintf('Correct trials %d, Incorrect trials %d',reward_counter-1,mistake_counter-1));
else % wrong receptacle
if ~poked_this_trial
disp('*** ACTIVE CUE, INCORRECT POKE ***');
mistake_counter = mistake_counter + 1;
poked_this_trial = 1;
end
end
else % no reward active, do nothing
disp('*** INACTIVE CUE, INCORRECT POKE ***');
%mistake_counter = mistake_counter + 1;
end
end % of photobeam broken loop
% check if a new trial (sound) is starting
if t_elapsed > eventLog.trial_times(trial_count)
switch eventLog.trial_list(trial_count) % check what trial it is
case 1
play(tone1);
target_rewarded = [0 tone_to_pellets(1)];
case 2
play(tone2);
target_rewarded = [0 tone_to_pellets(2)];
case 3
play(tone3);
target_rewarded = [0 tone_to_pellets(3)];
end
sound_timer = tic;
trial_count = trial_count + 1;
poked_this_trial = 0;
disp(sprintf('New trial started (%d pellets): updated trial count is %d',target_rewarded(2),trial_count));
end
% check if we need to stop sound
if ~isempty(sound_timer) & toc(sound_timer) > duration
switch eventLog.trial_list(trial_count - 1)
case 1
stop(tone1)
case 2
stop(tone2)
case 3
stop(tone3)
end
end
previous_broken = pb_broken;
end % of main while loop