The PsyScope Home Page is here. It contains lots of information, the PsyScope manual, PsyScope for Os 9, and several example scripts.
The PsyScope page at Hamilton College has an old but still very effective tutorial for PsyScope beginners.
This is Robosoft Home Page. Robosoft helped porting the code from Os 9 to Os X. It made a complete mess out of it and we are still struggling to recover from the disasters it introduced.
We will use the Black Box Toolkit to test PsyScope's timing properties. If you are seriously interested in the timing properties of your input devices, check the articles listed in the Black Box Web Page.
This section contains scripts and stimuli that can be useful for understanding techniques available in PsyScope X (and in most cases also in PsyScope 9). The scripts work in PsyScope X Beta, under Tiger and Panther.
This is a script containing examples of the new movie commands, running some rather big trailers for testing purposes (careful, 57MB). This is another version of the same script, but with some movies suited for testing precise frame synchronization (19 MB). This is the same script without movies, for those who cannot afford big downloads. Add your own movies for testing. (You need at least Beta I to run them).
In these examples, you change the rate of a movie each time a new trial is run. In one script (Movierate Script), the rate is determined by fixed values in a list. In a second script (Movierate Formula Script), the rate is determined by powers of 2, and the powers are actually assigned by a formula that uses the list to increase the exponent of the powers of 2. This script is useful to also see how you can use formulas in order to set values of stimuli in a script. The ConditionalMovie Script shows you how to use the new Movie Condition: a second movie will start when the first movie reached 10 seconds of its internal timer, regardless of the pauses or of the changes in movie rate. TwoSymMovies Script is basically the same, but now the two movies are symultaneous. If you pause the movies, you can also quickly check the movie alignments by seeing how many frame numbers of difference they display.
The Steve script shows you how you can modify the movie rate within a single trial, while the movie is playing, without loss of continuity. The data file keeps track of all the movie rate changes (which occur every 100 ms).
This is a collection of few script to exemplify the properties of the new USS Button box supported by PsyScope X.
VoiceFeedback shows visual feedback at button presses and voice input.
SimpletimeBbox within and simple bbox between are scripts meant to test a very long stretch of presses (ideally automatically generated at fixed intervals) to test timing properties. The simpletimeBbox within script allows you to record many RTs within the same trial. The simple bbox between script does the same, but for every RT a new trial is run.
UsbBboxLights shows how to use the LED lights. It also shows how to assign values of internal parameters of the bbox to PsyScope X variables.
InitialMask shows how the mask can be changed during the experiment.
The USBBBoxSerialExample Script shows several more advanced features:
These scripts contain some examples of how to use the new Serial Out command for communicating with external devices via an usb-to serial converter. Read the relevant documentation to understand it.
As several people asked, I prepared a couple of elementary scripts that show how one can give feedback in PsyScope X -- something that should be elementary, but is not. The scripts show how one can save and successively present a string typed by a subject, or a single keypress, whether numeric or alphanumeric.
--Variables and Stimulus Properties. This script shows how you can use values of variables to change the properties of an event. In the example, you increase the duration of an event by powers of 2. You may be interested in it if you want to understand how to use variables in PsyScope.
--Variables of type String. The French Script shows how you can use the new type "String" introduced in Beta II. Besides being informative, it will help you learning all what you need to know about French. Doc for the right syntax for string type is here.
--Composing the stimuli with variable values changing within trials. The French Script also shows several other things. One is to help you understand how you can use the values of variables to compose text stimuli when the variable values change during the execution of the same trial. The script changevalues script is also a more elementary example of how variables update within trials in PsyScope X.
-- Multiplying events with the ~ operator. Another useful aspect of the French script is that it shows how you can use the ~ operator to reduce the size of your script. Suppose that you want to change the size of a stimulus at each trial, or else, the number of repetition of an event for each trials. Instead of scripting a complicated script, you can have one single event, or one single stimulus, and "multiply" it with ~. You can obtain "Hello Hello Hello" by writing strcat("Hello" ~3), and if instead of 3 you have a numerical variable that changes across trials, you can modify the size of the stimulus at leisure. Of course this holds for other stimulus properties.
-- The difference between Factor Lists and Script lists. One of the most confusing aspects of PsyScope is the difference between Factor lists (i.e., lists as you define them in the graphical interface) and "plain" lists -- lists that you write directly in the script. Often you want to have a design with a list of, say, 4 elements. You run 4 trials, and find that some of the elements are repeated. Thus, you want to conclude that the randomization routines do not work. In fact, what often happens is that your script may contain another list, and the list cross with other lists (or factors) to exhaust the combinatory possibilities.
As an example: suppose you have two lists of 4 elements, each associated to a different cell in a table, or with a different event in the same trial, or with different stimulus properties of the same event. You would think that if you run 4 trials (randomly), you exhaust the two lists and no repeats should ever occur within those 4 trials. However, this is not the case. The lists cross, and in order to exhaust the crossing, you need 4 by 4 trials. Of course, if you run less than 16 trials (e.g., the 4 trials you originally wanted to run), you may have repeats -- that's part of the randomization.
Things work differently if you use lists defined in the script. In that case, even if you have several lists, they are "independent objects", and hence randomization is entirely separated for each list. So in the previous example, if you have two lists of 4 elements defined in a script, running 4 trials will exhaust the lists. (Of course, in this case you will loose the full combinatorics of the elements in the lists. So if you have a design with 2 lists, one of which has 4 elements and the other one has 3, even if you run 12 trials you will *not* have all the combinations between the two lists. Such exhaustivity is guaranteed instead if you use graphical (factor) lists).
These two scripts make the difference clear (I hope). The FactorList Script contains two lists of 4 elements. The script runs 16 trials, and you can check in the data file that all the combinations of the two lists are represented exactly once. However, if you forget that you have two lists, or think that they are independent and concentrate on one list only (e.g., the stimuli list), and want to exhaust its elements in one run, then you will be tempted to run 4 trials. As a result, most likely will find repeats in the stimuli and will think that the program has a randomization bug. It is not the case.
By comparison, the ListList Script is the same template, but lists are defined in the script directly. In this case, you can check that if you run 16 trials all combinations need not to occur just once, because the lists are independent. However, for the same reason, if you run exactly 4 trials, all the 4 elements of each list will appear exactly once.
--How to access the Time field of a Reaction Time. Very often, you will want to consult when something occurred during a trial. In order to do that, in PsyScope you have to take a Reaction Time, and then see at what moment the RT action occurred.
RT actions generate a complex record, and one of its field is the value you are interested in. You have to get to that damn field! In order to do that, the best solution I found is as follows
- Define a variable of type Response (say, you call it MyResp), and a variable of type Integer or Long Integer, or Real (say, you call it MyTime).
- Take a RT when you need, and assign it to MyResp.
- Now you can access the Time field with the syntax Myresp->time, and use this to assign the time value to MyTime.
The scripts contained in the ConditionalTime folder show simple examples of how this can be achieved. The scripts do the following: Any time you press a key they take a RT; They shows that RT, plus the cumulative sum of all RTs you have taken so far; and they end the template containing the RT action on a mouse click and start a new template.
The ConditionalSingle script shows how you can do this by repeatedly taking RTs within one single, long lasting event. The ConditionalRepeated script shows how you can do it by using a short event that is repeated as many times as you want. The difference will be that in the first case, all your RTs will be taken starting from the beginning of that event, and hence will necessarily be increasingly higher values. In the second case instead, because the event ends and is being repeated several times, each RT will be aligned to the beginning of each repetition of that event, and hence the RT values will correspond to the actual time from one keypress to another.
--How to correctly save the Time field of a Reaction Time in the data file as a variable value. The two scripts in the ConditionalTime folder also show you how to solve another related problem.
Suppose you have assigned the time value of a RT to a variable, as explained above (call it MyTime). You now want to save that variable into the data file. The only way you have to write in the data file is to take a RT action. But the RT action you take is also the action you use to save a line of values in the data file! So for that line of values, the value of your variable will be systematically wrong, because you assign the value of the RT time filed to that variable after you have taken the RT! Not good.
Thanks to the fact that PsyScope X dynamically upgrades the values of variables within a single trial, you can now use a "trick" to solve this problem, by taking two RTs one after the other, as follows:
- You specify that the first RT should NOT to be saved in the data file.
-You then assign the value of that RT to your variable MyTime.
-Then, you take a second RT, which will be written in the data file.
This second RT will occur after the variable MyTime has received its value, and so it will have the right time value. Because both RTs and the value assignment occur within the same millisecond, the time value of the second RT will not change from that of the first, but the value of the MyTime variable will be the correct RT value. This correspond to write instructions like these in PsyScript:
Conditions[ End ] => Actions[ RT[ NULL NULL MyResp var_only ] set[MyTime "Myresp->time"] RT ]
where RT[ NULL NULL MyResp var_only ] takes a RT, assigns it to the variable Myresp (which is a response type variable), and it marks that the Rt should not be recorded in the data file. Then set[MyTime "Myresp->time"] assigns the time field of that response variable to the variable "MyTime" (which is of type integer, or long integer, or real), and the final RT gets the reaction time and writes the right values to the data files. NOTICE THAT THE ORDER OF THESE ACTIONS IS CRUCIAL.
You can run the scripts, and check the data file to see the relation between the "time" value and the value of your variables, to see that everything is right.
-- How to vary online properties of what comes next based on the RT of a preceding trial. The scripts in the ConditionalTime folder are also useful to see how to solve another problem. Say you want to change the properties of a stimulus according to how fast a subject responded in a previous trial. For example, you want to say: if s/he was fast, make the next stimulus red. If s/he was slow, make it blue.
There are several ways to do that in PsyScope. The scripts show one of them which allow you to see how to properly use a simple function definition. The technique is simple:
-You use the same procedure as explained above in order to assign the value of the RT of an event to a numerical variable.
- Now you also script a function which uses that variable value.
The function must be added in the #> TrialManagerVariables part of the script. That function will say: If MyTime was more than a certain value, give "Blue" as a result; Otherwise, give "Red":
MyFunction:: Result: if(@MyTime>5000 "Blue" "Red")
Notice the syntax: MyFunction has to have a separate line with the Result: identifier. After it, you can write whatever you want -- expressions, numbers, operations. In this case, we write a logical expression. "Blue" and "Red" are strings of letters.
Finally, you use a function call as the value of the parameters of another event.
For simplicity, in the example, the event is a text event, that resides in another template, and we vary its color and its stimulus according to the value of that function:
Duration: key[Any] Mouse[ Click ]
The important point to notice here is that the stimulus adn the color are a simple call to MyFunction, without arguments. The script will present the word "Blue" written in blue or the word "Red" written in red.
--Non trivial randomization constraints. This is a cute script that shows how to satisfy some non trivial randomization constraints, by using direct scripting of lists. You may be interested in it if you want to understand how to use lists and direct scripting in PsyScope. The discussion may be interesting for others, so I put the explanation here.
Other very interesting public domain software projects for psychologists using Macs and OS X exist.
-- Vision Egg is a program written in Python that can run entire experiments.
-- PsyScript is a program using Applescript. It is currently being ported to Os X.
-- The PsychToolbox and its brother (sister?) VideoToolbox are well known, rich, and widely used environments to design experiments using Matlab. The PsychToolbox is currently being ported to Os X. In the future, it would be great to integrate it with PsyScope.
-- MacScience can connect you to many sites containing information about the Mac and the sciences (Compositionality vindicated!)
Christophe Pallier's site has zillions of interesting things, including code we aim to incorporate in PsyScope. It's a Linux-oriented rather than Os X-oriented site, but pobody is nerfect. Christophe has also written EXPE, a very good GNU experimental program running under DOS, and Shuffle, a Perl program that lets you randomize lists with conditions.
-- Macosxspeed contains several useful tips if you want to understand how to put your machine in the most favorable condition to perform fast.