diff --git a/neurodamus/core/stimuli.py b/neurodamus/core/stimuli.py index 739e6cff..4a64e853 100644 --- a/neurodamus/core/stimuli.py +++ b/neurodamus/core/stimuli.py @@ -10,12 +10,13 @@ class SignalSource: - def __init__(self, base_amp=0.0, *, delay=0, rng=None): + def __init__(self, base_amp=0.0, *, delay=0, rng=None, represents_physical_electrode=False): """ Creates a new signal source, which can create composed signals Args: base_amp: The base (resting) amplitude of the signal (Default: 0) rng: The Random Number Generator. Used in the Noise functions + represents_physical_electrode: Whether the source represents a phsyical electrode or missing synaptic input """ h = Neuron.h self.stim_vec = h.Vector() @@ -23,6 +24,7 @@ def __init__(self, base_amp=0.0, *, delay=0, rng=None): self._cur_t = 0 self._base_amp = base_amp self._rng = rng + self._represents_physical_electrode = represents_physical_electrode if delay > .0: self._add_point(base_amp) self._cur_t = delay @@ -379,7 +381,13 @@ class _Clamp: def __init__(self, cell_section, position=0.5, clamp_container=None, stim_vec_mode=True, time_vec=None, stim_vec=None, **clamp_params): - self.clamp = Neuron.h.IClamp(position, sec=cell_section) + + # Checks if new MembraneCurrentSource mechanism is available and if source does not represent physical electrode + if self._represents_physical_electrode == False and hasattr(Neuron.h, "MembraneCurrentSource"): + self.clamp = Neuron.h.MembraneCurrentSource(position, sec=cell_section) + else: + self.clamp = Neuron.h.IClamp(position, sec=cell_section) + if stim_vec_mode: assert time_vec is not None and stim_vec is not None self.clamp.dur = time_vec[-1] @@ -434,8 +442,8 @@ class _DynamicClamp: def __init__(self, cell_section, position=0.5, clamp_container=None, stim_vec_mode=True, time_vec=None, stim_vec=None, reversal=0.0, **clamp_params): - # Checks if new conductanceSource mechanism is available - if hasattr(Neuron.h, "conductanceSource"): + # Checks if new conductanceSource mechanism is available and if source does not represent physical electrode + if self._represents_physical_electrode == False and hasattr(Neuron.h, "conductanceSource"): self.clamp = Neuron.h.conductanceSource(position, sec=cell_section) else: self.clamp = Neuron.h.SEClamp(position, sec=cell_section) diff --git a/neurodamus/stimulus_manager.py b/neurodamus/stimulus_manager.py index 6414adce..8aa7546f 100644 --- a/neurodamus/stimulus_manager.py +++ b/neurodamus/stimulus_manager.py @@ -86,6 +86,10 @@ def __init__(self, _target, stim_info: dict, _cell_manager): self.duration = float(stim_info["Duration"]) # duration [ms] self.delay = float(stim_info["Delay"]) # start time [ms] + if 'self.represents_physical_electrode' in stim_info.keys(): + self.represents_physical_electrode = stim_info['represents_physical_electrode'] + else: + self.represents_physical_electrode = False @StimulusManager.register_type class OrnsteinUhlenbeck(BaseStim): @@ -123,7 +127,7 @@ def __init__(self, target, stim_info: dict, cell_manager): rng = random.Random123(seed1, seed2, seed3(gid)) # setup RNG ou_args = (self.tau, self.sigma, self.mean, self.duration) - ou_kwargs = {'dt': self.dt, 'delay': self.delay, 'rng': rng} + ou_kwargs = {'dt': self.dt, 'delay': self.delay, 'rng': rng, 'represents_physical_electrode':self.represents_physical_electrode} # inject Ornstein-Uhlenbeck signal if stim_info["Mode"] == "Conductance": cs = ConductanceSource.ornstein_uhlenbeck(*ou_args, **ou_kwargs, @@ -252,7 +256,7 @@ def __init__(self, target, stim_info: dict, cell_manager): rng = random.Random123(seed1, seed2, seed3(gid)) # setup RNG shotnoise_args = (self.tau_D, self.tau_R, self.rate, self.amp_mean, self.amp_var, self.duration) - shotnoise_kwargs = {'dt': self.dt, 'delay': self.delay, 'rng': rng} + shotnoise_kwargs = {'dt': self.dt, 'delay': self.delay, 'rng': rng, 'represents_physical_electrode':self.represents_physical_electrode} # generate shot noise current source if stim_info["Mode"] == "Conductance": cs = ConductanceSource.shot_noise(*shotnoise_args, **shotnoise_kwargs, @@ -455,7 +459,7 @@ def __init__(self, target, stim_info: dict, cell_manager): # generate ramp current source cs = CurrentSource.ramp(self.amp_start, self.amp_end, self.duration, - delay=self.delay) + delay=self.delay, represents_physical_electrode=self.represents_physical_electrode) # attach current source to section cs.attach_to(sc.sec, tpoint_list.x[sec_id]) self.stimList.append(cs) # save CurrentSource @@ -581,7 +585,7 @@ def __init__(self, target, stim_info: dict, cell_manager): # generate noise current source cs = CurrentSource.noise(self.mean, self.var, self.duration, - dt=self.dt, delay=self.delay, rng=rng) + dt=self.dt, delay=self.delay, rng=rng, represents_physical_electrode=self.represents_physical_electrode) # attach current source to section cs.attach_to(sc.sec, tpoint_list.x[sec_id]) self.stimList.append(cs) # save CurrentSource @@ -661,7 +665,7 @@ def __init__(self, target, stim_info: dict, cell_manager): # generate pulse train current source cs = CurrentSource.train(self.amp, self.freq, self.width, - self.duration, delay=self.delay) + self.duration, delay=self.delay,represents_physical_electrode=self.represents_physical_electrode) # attach current source to section cs.attach_to(sc.sec, tpoint_list.x[sec_id]) self.stimList.append(cs) # save CurrentSource @@ -697,7 +701,7 @@ def __init__(self, target, stim_info: dict, cell_manager): # generate sinusoidal current source cs = CurrentSource.sin(self.amp, self.duration, self.freq, - step=self.dt, delay=self.delay) + step=self.dt, delay=self.delay,represents_physical_electrode=self.represents_physical_electrode) # attach current source to section cs.attach_to(sc.sec, tpoint_list.x[sec_id]) self.stimList.append(cs) # save CurrentSource @@ -733,12 +737,9 @@ def __init__(self, target, stim_info: dict, cell_manager): if not sc.exists(): continue - # If conductanceSource not available, insert standard SEClamp - if hasattr(Nd.h, "conductanceSource"): - seclamp = Nd.h.conductanceSource(tpoint_list.x[sec_id], sec=sc.sec) - else: - # create single electrode voltage clamp at location - seclamp = Nd.h.SEClamp(tpoint_list.x[sec_id], sec=sc.sec) + + # create single electrode voltage clamp at location + seclamp = Nd.h.SEClamp(tpoint_list.x[sec_id], sec=sc.sec) seclamp.rs = self.rs seclamp.dur1 = self.duration