This isn’t going to be super-interesting to almost anyone, but I figured the cloud was as good a place as any to post my preliminary notes on Aaron Geller and Per Sederberg’s Python Experiment-Programming Library, known to its friends as PyEPL. It’s more or less what you’d expect it to be — a Python package that manages a lot of the grungy tasks, from low-level hardware management to higher-level things like data logging, that underlie a computerized psychology experiment. I do generally believe that using open-source tools is, if not the best idea in all situations, at least a good habit to get into — there may come a day where I find myself working at a university that doesn’t have a Matlab site license — and, in my lame-duck period, I have time to learn a new platform. I’ve had some Python off and on for the last… almost nine years? So this isn’t utterly new to me, and I’ve even tried to program things in PyEPL before, but this is the first thing I’ve really gotten working soup to nuts.
I should emphasize that these notes are just the hacks that got things working for me. Any universally quantified statements I might appear to be making about Python or PyEPL should be read as lessons from my 48 hours of semi-serious work on this experiment, not as pronouncements from someone who is or believes himself to be especially authoritative about anything.
- Python is pass-by-reference. No it’s not — just ask Google — but if you spend 90% of your time coding in Matlab, you’re probably going to try to fork a list or a dictionary using assignment, and then you’ll be really frustrated for a while when your old object starts inheriting the values of the new object.
copy.deepcopyhas gotten me around this, but there may be better solutions.
- You can actually set the size of an
Imageobject in its arguments. For most of the experiment, I was presenting one image at a time and using
Image.presentto display them. But when I wanted to present a matrix of them in specific positions,
VideoTrack.showProportionalseemed like the right thing — except that it wouldn’t change their sizes.
Image($YOURFILENAME,propxsize=0.1,propysize=0.1)will present the image at 10% scale when supplied to
instructis optional only if you’re not fussed about running an experiment after giving instructions. At any rate, I couldn’t figure out how to advance past the
instructcommand without supplying that argument.
- Reaction time is more easily derived from the
Showable.presentmethod than from the keyboard log.
- Another Python-only point: You might think you’re pretty smart to initialize a 10-x-10 matrix of zeroes using
matrix = [*10]*10. And you might be right — but the resulting construct will still exhibit totally fucked-up behavior. Anyone who has a workaround for this should feel free to tell me immediately. (If it involves numpy, which it probably does, feel free to tell me how the resulting object will play with standard Python.)
- Using a config file is good programming practice. So what? Scripting experiments isn’t software engineering. However, PyEPL rewards this particular good programming practice by saving a copy of your config file with the subject’s data, meaning you don’t have to write code to log it — or, worse, forget to write code to log it and lose the value of some key parameter that’s totally critical to your analysis.
That’s all I’ve got for now. If you want to learn more about PyEPL and computerized experimentation, my friend Greg has a collaborative PyEPL blog and a nice post on running psychology experiments for you to browse.