Skip to content

Commit

Permalink
Adds the ability to extract for absolute amplitude in addition to (#114)
Browse files Browse the repository at this point in the history
relative amplitude
  • Loading branch information
DrTaDa committed Dec 12, 2022
1 parent 14c40e9 commit 1511589
Show file tree
Hide file tree
Showing 13 changed files with 139 additions and 118 deletions.
8 changes: 0 additions & 8 deletions bluepyefe/ecode/DeHyperPol.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,5 @@ def compute_relative_amp(self, amp_threshold):
self.amp2_rel = 100.0 * self.amp2 / amp_threshold
self.hypamp_rel = 100.0 * self.hypamp / amp_threshold

def in_target(self, target, tolerance):
"""Returns a boolean. True if the amplitude of the eCode is close to
target and False otherwise."""
if numpy.abs(target - self.amp_rel) < tolerance:
return True
else:
return False

def get_plot_amplitude_title(self):
return " ({:.01f}%/{:.01f}%)".format(self.amp_rel, self.amp2_rel)
8 changes: 0 additions & 8 deletions bluepyefe/ecode/HyperDePol.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,5 @@ def compute_relative_amp(self, amp_threshold):
self.amp2_rel = 100.0 * self.amp2 / amp_threshold
self.hypamp_rel = 100.0 * self.hypamp / amp_threshold

def in_target(self, target, tolerance):
"""Returns a boolean. True if the amplitude of the eCode is close to
target and False otherwise."""
if numpy.abs(target - self.amp_rel) < tolerance:
return True
else:
return False

def get_plot_amplitude_title(self):
return " ({:.01f}%/{:.01f}%)".format(self.amp_rel, self.amp2_rel)
7 changes: 1 addition & 6 deletions bluepyefe/ecode/SpikeRec.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,7 @@ def generate(self):

return t, current

def compute_relative_amp(self, amp_threshold):
"""Divide all the amplitude in the stimuli by the spiking amplitude"""
self.amp_rel = 100.0 * self.amp / amp_threshold
self.hypamp_rel = 100.0 * self.hypamp / amp_threshold

def in_target(self, target, tolerance):
def in_target(self, target, tolerance, absolute_amplitude):
"""Returns a boolean. True if the delta of the eCode is close to
target and False otherwise."""
logger.warning(
Expand Down
12 changes: 0 additions & 12 deletions bluepyefe/ecode/negCheops.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,3 @@ def generate(self):
current[mid:toff] += numpy.linspace(self.amp, 0.0, toff - mid)

return time, current

def compute_relative_amp(self, amp_threshold):
self.amp_rel = 100.0 * self.amp / amp_threshold
self.hypamp_rel = 100.0 * self.hypamp / amp_threshold

def in_target(self, target, tolerance):
"""Returns a boolean. True if the amplitude of the eCode is close to
target and False otherwise."""
if numpy.abs(target - self.amp_rel) < tolerance:
return True
else:
return False
12 changes: 0 additions & 12 deletions bluepyefe/ecode/posCheops.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,3 @@ def generate(self):
current[mid:toff] += numpy.linspace(self.amp, 0.0, toff - mid)

return time, current

def compute_relative_amp(self, amp_threshold):
self.amp_rel = 100.0 * self.amp / amp_threshold
self.hypamp_rel = 100.0 * self.hypamp / amp_threshold

def in_target(self, target, tolerance):
"""Returns a boolean. True if the amplitude of the eCode is close to
target and False otherwise."""
if numpy.abs(target - self.amp_rel) < tolerance:
return True
else:
return False
13 changes: 0 additions & 13 deletions bluepyefe/ecode/ramp.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,3 @@ def generate(self):
)

return t, current

def compute_relative_amp(self, amp_threshold):
"""Divide all the amplitude in the stimuli by the spiking amplitude"""
self.amp_rel = 100.0 * self.amp / amp_threshold
self.hypamp_rel = 100.0 * self.hypamp / amp_threshold

def in_target(self, target, tolerance):
"""Returns a boolean. True if the amplitude of the eCode is close to
target and False otherwise."""
if numpy.abs(target - self.amp_rel) < tolerance:
return True
else:
return False
11 changes: 7 additions & 4 deletions bluepyefe/ecode/sAHP.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,16 @@ def compute_relative_amp(self, amp_threshold):
self.amp2_rel = 100.0 * self.amp2 / amp_threshold
self.hypamp_rel = 100.0 * self.hypamp / amp_threshold

def in_target(self, target, tolerance):
def in_target(self, target, tolerance, absolute_amplitude=False):
"""Returns a boolean. True if the amplitude of the eCode is close to
target and False otherwise."""
if numpy.abs(target - self.amp2_rel) < tolerance:

effective_amp = self.amp2 if absolute_amplitude else self.amp2_rel

if numpy.abs(target - effective_amp) < tolerance:
return True
else:
return False

return False

def get_plot_amplitude_title(self):
return " ({:.01f}%/{:.01f}%)".format(self.amp_rel, self.amp2_rel)
13 changes: 0 additions & 13 deletions bluepyefe/ecode/sineSpec.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,16 +129,3 @@ def generate(self):
current += self.hypamp

return t, current

def compute_relative_amp(self, amp_threshold):
"""Divide all the amplitude in the stimuli by the spiking amplitude"""
self.amp_rel = 100.0 * self.amp / amp_threshold
self.hypamp_rel = 100.0 * self.hypamp / amp_threshold

def in_target(self, target, tolerance):
"""Returns a boolean. True if the amplitude of the eCode is close to
target and False otherwise."""
if numpy.abs(target - self.amp_rel) < tolerance:
return True
else:
return False
13 changes: 0 additions & 13 deletions bluepyefe/ecode/step.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,16 +177,3 @@ def generate(self):
current[ton_idx:toff_idx] += self.amp

return t, current

def compute_relative_amp(self, amp_threshold):
"""Divide all the amplitude in the stimuli by the spiking amplitude"""
self.amp_rel = 100.0 * self.amp / amp_threshold
self.hypamp_rel = 100.0 * self.hypamp / amp_threshold

def in_target(self, target, tolerance):
"""Returns a boolean. True if the amplitude of the eCode is close to
target and False otherwise."""
if numpy.abs(target - self.amp_rel) < tolerance:
return True
else:
return False
55 changes: 38 additions & 17 deletions bluepyefe/extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,10 @@ def compute_rheobase(


def _build_protocols(
targets, global_rheobase, protocol_mode, efel_settings=None
targets,
global_rheobase,
protocol_mode,
efel_settings=None
):
"""Build a list of Protocols that matches the expected targets"""

Expand Down Expand Up @@ -355,6 +358,7 @@ def _build_protocols(
def group_efeatures(
cells,
targets,
absolute_amplitude=False,
use_global_rheobase=True,
protocol_mode='mean',
efel_settings=None
Expand All @@ -380,6 +384,9 @@ def group_efeatures(
'Threshold': -10.
}
}]
absolute_amplitude (bool): if True, will use the absolute amplitude
instead of the relative amplitudes of the recordings when checking
if a recording has to be used for a given target.
use_global_rheobase (bool): As the final amplitude of a target is the
mean of the amplitude of the cells, a global rheobase can be used
to avoid issues when a cell matches a target but not another one.
Expand All @@ -399,7 +406,7 @@ def group_efeatures(
efel_settings = {}

global_rheobase = None
if use_global_rheobase:
if use_global_rheobase and not absolute_amplitude:
global_rheobase = numpy.nanmean(
[c.rheobase for c in cells if c.rheobase is not None]
)
Expand All @@ -408,22 +415,23 @@ def group_efeatures(
targets,
global_rheobase=global_rheobase,
protocol_mode=protocol_mode,
efel_settings=efel_settings
efel_settings=efel_settings,
)

for protocol in protocols:
for cell in cells:

if cell.rheobase is None:
if cell.rheobase is None and not absolute_amplitude:
continue

for recording in cell.get_recordings_by_protocol_name(
protocol.name
):

if recording.in_target(
protocol.amplitude,
protocol.tolerance
protocol.amplitude,
protocol.tolerance,
absolute_amplitude
):
protocol.append(recording)

Expand Down Expand Up @@ -659,6 +667,7 @@ def _extract_with_targets(
files_metadata,
targets=None,
protocols_rheobase=None,
absolute_amplitude=False,
recording_reader=None,
map_function=map,
low_memory_mode=False,
Expand All @@ -683,16 +692,18 @@ def _extract_with_targets(
files_metadata, recording_reader, targets, efel_settings
)

compute_rheobase(
cells,
protocols_rheobase=protocols_rheobase,
rheobase_strategy=rheobase_strategy,
rheobase_settings=rheobase_settings
)
if not absolute_amplitude:
compute_rheobase(
cells,
protocols_rheobase=protocols_rheobase,
rheobase_strategy=rheobase_strategy,
rheobase_settings=rheobase_settings
)

protocols = group_efeatures(
cells,
targets,
absolute_amplitude=absolute_amplitude,
use_global_rheobase=True,
protocol_mode=protocol_mode,
efel_settings=efel_settings
Expand Down Expand Up @@ -806,6 +817,7 @@ def extract_efeatures(
targets=None,
threshold_nvalue_save=1,
protocols_rheobase=None,
absolute_amplitude=False,
recording_reader=None,
map_function=map,
write_files=False,
Expand Down Expand Up @@ -839,9 +851,11 @@ def extract_efeatures(
need to be present in the file metadata of different protocols if
the path contains data coming from different stimuli (eg: for NWB).
targets (list): define the efeatures to extract as well as which
protocols and current amplitude (expressed in % of the rheobase)
they should be extracted. If targets are not provided, automatic
targets will be used. Of the form:
protocols and current amplitude (expressed either in % of the
rheobase if absolute_amplitude if False or in nA if
absolute_amplitude is True) they should be extracted.
If targets are not provided, automatic targets will be used.
Of the form:
[{
"efeature": "AP_amplitude",
"protocol": "IDRest",
Expand All @@ -857,6 +871,9 @@ def extract_efeatures(
an efeatures to be averaged and returned in the output.
protocols_rheobase (list): names of the protocols that will be
used to compute the rheobase of the cells. E.g: ['IDthresh'].
absolute_amplitude (bool): if True, will use the absolute amplitude
instead of the relative amplitudes of the recordings when checking
if a recording has to be used for a given target.
recording_reader (function): custom recording reader function. It's
inner working has to match the metadata entered in files_metadata.
map_function (function): Function used to map (parallelize) the
Expand Down Expand Up @@ -902,7 +919,7 @@ def extract_efeatures(
)
efel_settings = DEFAULT_EFEL_SETTINGS.copy()

if protocols_rheobase is None:
if protocols_rheobase is None and not absolute_amplitude:
logger.warning(
"protocols_rheobase is None. Default protocol names will be used"
)
Expand All @@ -925,7 +942,10 @@ def extract_efeatures(
if targets is not None and auto_targets is not None:
raise Exception("Cannot specify both targets and auto_targets.")

if targets is None or auto_targets is not None:
if (
not absolute_amplitude and
(targets is None or auto_targets is not None)
):
cells, protocols, targets = _extract_auto_targets(
files_metadata,
protocols_rheobase,
Expand All @@ -942,6 +962,7 @@ def extract_efeatures(
files_metadata,
targets,
protocols_rheobase,
absolute_amplitude,
recording_reader,
map_function,
low_memory_mode,
Expand Down
10 changes: 6 additions & 4 deletions bluepyefe/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,21 @@ def __init__(
tolerance,
feature_targets=None,
global_rheobase=None,
mode="mean"
mode="mean",
):
"""Constructor
Args:
name (str): name of the protocol (ex: 'APWaveform')
amplitude (float): amplitude of the current stimuli for the
present protocol (expressed as a percentage of the
threshold amplitude (rheobase))
threshold amplitude or in absolute current depending on the
setting absolute_amplitude)
tolerance (float): tolerance around the target amplitude in which
an experimental recording will be seen as a hit during
efeatures extraction (expressed as a percentage of the
threshold amplitude (rheobase))
threshold amplitude or in absolute current depending on the
setting absolute_amplitude)
feature_targets (list): list of EFeatureTarget associated to the
protocol
global_rheobase (float): average rheobase across all cells
Expand Down Expand Up @@ -187,7 +189,7 @@ def reduce_ecode(self, ecode, operator):
amp_rel = operator([c["amp_rel"] for c in params])
mean_param = float(amp_rel) * self.global_rheobase / 100.
else:
mean_param = operator([c[key] for c in params])
mean_param = operator([numpy.nan if c[key] is None else c[key] for c in params])

setattr(ecode, key, mean_param)

Expand Down
17 changes: 17 additions & 0 deletions bluepyefe/recording.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,23 @@ def compute_spikecount(self, efel_settings=None, offset_voltage=20.):
"voltage goes higher than the spike detection threshold."
)

def in_target(self, target, tolerance, absolute_amplitude=False):
"""Returns a boolean. True if the amplitude of the eCode is close to
target and False otherwise."""

effective_amp = self.amp if absolute_amplitude else self.amp_rel

if numpy.abs(target - effective_amp) < tolerance:
return True

return False

def compute_relative_amp(self, amp_threshold):
"""Divide all the amplitude in the stimuli by the spiking amplitude"""

self.amp_rel = 100.0 * self.amp / amp_threshold
self.hypamp_rel = 100.0 * self.hypamp / amp_threshold

def get_plot_amplitude_title(self):
return " ({:.01f}%)".format(self.amp_rel)

Expand Down
Loading

0 comments on commit 1511589

Please sign in to comment.