试用次数超过对象的次数,我的随机播放算法就会崩溃

时间:2018-07-13 09:10:18

标签: python psychopy experimental-design

我正在尝试进行实验,其中扫描文件夹中的图像。对于每个试验,都会显示一个目标和一些(7)牵张器图像。之后,有一半的人会看到目标图像,另一半的人则没有显示先前的图像。

我当前的代码工作正常,但前提是试验次数少于对象次数:

repeats = 20

# Scan dir for images
jpgs = []

for path, dirs, files in os.walk(directory):
    for f in files:
        if f.endswith('.jpg'):
            jpgs.append(f)

# Shuffle up jpgs
np.random.shuffle(jpgs)

# Create list with target and probe object, Half random, half identical
display = []
question = []
sameobject = []
position = np.repeat([0,1,2,3,4,5,6,7], repeats)
for x in range(1,(repeats*8)+1):
    display.append(jpgs[x])
    if x % 2 == 0:
        question.append(jpgs[-x])
        sameobject.append(0)
    else:
        question.append(jpgs[x])
        sameobject.append(1)

# Concatonate objects together
together = np.c_[display,question,position,sameobject] 
np.random.shuffle(together)

for x in together:
        # Shuffle and set image
        np.random.shuffle(jpgs)
        myList = [i for i in jpgs if i != together[trial,0]]
        myList = [i for i in myList if i != together[trial,1]]

        # Set correct image for target
        myList[int(together[trial,2])] = together[trial,0]

首先,我知道这是可怕的代码。但这会使工作粗略地完成。具有200张jpg和20张重复图片,它可以正常工作。如果将重复次数设置为30,则会崩溃。

这是重复率过高的示例:

  File "H:\Code\Stims\BetaObjectPosition.py", line 214, in <module>
    display.append(jpgs[x])
IndexError: list index out of range

是否有一种方法可以更新代码,从而在整个实验中尽可能均匀地使用所有对象(一个对象不应显示3次,而另一个对象显示为0)则可以进行更多试验?

Full, reproducible example

如果有人能看到一种明显的方法来平衡选择7个干扰项图像的方式,则奖励点。

感谢您抽出宝贵时间阅读本文档。希望您能对我有所帮助。

1 个答案:

答案 0 :(得分:1)

最少更改代码的解决方案应该是将每次将jpgs[x]的调用更改为jpgs[x % len(jpgs)] 1 。这应该摆脱IndexError;它基本上将列表索引“围绕边缘”包装起来,以确保它不会过大。尽管我不确定它如何与jpgs[-x]调用交互。

另一种选择是实现一个类,该类从较短的对象生成较长的对象序列。 示例:

from random import shuffle


class InfiniteRepeatingSequence(object):
  def __init__(self, source_list):
      self._source = source_list
      self._current = []

  def next(self):
      if len(self._current) == 0:
          # copy the source
          self._current = self._source[:]

          shuffle(self._current)

      # get and remove an item from a list
      return self._current.pop()

该类无限期地重复该列表。在重新使用列表之前,请确保每个元素使用一次。 它可以轻松地变成迭代器(尝试将next更改为__next__)。但是要小心,因为上面的类会生成无限个元素序列。


1 有关 modulo 运算符的说明,请参见“ How does % work in Python?”。

编辑:已添加到模数问题的链接。