Using 3D Goggles for Continuous Flash Suppression

Hello,

My lab recently got these 3D goggles that we want to employ for Continuous Flash Suppression. I'm not very tech-savvy, but as I understand it, each screen on the goggles (one for either eye) displays every other frame of a source. If the source is my laptop (refresh rate is 60 Hz), then the frames effectively alternate between the two screens on the goggles (e.g. "odd" frames to the left eye, "even" frames to the right eye) so that each refreshes at 30 Hz.

Am I making sense so far?

The code that we have (two versions, in fact) successfully alternates the displays; so we do indeed get a CFS effect. However, we haven't been able to define particular frames as "odd" or "even". As a result, every time we run the code (and for every trial in the code), the goggles will arbitrarily display the dynamic Mondrian to, e.g., the left eye on trial 1, but then to the right eye on trial 2. As such, we can't say anything about which eye was presented with the Mondrian mask vs. the stimulus.

Is there any way to define particular frames as odd or even, taking into account the need for a response screen (which will stay up until participants respond)? It seems like it would be simple if the monitor's refresh rate could be reset, so that the first frame after a reset would always go to one particular screen on the goggles. Is it possible to do that, or something like it? Or, for anyone with experience employing CFS with 3D goggles (and the like), is there a simpler way to get this to work that we're simply overlooking?

Here are examples of the two code types (if you need more information or more of the code in order to offer help, please feel free to ask):



%get paramaters
params=getParams;


%read picture
picturename1='odd'; % this is just defining the image file name
picturename2='even';

picture1=imread(picturename1, 'jpg');
%(picture name defined above)
picture2=imread(picturename2, 'jpg');

pictureIndex1=Screen('MakeTexture',params.wPtr,picture1);%µÚÒ»·ùͼƬ¶ÔÓ¦µÄÖ¸Õë
pictureIndex2=Screen('MakeTexture',params.wPtr,picture2);

%present picture
background4(params);
vbl=Screen('Flip',params.wPtr);

for i=1:1000 %%change display time
%if i<150
%Screen('DrawTexture',params.wPtr,pictureIndex1,[],params.Location);
%vbl=Screen('Flip',params.wPtr,vbl+params.ifi-0.5*params.ifi);
%else
%Screen('DrawTexture',params.wPtr,pictureIndex2,[],params.Location);
%vbl=Screen('Flip',params.wPtr,vbl+params.ifi-0.5*params.ifi);
%end
if mod(i,2)==1
Screen('DrawTexture',params.wPtr,pictureIndex1,[],params.Location);
vbl=Screen('Flip',params.wPtr,vbl+params.ifi-0.5*params.ifi);
end
if mod(i,2)==0
Screen('DrawTexture',params.wPtr,pictureIndex2,[],params.Location);
vbl=Screen('Flip',params.wPtr,vbl+params.ifi-0.5*params.ifi);
end
end

Screen('CloseAll');
___________________________________________

%binocular rivalry u


clear all;
%get paramaters
params=getParams;

%read picture
picturename1='odd'; %left eye
picturename2='even'; %right eye

picture1=imread(picturename1, 'jpg');
picture2=imread(picturename2, 'jpg');


pictureIndex1=Screen('MakeTexture',params.wPtr,picture1);
pictureIndex2=Screen('MakeTexture',params.wPtr,picture2);


%present picture
%fill the first frame with something to get the start time, e.g. black retangle; here use the two
%pictures
Screen('SelectStereoDrawBuffer', params.wPtr, 0);
Screen('DrawTexture',params.wPtr,pictureIndex1,[],params.Location);

Screen('SelectStereoDrawBuffer', params.wPtr, 1);
Screen('DrawTexture',params.wPtr,pictureIndex2,[],params.Location); %tells which eye gets shown stimulus
% change to pictureIndex2{i} for Mondrian?

% Tell Psychtoolbox that no further drawing commands will be issued to 'windowPtr'
% before the next Screen('Flip') or Screen('AsyncFlipBegin') command.
% This is a hint that allows to optimize drawing performance on some occasions.
% Don't issue this command multiple times between a Flip, it will degrade
% performance or even cause undefined stimulus display!
Screen('DrawingFinished', params.wPtr);
vbl=Screen('Flip',params.wPtr);

for i=1:150

Screen('SelectStereoDrawBuffer', params.wPtr, 0);
Screen('DrawTexture',params.wPtr,pictureIndex1,[],params.Location);

Screen('SelectStereoDrawBuffer', params.wPtr, 1);
Screen('DrawTexture',params.wPtr,pictureIndex2,[],params.Location);
Screen('DrawingFinished', params.wPtr);
vbl=Screen('Flip',params.wPtr,vbl+params.ifi-0.5*params.ifi);
end

Screen('CloseAll');
What hardware/operating system/graphics card? What type of goggles?

You use shutter glasses for frame-sequential stereo presentation as far as i understand: The display alternates between left and right eye image and the shutter glasses open and close the left and right eye accordingly.

Normally you won't code this yourself as you did, but use frame-sequential stereo presentation mode (stereoMode = 1). If you run ImagingStereoDemo(1) it will do just that. You'll have two frame buffers, one for each eye and the system will take care of synchronizing everything.

The command Screen('SelectStereoDrawBuffer', window, bufferid, param); allows to select which eyes image to draw (bufferid=0 left, 1 = right). It also allows via the 'param' value to choose if stimulus onset after a Screen('Flip') should happen on even or odd refresh cycles (left or right eye). But normally you don't need that, you just need the correct images to go to the correct eyes.

How well this works depends on your graphics card, driver, operating system and the type of goggles you have and how the goggles synchronize to the video signal.

