Skip to content

Commit

Permalink
doc neo.rawio
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuel Garcia committed Aug 28, 2017
1 parent e23f7f7 commit 318c285
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 57 deletions.
120 changes: 100 additions & 20 deletions doc/source/rawio.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Neo RawIO
******

.. currentmodule:: neo
.. currentmodule:: neo.rawio


.. _neo_rawio_API:
Expand All @@ -15,9 +15,12 @@ For short:
of neo objects from a data source (file, url, or directory).
When reading all neo object are correctly scaled to the correct units.
Write consist to make a set of neo object persistent in a file format.
Here the neo tree can be totally asymetric along Block and Segment.
* **neo.rawio** is a low level layer that do read only. Read consist of getting
numpy buffers (often int16/int64) of signals/spike/event.
Scalling to real value (microV, times, ...) is done in a second step.
Here underlying object must be consistent along Block and Segment for a given
data source.


This neo.rawio API have been added for developpers.
Expand Down Expand Up @@ -45,26 +48,32 @@ The neo.rawio is less flexible that neo.io and have some limitaion:
a the same time.
* Units must have SpikeTrain event if empty along all Block and Segment
* Epoch and Event are processed the same way (with durations=None for event).



For intuitive comparison of neo.io and neo.rawio see:
* example/read_file_neo_io.py
* example/read_file_neo_rawio.py


One speculative benefit of this neo.rawio should be that a developer
should be able to code a new RawIO class with few knownledge of the neo tree
object and the python quantity module.



Basic usage
===========


First create a reader from a class::

>>>> from neo.rawio import PlexonRawIO
>>>> reader =PlexonRawIO(filename='File_plexon_1.plx')
>>> from neo.rawio import PlexonRawIO
>>> reader =PlexonRawIO(filename='File_plexon_3.plx')

Then browse the internal header and display informations::

>>>> reader.parse_header()
>>>> print(header)
>>> reader.parse_header()
>>> print(header)
PlexonRawIO: File_plexon_3.plx
nb_block: 1
nb_segment: [1]
Expand All @@ -77,8 +86,8 @@ about channels: **signal_channels**, **unit_channels**, **event_channels**.

All theses information are internally available in the *header* dict::

>>>> for k, v in reader.header.items():
print(k, v)
>>> for k, v in reader.header.items():
... print(k, v)
signal_channels [('V1', 0, 1000., 'int16', '', 2.44140625, 0., 0)]
event_channels []
nb_segment [1]
Expand All @@ -90,24 +99,95 @@ All theses information are internally available in the *header* dict::

Read signal chunk of data and scale them::

