2016-04-15 10 views
0

Ich habe ein Experiment in der Coder-Sektion von PsychoPy entwickelt. Es ist eine relativ einfache Aufgabe, erfordert aber viel Text und Bild. Ich habe versucht, das ganze Experiment läuft (besteht aus 123 Studien) vor ein paar Tagen, und um den 28. Iteration erhielt ich folgende Fehlermeldung:PsychoPy textStim Speicherleck Problem

WindowsError: Ausnahme: Zugriffsverletzung schriftlich 0x00000004

ich in diese sah, und Es scheint, dass in Pyglet ein Speicherleck auftritt, der beim Zeichnen einer großen Menge von Textstimulationen im Fenster auftritt. Ich habe meinen Code so verfeinert, dass nur die Textkomponenten geändert werden, wenn das Experiment es erfordert. Ich liste meinen gesamten Code unten als Referenz:

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() 

ich mich gefragt, ob jemand einen Vorschlag zu hat, wie der Code zu verfeinern besser, so dass der Speicherverlust Fehler werden nicht auftreten. Wenn dieser Fehler nicht behoben werden kann, wäre es die beste Lösung, das Experiment mit PsychoPy Builder zu replizieren?

+0

Die Entwicklung eines minimalen reproduzierbaren Beispiels würde Ihnen helfen, das Problem einzugrenzen und die Wahrscheinlichkeit zu erhöhen, dass jemand Ihren Code tatsächlich liest. –

+0

, d. H. Es ist schwer zu sagen, ob Sie tatsächlich der festgelegten Anleitung folgen, um nur die Texteigenschaft eines Textreizes zu aktualisieren, wenn sich dieser Wert tatsächlich geändert hat. Auch, wo immer es möglich ist, erstellen Sie keine Textreize mehrmals. Erstellen Sie sie einmal und aktualisieren Sie dann ihre Eigenschaften nach Bedarf. –

+0

Hallo Michael, könntest du erklären, was die etablierte Anleitung ist, um Text- und Bildreize richtig zu aktualisieren, weil ich dachte, ich würde es richtig machen. Zum Beispiel setze ich am oberen Rand meines Skripts eine Bildvariable mit dem Namen image und dann im Rest des Scripts, wenn ich eines seiner Attribute ändern muss (zB Position, das Bild selbst), dann würde ich es ändern, indem ich image mache .image = etc, image.pos = usw. Ich dachte, dass diese Methode eine gute Möglichkeit ist, Speicher zu sparen. Gibt es eine effizientere Möglichkeit, ihre Eigenschaften zu aktualisieren? – djl

Antwort

0

Meine Vermutung ist, dass diese aus einem Speicherleck kommt, die in Pyglet zu existieren scheint (das ist, was wir für Text-Rendering verwenden): https://bitbucket.org/pyglet/pyglet/issues/66/memory-leak-in-fonttext Klingt wie eine der Pyglet Entwickler dafür ein Update gefunden hat, aber das isn Ich werde für eine Weile nicht mit einbezogen.

PsychoPy hat auch eine Stimulus-Klasse namens TextBox. Das ist komplett von Grund auf (von Sol Simpson) geschrieben und ist in vielerlei Hinsicht effizienter, unterstützt aber Fonts nicht sehr gut (insbesondere unterstützt es derzeit nur Mono-Spaced-Fonts). Ich bin sicher, dass das nicht die gleichen Speicherprobleme zeigen wird, wenn Sie das verwenden können.