E.g., Linux or MS-Windows with NVidia Quadro stereo cards or AMD Fire stereo cards will just work. OSX with any NVidia or AMD card and goggles that use the blue-line sync method should just work (should, because some versions of OSX are totally broken in stereo mode and just crash the whole machine if you enable stereo -- Apples attention to detail, just love it).

For all other operating system + graphics card combinations, PTB has a built-in stereo mode which tries to approximate the behaviour of the professional solutions. PTB will alternate the eye images automatically and generate sync signals for goggles with blue-line sync method. How well this works depends on how good the presentation timing of your system is, but it should always be equal or better than what you do at the moment manually, and certainly more convenient to use.

-mario

--- In psychtoolbox@yahoogroups.com, "samhaingrim44" wrote:
>
> Hello,
>
> My lab recently got these 3D goggles that we want to employ for Continuous Flash Suppression. I'm not very tech-savvy, but as I understand it, each screen on the goggles (one for either eye) displays every other frame of a source. If the source is my laptop (refresh rate is 60 Hz), then the frames effectively alternate between the two screens on the goggles (e.g. "odd" frames to the left eye, "even" frames to the right eye) so that each refreshes at 30 Hz.
>
> Am I making sense so far?
>
> The code that we have (two versions, in fact) successfully alternates the displays; so we do indeed get a CFS effect. However, we haven't been able to define particular frames as "odd" or "even". As a result, every time we run the code (and for every trial in the code), the goggles will arbitrarily display the dynamic Mondrian to, e.g., the left eye on trial 1, but then to the right eye on trial 2. As such, we can't say anything about which eye was presented with the Mondrian mask vs. the stimulus.
>
> Is there any way to define particular frames as odd or even, taking into account the need for a response screen (which will stay up until participants respond)? It seems like it would be simple if the monitor's refresh rate could be reset, so that the first frame after a reset would always go to one particular screen on the goggles. Is it possible to do that, or something like it? Or, for anyone with experience employing CFS with 3D goggles (and the like), is there a simpler way to get this to work that we're simply overlooking?
>
> Here are examples of the two code types (if you need more information or more of the code in order to offer help, please feel free to ask):
>
>
>
> %get paramaters
> params=getParams;
>
>
> %read picture
> picturename1='odd'; % this is just defining the image file name
> picturename2='even';
>
> picture1=imread(picturename1, 'jpg');
> %(picture name defined above)
> picture2=imread(picturename2, 'jpg');
>
> pictureIndex1=Screen('MakeTexture',params.wPtr,picture1);%µÚÒ»·ùͼƬ¶ÔÓ¦µÄÖ¸Õë
> pictureIndex2=Screen('MakeTexture',params.wPtr,picture2);
>
> %present picture
> background4(params);
> vbl=Screen('Flip',params.wPtr);
>
> for i=1:1000 %%change display time
> %if i<150
> %Screen('DrawTexture',params.wPtr,pictureIndex1,[],params.Location);
> %vbl=Screen('Flip',params.wPtr,vbl+params.ifi-0.5*params.ifi);
> %else
> %Screen('DrawTexture',params.wPtr,pictureIndex2,[],params.Location);
> %vbl=Screen('Flip',params.wPtr,vbl+params.ifi-0.5*params.ifi);
> %end
> if mod(i,2)==1
> Screen('DrawTexture',params.wPtr,pictureIndex1,[],params.Location);
> vbl=Screen('Flip',params.wPtr,vbl+params.ifi-0.5*params.ifi);
> end
> if mod(i,2)==0
> Screen('DrawTexture',params.wPtr,pictureIndex2,[],params.Location);
> vbl=Screen('Flip',params.wPtr,vbl+params.ifi-0.5*params.ifi);
> end
> end
>
> Screen('CloseAll');
> ___________________________________________
>
> %binocular rivalry u
>
>
> clear all;
> %get paramaters
> params=getParams;
>
> %read picture
> picturename1='odd'; %left eye
> picturename2='even'; %right eye
>
> picture1=imread(picturename1, 'jpg');
> picture2=imread(picturename2, 'jpg');
>
>
> pictureIndex1=Screen('MakeTexture',params.wPtr,picture1);
> pictureIndex2=Screen('MakeTexture',params.wPtr,picture2);
>
>
> %present picture
> %fill the first frame with something to get the start time, e.g. black retangle; here use the two
> %pictures
> Screen('SelectStereoDrawBuffer', params.wPtr, 0);
> Screen('DrawTexture',params.wPtr,pictureIndex1,[],params.Location);
>
> Screen('SelectStereoDrawBuffer', params.wPtr, 1);
> Screen('DrawTexture',params.wPtr,pictureIndex2,[],params.Location); %tells which eye gets shown stimulus
> % change to pictureIndex2{i} for Mondrian?
>
> % Tell Psychtoolbox that no further drawing commands will be issued to 'windowPtr'
> % before the next Screen('Flip') or Screen('AsyncFlipBegin') command.
> % This is a hint that allows to optimize drawing performance on some occasions.
> % Don't issue this command multiple times between a Flip, it will degrade
> % performance or even cause undefined stimulus display!
> Screen('DrawingFinished', params.wPtr);
> vbl=Screen('Flip',params.wPtr);
>
> for i=1:150
>
> Screen('SelectStereoDrawBuffer', params.wPtr, 0);
> Screen('DrawTexture',params.wPtr,pictureIndex1,[],params.Location);
>
> Screen('SelectStereoDrawBuffer', params.wPtr, 1);
> Screen('DrawTexture',params.wPtr,pictureIndex2,[],params.Location);
> Screen('DrawingFinished', params.wPtr);
> vbl=Screen('Flip',params.wPtr,vbl+params.ifi-0.5*params.ifi);
> end
>
> Screen('CloseAll');
>