Analyzing Experimental Data¶
Events, Event Stream, and Event File¶
The basic unit of MWorks experimental data is the event. An MWorks event consists of an event code, a time stamp, and a value (i.e. the payload).
Most events announce a change in the value of a variable. The codec (or variable codec) provides the mapping between event codes and their associated variables. Additionally, some system events use codes that are not associated with a variable.
The sequence of events generated by a running experiment is called the event stream. The on-disk record of an experiment’s event stream is known as the event file. Event files are stored on the machine running MWServer, in the directory $HOME/Documents/MWorks/Data, where $HOME is the path to the user’s home directory (e.g. /Users/chris).
Analyzing the Event File¶
To analyze the results of a completed run of an experiment, you must extract the relevant events from the run’s event file. MWorks provides tools for loading event data in to Python or MATLAB.
Using Python¶
Setup¶
To use MWorks’ data analysis tools for Python, you must first make the mworks package available to your Python code. You can do this on a per-script basis by adding the directory /Library/Application Support/MWorks/Scripting/Python to the module search path:
import sys
sys.path.insert(0, '/Library/Application Support/MWorks/Scripting/Python')
If you want the mworks package to be available to all Python code you run, you can create an mworks.pth file in your per-user site-packages directory. For example, for Python 2.7, execute the following commands in a Terminal window:
mkdir -p ~/Library/Python/2.7/lib/python/site-packages
echo '/Library/Application Support/MWorks/Scripting/Python' > ~/Library/Python/2.7/lib/python/site-packages/mworks.pth
Opening and Closing¶
To open an event file, use the MWKFile class from the mworks.data module:
from mworks.data import MWKFile
f = MWKFile('my_data.mwk')
f.open()
When you are done using the file, you should close it:
f.close()
Alternatively, you can use the with statement to handle opening and closing of the file in an implicit, exception-safe fashion:
with MWKFile('my_data.mwk') as f:
# Analysis code goes here
...
Selecting Events¶
Once the file is open, extract events using the get_events method. If called with no arguments, this method returns all events in the file:
all_events = f.get_events()
You can also use keyword arguments to filter events by code or time. The codes argument takes a list of event codes or variable names and selects only events with matching codes. For example, we can extract all events for the variables red_selected, green_selected, and blue_selected (which appear in the “Find the Circle” example in Running an Experiment) like this:
events = f.get_events(codes=['red_selected', 'green_selected', 'blue_selected'])
The time_range argument takes a list containing a start time and stop time and selects only events whose time stamps fall within that range:
events = f.get_events(time_range=[t1, t2])
You can specify both codes and time_range to filter on code and time simultaneously.
When analyzing large event files, you may want to extract events one at a time, in order to avoid filling up system memory. To do this, use the get_events_iter method. This method takes the same arguments as get_events. However, instead of loading all matching events in to a single, list-like object, get_events_iter returns an iterator, each iteration of which loads a single event from the data file. For example, here is how you would use get_events_iter to process every event:
for event in f.get_events_iter():
# Use data from event
...
Accessing Event Data¶
Once you have extracted an event, you can access its event code, time stamp, and value via the code, time, and data properties of the event object:
>>> evt = events[0]
>>> evt.code
36
>>> evt.time
30343102
>>> evt.data
0
The code and time properties always have integer values. However, data can be a boolean, integer, float, string, list, or dictionary:
>>> events = f.get_events(codes=['#announceMessage'])
>>> events[15].data
{'origin': 1, 'message': '4 of 10 trials were correct (68217117)', 'type': 0, 'domain': 0}
Using the Codec¶
To convert an event code to a variable name, use the codec property of the MWKFile object:
>>> f.codec[36]
'red_selected'
To convert a variable name to an event code, use the reverse_codec property:
>>> f.reverse_codec['red_selected']
36
Using MATLAB¶
Setup¶
To use MWorks’ data analysis tools for MATLAB, you must first add the directory /Library/Application Support/MWorks/Scripting/Matlab to the search path:
addpath('/Library/Application Support/MWorks/Scripting/Matlab')
Selecting Events¶
To extract events from an event file, use the getEvents function. If called with just the filename, this function returns all events in the file:
all_events = getEvents('my_data.mwk')
To extract only events with specific event codes, provide an array containing the desired codes as the second argument:
events = getEvents('my_data.mwk', [36, 37, 38])
To further restrict the retrieved events to a particular time range, specify a minimum and maximum time as the third and fourth arguments, respectively:
events = getEvents('my_data.mwk', [36, 37, 38], t1, t2)
To extract all events in a given time range, pass an empty array as the second argument:
events = getEvents('my_data.mwk', [], t1, t2)
Accessing Event Data¶
The getEvents function returns a structure array containing all selected events. The event code, time stamp, and value of each event are accessible via the event_code, time_us, and data fields of each array element:
>> evt = events(1);
>> evt.event_code
ans =
int32
36
>> evt.time_us
ans =
int64
30343102
>> evt.data
ans =
int64
0
The event_code and time_us fields always have integer values. However, the type of data can be logical, integer, floating point, string, cell, struct, or Map:
>> events = getEvents('my_data.mwk', [6]);
>> events(16).data
ans =
struct with fields:
message: '4 of 10 trials were correct (68217117)'
origin: 1
type: 0
domain: 0
Using the Codec¶
To convert an event code to a variable name, use the Map returned by the getCodec function:
>> codec = getCodec('my_data.mwk');
>> codec(36)
ans =
'red_selected'
To convert a variable name to an event code, use the Map returned by the getReverseCodec function:
>> reverse_codec = getReverseCodec('my_data.mwk');
>> reverse_codec('red_selected')
ans =
int64
36