Source code for bluepyefe.rheobase
"""Functions related to the computation of the rheobase"""
"""
Copyright (c) 2022, EPFL/Blue Brain Project
This file is part of BluePyEfe <https://github.com/BlueBrain/BluePyEfe>
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License version 3.0 as published
by the Free Software Foundation.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
import logging
import numpy
logger = logging.getLogger(__name__)
def _get_list_spiking_amplitude(cell, protocols_rheobase):
"""Return the list of sorted list of amplitude that triggered at least
one spike"""
amps = []
spike_counts = []
for i, rec in enumerate(cell.recordings):
if rec.protocol_name in protocols_rheobase:
if rec.spikecount is not None:
amps.append(rec.amp)
spike_counts.append(rec.spikecount)
if rec.amp < 0.01 and rec.spikecount >= 1:
logger.warning(
f"A recording of cell {cell.name} protocol "
f"{rec.protocol_name} shows spikes at a "
"suspiciously low current in a trace from file"
f" {rec.files}. Check that the ton and toff are"
"correct or for the presence of unwanted spikes."
)
if amps:
amps, spike_counts = zip(*sorted(zip(amps, spike_counts)))
return amps, spike_counts
[docs]
def compute_rheobase_absolute(cell, protocols_rheobase, spike_threshold=1):
""" Compute the rheobase by finding the smallest current amplitude
triggering at least one spike.
Args:
cell (Cell): cell for which to compute the rheobase
protocols_rheobase (list): names of the protocols that will be
used to compute the rheobase of the cells. E.g: ['IDthresh'].
spike_threshold (int): number of spikes above which a recording
is considered to compute the rheobase.
"""
amps, spike_counts = _get_list_spiking_amplitude(cell, protocols_rheobase)
for amp, spike_count in zip(amps, spike_counts):
if spike_count >= spike_threshold:
cell.rheobase = amp
break
[docs]
def compute_rheobase_flush(cell, protocols_rheobase, flush_length=1, upper_bound_spikecount=None):
""" Compute the rheobase by finding the smallest current amplitude that::
1. Triggered at least one spike
2. Is followed by flush_length other traces that also trigger spikes.
The advantage of this strategy is that it ignores traces showing spurious
spikes at low amplitudes.
Args:
cell (Cell): cell for which to compute the rheobase
protocols_rheobase (list): names of the protocols that will be
used to compute the rheobase of the cells. E.g: ['IDthresh'].
flush_length (int): number of traces that needs to show spikes for
the candidate trace to be considered the rheobase.
upper_bound_spikecount (int): if the spikecount of a recording is higher
than this number, the recording will not trigger the start of a flush
"""
amps, spike_counts = _get_list_spiking_amplitude(cell, protocols_rheobase)
for i, amp in enumerate(amps):
# We missed the threshold
if upper_bound_spikecount is not None:
if spike_counts[i] > upper_bound_spikecount:
break
if spike_counts[i]:
end_flush = min(i + 1 + flush_length, len(amps))
if (
numpy.count_nonzero(spike_counts[i + 1:end_flush]) == flush_length
):
cell.rheobase = amp
break
[docs]
def compute_rheobase_majority_bin(
cell, protocols_rheobase, min_step=0.01, majority=0.5
):
""" Compute the rheobase by finding the smallest current amplitude
triggering at least 1 spikes in the majority (default 50%) of the
recordings.
Args:
cell (Cell): cell for which to compute the rheobase
protocols_rheobase (list): names of the protocols that will be
used to compute the rheobase of the cells. E.g: ['IDthresh'].
min_step (float): minimum step above which amplitudes can be
considered as separate steps
majority (float): the proportion of sweeps with spike_threshold
spikes to consider the target amplitude as rheobase
"""
amps, spike_counts = _get_list_spiking_amplitude(cell, protocols_rheobase)
bins = numpy.arange(min(amps), max(amps), min_step)
bins_of_amps = numpy.digitize(amps, bins, right=False)
for i, bin in enumerate(bins):
spikes = [
spike_counts[j] for j, idx in enumerate(bins_of_amps) if idx == i
]
perc_spiking = numpy.mean([bool(s) for s in spikes])
if perc_spiking >= majority:
cell.rheobase = bin + (min_step / 2.)
break
[docs]
def compute_rheobase_interpolation(cell, protocols_rheobase):
""" Compute the rheobase by fitting the reverse IF curve and finding the
intersection with the line x = 1.
Args:
cell (Cell): cell for which to compute the rheobase
protocols_rheobase (list): names of the protocols that will be
used to compute the rheobase of the cells. E.g: ['IDthresh'].
"""
amps, spike_counts = _get_list_spiking_amplitude(cell, protocols_rheobase)
# Remove the excess zeros
idx = next(
(i for i in range(len(amps) - 1) if not spike_counts[i] and spike_counts[i + 1]),
None
)
if idx is None:
return
amps = amps[idx:]
spike_counts = spike_counts[idx:]
if amps:
try:
fit = numpy.poly1d(numpy.polyfit(spike_counts, amps, deg=1))
except:
logger.error(
f"Rheobase interpolation did not converge on cell {cell.name}"
)
return
cell.rheobase = fit(1)