2016-04-15 18 views
0

私はPsychoPyのコーダセクションで実験を行っています。これは比較的簡単な作業ですが、テキストや画像の描画にはかなりの量が必要です。私は数日前(123件の試験からなる)全体の実験を実行してみました、と私は次のエラーを受け取った28日反復周り:PsychoPy textStimメモリリークの問題

WindowsError:例外:アクセス違反の書き込み0x00000004

私はこれに見て、ウィンドウに大量のテキストを描画するときに発生するpygletで発生するメモリリークの問題があるようです。私はコードが洗練されていて、実験で要求されたときにのみテキストコンポーネントを変更しました。私は、参照として以下に私の全体のコードをリストアップしています:

from __future__ import division 
from psychopy import locale_setup, visual, core, event, data, gui 
import numpy as np 
import pandas as pd 
import sys, os, csv, time, random 
from win32api import GetSystemMetrics 

#Directory: 
cwd = os.path.dirname(os.path.abspath(__file__)) 

#GUI: 
expName = "CMNT" 
expInfo = {"participant": "", "session": "001", "condition": "F1"}  #Condition Files: F1, F2, M1, or M2 
condition = expInfo["condition"] 
condition = expInfo["condition"] 
dlg = gui.DlgFromDict(dictionary = expInfo, title = expName, order = ["participant","session","condition"]) 
if dlg.OK == False: 
    core.quit() 

#Window: 
win = visual.Window(size = (GetSystemMetrics(0), GetSystemMetrics(1)),  fullscr = True, pos = (0,0), units = "norm", color = "Gray") 

#Turn off Mouse 
event.Mouse(visible = False) 

#Timers: 
timer = core.Clock() 
breakTimer = core.Clock() 

#Load Condition File: 
stim_df = pd.read_csv("exp_stimuli.csv", nrows = 124) 
run_length = 123 

#Output Directory: 
fileLocation = cwd + "\%s_data\%s" %(expName, expInfo["participant"]) 
if not os.path.exists(fileLocation): 
    os.makedirs(fileLocation) 
os.chdir(fileLocation) 
if os.path.isfile("logFile.csv"): 
    os.remove("logFile.csv") 

#List and Panda File Header 
run_param_list = [] 
header = ["Block","MentalState", "Condition", "Speaker","Prompt", "RespButton", "CorrAnswer","RT(sec)", "ACC"] 

#Define text and image stimuli 
text = visual.TextStim(win = win, text = '', height = 0.1, pos = (0,0), color="White") 
image = visual.ImageStim(win = win, pos = (0,0), size = (0.1,0.1), image = cwd + "\\" + "gray.png") 

#Run Instruction Page: 
text.text = '\t\tREMEMBER:\n\t\tAnswer each question,\n\t\t"Which should I  pick?"\n\t\tusing the LEFT and RIGHT\n\t\tarrow key.' 
text.height = 0.1 
text.draw() 
win.flip() 
while True: 
    theseKeys = event.getKeys() 
    if "escape" in theseKeys: 
     core.quit() 
    if len(theseKeys): 
     break 

