Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed a bug in RSVP stimuli and a rounding issue in stimulus duration #158

Merged
merged 2 commits into from
Mar 25, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion +neurostim/plugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ function setChangesInTrial(o,prm)
end
end

methods (Access={?neuorstim.plugin,?neurostim.parameter})
methods (Access={?neuorstim.plugin,?neurostim.parameter,?neurostim.stimulus})

%Accessing neurostim.parameters is much slower than accessing a raw
%member variable. Because we define many such parms (with addProperty) in the base
Expand Down
34 changes: 19 additions & 15 deletions +neurostim/stimulus.m
Original file line number Diff line number Diff line change
Expand Up @@ -237,17 +237,19 @@ function addDiodeFlasher(s,varargin)

methods (Access=private)

function s = updateRSVP(s)
function s = updateRSVP(s,sOnFrame,cFrame)
% Called from baseBeforeFrame only when the stimulus is on.
%How many frames for item + blank (ISI)?
nFramesPerItem = s.cic.ms2frames(s.rsvp.duration+s.rsvp.isi);
%How many frames since the RSVP stream started?
rsvpFrame = s.cic.frame-s.onFrame;
% How many frames for item + blank (ISI)?
durationInFrames = s.cic.ms2frames(s.rsvp.duration,true);
isiInFrames = s.cic.ms2frames(s.rsvp.isi,true);
nrFramesPerItem = durationInFrames+isiInFrames;
% What is the frame we are preparing (base -0 relative to the first frame of the stimulus)
rsvpFrame = cFrame-sOnFrame;
%Which item frame are we in?
itemFrame = mod(rsvpFrame, nFramesPerItem);
itemFrame = mod(rsvpFrame, nrFramesPerItem);
%If at the start of a new element, move the design to the
% next "trial"
if itemFrame==0
if itemFrame==0 % First of an item
ok = beforeTrial(s.rsvp.design);
if ~ok
% Ran out of "trials"
Expand All @@ -258,11 +260,11 @@ function addDiodeFlasher(s,varargin)
for sp=1:size(specs,1)
s.(specs{sp,2}) = specs{sp,3};
end
localizeParms(s,true); % Update those loc parameters that change within a trial
bartkrekelberg marked this conversation as resolved.
Show resolved Hide resolved
end

%Blank now if it's time to do so.
startIsiFrame = s.cic.ms2frames(s.rsvp.duration);
s.flags.on = itemFrame < startIsiFrame; % Blank during rsvp isi
s.flags.on = itemFrame < durationInFrames; % Blank during rsvp isi (< because itemFrame is base-0)
if s.rsvp.log
if itemFrame == 0
s.rsvpIsi = false;
Expand Down Expand Up @@ -373,13 +375,15 @@ function baseBeforeFrame(s)
if isinf(s.loc_on)
s.flags.on =false; %Dont bother checking the rest
else
sOnFrame = round(s.loc_on.*s.cic.screen.frameRate/1000)+1;
%sOnFrame = s.cic.ms2frames(sOn,true)+1; % rounded==true
% Time is base-0 but frames are base-1 (frame 1 is the
% first that can be visible on the screen).
sOnFrame = round(s.loc_on.*s.cic.screen.frameRate/1000)+1;
if cFrame < sOnFrame % Not on yet.
s.flags.on = false;
else % Is on already or turning on. Checck that we have not
% reached full duration yet.
sOffFrame = round((s.loc_on+s.loc_duration)*s.cic.screen.frameRate/1000);
else % Is on already or turning on.
% Checck that we have not reached full duration yet.
% No +1 here.
sOffFrame = sOnFrame + round(s.loc_duration*s.cic.screen.frameRate/1000);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the key change for the duration fix.

%sOffFrame = s.cic.ms2frames(sOn+s.duration,true);
s.flags.on = cFrame <sOffFrame;
end
Expand All @@ -388,7 +392,7 @@ function baseBeforeFrame(s)
%% RSVP mode
% Update parameter values if necesssary
if s.rsvp.active && s.flags.on
bartkrekelberg marked this conversation as resolved.
Show resolved Hide resolved
s=updateRSVP(s);
s=updateRSVP(s,sOnFrame,cFrame);
end

%%
Expand Down