Extracellular ephys example storing spike eventsΒΆ

#!/usr/bin/python
import sys
import nwb
import numpy as np
from nwb.nwbco import *

""" 
Store extracellular ephys data

"""

########################################################################
# create a new NWB file
# several settings are specified when doing so. these can be supplied within
#   the NWB constructor or defined in a dict, as in in this example
settings = {}
settings["filename"] = "sample_extracellular_spikes.nwb"

# each file should have a descriptive globally unique identifier 
#   that specifies the lab and this experiment session
# the function nwb.create_identifier() is recommended to use as it takes
#   the string and appends the present date and time
settings["identifier"] = nwb.create_identifier("extracellular spikes example")

# indicate that it's OK to overwrite exting file
settings["overwrite"] = True

# specify the start time of the experiment. all times in the NWB file
#   are relative to experiment start time
# if the start time is not specified the present time will be used
settings["start_time"] = "Sat Jul 04 2015 3:14:16"

# provide one or two sentences that describe the experiment and what
#   data is in the file
settings["description"] = "Test file demonstrating a simple extracellular ephys recording"

# create the NWB object. this manages the file
print "Creating " + settings["filename"]
neurodata = nwb.NWB(**settings)

########################################################################
# create two electrical series, one with a single electrode and one with many
# then create a spike event series

# first create the electrode map
# example simulated recording is made from two 2-electrode probes named
#   'p0' and 'p1'. we need to define the locations of the electrodes
#   relative to each probe, and the location of the probes
# electrode coordinates are in meters and their positions 
#   are relative to each other. the location of the probe itself is
#   stored separately. using absolute coordinates here, if they are known, 
#   is still OK
electrode_map = [[0, 0, 0], [0, 1.5e-6, 0], [0, 0, 0], [0, 3.0e-5, 0]]
electrode_group = [ "p0", "p0", "p1", "p1" ]
neurodata.set_metadata(EXTRA_ELECTRODE_MAP, electrode_map)
neurodata.set_metadata(EXTRA_ELECTRODE_GROUP, electrode_group)
# set electrode impedances
neurodata.set_metadata(EXTRA_IMPEDANCE, [ 1e6, 1.1e6, 1.2e6, 1.3e6 ])

# define the placement of each probe
neurodata.set_metadata(EXTRA_SHANK_LOCATION("p0"), "CA1, left hemisphere, stereotactic coordinates xx, yy")
neurodata.set_metadata(EXTRA_SHANK_LOCATION("p1"), "CA3, left hemisphere, stereotactic coordinates xx, yy")

########################################################################
# the example is of two 2-electrode probes. the electrode data from these
#   probes can be stored individually, grouped as probes (eg, 2-electrode
#   pair) or all stored together. these approaches are all exampled here 

# create time series with all electrode data stored together
quad = neurodata.create_timeseries("ElectricalSeries", "quad", "acquisition")
quad.set_comment("Data corresponds to four electrodes (two probes)")
quad.set_data(np.zeros((10000, 4)))
quad.set_time(np.arange(10000) * 0.0001)
# indicate that we're recording from the first electrode defined in the
#   above map (electrode numbers start at zero, so electrodes are 
#   0, 1, 2 and 3
quad.set_value("electrode_idx", [0, 1, 2, 3])
# finish the time series and write data to disk
quad.finalize()

########################################################################
# spikes can be reported by hardware or be detected by software
# in both cases, they are considered to be processed data and so belong
#   in a processing module

# create the module
spike_mod = neurodata.create_module("my spikes")

# create an interface that stores the events. here they will be stored
#   with their waveforms, such as would be the input to a spike-sorting
#   algorithm
spike_iface = spike_mod.create_interface("EventWaveform")
spike_iface.set_source("Data from device FooBar-X1 using dynamic multi-phasic threshold of 5xRMS")

# the event waveform interface publishes a SpikeEventSeries. make 
#   that series
spike = neurodata.create_timeseries("SpikeEventSeries", "my waveforms")
spike.set_comment("Snapshots of spike events pulled from a recording")
spike.set_value("electrode_idx", [2, 3])    # probe 'p1'
# describe the source of the data (may be redundant w/ interface source)
spike.set_value("source", "Data from device FooBar-X1 using dynamic multi-phasic threshold of 5xRMS")
# make some bogus simulated data
# this is 20 events all having the same shape and a pseudorandom time
evt = np.zeros((8,2))
evt[3][0] = 0.01
evt[4][0] = -0.005
evt[3][1] = 0.005
evt[4][1] = -0.0025
data = []
t = []
last = 1.0
for i in range(20):
    data.append(evt)
    last = last + (i * 17) % 29
    t.append(last)
# 
spike.set_time(t)
spike.set_data(data)
# if data were stored in another unit such as microvolts, it would be
#   necessary to specify a converstion between that unit and Volts.
#   that would be done using the following:
#spike.set_data(data, conversion=1.0e-6)

# add the time series to the interface. the interface will manage 
#   finalizing the time series
spike_iface.add_timeseries(spike)

# now close the interface and its parent module
spike_iface.finalize()
spike_mod.finalize()

# close file, otherwise it will fail to write properly
neurodata.close()

Previous topic

Extracellular ephys example

This Page