>>>> channel_indexes = None  #could be channel_indexes = [0]
>>>> raw_sigs = reader.get_analogsignal_chunk(block_index=0, seg_index=0,
>>> channel_indexes = None  #could be channel_indexes = [0]
>>> raw_sigs = reader.get_analogsignal_chunk(block_index=0, seg_index=0,
i_start=1024, i_stop=2048, channel_indexes=channel_indexes)
>>>> float_sigs = reader.rescale_signal_raw_to_float(raw_sigs, dtype='float64')
>>>> sampling_rate = reader.get_signal_sampling_rate()
>>>> t_start = reader.get_signal_t_start(block_index=0, seg_index=0)
>>>> units =reader.header['signal_channels'][0]['units']
>>>> print(raw_sigs.shape, raw_sigs.dtype)
>>>> print(float_sigs.shape, float_sigs.dtype)
>>>> print(sampling_rate, t_start, units)
>>> float_sigs = reader.rescale_signal_raw_to_float(raw_sigs, dtype='float64')
>>> sampling_rate = reader.get_signal_sampling_rate()
>>> t_start = reader.get_signal_t_start(block_index=0, seg_index=0)
>>> units =reader.header['signal_channels'][0]['units']
>>> print(raw_sigs.shape, raw_sigs.dtype)
>>> print(float_sigs.shape, float_sigs.dtype)
>>> print(sampling_rate, t_start, units)
(1024, 1) int16
(1024, 1) float64
1000.0 0.0 V


Inspect units channel. Each channel give a SpikeTrain for each Segment.
Note that for many format a physical channel can have several units after spike
sorting. So th nb_unit could be more than physical channel or signal channels.

>>> nb_unit = reader.unit_channels_count()
nb_unit 30
>>> print('nb_unit', nb_unit)
>>> for unit_index in range(nb_unit):
... nb_spike = reader.spike_count(block_index=0, seg_index=0, unit_index=unit_index)
... print('unit_index', unit_index, 'nb_spike', nb_spike)
unit_index 0 nb_spike 701
unit_index 1 nb_spike 716
unit_index 2 nb_spike 69
unit_index 3 nb_spike 12
unit_index 4 nb_spike 95
unit_index 5 nb_spike 37
unit_index 6 nb_spike 25
unit_index 7 nb_spike 15
unit_index 8 nb_spike 33
...


Get spike timestamps and convert to spike times between 0 and 10 seconds::

>>> spike_timestamps = reader.spike_timestamps(block_index=0, seg_index=0, unit_index=0,
t_start=0., t_stop=10.)
>>> print(spike_timestamps.shape, spike_timestamps.dtype, spike_timestamps[:5])
(424,) int64 [ 90 420 708 1020 1310]
>>> spike_times = reader.rescale_spike_timestamp( spike_timestamps, dtype='float64')
>>> print(spike_times.shape, spike_times.dtype, spike_times[:5])
(424,) float64 [ 0.003 0.014 0.0236 0.034 0.04366667]


Get spike waveforms between 0 and 10s::

>>> raw_waveforms = reader.spike_raw_waveforms( block_index=0, seg_index=0, unit_index=0,
t_start=0., t_stop=10.)
>>> print(raw_waveforms.shape, raw_waveforms.dtype, raw_waveforms[0,0,:4])
(424, 1, 64) int16 [-449 -206 34 40]
>>> float_waveforms = reader.rescale_waveforms_to_float(raw_waveforms, dtype='float32', unit_index=0)
>>> print(float_waveforms.shape, float_waveforms.dtype, float_waveforms[0,0,:4])
(424, 1, 64) float32 [-0.65771484 -0.30175781 0.04980469 0.05859375]



Count event per channel::

>>> reader = PlexonRawIO(filename='File_plexon_2.plx')
>>> reader.parse_header()
>>> nb_event_channel = reader.event_channels_count()
nb_event_channel 28
>>> print('nb_event_channel', nb_event_channel)
>>> for chan_index in range(nb_event_channel):
... nb_event = reader.event_count(block_index=0, seg_index=0, event_channel_index=chan_index)
... print('chan_index',chan_index, 'nb_event', nb_event)
chan_index 0 nb_event 1
chan_index 1 nb_event 0
chan_index 2 nb_event 0
chan_index 3 nb_event 0
...


Read event timestamps and times for chanindex=0 and with time limits (t_start=None, t_stop=None)::

>>> ev_timestamps, ev_durations, ev_labels = reader.event_timestamps(block_index=0, seg_index=0, event_channel_index=0,
t_start=None, t_stop=None)
>>> print(ev_timestamps, ev_durations, ev_labels)
[1268] None ['0']
>>> ev_times = reader.rescale_event_timestamp(ev_timestamps, dtype='float64')
>>> print(ev_times)
[ 0.0317]

.. trdesclous_: https://github.com/tridesclous/tridesclous



.. _tridesclous: https://github.com/tridesclous/tridesclous
86 changes: 49 additions & 37 deletions examples/read_files_neo_rawio.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
# -*- coding: utf-8 -*-
"""
This is an example for reading files with neo.io
This is an example for reading files with neo.rawio
compare with read_files_neo_io.py
"""

import urllib
from neo.rawio import PlexonRawIO

from neo.rawio import PlexonRawIO, Spike2RawIO



# Plexon files
#Get Plexon files
distantfile = 'https://portal.g-node.org/neo/plexon/File_plexon_3.plx'
localfile = './File_plexon_3.plx'
urllib.request.urlretrieve(distantfile, localfile)


# create a reader
reader = PlexonRawIO(filename='File_plexon_3.plx')
reader.parse_header()
print(reader)
print(reader.header)

for k, v in reader.header.items():
print(k, v)

#Read signal chunks
channel_indexes = None #could be channel_indexes = [0]
raw_sigs = reader.get_analogsignal_chunk(block_index=0, seg_index=0,
Expand All @@ -36,34 +34,48 @@
print(sampling_rate, t_start, units)


#Count unit and spike per units
nb_unit = reader.unit_channels_count()
print('nb_unit', nb_unit)
for unit_index in range(nb_unit):
nb_spike = reader.spike_count(block_index=0, seg_index=0, unit_index=unit_index)
print('unit_index', unit_index, 'nb_spike', nb_spike)


#Read spike times
spike_timestamps = reader.spike_timestamps(block_index=0, seg_index=0, unit_index=0,
t_start=0., t_stop=10.)
print(spike_timestamps.shape, spike_timestamps.dtype, spike_timestamps[:5])
spike_times = reader.rescale_spike_timestamp( spike_timestamps, dtype='float64')
print(spike_times.shape, spike_times.dtype, spike_times[:5])


#Read spike waveforms
raw_waveforms = reader.spike_raw_waveforms( block_index=0, seg_index=0, unit_index=0,
t_start=0., t_stop=10.)
print(raw_waveforms.shape, raw_waveforms.dtype, raw_waveforms[0,0,:4])
float_waveforms = reader.rescale_waveforms_to_float(raw_waveforms, dtype='float32', unit_index=0)
print(float_waveforms.shape, float_waveforms.dtype, float_waveforms[0,0,:4])



#Count event per channel
reader = PlexonRawIO(filename='File_plexon_2.plx')
reader.parse_header()
nb_event_channel = reader.event_channels_count()
print('nb_event_channel', nb_event_channel)
for chan_index in range(nb_event_channel):
nb_event = reader.event_count(block_index=0, seg_index=0, event_channel_index=chan_index)
print('chan_index',chan_index, 'nb_event', nb_event)


#Read event timestamps and times (take anotehr file)
distantfile = 'https://portal.g-node.org/neo/plexon/File_plexon_2.plx'
localfile = './File_plexon_2.plx'
urllib.request.urlretrieve(distantfile, localfile)

# read the blocks
#~ blks = reader.read(cascade=True, lazy=False)
#~ print (blks)
#~ # access to segments
#~ for blk in blks:
#~ for seg in blk.segments:
#~ print (seg)
#~ for asig in seg.analogsignals:
#~ print (asig)
#~ for st in seg.spiketrains:
#~ print (st)


#~ # CED Spike2 files
#~ distantfile = 'https://portal.g-node.org/neo/spike2/File_spike2_1.smr'
#~ localfile = './File_spike2_1.smr'
#~ urllib.request.urlretrieve(distantfile, localfile)

#~ # create a reader
#~ reader = neo.io.Spike2IO(filename='File_spike2_1.smr')
#~ # read the block
#~ bl = reader.read(cascade=True, lazy=False)[0]
#~ print (bl)
#~ # access to segments
#~ for seg in bl.segments:
#~ print (seg)
#~ for asig in seg.analogsignals:
#~ print (asig)
#~ for st in seg.spiketrains:
#~ print (st)
ev_timestamps, ev_durations, ev_labels = reader.event_timestamps(block_index=0, seg_index=0, event_channel_index=0,
t_start=None, t_stop=None)
print(ev_timestamps, ev_durations, ev_labels)
ev_times = reader.rescale_event_timestamp(ev_timestamps, dtype='float64')
print(ev_times)

0 comments on commit 318c285

Please sign in to comment.