-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ENH] Integrate trials object with Fano factor #645
Open
Moritz-Alexander-Kern
wants to merge
13
commits into
NeuralEnsemble:master
Choose a base branch
from
INM-6:enh/trials_fano_factor
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 9 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
4011266
add handling for trial object
Moritz-Alexander-Kern 218a653
add tests
Moritz-Alexander-Kern ed5ca52
Merge branch 'master' into enh/trials_fano_factor
Moritz-Alexander-Kern 29694fa
add tests for trial object pooling trials or spiketrains
Moritz-Alexander-Kern 1711f43
add parameters pool_trials, pool_spiketrains
Moritz-Alexander-Kern 7b0ccf9
add type check for pool parameters
Moritz-Alexander-Kern 1925bf3
refactor type annotations
Moritz-Alexander-Kern 3c1eb5d
add to docstring
Moritz-Alexander-Kern 6bb2fc3
add user warning and did refactoring of function
Moritz-Alexander-Kern 69a4d24
remove pool trials parameter
Moritz-Alexander-Kern 5b1cf75
add paramter ignored for spiketrainslist to docstring
Moritz-Alexander-Kern 303f363
remove user warning to manually check duration for numpy arrays
Moritz-Alexander-Kern e9e6778
remove pool_trials arg
Moritz-Alexander-Kern File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,7 +74,7 @@ | |
import scipy.signal | ||
from numpy import ndarray | ||
from scipy.special import erf | ||
from typing import Union | ||
from typing import List, Union | ||
|
||
import elephant.conversion as conv | ||
import elephant.kernels as kernels | ||
|
@@ -270,10 +270,12 @@ def mean_firing_rate(spiketrain, t_start=None, t_stop=None, axis=None): | |
return rates | ||
|
||
|
||
def fanofactor(spiketrains, warn_tolerance=0.1 * pq.ms): | ||
def fanofactor(spiketrains: Union[List[neo.SpikeTrain], List[pq.Quantity], List[np.ndarray], elephant.trials.Trials], | ||
warn_tolerance: pq.Quantity = 0.1 * pq.ms, pool_trials: bool = False, pool_spike_trains: bool = False | ||
) -> Union[float, List[float], List[List[float]]]: | ||
r""" | ||
Evaluates the empirical Fano factor F of the spike counts of | ||
a list of `neo.SpikeTrain` objects. | ||
a list of `neo.SpikeTrain` objects or `elephant.trials.Trial` object. | ||
|
||
Given the vector v containing the observed spike counts (one per | ||
spike train) in the time window [t0, t1], F is defined as: | ||
|
@@ -288,32 +290,42 @@ def fanofactor(spiketrains, warn_tolerance=0.1 * pq.ms): | |
|
||
Parameters | ||
---------- | ||
spiketrains : list | ||
spiketrains : list or elephant.trials.Trial | ||
List of `neo.SpikeTrain` or `pq.Quantity` or `np.ndarray` or list of | ||
spike times for which to compute the Fano factor of spike counts. | ||
spike times for which to compute the Fano factor of spike counts, or | ||
an `elephant.trials.Trial` object, here the behavior can be controlled with the | ||
pool_trials and pool_spike_trains parameters. | ||
warn_tolerance : pq.Quantity | ||
In case of a list of input neo.SpikeTrains, if their durations vary by | ||
more than `warn_tolerence` in their absolute values, throw a warning | ||
more than `warn_tolerance` in their absolute values, throw a warning | ||
(see Notes). | ||
Default: 0.1 ms | ||
pool_trials : bool, optional | ||
If True, pool spike trains across trials before computing the Fano factor. | ||
Default: False | ||
pool_spike_trains : bool, optional | ||
Moritz-Alexander-Kern marked this conversation as resolved.
Show resolved
Hide resolved
|
||
If True, pool spike trains within each trial before computing the Fano factor. | ||
Default: False | ||
Moritz-Alexander-Kern marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Returns | ||
------- | ||
fano : float | ||
fano : float, list of floats or list of list of floats | ||
The Fano factor of the spike counts of the input spike trains. | ||
Returns np.NaN if an empty list is specified, or if all spike trains | ||
are empty. | ||
are empty. If a `Trial` object is provided, returns a list of Fano | ||
factors. | ||
|
||
Raises | ||
------ | ||
TypeError | ||
If the input spiketrains are neo.SpikeTrain objects, but | ||
`warn_tolerance` is not a quantity. | ||
If the parameters `pool_trials` or `pool_spike_trains` are not of type bool. | ||
|
||
Notes | ||
----- | ||
The check for the equal duration of the input spike trains is performed | ||
only if the input is of type`neo.SpikeTrain`: if you pass a numpy array, | ||
only if the input is of type`neo.SpikeTrain`: if you pass e.g. a numpy array, | ||
please make sure that they all have the same duration manually. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. move notes to spiketrains parameter docstring |
||
|
||
Examples | ||
|
@@ -328,29 +340,59 @@ def fanofactor(spiketrains, warn_tolerance=0.1 * pq.ms): | |
0.07142857142857142 | ||
|
||
""" | ||
# Build array of spike counts (one per spike train) | ||
spike_counts = np.array([len(st) for st in spiketrains]) | ||
|
||
# Compute FF | ||
if all(count == 0 for count in spike_counts): | ||
# empty list of spiketrains reaches this branch, and NaN is returned | ||
return np.nan | ||
|
||
if all(isinstance(st, neo.SpikeTrain) for st in spiketrains): | ||
if not is_time_quantity(warn_tolerance): | ||
raise TypeError("'warn_tolerance' must be a time quantity.") | ||
durations = [(st.t_stop - st.t_start).simplified.item() | ||
for st in spiketrains] | ||
durations_min = min(durations) | ||
durations_max = max(durations) | ||
if durations_max - durations_min > warn_tolerance.simplified.item(): | ||
warnings.warn("Fano factor calculated for spike trains of " | ||
"different duration (minimum: {_min}s, maximum " | ||
"{_max}s).".format(_min=durations_min, | ||
_max=durations_max)) | ||
|
||
fano = spike_counts.var() / spike_counts.mean() | ||
return fano | ||
# Check if parameters are of the correct type | ||
if not isinstance(pool_trials, bool): | ||
raise TypeError(f"'pool_trials' must be of type bool, but got {type(pool_trials)}") | ||
elif not isinstance(pool_spike_trains, bool): | ||
raise TypeError(f"'pool_spike_trains' must be of type bool, but got {type(pool_spike_trains)}") | ||
elif not is_time_quantity(warn_tolerance): | ||
raise TypeError(f"'warn_tolerance' must be a time quantity, but got {type(warn_tolerance)}") | ||
|
||
def _check_input_spiketrains_durations(spiketrains: Union[List[neo.SpikeTrain], List[pq.Quantity], | ||
List[np.ndarray]]) -> None: | ||
if spiketrains and all(isinstance(st, neo.SpikeTrain) for st in spiketrains): | ||
durations = np.array(tuple(st.duration for st in spiketrains)) | ||
if np.max(durations) - np.min(durations) > warn_tolerance: | ||
warnings.warn(f"Fano factor calculated for spike trains of " | ||
f"different duration (minimum: {np.min(durations)}s, maximum " | ||
f"{np.max(durations)}s).") | ||
else: | ||
warnings.warn(f"Spiketrains was of type {type(spiketrains)}, which does not support automatic duration" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove warning |
||
f"check. The parameter 'warn_tolerance' will have no effect. Please ensure manually that" | ||
f"all spike trains have the same duration.") | ||
|
||
def _compute_fano(spiketrains: Union[List[neo.SpikeTrain], List[pq.Quantity], List[np.ndarray]]) -> float: | ||
# Check spike train durations | ||
_check_input_spiketrains_durations(spiketrains) | ||
# Build array of spike counts (one per spike train) | ||
spike_counts = np.array(tuple(len(st) for st in spiketrains)) | ||
# Compute FF | ||
if np.all(np.array(spike_counts) == 0): | ||
# empty list of spiketrains reaches this branch, and NaN is returned | ||
return np.nan | ||
else: | ||
return spike_counts.var()/spike_counts.mean() | ||
|
||
if isinstance(spiketrains, elephant.trials.Trials): | ||
if not pool_trials and not pool_spike_trains: | ||
return [[_compute_fano([spiketrain]) for spiketrain in spiketrains.get_spiketrains_from_trial_as_list(idx)] | ||
for idx in range(spiketrains.n_trials)] | ||
elif not pool_trials and pool_spike_trains: | ||
return [_compute_fano(spiketrains.get_spiketrains_from_trial_as_list(idx)) | ||
for idx in range(spiketrains.n_trials)] | ||
elif pool_trials and not pool_spike_trains: | ||
list_of_lists_of_spiketrains = [ | ||
spiketrains.get_spiketrains_from_trial_as_list(trial_id=trial_no) | ||
for trial_no in range(spiketrains.n_trials)] | ||
return [_compute_fano([list_of_lists_of_spiketrains[trial_no][st_no] | ||
for trial_no in range(len(list_of_lists_of_spiketrains))]) | ||
for st_no in range(len(list_of_lists_of_spiketrains[0]))] | ||
elif pool_trials and pool_spike_trains: | ||
return [_compute_fano( | ||
[spiketrain for trial_no in range(spiketrains.n_trials) | ||
for spiketrain in spiketrains.get_spiketrains_from_trial_as_list(trial_id=trial_no)])] | ||
else: # Legacy behavior | ||
return _compute_fano(spiketrains) | ||
|
||
|
||
def __variation_check(v, with_nan): | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove parameter -> default behavior for trial object as input