Skip to content

Instantly share code, notes, and snippets.

@smithdanielle
Created January 21, 2015 15:42
Show Gist options
  • Save smithdanielle/1e8162d4ac94b1f2b126 to your computer and use it in GitHub Desktop.
Save smithdanielle/1e8162d4ac94b1f2b126 to your computer and use it in GitHub Desktop.
A script that draws the dots for #stereothreshold and shows them in a figure. When finalised, ALL CHANGES HERE NEED TO BE TRANSFERRED TO STEREOTHRESHOLD.M IN STEREOTHRESHOLD SPACE-THEME BRANCH
close all
clear all;
screenParams.Res = [1024 768];
visAngPxl = 0.0018; % visual angle subtended by a single pixel
% Find center of screen:
xcen = screenParams.Res(1)/2;
ycen = screenParams.Res(2)/2;
dot.size = 0.0620;
dot.density = 28.3; % dot density in percentage coverage -- 0.17 is sparse, 28.3 is dense;
dot.area = [1.8 1.35]; % 2 degrees x 2 degrees, replication of Gantz & Bedell (2011)
dot.number = round(((dot.density*dot.area(1)^2)/(dot.size*pi))); % number of background dots
[dot.X,dot.Y] = meshgrid(xcen-0.5*round(dot.area(1)/visAngPxl):1.2*round(dot.size/visAngPxl):xcen + 0.5*round(dot.area(1)/visAngPxl), ycen-0.5*round(dot.area(2)/visAngPxl):1.2*round(dot.size/visAngPxl):ycen + 0.5*round(dot.area(2)/visAngPxl));
line.disp = 0.16;
disp = 0.14;
% Make dots
dot.jX = jitter(dot.X, 0.75,1); % jitter the dots using a normal distribution
dot.jY = jitter(dot.Y, 0.75,1); % with magnitude of 15% of smallest dot-to-dot spacing
dot.left.X = dot.jX + round((line.disp/2)/visAngPxl) + (round(((disp)/2)/visAngPxl));
dot.right.X = dot.jX - round((line.disp/2)/visAngPxl) - (round(((disp)/2)/visAngPxl));
dot.left.Y = dot.jY;
dot.right.Y = dot.jY;
% Make rocket
[I, map, alpha] = imread('rocket-transparency.png');
I(I == 0) = 128;
G = fspecial('gaussian', [5 5], 2);
Ig = imfilter(I, G, 'same');
Ig(Ig < 128) = 128;
Ig = padarray(Ig,[5 5], 128);
Ig(:,:,2) = Ig(:,:,1);
Ig(:,:,3) = Ig(:,:,1);
line.jitter.x = 0;
% Remove dots that are within "line.clearArea.spacing" degrees of the line
line.clearArea.spacing = dot.size;
line.clearArea.X = [xcen-0.5*size(Ig(:,:,1),2)-round(line.clearArea.spacing/visAngPxl):xcen+0.5*size(Ig(:,:,1),2)+round(line.clearArea.spacing/visAngPxl)];
line.clearArea.Y = [ycen-0.5*size(Ig(:,:,1),1)-round(line.clearArea.spacing/visAngPxl):ycen+0.5*size(Ig(:,:,1),1)+round(line.clearArea.spacing/visAngPxl)];
% How I currently decide which dots to draw
% dot.dstRects.left = zeros(4, dot.number);
% dot.dstRects.left = CenterRectOnPoint(texrect, dot.left.X(indicesOfAllPoints(1:dot.number))', dot.left.Y(indicesOfAllPoints(1:dot.number))')';
% dot.dstRects.right = zeros(4, dot.number);
% dot.dstRects.right = CenterRectOnPoint(texrect, dot.right.X(indicesOfAllPoints(1:dot.number))', dot.left.Y(indicesOfAllPoints(1:dot.number))')';
% Create mask for left, right, and cyclopean eyes
mask.left = dot.left.X>(min(line.clearArea.X)+line.jitter.x + round((line.disp/2)/visAngPxl)) & dot.left.X< (max(line.clearArea.X)+line.jitter.x+ round((line.disp/2)/visAngPxl)) &...
dot.jY>min(line.clearArea.Y) & dot.jY< max(line.clearArea.Y);
mask.right = dot.right.X>(min(line.clearArea.X)+line.jitter.x - round((line.disp/2)/visAngPxl)) & dot.right.X< (max(line.clearArea.X)+line.jitter.x- round((line.disp/2)/visAngPxl)) &...
dot.jY>min(line.clearArea.Y) & dot.jY< max(line.clearArea.Y);
mask.av = dot.jX>(min(line.clearArea.X)+line.jitter.x) & dot.jX< (max(line.clearArea.X)+line.jitter.x) &...
dot.jY>min(line.clearArea.Y) & dot.jY< max(line.clearArea.Y);
dot.left.masked.X = dot.left.X;
dot.right.masked.X = dot.right.X;
dot.av.masked.X = dot.jX;
dot.left.masked.Y = dot.left.Y;
dot.right.masked.Y = dot.right.Y;
dot.av.masked.Y = dot.jY;
dot.left.masked.X(mask.left) = nan;
dot.right.masked.X(mask.right) = nan;
dot.av.masked.X(mask.av) = nan;
dot.left.masked.Y(mask.left) = nan;
dot.right.masked.Y(mask.right) = nan;
dot.av.masked.Y(mask.av) = nan;
%%%%%%%% Y okay until here... number of elements end up different, so screws with indexing later
%%%%%%%% IDEA: index in pairs; concatenate both Y indices and use for both...
%%%%%%%% but what about resulting different-sized X? It works well enough
%%%%%%%% just using dot.left.masked.X(indicesOfAllPoints(1:(min([dot.number size(indicesOfAllPoints,2)]))))
%%%%%%%% NOOOOOO you end up with monocular dots :(
% dot.left.reduced.index.X = ~isnan(dot.left.masked.X);
% dot.left.reduced.index.Y = ~isnan(dot.left.masked.Y);
% dot.left.reduced.X = dot.left.masked.X(dot.left.reduced.index.X(:));
% dot.left.reduced.Y = dot.left.masked.Y(dot.left.reduced.index.Y(:));
% dot.right.reduced.index.X = ~isnan(dot.right.masked.X);
% dot.right.reduced.index.Y = ~isnan(dot.right.masked.Y);
% dot.right.reduced.X = dot.right.masked.X(dot.right.reduced.index.X(:));
% dot.right.reduced.Y = dot.right.masked.Y(dot.right.reduced.index.Y(:));
% dot.av.reduced.index.X = ~isnan(dot.av.masked.X);
% dot.av.reduced.index.Y = ~isnan(dot.av.masked.Y);
% dot.av.reduced.X = dot.av.masked.X(dot.av.reduced.index.X(:));
% dot.av.reduced.Y = dot.av.masked.Y(dot.av.reduced.index.Y(:));
% numElements.left = numel(dot.left.reduced.X); % allows for linear indexing
% numElements.right = numel(dot.right.reduced.X);
numElements.left = numel(dot.left.masked.X); % allows for linear indexing
numElements.right = numel(dot.right.masked.X);
indicesOfAllPoints = randperm(min([numElements.left numElements.right]));
% How I should decide which dots to draw, to allow for easy redrawing etc.
% dot.actual.left.X = dot.left.reduced.X(indicesOfAllPoints(1:(min([dot.number size(indicesOfAllPoints,2)]))));
% dot.actual.left.Y = dot.left.reduced.Y(indicesOfAllPoints(1:(min([dot.number size(indicesOfAllPoints,2)]))));
% dot.actual.right.X = dot.right.reduced.X(indicesOfAllPoints(1:(min([dot.number size(indicesOfAllPoints,2)]))));
% dot.actual.right.Y = dot.right.reduced.Y(indicesOfAllPoints(1:(min([dot.number size(indicesOfAllPoints,2)]))));
% dot.actual.av.X = dot.av.reduced.X(indicesOfAllPoints(1:(min([dot.number size(indicesOfAllPoints,2)]))));
% dot.actual.av.Y = dot.av.reduced.Y(indicesOfAllPoints(1:(min([dot.number size(indicesOfAllPoints,2)]))));
dot.actual.left.X = dot.left.masked.X(indicesOfAllPoints(1:(min([dot.number size(indicesOfAllPoints,2)]))));
dot.actual.left.Y = dot.left.masked.Y(indicesOfAllPoints(1:(min([dot.number size(indicesOfAllPoints,2)]))));
dot.actual.right.X = dot.right.masked.X(indicesOfAllPoints(1:(min([dot.number size(indicesOfAllPoints,2)]))));
dot.actual.right.Y = dot.right.masked.Y(indicesOfAllPoints(1:(min([dot.number size(indicesOfAllPoints,2)]))));
dot.actual.av.X = dot.av.masked.X(indicesOfAllPoints(1:(min([dot.number size(indicesOfAllPoints,2)]))));
dot.actual.av.Y = dot.av.masked.Y(indicesOfAllPoints(1:(min([dot.number size(indicesOfAllPoints,2)]))));
dot.adjusted.right.X = dot.actual.right.X;
dot.adjusted.left.X = dot.actual.left.X;
% Low density fix; trying to move dots back in, but will end up with monocular cues
% dot.adjusted.right.X(dot.actual.right.X<0) = dot.actual.right.X(dot.actual.right.X<0) + (0 - min(dot.actual.right.X(dot.actual.right.X<0)));
% dot.adjusted.left.X(dot.actual.right.X<0) = dot.actual.left.X(dot.actual.right.X<0) + (0 - min(dot.actual.right.X(dot.actual.right.X<0)));
% dot.adjusted.left.X(dot.actual.left.X>screenParams.Res(1)) = dot.actual.left.X(dot.actual.left.X>screenParams.Res(1)) - (max(dot.actual.left.X(dot.actual.left.X>screenParams.Res(1))) - screenParams.Res(1));
% dot.adjusted.right.X(dot.actual.left.X>screenParams.Res(1)) = dot.actual.right.X(dot.actual.left.X>screenParams.Res(1)) - (max(dot.actual.left.X(dot.actual.left.X>screenParams.Res(1))) - screenParams.Res(1));
% High density fix: wrap around dots that are outside screen due to disparity shift
dot.adjusted.right.X(dot.actual.right.X<0) = (dot.actual.right.X(dot.actual.right.X<0)) + screenParams.Res(1);
dot.adjusted.left.X(dot.actual.left.X>screenParams.Res(1)) = dot.actual.left.X(dot.actual.left.X>screenParams.Res(1)) - screenParams.Res(1);
% Positions of dots without manipulating disparity
figure()
rectangle('Position',[0,0,1024,768],...
'FaceColor','k')
hold on
rectangle('Position',[min(line.clearArea.X),min(line.clearArea.Y),max(line.clearArea.X)-min(line.clearArea.X),max(line.clearArea.Y)-min(line.clearArea.Y)],...
'FaceColor',[0.5 0.5 0.5])
scatter(dot.actual.av.X, dot.actual.av.Y, [], 'green')
hold off
%
% % Positions of dots while manipulating disparity
% figure()
% rectangle('Position',[0,0,1024,768],...
% 'FaceColor','k')
% hold on
% scatter(dot.adjusted.left.X, dot.actual.left.Y, [], 'blue')
% scatter(dot.adjusted.right.X, dot.actual.right.Y, [], 'red')
% legend('left eye', 'right eye')
%
% hold off
% % Draw dots with rocket mask applied
% left = figure();
% set(left,'name','Mask for left eye','numbertitle','off')
% rectangle('Position',[0,0,1024,768],...
% 'FaceColor','k')
% hold on
% rectangle('Position',[min(line.clearArea.X)+round((line.disp/2)/visAngPxl),min(line.clearArea.Y),max(line.clearArea.X)-min(line.clearArea.X),max(line.clearArea.Y)-min(line.clearArea.Y)],...
% 'FaceColor',[0.5 0.5 0.5])
% scatter(dot.left.masked.X, dot.actual.left.Y, [], 'blue')
% scatter(dot.adjusted.right.X, dot.actual.right.Y, [], 'red')
% legend('left eye', 'right eye')
%
% hold off
%
% right = figure();
% set(right,'name','Mask for right eye','numbertitle','off')
% rectangle('Position',[0,0,1024,768],...
% 'FaceColor','k')
% hold on
% rectangle('Position',[min(line.clearArea.X)-round((line.disp/2)/visAngPxl),min(line.clearArea.Y),max(line.clearArea.X)-min(line.clearArea.X),max(line.clearArea.Y)-min(line.clearArea.Y)],...
% 'FaceColor',[0.5 0.5 0.5])
% scatter(dot.adjusted.left.X, dot.actual.left.Y, [], 'blue')
% scatter(dot.right.masked.X, dot.actual.right.Y, [], 'red')
% legend('left eye', 'right eye')
% Draw dots with rocket mask applied
left = figure();
set(left,'name','Mask for left eye','numbertitle','off')
rectangle('Position',[0,0,1024,768],...
'FaceColor','k')
hold on
rectangle('Position',[min(line.clearArea.X)+round((line.disp/2)/visAngPxl),min(line.clearArea.Y),max(line.clearArea.X)-min(line.clearArea.X),max(line.clearArea.Y)-min(line.clearArea.Y)],...
'FaceColor',[0.5 0.5 0.5])
scatter(dot.adjusted.left.X, dot.actual.left.Y, [], 'blue')
scatter(dot.adjusted.right.X, dot.actual.right.Y, [], 'red')
legend('left eye', 'right eye')
hold off
right = figure();
set(right,'name','Mask for right eye','numbertitle','off')
rectangle('Position',[0,0,1024,768],...
'FaceColor','k')
hold on
rectangle('Position',[min(line.clearArea.X)-round((line.disp/2)/visAngPxl),min(line.clearArea.Y),max(line.clearArea.X)-min(line.clearArea.X),max(line.clearArea.Y)-min(line.clearArea.Y)],...
'FaceColor',[0.5 0.5 0.5])
scatter(dot.adjusted.left.X, dot.actual.left.Y, [], 'blue')
scatter(dot.adjusted.right.X, dot.actual.right.Y, [], 'red')
legend('left eye', 'right eye')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment