Skip to content

Commit

Permalink
Merge pull request #88 from BlueBrain/BPE-compatibility
Browse files Browse the repository at this point in the history
BluePyEfe compatibility
  • Loading branch information
AurelienJaquier authored Dec 5, 2023
2 parents 0d187a5 + 5678809 commit cafd56b
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 126 deletions.
7 changes: 7 additions & 0 deletions bluepyemodel/ecode/dehyperpol.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class DeHyperpol(BPEM_stimulus):

"""DeHyperpol current stimulus
The hyperpolarizing step is usually fixed at 150% of rheobase, and the hyperpolarizing step
can usually vary from -40% to -160% of rheobase.
.. code-block:: none
holdi holdi+amp holdi+amp2 holdi
Expand All @@ -55,11 +58,15 @@ def __init__(self, location, **kwargs):
location(Location): location of stimulus
"""

hyper_amp_rel = kwargs.get("thresh_perc", None)
self.depol_amp = kwargs.get("amp", None)
self.depol_amp_rel = kwargs.get("amp_rel", None)
self.hyper_amp = kwargs.get("amp2", None)
self.hyper_amp_rel = kwargs.get("amp2_rel", None)

if self.hyper_amp_rel is None and hyper_amp_rel is not None:
self.hyper_amp_rel = hyper_amp_rel

if self.hyper_amp is None and self.hyper_amp_rel is None:
raise TypeError(
f"In stimulus {self.name}, hyper_amp and hyper_amp_rel cannot be both None."
Expand Down
17 changes: 15 additions & 2 deletions bluepyemodel/ecode/hyperdepol.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class HyperDepol(BPEM_stimulus):

"""HyperDepol current stimulus
The hyperpolarizing step is usually fixed at 100% of rheobase, and the hyperpolarizing step
can usually vary from -40% to -160% of rheobase.
.. code-block:: none
holdi holdi+hyper_amp holdi+depol_amp holdi
Expand Down Expand Up @@ -56,10 +59,20 @@ def __init__(self, location, **kwargs):
location(Location): location of stimulus
"""

amp = kwargs.get("amp", None)
amp2 = kwargs.get("amp2", None)
hyper_amp_rel = kwargs.get("thresh_perc", None)
self.hyper_amp = kwargs.get("hyper_amp", None)
self.hyper_amp_rel = kwargs.get("hyper_amp_rel", -100.0)
self.hyper_amp_rel = kwargs.get("hyper_amp_rel", None)
self.depol_amp = kwargs.get("depol_amp", None)
self.depol_amp_rel = kwargs.get("depol_amp_rel", 100.0)
self.depol_amp_rel = kwargs.get("depol_amp_rel", None)

if self.hyper_amp is None and amp is not None:
self.hyper_amp = amp
if self.depol_amp is None and amp2 is not None:
self.depol_amp = amp2
if self.hyper_amp_rel is None and hyper_amp_rel is not None:
self.hyper_amp_rel = hyper_amp_rel

if self.hyper_amp is None and self.hyper_amp_rel is None:
raise TypeError(
Expand Down
101 changes: 51 additions & 50 deletions bluepyemodel/ecode/negcheops.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class NegCheops(BPEM_stimulus):
: : \ / : : \ / : : \ / : :
: : ' : : ' : : ' : :
: : : : : : : :
<- delay -><-- 2 * ramp1_duration --><- inter_delay -><-- 2 * ramp2_duration --><- inter_delay -><-- 2 * ramp3_duration --> totduration
t=0 delay t1 t2 t3 t4 toff totduration
"""

name = "NegCheops"
Expand Down Expand Up @@ -79,10 +79,27 @@ def __init__(self, location, **kwargs):
self.delay = kwargs.get("delay", 1750.0)
self.total_duration = kwargs.get("totduration", 18222.0)

self.ramp1_duration = kwargs.get("ramp1_duration", 3333.0)
self.ramp2_duration = kwargs.get("ramp2_duration", 1666.0)
self.ramp3_duration = kwargs.get("ramp3_duration", 1111.0)
self.inter_delay = kwargs.get("inter_delay", 2000.0)
ramp1_duration = kwargs.get("ramp1_duration", 3333.0)
ramp2_duration = kwargs.get("ramp2_duration", 1666.0)
ramp3_duration = kwargs.get("ramp3_duration", 1111.0)
inter_delay = kwargs.get("inter_delay", 2000.0)

self.t1 = kwargs.get("t1", None)
self.t2 = kwargs.get("t2", None)
self.t3 = kwargs.get("t3", None)
self.t4 = kwargs.get("t4", None)
self.toff = kwargs.get("toff", None)

if self.t1 is None and ramp1_duration is not None and self.delay is not None:
self.t1 = self.delay + 2 * ramp1_duration
if self.t2 is None and inter_delay is not None and self.t1 is not None:
self.t2 = self.t1 + inter_delay
if self.t3 is None and ramp2_duration is not None and self.t2 is not None:
self.t3 = self.t2 + 2 * ramp2_duration
if self.t4 is None and inter_delay is not None and self.t3 is not None:
self.t4 = self.t3 + inter_delay
if self.toff is None and ramp3_duration is not None and self.t4 is not None:
self.toff = self.t4 + 2 * ramp3_duration

super().__init__(
location=location,
Expand All @@ -94,13 +111,7 @@ def stim_start(self):

@property
def stim_end(self):
return (
self.delay
+ 2.0 * self.inter_delay
+ 2.0 * self.ramp1_duration
+ 2.0 * self.ramp2_duration
+ 2.0 * self.ramp3_duration
)
return self.toff

@property
def amplitude(self):
Expand All @@ -126,25 +137,23 @@ def instantiate(self, sim=None, icell=None):

self.time_vec.append(self.delay)
self.current_vec.append(holding_current)
self.time_vec.append(self.delay + self.ramp1_duration)
self.time_vec.append((self.t1 + self.delay) / 2.0)
self.current_vec.append(holding_current + self.amplitude)
self.time_vec.append(self.delay + 2.0 * self.ramp1_duration)
self.time_vec.append(self.t1)
self.current_vec.append(holding_current)

start_cheops2 = self.delay + 2.0 * self.ramp1_duration + self.inter_delay
self.time_vec.append(start_cheops2)
self.time_vec.append(self.t2)
self.current_vec.append(holding_current)
self.time_vec.append(start_cheops2 + self.ramp2_duration)
self.time_vec.append((self.t2 + self.t3) / 2.0)
self.current_vec.append(holding_current + self.amplitude)
self.time_vec.append(start_cheops2 + 2.0 * self.ramp2_duration)
self.time_vec.append(self.t3)
self.current_vec.append(holding_current)

start_cheops3 = start_cheops2 + 2.0 * self.ramp2_duration + self.inter_delay
self.time_vec.append(start_cheops3)
self.time_vec.append(self.t4)
self.current_vec.append(holding_current)
self.time_vec.append(start_cheops3 + self.ramp3_duration)
self.time_vec.append((self.t4 + self.toff) / 2.0)
self.current_vec.append(holding_current + self.amplitude)
self.time_vec.append(start_cheops3 + 2.0 * self.ramp3_duration)
self.time_vec.append(self.toff)
self.current_vec.append(holding_current)

self.time_vec.append(self.total_duration)
Expand All @@ -167,33 +176,25 @@ def generate(self, dt=0.1):
t = numpy.arange(0.0, self.total_duration, dt)
current = numpy.full(t.shape, holding_current, dtype="float64")

idx_ton = int(self.delay / dt)
idx_inter_delay = int(self.inter_delay / dt)
idx_ramp1_duration = int(self.ramp1_duration / dt)
idx_ramp2_duration = int(self.ramp2_duration / dt)
idx_ramp3_duration = int(self.ramp3_duration / dt)

current[idx_ton : idx_ton + idx_ramp1_duration] += numpy.linspace(
0.0, self.amplitude, idx_ramp1_duration + 1
)[:-1]
current[
idx_ton + idx_ramp1_duration : idx_ton + (2 * idx_ramp1_duration)
] += numpy.linspace(self.amplitude, 0.0, idx_ramp1_duration + 1)[:-1]

idx_ton2 = idx_ton + (2 * idx_ramp1_duration) + idx_inter_delay
current[idx_ton2 : idx_ton2 + idx_ramp2_duration] += numpy.linspace(
0.0, self.amplitude, idx_ramp2_duration + 1
)[:-1]
current[
idx_ton2 + idx_ramp2_duration : idx_ton2 + (2 * idx_ramp2_duration)
] += numpy.linspace(self.amplitude, 0.0, idx_ramp2_duration + 1)[:-1]

idx_ton3 = idx_ton2 + (2 * idx_ramp2_duration) + idx_inter_delay
current[idx_ton3 : idx_ton3 + idx_ramp3_duration] += numpy.linspace(
0.0, self.amplitude, idx_ramp3_duration + 1
)[:-1]
current[
idx_ton3 + idx_ramp3_duration : idx_ton3 + (2 * idx_ramp3_duration)
] += numpy.linspace(self.amplitude, 0.0, idx_ramp3_duration + 1)[:-1]
ton = int(self.delay / dt)
t1 = int(self.t1 / dt)
t2 = int(self.t2 / dt)
t3 = int(self.t3 / dt)
t4 = int(self.t4 / dt)
toff = int(self.toff / dt)

mid = int(0.5 * (ton + t1))
current[ton:mid] += numpy.linspace(0.0, self.amp, mid - ton + 1)[:-1]
current[mid:t1] += numpy.linspace(self.amp, 0.0, t1 - mid + 1)[:-1]

# Second peak
mid = int(0.5 * (t2 + t3))
current[t2:mid] += numpy.linspace(0.0, self.amp, mid - t2 + 1)[:-1]
current[mid:t3] += numpy.linspace(self.amp, 0.0, t3 - mid + 1)[:-1]

# Third peak
mid = int(0.5 * (t4 + toff))
current[t4:mid] += numpy.linspace(0.0, self.amp, mid - t4 + 1)[:-1]
current[mid:toff] += numpy.linspace(self.amp, 0.0, toff - mid + 1)[:-1]

return t, current
109 changes: 55 additions & 54 deletions bluepyemodel/ecode/poscheops.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class PosCheops(BPEM_stimulus):
: : : : : : : ^
: : : : : : : :
: : : : : : : :
<- delay -><-- 2 * ramp1_duration --><- inter_delay -><-- 2 * ramp2_duration --><- inter_delay -><-- 2 * ramp3_duration --> totduration
t=0 delay t1 t2 t3 t4 toff totduration
"""

name = "PosCheops"
Expand Down Expand Up @@ -78,10 +78,30 @@ def __init__(self, location, **kwargs):

self.delay = kwargs.get("delay", 250.0)

self.ramp1_duration = kwargs.get("ramp1_duration", 4000.0)
self.ramp2_duration = kwargs.get("ramp2_duration", 2000.0)
self.ramp3_duration = kwargs.get("ramp3_duration", 1333.0)
self.inter_delay = kwargs.get("inter_delay", 2000.0)
ramp1_duration = kwargs.get("ramp1_duration", 4000.0)
ramp2_duration = kwargs.get("ramp2_duration", 2000.0)
ramp3_duration = kwargs.get("ramp3_duration", 1333.0)
inter_delay = kwargs.get("inter_delay", 2000.0)

self.t1 = kwargs.get("t1", None)
self.t2 = kwargs.get("t2", None)
self.t3 = kwargs.get("t3", None)
self.t4 = kwargs.get("t4", None)
self.toff = kwargs.get("toff", None)
self.total_duration = kwargs.get("totduration", None)

if self.t1 is None and ramp1_duration is not None and self.delay is not None:
self.t1 = self.delay + 2 * ramp1_duration
if self.t2 is None and inter_delay is not None and self.t1 is not None:
self.t2 = self.t1 + inter_delay
if self.t3 is None and ramp2_duration is not None and self.t2 is not None:
self.t3 = self.t2 + 2 * ramp2_duration
if self.t4 is None and inter_delay is not None and self.t3 is not None:
self.t4 = self.t3 + inter_delay
if self.toff is None and ramp3_duration is not None and self.t4 is not None:
self.toff = self.t4 + 2 * ramp3_duration
if self.total_duration is None and self.toff is not None:
self.total_duration = self.toff + 250.0

super().__init__(
location=location,
Expand All @@ -93,17 +113,7 @@ def stim_start(self):

@property
def stim_end(self):
return (
self.delay
+ 2.0 * self.inter_delay
+ 2.0 * self.ramp1_duration
+ 2.0 * self.ramp2_duration
+ 2.0 * self.ramp3_duration
)

@property
def total_duration(self):
return self.stim_end + self.delay
return self.toff

@property
def amplitude(self):
Expand All @@ -129,25 +139,23 @@ def instantiate(self, sim=None, icell=None):

self.time_vec.append(self.delay)
self.current_vec.append(holding_current)
self.time_vec.append(self.delay + self.ramp1_duration)
self.time_vec.append((self.t1 + self.delay) / 2.0)
self.current_vec.append(holding_current + self.amplitude)
self.time_vec.append(self.delay + 2.0 * self.ramp1_duration)
self.time_vec.append(self.t1)
self.current_vec.append(holding_current)

start_cheops2 = self.delay + 2.0 * self.ramp1_duration + self.inter_delay
self.time_vec.append(start_cheops2)
self.time_vec.append(self.t2)
self.current_vec.append(holding_current)
self.time_vec.append(start_cheops2 + self.ramp2_duration)
self.time_vec.append((self.t2 + self.t3) / 2.0)
self.current_vec.append(holding_current + self.amplitude)
self.time_vec.append(start_cheops2 + 2.0 * self.ramp2_duration)
self.time_vec.append(self.t3)
self.current_vec.append(holding_current)

start_cheops3 = start_cheops2 + 2.0 * self.ramp2_duration + self.inter_delay
self.time_vec.append(start_cheops3)
self.time_vec.append(self.t4)
self.current_vec.append(holding_current)
self.time_vec.append(start_cheops3 + self.ramp3_duration)
self.time_vec.append((self.t4 + self.toff) / 2.0)
self.current_vec.append(holding_current + self.amplitude)
self.time_vec.append(start_cheops3 + 2.0 * self.ramp3_duration)
self.time_vec.append(self.toff)
self.current_vec.append(holding_current)

self.time_vec.append(self.total_duration)
Expand All @@ -170,33 +178,26 @@ def generate(self, dt=0.1):
t = numpy.arange(0.0, self.total_duration, dt)
current = numpy.full(t.shape, holding_current, dtype="float64")

idx_ton = int(self.delay / dt)
idx_inter_delay = int(self.inter_delay / dt)
idx_ramp1_duration = int(self.ramp1_duration / dt)
idx_ramp2_duration = int(self.ramp2_duration / dt)
idx_ramp3_duration = int(self.ramp3_duration / dt)

current[idx_ton : idx_ton + idx_ramp1_duration] += numpy.linspace(
0.0, self.amplitude, idx_ramp1_duration + 1
)[:-1]
current[
idx_ton + idx_ramp1_duration : idx_ton + (2 * idx_ramp1_duration)
] += numpy.linspace(self.amplitude, 0.0, idx_ramp1_duration + 1)[:-1]

idx_ton2 = idx_ton + (2 * idx_ramp1_duration) + idx_inter_delay
current[idx_ton2 : idx_ton2 + idx_ramp2_duration] += numpy.linspace(
0.0, self.amplitude, idx_ramp2_duration + 1
)[:-1]
current[
idx_ton2 + idx_ramp2_duration : idx_ton2 + (2 * idx_ramp2_duration)
] += numpy.linspace(self.amplitude, 0.0, idx_ramp2_duration + 1)[:-1]

idx_ton3 = idx_ton2 + (2 * idx_ramp2_duration) + idx_inter_delay
current[idx_ton3 : idx_ton3 + idx_ramp3_duration] += numpy.linspace(
0.0, self.amplitude, idx_ramp3_duration + 1
)[:-1]
current[
idx_ton3 + idx_ramp3_duration : idx_ton3 + (2 * idx_ramp3_duration)
] += numpy.linspace(self.amplitude, 0.0, idx_ramp3_duration + 1)[:-1]
ton = int(self.delay / dt)
t1 = int(self.t1 / dt)
t2 = int(self.t2 / dt)
t3 = int(self.t3 / dt)
t4 = int(self.t4 / dt)
toff = int(self.toff / dt)

# First peak
mid = int(0.5 * (ton + t1))
current[ton:mid] += numpy.linspace(0.0, self.amp, mid - ton + 1)[:-1]
current[mid:t1] += numpy.linspace(self.amp, 0.0, t1 - mid + 1)[:-1]

# Second peak
mid = int(0.5 * (t2 + t3))
current[t2:mid] += numpy.linspace(0.0, self.amp, mid - t2 + 1)[:-1]
current[mid:t3] += numpy.linspace(self.amp, 0.0, t3 - mid + 1)[:-1]

# Third peak
mid = int(0.5 * (t4 + toff))
current[t4:mid] += numpy.linspace(0.0, self.amp, mid - t4 + 1)[:-1]
current[mid:toff] += numpy.linspace(self.amp, 0.0, toff - mid + 1)[:-1]

return t, current
3 changes: 3 additions & 0 deletions bluepyemodel/ecode/sahp.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class sAHP(BPEM_stimulus):

"""sAHP current stimulus
The long step (here amp) is usually fixed at 40% of rheobase, and the short step (here amp2)
can usually vary from 150% to 300% of rheobase.
.. code-block:: none
holdi holdi+long_amp holdi+amp holdi+long_amp holdi
Expand Down
5 changes: 1 addition & 4 deletions bluepyemodel/ecode/sinespec.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def __init__(self, location, **kwargs):

self.delay = kwargs.get("delay", 0.0)
self.duration = kwargs.get("duration", 5000.0)
self.total_duration = kwargs.get("totduration", 5000.0)

super().__init__(
location=location,
Expand All @@ -61,10 +62,6 @@ def stim_start(self):
def stim_end(self):
return self.duration + self.delay

@property
def total_duration(self):
return self.duration + self.delay

@property
def amplitude(self):
if self.amp_rel is None or self.threshold_current is None:
Expand Down
Loading

0 comments on commit cafd56b

Please sign in to comment.