Reading saved data

[[This document is pretty out of date]]

Plexon files

Neural data, any attached analog input data, and synchronization markers for accompanying HDF5 files are stored in Plexon’s .plx file format.

Plexon has graciously provided some C headers for their stuff. Unfortunately, most of it is poorly organized, and ripped verbatim from incomplete code, so much of it had to be reverse engineered.

Using Plexfile

Included with the plexon library is a Plexfile module, which allows the quick reslicing of *.plx files.

To open a plexon file:

from plexon import plexfile
plx = plexfile.openFile("demo.plx")

The first time you attempt to open a large file, it will take a while because it has to be indexed. It should save a cache file and in the future it will be faster if it finds the cache.

To read all the spikes from time 0:10 seconds,

plx.spikes[:10].data

Unlike normal python slicing, decimal slices are ok:

plx.spikes[0.5:2.5].data

Be aware of how much time you slice, as you will QUICKLY run out of memory!

A slice like the above will return a record array with three data types: ts, chan, and unit.

To retrieve the timestamps where spikes occurred within a time slice, along with the corresponding channel and unit numbers:

spike_times = plx.spikes[0.5:2.5].data['ts']
spike_chans = plx.spikes[0.5:2.5].data['chan']
spike_units = plx.spikes[0.5:2.5].data['unit']

You can filter out data for a particular unit using logical combinations of the unit and channel labels. Channels here are labeled 1-256 to match the Plexon convention, but unit labels have been changed from letters to numbers (0 = unsorted, 1 = a, 2 = b, etc.). For example:

spikes = plx.spikes[0.5:2.5].data
unit161a = spikes[np.logical_and(spikes['chan'] == 161, spikes['unit'] == 1)]['ts']

will return the timestamps of all of unit 161a’s spikes between .5 and 2.5s.

To retrieve spike waveforms instead of timestamps:

waveforms = plx.spikes[0.5:2.5].waveforms
unit161a = waveforms[np.logical_and(spikes.data['chan'] == 161, spikes.data['unit'] == 1)]

For continuous data, use the corresponding names wideband, spkc, lfp, analog. Timestamps and data values can be extracted independently from a slice, and both are returned as a time x channel array. For example:

plx.lfp[.5:2.5].time
plx.lfp[.5:2.5].data

will return the timestamps and data respectively from 0.5 to 2.5 s for all available LFP channels in the file. If you’d like to slice from individual channels, use typical python slice semantics:

touch = plx.analog[0.5:2.5, 0].data          # retrieve channel AN01 data
data1 = plx.wideband[0.5:2.5, 140:160].data  # retrieve channels WB141 - WB160 data
data2 = plx.spkc[0.5:2.5, [145, 161]].time   # retrieve channels SPKC146 and SPKC162 timestamps

The plexfile module has a built in binning function. It’s written in C and therefore runs fast enough to be used in real time. It must be called from from a plx file object (as opposed to a slice of data). It takes two inputs– bintimes (an array of floats representing the end time of each desired bin), and optional input binlen (a float representing the desired bin length in seconds, default value = .1). The function returns an iterable containing spike counts for all units and all bins:

times = np.linspace(1, 10, 200)
iterspike = plx.spikes.bin(times, binlen=1.)
x = np.array([bin for bin in iterspike])

Visualize the output:

imshow(x)
xlabel('Unit')
ylabel('Time (bin)')

Make sure the values in the bintimes input are floats and not integers, otherwise you’ll get a type error!

HDF5 files

Data from all attached systems except Plexon, as well as the state transition logs are stored in .hdf files.

First, load the file:

import tables
hdffile = tables.openFile(fname)

The position data is a timesample x marker# x 4 record array. The last dimension contains x,y, and z positions followed by a condition value.

Table Of Contents

Previous topic

Analyzing Data

Next topic

Comment and doc string format guide

This Page