Skip to content

Commit

Permalink
Merge pull request NeuralEnsemble#219 from INM-6/feature/spiketrain_snr
Browse files Browse the repository at this point in the history
* Added waveform_snr function
* Added unittest for waveform_snr function
* Added name to authorlist
* Added atom-related files to .gitignore
  • Loading branch information
dizcza committed May 20, 2019
2 parents 5fbc0fd + b779582 commit 61b9fd0
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ nosetests.xml
.settings
*.tmp*
.idea
.pytest_cache/

# Compiled source #
###################
Expand Down
1 change: 1 addition & 0 deletions doc/authors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ contribution, and may not be the current affiliation of a contributor.
* Michael von Papen [1]
* Robin Gutzen [1]
* Felipe Méndez [10]
* Simon Essink [1]

1. Institute of Neuroscience and Medicine (INM-6), Computational and Systems Neuroscience & Institute for Advanced Simulation (IAS-6), Theoretical Neuroscience, Jülich Research Centre and JARA, Jülich, Germany
2. Unité de Neurosciences, Information et Complexité, CNRS UPR 3293, Gif-sur-Yvette, France
Expand Down
49 changes: 49 additions & 0 deletions elephant/test/test_waveform_features.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""
Unit tests for the waveform_feature module.
:copyright: Copyright 2014-2019 by the Elephant team, see AUTHORS.txt.
:license: Modified BSD, see LICENSE.txt for details.
"""

from __future__ import division

import unittest
import neo
import numpy as np
import quantities as pq

from elephant import waveform_features


class WaveformSignalToNoiseRatioTestCase(unittest.TestCase):
def setUp(self):
self.spiketrain_without_waveforms = neo.SpikeTrain(
[0.5, 0.7, 1.2, 2.3, 4.3, 5.5, 6.7] * pq.s, t_stop=10.0 * pq.s)
self.spiketrain_with_zero_waveforms = neo.SpikeTrain(
[0.5, 0.7, 1.2, 2.3, 4.3, 5.5, 6.7] * pq.s, t_stop=10.0 * pq.s)
self.spiketrain_with_zero_waveforms.waveforms = \
np.zeros((10, 1, 10)) * pq.uV

self.spiketrain_with_waveforms = neo.SpikeTrain(
[0.5, 6.7] * pq.s, t_stop=10.0 * pq.s)
self.spiketrain_with_waveforms.waveforms = \
np.arange(20).reshape((2, 1, 10)) * pq.uV

def test_without_wavefroms(self):
self.assertRaises(ValueError, waveform_features.waveform_snr,
self.spiketrain_without_waveforms)

def test_with_zero_waveforms(self):
result = waveform_features.waveform_snr(
self.spiketrain_with_zero_waveforms)
self.assertTrue(np.isnan(result))

def test_with_waveforms(self):
target_value = 0.9
result = waveform_features.waveform_snr(
self.spiketrain_with_waveforms)
self.assertEqual(result, target_value)


if __name__ == '__main__':
unittest.main()
74 changes: 74 additions & 0 deletions elephant/waveform_features.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
"""
Features of waveforms (e.g waveform_snr).
:copyright: Copyright 2014-2016 by the Elephant team, see AUTHORS.txt.
:license: Modified BSD, see LICENSE.txt for details.
"""

from __future__ import division, print_function

import numpy as np
import quantities as pq
import neo
import warnings


def waveform_snr(spiketrain):
"""
Return the signal-to-noise ratio of the waveforms of a SpikeTrain.
Signal-to-noise ratio is defined as the difference in mean peak-to-trough
voltage divided by twice the mean SD. The mean SD is computed by
measuring the SD of the spike waveform over all acquired spikes
at each of the sample time points of the waveform and then averaging [1].
Parameters
----------
spiketrain : Neo SpikeTrain
The spike times with attached waveforms.
Returns
-------
snr : float
signal-to-noise ratio according to Hatsopoulos 2007
Raises
------
ValueError
If `spiketrain` has no attached waveforms.
References
----------
[1] Hatsopoulos, N. G., Xu, Q. & Amit, Y.
Encoding of Movement Fragments in the Motor Cortex.
J. Neurosci. 27, 5105–5114 (2007).
"""

# check whether spiketrain contains waveforms
if spiketrain.waveforms is None:
raise ValueError('There are no waveforms attached to this \
neo.Spiketrain. Did you forget to set \
load_waveforms=True in neoIO.read_block()?')

# average over all waveforms for each bin
mean_waveform = np.mean(spiketrain.waveforms.magnitude, axis=0)[0]
# standard deviation over all waveforms for each bin
std_waveform = np.std(spiketrain.waveforms.magnitude, axis=0)[0]
mean_std = np.mean(std_waveform)

# signal
peak_to_trough_voltage = np.max(mean_waveform) - np.min(mean_waveform)
# noise
noise = 2 * mean_std

if noise == 0:
warnings.warn('The noise was evaluated to 0.')
snr = np.nan
else:
snr = peak_to_trough_voltage / noise
return snr

0 comments on commit 61b9fd0

Please sign in to comment.