#Begin Trials: 
for i in xrange(run_length): 
    if stim_df["MentalState"][i] == "0": 
     breakTimer.reset() 
     while breakTimer.getTime() < 15.0: 
     text.text = "+" 
     text.height = 0.25 
     text.pos = (0,0) 
     text.draw() 
    win.flip() 
    else: 
     #win.flip() 
     timer.reset() 
     exit_press = [] 
     event_press = [] 

     speaker = visual.TextStim(win, text = stim_df["speaker"][i], height = 0.1, pos = (0,0.6)) 
     speaker.setAutoDraw(True) 

     #0.5 seconds 
     while timer.getTime() < 0.5: 
      win.flip() 

     #3.0 seconds 
     if stim_df["speaker"][i] == "Computer": 
      text.text = stim_df["prompt"][i] 
      text.pos = (-0.1,0) 
      text.height = 0.08 
      text_box_length = text.boundingBox[0]/GetSystemMetrics(0)*2 

      image.image = cwd + "\\" + "gray.png" 
      image.pos = (-0.1,0) 
      image.size = (text_box_length, 0.35) 

      image.draw() 
      text.draw() 
     else: 
      text.text = stim_df["prompt"][i] 
      text.pos = (-0.1,0) 
      text.height = 0.08 
      text_box_length = text.boundingBox[0]/GetSystemMetrics(0)*2 

      image.image = cwd + "\\" + "blue.png" 
      image.pos = (-0.1,0) 
      image.size = (text_box_length, 0.35) 

      image.draw() 
      text.draw() 

     win.flip() 
     while timer.getTime() < 3.5: 
      exit_press += event.getKeys() 
      if "escape" in exit_press: 
       core.quit()    
     onset_Time = timer.getTime() 
     speaker.setAutoDraw(False) 

     #3.5 seconds 
     text.text = stim_df["question"][i] 
     text.pos = (0,0.6) 
     text.height = 0.1 
     text.draw() 

     text.text = stim_df["answerA"][i] 
     text.pos = (-0.3, -0.5) 
     text.draw() 

     text.text = stim_df["answerB"][i] 
     text.pos = (0.3, -0.5) 
     text.height = 0.1 
     text.draw() 
     win.flip() 

     length = 0 
     while timer.getTime() < 7.0: 
      event_press += event.getKeys(keyList = ["left","right"]) 
      if len(event_press) > length: 
       RT = timer.getTime() - onset_Time 
       length = len(event_press) 
      elif len(event_press) == 0: 
       RT = "N/A"    
      exit_press += event.getKeys() 
      if "escape" in exit_press: 
       core.quit() 

     #Jitter 1 time 
     text.text = "+" 
     text.pos = (0,0) 
     text.height = 0.25 
     text.draw() 
     win.flip()   
     while timer.getTime() < 7.0 + (stim_df["jitter1"][i]/1000): 
      exit_press += event.getKeys() 
      if "escape" in exit_press: 
       core.quit() 
     #Check Conditional Input   
     try: 
      response = event_press[-1] 
     except: 
      response = None 

     if response == "left": 
      reply = stim_df["answerA"][i] 
      if reply == stim_df["corrAnswer"][i]: 
       acc = 1 
      else: 
       acc = 0 
     elif response == "right": 
      reply = stim_df["answerB"][i] 
      if reply == stim_df["corrAnswer"][i]: 
       acc = 1 
      else: 
       acc = 0 
     elif response == None: 
      response = "N/A" 
      reply = stim_df["corrAnswer"][i] 
      acc = 0 

     text.text = reply 
     text.height = 0.08 
     text.pos = (0.1,0.3) 
     #2 seconds 
     if stim_df["speaker"][i] == "Computer":  
      text.text = reply 
      text.height = 0.08 
      text.pos = (0.1,0.3) 

      speaker.draw() 
      image.image = cwd + "\\" + "gray.png" 
      image.size = (text.boundingBox[0]/GetSystemMetrics(0)*2 + 0.2, text.boundingBox[1]/GetSystemMetrics(1)*2 + 0.1) 
      image.pos = (0.1, 0.3) 

      image.draw() 
      text.draw() 

      text.pos = (-0.1,-0.1) 
      text.text = reply + u" \u2713" 
      text_box_length = text.boundingBox[0]/GetSystemMetrics(0)*2 + 0.1 

      image.image = cwd + "\\" + "gray.png" 
      image.size = (text.boundingBox[0]/GetSystemMetrics(0)*2 + 0.1, text.boundingBox[1]/GetSystemMetrics(1)*2 + 0.1) 
      image.pos = (-0.1,-0.1) 

      image.draw() 
      text.draw() 
     else: 
      text.text = reply 
      text.height = 0.08 
      text.pos = (0.1,0.3) 

      speaker.draw() 
      image.image = cwd + "\\" + "green.png" 
      image.size = (text.boundingBox[0]/GetSystemMetrics(0)*2 + 0.1, text.boundingBox[1]/GetSystemMetrics(1)*2 + 0.1) 
      image.pos = (0.1,0.3) 

      image.draw() 
      text.draw() 

      text.text = reply + " :)" 
      text.pos = (-0.1,-0.1) 

      image.image = cwd + "\\" + "blue.png" 
      image.size = (text.boundingBox[0]/GetSystemMetrics(0)*2 + 0.1, text.boundingBox[1]/GetSystemMetrics(1)*2 + 0.1) 
      image.pos = (-0.1, -0.1) 

      image.draw() 
      text.draw() 
     win.flip() 
     while timer.getTime() < 9.0 + (stim_df["jitter1"][i]/1000): 
      exit_press += event.getKeys() 
      if "escape" in exit_press: 
       core.quit() 

     #Jitter 2 time 
     text.text = "+" 
     text.height = 0.25 
     text.pos = (0,0) 
     text.draw() 
     win.flip() 
     while timer.getTime() < 11.0 + (stim_df["jitter1"][i]/1000) + (stim_df["jitter2"][i]/1000): 
      exit_press += event.getKeys() 
      if "escape" in exit_press: 
       core.quit() 

     #Panda Output File 
     run_param_list.append([stim_df["block"][i], stim_df["MentalState"][i], condition, stim_df["speaker"][i], stim_df["prompt"][i], response, stim_df["corrAnswer"][i], RT, acc]) 
     fid = pd.DataFrame(run_param_list, columns = header) 
     fid.to_csv("logFile.csv", header = True) 

#Close up Shop: 
win.close() 
core.quit() 

誰でもメモリリークのエラーが発生しないように、より良いコードを改良する方法についての提案を持っている場合、私は思っていました。このエラーを解決できない場合は、PsychoPy Builderを使用して実験を複製するのが最善の解決策ですか?

+0

最小限の再現可能な例を作成すると、問題を絞り込むだけでなく、コードを実際に読んでいる人の確率を上げるのに役立ちます。 –

+0

つまり、実際に変更されたテキスト刺激のテキストプロパティのみを更新するように、既存のガイダンスに従っているかどうかは分かりません。また、できる限り、テキスト刺激を複数回作成しないでください。それらを一度作成し、必要に応じてプロパティを更新するだけです。 –

+0

こんにちはマイケル、私は正しくそれをやっていると思ったので、テキストと画像の刺激を適切に更新するための確立された指針が何であるかを明確にすることができます。例えば、私のスクリプトの最上部付近では、imageという変数をイメージに設定し、その属性(つまり、位置、画像そのもの)を変更する必要がある場合は、スクリプトの残りの部分に画像を設定して変更します.image = etc、image.pos =など。私はこのメソッドがメモリに保存するのに良い方法だと思った。プロパティを更新する効率的な方法はありますか? – djl

答えて

0

私の推測では、これは(私たちは、テキストの描画に使用するものである)pygletに存在しているようだメモリリークから来ているということです。それが、そのISNの修正を発見した https://bitbucket.org/pyglet/pyglet/issues/66/memory-leak-in-fonttext はpygletの開発者の一人のようですねしばらくの間、含まれるつもりはありません。

PsychoPyには、TextBoxという刺激クラスもあります。これは完全に(Sol Simpsonによる)最初から書かれており、多くの点でより効率的ですが、フォントを非常にうまくサポートしていません(具体的には、現時点でモノスペースのフォントしかサポートしていません)。もしあなたがそれを使用できるのであれば、同じメモリ問題を表示しないだろうと確信しています。

関連する問題