"""Synapse Stimuli."""
# Copyright 2020-2022 Blue Brain Project / EPFL
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import random
from bluepyopt import ephys
[docs]
class NrnNetStimStimulusCustom(ephys.stimuli.Stimulus):
"""Current stimulus based on current amplitude and time series.
Attributes:
total_duration (float): duration of run (ms)
locations (list): synapse point processes locations to connect to
interval (float): time between spikes (ms)
number (int): average number of spikes
start (float): most likely start time of first spike (ms)
noise (float): fractional randomness (0 deterministic,
1 negexp interval distrubtion)
connections (dict): contains simulator NetCon and NetStim
so that they are persistent
"""
def __init__(
self,
locations=None,
total_duration=None,
interval=None,
number=None,
start=None,
noise=0,
):
"""Constructor.
Args:
locations (list): synapse point processes locations to connect to
total_duration (float): duration of run (ms)
interval (float): time between spikes (ms)
number (int): average number of spikes
start (float): most likely start time of first spike (ms)
noise (float): fractional randomness (0 deterministic,
1 negexp interval distrubtion)
"""
super().__init__()
if total_duration is None:
raise ValueError("NrnNetStimStimulus: Need to specify a total duration")
self.total_duration = total_duration
self.locations = locations
self.interval = interval
self.number = number
self.start = start
self.noise = noise
self.connections = {}
[docs]
def instantiate(self, sim=None, icell=None):
"""Instantiate stimuli and connections.
Args:
sim (bluepyopt.ephys.NrnSimulator): neuron simulator
icell (neuron cell): cell instantiation in simulator
"""
if self.connections is None:
self.connections = {}
for location in self.locations:
self.connections[location.name] = []
for synapse in location.instantiate(sim=sim, icell=icell):
netstim = sim.neuron.h.NetStim()
netstim.interval = (
synapse.interval if synapse.interval is not None else self.interval
)
netstim.number = (
synapse.number if synapse.number is not None else self.number
)
netstim.start = (
synapse.start if synapse.start is not None else self.start
)
netstim.noise = (
synapse.noise if synapse.noise is not None else self.noise
)
netcon = sim.neuron.h.NetCon(
netstim, synapse.hsynapse, -30, synapse.delay, synapse.weight
)
self.connections[location.name].append((netcon, netstim))
[docs]
def destroy(self, sim=None):
"""Destroy stimulus.
Args:
sim (bluepyopt.ephys.NrnSimulator): neuron simulator
"""
# pylint: disable=unused-argument
self.connections = None
def __str__(self):
"""String representation."""
# pylint: disable=consider-using-f-string
return (
"Netstim at %s" % ",".join(location for location in self.locations)
if self.locations is not None
else "Netstim"
)
[docs]
class NrnVecStimStimulusCustom(ephys.stimuli.Stimulus):
"""Current stimulus based on stochastic current amplitude.
Attributes:
total_duration (float): time after which no synapses are allowed to fire (ms)
locations (list): synapse point processes locations to connect to
start (float): most likely start time of first spike (ms)
seed (int): seed for random number generator
vecstim_random (str): origin of the random nmb gener. can be "python" or "neuron"
pre_spike_train (list): list of spike train. If None, will be generated by random numbers
connections (dict): contains simulator NetCon and VecStim and time Vector
so that they are persistent
"""
def __init__(
self,
locations=None,
start=None,
stop=None,
seed=1,
vecstim_random="python",
pre_spike_train=None,
):
"""Constructor.
Args:
locations (list): synapse point processes locations to connect to
start (float): most likely start time of first spike (ms)
stop (float): time after which no synapses are allowed to fire (ms)
seed (int): seed for random number generator
vecstim_random (str): origin of the random nmb gener. can be "python" or "neuron"
pre_spike_train (list): list of spike train.
If None, will be generated by random numbers
"""
super().__init__()
if stop is None:
raise ValueError("NrnVecStimStimulus: Need to specify a stop time")
# must be named total_duration because of ephys.protocols
self.total_duration = stop
self.locations = locations
self.start = start
self.seed = seed
self.vecstim_random = vecstim_random
self.pre_spike_train = pre_spike_train
self.connections = {}
[docs]
def instantiate(self, sim=None, icell=None):
"""Instantiate stimuli and connections.
Args:
sim (bluepyopt.ephys.NrnSimulator): neuron simulator
icell (neuron cell): cell instantiation in simulator
"""
if self.connections is None:
self.connections = {}
if self.pre_spike_train is None:
if self.vecstim_random == "python":
random.seed(self.seed)
else:
rand = sim.neuron.h.Random(self.seed)
rand.uniform(self.start, self.total_duration)
for location in self.locations:
self.connections[location.name] = []
for synapse in location.instantiate(sim=sim, icell=icell):
# create spike_train
if self.pre_spike_train is not None:
spike_train = self.pre_spike_train
else:
if self.vecstim_random == "python":
spike_train = [random.uniform(self.start, self.total_duration)]
else:
spike_train = [rand.repick()]
t_vec = sim.neuron.h.Vector(spike_train)
vecstim = sim.neuron.h.VecStim()
vecstim.play(t_vec, sim.dt)
netcon = sim.neuron.h.NetCon(
vecstim, synapse.hsynapse, -30, synapse.delay, synapse.weight
)
self.connections[location.name].append((netcon, vecstim, t_vec))
[docs]
def destroy(self, sim=None):
"""Destroy stimulus.
Args:
sim (bluepyopt.ephys.NrnSimulator): neuron simulator
"""
# pylint: disable=unused-argument
self.connections = None
def __str__(self):
"""String representation."""
# pylint: disable=consider-using-f-string
return (
"Vecstim at %s" % ",".join(location for location in self.locations)
if self.locations is not None
else "Vecstim"
)
[docs]
class NetConSpikeDetector(ephys.stimuli.Stimulus):
"""Netcon linking output from pre-cell to post-cell's synapses.
Attributes:
total_duration (float): end time of connection (ms)
locations (list): synapse point processes locations to connect to
connections (dict): contains simulator NetCon so that they are persistent
"""
def __init__(self, total_duration=None, locations=None):
"""Constructor.
Args:
total_duration (float): end time of connection (ms)
locations (list): synapse point processes locations to connect to
"""
self.total_duration = total_duration
self.locations = locations
self.connections = {}
[docs]
def instantiate(self, sim, icell):
"""Instantiate connections.
Args:
sim (bluepyopt.ephys.NrnSimulator): neuron simulator
icell (neuron cell): cell instantiation in simulator
"""
if self.connections is None:
self.connections = {}
for location in self.locations:
self.connections[location.name] = []
for synapse in location.instantiate(sim=sim, icell=icell):
# taken from bglibpy.cell.create_netcon_spikedetector
# M. Hines magic to return a variable by reference to a python function
netcon = sim.neuron.h.ref(None)
icell.getCell().connect2target(synapse.hsynapse, netcon)
netcon = netcon[0]
netcon.weight[0] = synapse.weight
netcon.delay = synapse.delay
self.connections[location.name].append(netcon)
[docs]
def destroy(self, sim=None):
"""Destroy stimulus.
Args:
sim (bluepyopt.ephys.NrnSimulator): neuron simulator
"""
# pylint: disable=unused-argument
self.connections = None
def __str__(self):
"""String representation."""
# pylint: disable=consider-using-f-string
return (
"NetconSpikeDetector at %s"
% ",".join(location for location in self.locations)
if self.locations is not None
else "NetconSpikeDetector"
)