Programming with PsychoPy, 6 Structuring: separate files

In the last assignment you have learned to make a function with an argument. The text string sent to the function was used to define the question it showed. This was done from the main program. But, functions can also be called from within another function.

By this, all individual functions created for your experiment can be seen as building blocks forming your experiment. As we progress in programming our experiment and the code and number of functions increase, we need to organize the code. We can for example take all functions out of the main program file and make a separate function file for them. Let's call this file amalia.py. Replace amalia with your own name. Make sure the file name is unique. This file name will be the name of the module containing the functions. Best is to choose a name that describes the functions contained in the file. math.py is a very nice name for a file containing math functions for instance. By doing this, we get a nicely structured experiment, allowing us to keep overview. Since we do not know yet what will be in the file, it is ok to use your first name. However, do not do that again in the future. Files and modules should have meaningful names.

Let's make a file that contains just one function. One that you can call at any moment and that prints the time to your Output window and the message that you give to it. Note how the format function can be used to string together the hours, the minutes and the seconds. The format function has many option. You can look them up in the manual: http://docs.python.org/2/library/string.html (which admittedly is a bit hard to read since the function has so many options). You can for instance do "{}-{}-{}".format(day, month, year) to format a date if you have three numbers or use "{:.2f}".format(3.141592) to limit the number of decimals of pi to two.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# My functions.
 
from psychopy import core, visual, event
import math, time

## Function section
def debugLog(text):
	tSinceMidnight = time.time() % 86400
	tSinceWholeHour = tSinceMidnight % 3600
	minutes = tSinceWholeHour / 60
	hours = tSinceMidnight / 3600
	seconds = tSinceMidnight % 60
	print("log {:02d}:{:02d}:{:f}: {}".format(int(hours), int(minutes), seconds, text))

Save this file as amalia.py, or whatever your first name is. For sure, PsychoPy needs to know where to search for the variables and subroutines. Therefore, a link has to be made. The command import is the instruction we need to use the contents of another file. We use the import statement as follows:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from psychopy import core, visual, event
import time
import amalia

## Setup Section
win = visual.Window([400,300], fullscr=True, monitor="testMonitor")

## Experiment Section
for i in range(10):
	core.wait(1.000)
	win.flip()
	amalia.debugLog(i)

## Closing Section
win.close()
core.quit()

We made a module for you with a few more useful functions. Please download it, import it and use it in the assignments from now on. It is called my.py and can therefore be imported with import my. Note that it has the most dreadful name possible. Make sure you use meaningful names in the future.

Assignment 6: accuracy

  1. Run the code.
  2. Note that times are logged to microsecond accuracy. This doesn't make sense. Limit the logging of the time to milliseconds.
  3. The screens do not appear exactly 1 second apart. How much is the difference? You can calculate it yourself or change the code to do it for you. Change the waiting time. Let it increase in small steps (for instance 10 ms) from 1 s to 1.020 s. What happens to the difference between desired waiting time and actual waiting time? Can you explain the 'stepping' behaviour in the actual waiting time? Hint: Is the actual waiting time a multiple of some characteristic time? The effect may not be visible if your computer does not support he vsync feature.

Continue with the next lesson