在心理学中绘制连续线的有效方法

时间:2016-03-05 15:11:59

标签: psychopy

我正在寻找一种更有效的方法来在PsychoPy中绘制连续的线条。这就是我现在想出来的......

编辑:我能想到的唯一改进是,只有在鼠标真正移动时添加if (mspos1-mspos2).any():

才能添加新行
ms = event.Mouse(myWin)

lines = []

mspos1 = ms.getPos()
while True:
    mspos2 = ms.getPos()
    if (mspos1-mspos2).any():
        lines.append(visual.Line(myWin, start=mspos1, end=mspos2))
    for j in lines:
        j.draw()
    myWin.flip()
    mspos1 = mspos2

编辑:我尝试使用Shape.Stim(下面的代码),希望它能更好地工作,但它会更快地获得前卫......

vertices = [ms.getPos()]
con_line = visual.ShapeStim(myWin,
        lineColor='red',
        closeShape=False)
myclock.reset()
i = 0
while myclock.getTime() < 15:
    new_pos = ms.getPos()
    if (vertices[i]-new_pos).any():
        vertices.append(new_pos)
        i += 1
    con_line.vertices=vertices
    con_line.draw()
    myWin.flip()

1 个答案:

答案 0 :(得分:2)

问题在于,在循环的每次迭代中,在visual.Line中绘制那么多visual.ShapeStim或操纵那么多顶点变得过于强大。所以它会挂在绘图(对于线条)或顶点赋值(对于ShapeStim)上,只要鼠标移动到足以让线条显示不连续性(“前卫”)。

所以这是一个性能问题。这有两个想法:

  1. 在您想要向线条添加新坐标之前,为鼠标移动的最小距离设置较低的阈值。在下面的示例中,我强加了一个标准,即鼠标位置应该距离要记录的前一个顶点至少10个像素。在我的测试中,这将每秒记录的顶点数量压缩到大约三分之一。仅此策略将推迟性能问题,但不会阻止它,所以... ...
  2. 使用ShapeStim解决方案但定期使用新的ShapeStims,每个都有较少的顶点,以便更新的刺激不会太复杂。在下面的示例中,我将复杂度设置为500像素,然后再转换为新的刺激。在产生新的刺激时可能会有一个小故障,但我没有注意到。
  3. 结合这两种策略,在键盘上按下开始和结束鼠标绘图:

    # Setting things up
    from psychopy import visual, event, core
    import numpy as np
    
    # The crucial controls for performance. Adjust to your system/liking.
    distance_to_record = 10  # number of pixels between coordinate recordings
    screenshot_interval = 500  # number of coordinate recordings before shifting to a new ShapeStim
    
    # Stimuli
    myWin = visual.Window(units='pix')
    ms = event.Mouse()
    myclock = core.Clock()
    
    # The initial ShapeStim in the "stimuli" list. We can refer to the latest
    # as stimuli[-1] and will do that throughout the script. The others are 
    # "finished" and will only be used for draw.
    stimuli = [visual.ShapeStim(myWin,
            lineColor='white',
            closeShape=False,
            vertices=np.empty((0, 2)))]
    
    # Wait for a key, then start with this mouse position
    event.waitKeys()
    stimuli[-1].vertices = np.array([ms.getPos()])
    myclock.reset()
    while not event.getKeys():
        # Get mouse position
        new_pos = ms.getPos()
    
        # Calculating distance moved since last. Pure pythagoras.
        # Index -1 is the last row.index
        distance_moved = np.sqrt((stimuli[-1].vertices[-1][0]-new_pos[0])**2+(stimuli[-1].vertices[-1][1]-new_pos[1])**2)
    
        # If mouse has moved the minimum required distance, add the new vertex to the ShapeStim.
        if distance_moved > distance_to_record:
            stimuli[-1].vertices = np.append(stimuli[-1].vertices, np.array([new_pos]), axis=0)
    
        # ... and show it (along with any "full" ShapeStims
        for stim in stimuli:
            stim.draw()
        myWin.flip()
    
        # Add a new ShapeStim once the old one is too full
        if len(stimuli[-1].vertices) > screenshot_interval:
            print "new shapestim now!"
            stimuli.append(visual.ShapeStim(myWin, 
                                            lineColor='white', 
                                            closeShape=False, 
                                            vertices=[stimuli[-1].vertices[-1]]))  # start from the last vertex