如何在Matlab中跳过或延迟事件

问题描述 投票:0回答:1

这是我用于实验的脚本。
物体会听到 3 种不同的声音,每种声音代表不同的奖励金额。所以当声音1响起时,没有奖励,当声音2和3响起并且物体触发

photobeam(pb_broken)
时,就会给予奖励。

问题是,有时物体甚至没有听到声音就收到奖励,因为它们靠近光束,从而触发它,并导致它释放奖励。

我想防止这种情况发生,但我不知道该怎么做。 这是我的选择:

  1. 如果在提示音之前触发了光束 1(有 2 个光束),则跳过该提示音,然后继续实验(不要再次播放该提示音,并在原本应该出现的情况下继续进行下一个提示音)
  2. 如果光束 1 在奖励音(2 和 3)之前触发,则跳过该音(如上)
  3. 如果 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
matlab
1个回答
0
投票

这确实是一个无需动手即可解决的复杂问题,与其说是编程问题,不如说是实验设计问题。

您可能需要确保在开始新音调之前没有光束被中断,也许可以通过替换

 if t_elapsed > eventLog.trial_times(trial_count)

if t_elapsed > eventLog.trial_times(trial_count) & ~n_broken

您也可以在 pb梗阻检查语句的末尾添加一个 while 循环,以确保在退出 if 语句并继续之前 1 秒内没有新事件发生。但是,您还必须检查声音,并可能在退出该循环之前终止它。

作为最后的选择,运行各种控制(我确信你正在运行),例如没有奖励的实验,应该有助于检查随机障碍的可能性。

我不确定您有什么样的限制需要遵守严格的试验计划,但正如另一条评论提到的那样,最好记录事件的时间,但在继续新的任务之前允许系统有任意时间“清除”审判。

© www.soinside.com 2019 - 2024. All rights reserved.