如何沿着x轴绘制实时值的“移动”图(使用psychtoolbox)?

时间:2018-12-20 12:13:13

标签: matlab psychtoolbox

我正在使用psychtoolbox编写用于实时实验的代码来展示刺激。在我的实验中,我需要给受试者显示一张表示其表现的图表。我已经使用以下简单代码绘制了图形:

        % Draw the graph
        figure('visible','off','color',[0 0 0]);
        pcolor([0 Num_timepoint+2],[-10 0],ones(2,2));
        hold on;
        pcolor([0 Num_timepoint+2],[0 10],2*ones(2,2));
        colormap([79 167 255;255 187 221]/256);      
        plot(1:subloop,value0,'*-',...
        'color',[0,0,0],...
        'LineWidth',1,...
        'MarkerSize',5,...
        'MarkerEdgeColor','k',...
        'MarkerFaceColor',[0.5,0.5,0.5]);
        axis([0,Num_timepoint+2,-10,10]);
        saveas(gcf,'line_chart.png');   %save it
        close(figure);
        line_chart=imread('line_chart.png');   %read it
        resized_plot=imresize(line_chart,0.5);
        imageSize = size(resized_plot);
        [imageHeight,imageWidth,colorChannels]=size(resized_plot);
        bottomRect = [xCenter-imageWidth/1.5, yCenter+gapdown, xCenter+imageWidth/1.5, yCenter+gapdown+imageHeight];
        imageDisplay=Screen('MakeTexture', win0, resized_plot);
        Screen('DrawTexture', win0, imageDisplay, [], bottomRect);

不幸的是,这个简单的代码非常慢。另外,一旦新值出现,我就无法使图形沿x轴移动。

任何帮助都会很棒。预先感谢您的努力。

2 个答案:

答案 0 :(得分:1)

为什么要保存图形并将其重新显示为图像?也许我缺少了一些东西,但是您应该能够通过使用图的handles属性使用新数据更新现有图来完成您需要的工作:

 .... First time through we need the initial plot ....
 % Set up figure with colormaps and such but leave as 'visible','on'
 hPlot = plot(plot(1:subloop,value0,'*-',...
    'color',[0,0,0],...
    'LineWidth',1,...
    'MarkerSize',5,...
    'MarkerEdgeColor','k',...
    'MarkerFaceColor',[0.5,0.5,0.5]);
 hAxes = gca;


 .... Loop over your real time updates ....
 % Assuming value0 has subject's results from t=0 to t=now 
 hPlot.XData = value0; hPlot.YData = [1:subloop];   
 hAxes.XLim = [0 numTimePoints+2];
 hAxes.YLim = [-10 10]

 .... Continue test and update value0 ....

我认为应该使绘图保持最新状态,而不必将图形另存为文件,然后重新打开图像以显示给主题。

答案 1 :(得分:0)

如果要将数据移动一个样本,可以使用circshift函数。例如,如果希望新值显示在左侧,则可以将所有值向右移动1个样本,然后将新值添加到第一个位置。

要将MATLAB图形转换为Psychtoolbox纹理,无需保存,然后加载临时图像。您可以改为使用getframe函数来捕获MATLAB图形数据,然后将其提供给MakeTexture以将其转换为Psychtoolbox纹理。

我不确定您在子循环,value0等中实际使用的是什么值,但是我认为有一个示例可能与您想要的接近。在此示例中,绘制了30帧图形,每个图形在屏幕上显示1秒钟。新数据点是随机生成的,并出现在图的左侧。

根据实验的细节,您可能会发现这种方法仍然太慢。您也可以通过PsychToolbox绘图方法(例如DrawLines等)直接创建图形,尽管这将需要更多的精力。

try

    win0 = Screen('OpenWindow', 0, 0);

    Num_timepoint = 100;
    subloop = 100;
    value0 = zeros(1,100);

    num_demo_frames = 30;

    % Draw the graph
    fig_h = figure('visible','off','color',[0 0 0]);
    pcolor([0 Num_timepoint+2],[-10 0],ones(2,2));
    hold on;
    pcolor([0 Num_timepoint+2],[0 10],2*ones(2,2));
    colormap([79 167 255;255 187 221]/256);
    plot_h = plot(1:subloop,value0,'*-',...
        'color',[0,0,0],...
        'LineWidth',1,...
        'MarkerSize',5,...
        'MarkerEdgeColor','k',...
        'MarkerFaceColor',[0.5,0.5,0.5]);
    axis([0,Num_timepoint+2,-10,10]);

    for f = 1:num_demo_frames
        new_value = randn(1,1);
        data_values = plot_h.YData;
        data_values = circshift(data_values, 1);
        data_values(1) = new_value;
        plot_h.YData = data_values;

        plot_values = getframe(fig_h);
        imageDisplay=Screen('MakeTexture', win0, plot_values.cdata);
        Screen('DrawTexture', win0, imageDisplay);
        Screen('Flip', win0);
        WaitSecs(1);
    end

    sca;

catch e
    sca;
    rethrow(e);
end