Skip to content

Commit

Permalink
Merge pull request #539 from apdavison/nest-dev
Browse files Browse the repository at this point in the history
Merge nest-dev branch into master
  • Loading branch information
apdavison committed Nov 21, 2017
2 parents 35fd89f + c5ca823 commit da37e6b
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 21 deletions.
18 changes: 12 additions & 6 deletions ci/install_nest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@ set -e # stop execution in case of errors

if [ "$TRAVIS_PYTHON_VERSION" == "2.7" ] || [ "$TRAVIS_PYTHON_VERSION" == "3.5" ]; then
echo -e "\n========== Installing NEST ==========\n"
# Specify which version of NEST to install
#export NEST_VERSION="master"
export NEST_VERSION="2.12.0"
export NEST="nest-$NEST_VERSION"
export NEST_VERSION="2.14.0"

pip install cython==0.23.4
#wget https://github.com/nest/nest-simulator/archive/$NEST_VERSION.tar.gz -O $HOME/$NEST.tar.gz;
wget https://github.com/nest/nest-simulator/releases/download/v$NEST_VERSION/nest-$NEST_VERSION.tar.gz -O $HOME/$NEST.tar.gz

if [ "$NEST_VERSION" = "master" ]; then
export NEST="nest-simulator-$NEST_VERSION"
wget https://github.com/nest/nest-simulator/archive/$NEST_VERSION.tar.gz -O $HOME/$NEST.tar.gz;
else
export NEST="nest-$NEST_VERSION"
wget https://github.com/nest/nest-simulator/releases/download/v$NEST_VERSION/nest-$NEST_VERSION.tar.gz -O $HOME/$NEST.tar.gz
fi

pushd $HOME;
tar xzf $NEST.tar.gz;
ls;
Expand All @@ -18,8 +26,6 @@ if [ "$TRAVIS_PYTHON_VERSION" == "2.7" ] || [ "$TRAVIS_PYTHON_VERSION" == "3.5"
mkdir -p $HOME/build/$NEST
pushd $HOME/build/$NEST
export VENV=`python -c "import sys; print(sys.prefix)"`;
echo "VENV = $VENV";
echo "PATH = $PATH";
ln -s /opt/python/2.7.13/lib/libpython2.7.so $VENV/lib/libpython2.7.so;
ln -s /opt/python/3.5.3/lib/libpython3.5m.so $VENV/lib/libpython3.5.so;
export PYTHON_INCLUDE_DIR=$VENV/include/python${TRAVIS_PYTHON_VERSION}
Expand Down
17 changes: 13 additions & 4 deletions pyNN/brian/standardmodels/electrodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,21 @@ def _update_current(self):
for cell, idx in zip(self.cell_list, self.indices):
cell.parent.brian_group.i_inj[idx] = 0

def _record(self):
self.i_state_monitor = brian.StateMonitor(self.cell_list[0].parent.brian_group[self.indices[0]], 'i_inj', record=0)
def record(self):
self.i_state_monitor = brian.StateMonitor(self.cell_list[0].parent.brian_group[self.indices[0]], 'i_inj', record=0, when='start')
simulator.state.network.add(self.i_state_monitor)

def _get_data(self):
return numpy.array((self.i_state_monitor.times / ms, self.i_state_monitor[0] / nA))
def get_data(self):
# code based on brian/recording.py:_get_all_signals()
# because we use `when='start'`, we need to add the
# value at the end of the final time step.
device = self.i_state_monitor
current_t_value = device.P.state_('t')[device.record]
current_i_value = device.P.state_(device.varname)[device.record]
t_all_values = numpy.append(device.times, current_t_value)
i_all_values = numpy.append(device._values, current_i_value)
return (t_all_values / ms, i_all_values / nA)


class StepCurrentSource(BrianCurrentSource, electrodes.StepCurrentSource):
__doc__ = electrodes.StepCurrentSource.__doc__
Expand Down
18 changes: 18 additions & 0 deletions pyNN/nest/standardmodels/electrodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,24 @@ def get_native_parameters(self):
return ParameterSpace(dict((k, v) for k, v in all_params.items()
if k in self.get_native_names()))

def record(self):
self.i_multimeter = nest.Create('multimeter', params={'record_from': ['I'], 'interval' :state.dt})
nest.Connect(self.i_multimeter, self._device)

def get_data(self):
events = nest.GetStatus(self.i_multimeter)[0]['events']
# Similar to recording.py: NEST does not record values at
# the zeroth time step, so we add them here.
t_arr = numpy.insert(numpy.array(events['times']), 0, 0.0)
i_arr = numpy.insert(numpy.array(events['I']/1000.0), 0, 0.0)
# NEST and pyNN have different concepts of current initiation times
# To keep this consistent across simulators, we will have current
# initiating at the electrode at t_start and effect on cell at next dt
# This requires padding min_delay equivalent period with 0's
pad_length = int(state.min_delay/state.dt)
i_arr = numpy.insert(i_arr[:-pad_length], 0, [0]*pad_length)
return t_arr, i_arr


class DCSource(NestCurrentSource, electrodes.DCSource):
__doc__ = electrodes.DCSource.__doc__
Expand Down
15 changes: 12 additions & 3 deletions pyNN/neuron/standardmodels/electrodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,23 @@ def inject_into(self, cells):
self._h_iclamps[id] = h.IClamp(0.5, sec=id._cell.source_section)
self._devices.append(self._h_iclamps[id])

def _record(self):
def record(self):
self.itrace = h.Vector()
self.itrace.record(self._devices[0]._ref_i)
self.record_times = h.Vector()
self.record_times.record(h._ref_t)

def _get_data(self):
return numpy.array((self.record_times, self.itrace))
def get_data(self):
# NEURON and pyNN have different concepts of current initiation times
# To keep this consistent across simulators, pyNN will have current
# initiating at the electrode at t_start and effect on cell at next dt.
# This requires removing the first element from the current Vector
# as NEURON computes the currents one time step later. The vector length
# is compensated by repeating the last recorded value of current.
t_arr = numpy.array(self.record_times)
i_arr = numpy.array(self.itrace)[1:]
i_arr = numpy.append(i_arr, i_arr[-1])
return (t_arr, i_arr)


class DCSource(NeuronCurrentSource, electrodes.DCSource):
Expand Down
99 changes: 91 additions & 8 deletions test/system/scenarios/test_electrodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def issue442(sim):
assert_true(v0[peak_ind[0]] < v0[peak_ind[1]] and v0[peak_ind[1]] < v0[peak_ind[2]])


@register(exclude=["nest"])
@register()
def issue445(sim):
"""
This test basically checks if a new value of current is calculated at every
Expand All @@ -240,18 +240,18 @@ def issue445(sim):
"""
sim_dt = 0.1
simtime = 200.0
sim.setup(timestep=sim_dt, min_delay=1.5)
sim.setup(timestep=sim_dt, min_delay=1.0)
cells = sim.Population(1, sim.IF_curr_exp(v_thresh=-55.0, tau_refrac=5.0))
t_start=50.0
t_stop=125.0
acsource = sim.ACSource(start=t_start, stop=t_stop, amplitude=0.5, offset=0.0, frequency=100.0, phase=0.0)
cells[0].inject(acsource)
acsource._record()
acsource.record()

sim.run(simtime)
sim.end()

i_t_ac, i_amp_ac = acsource._get_data()
i_t_ac, i_amp_ac = acsource.get_data()
t_start_ind = numpy.argmax(i_t_ac >= t_start)
t_stop_ind = numpy.argmax(i_t_ac >= t_stop)
assert_true (all(val != val_next for val, val_next in zip(i_t_ac[t_start_ind:t_stop_ind-1], i_t_ac[t_start_ind+1:t_stop_ind])))
Expand Down Expand Up @@ -368,15 +368,97 @@ def issue487(sim):
assert_true (numpy.isclose(v_step_2_arr[0:int(step_2.times[0]/dt)], v_rest).all())


@register(exclude=["brian", "neuron", "nest"])
@register()
def issue_465_474(sim):
"""
Checks the current traces recorded for each of the four types of
electrodes in pyNN, and verifies that:
1) Length of the current traces are as expected
2) Values at t = t_start and t = t_stop present
3) Changes in current value occur at the expected time instant
4) Change in Vm begins at the immediate next time instant following current injection
"""
sim_dt = 0.1
sim.setup(min_delay=1.0, timestep = sim_dt)

v_rest = -60.0
cells = sim.Population(4, sim.IF_curr_exp(v_thresh=-55.0, tau_refrac=5.0, v_rest=v_rest))
cells.initialize(v=v_rest)

amp=0.5
offset = 0.1
start=50.0
stop=125.0

acsource = sim.ACSource(start=start, stop=stop, amplitude=amp, offset=offset, frequency=100.0, phase=0.0)
cells[0].inject(acsource)
acsource.record()

dcsource = sim.DCSource(amplitude=amp, start=start, stop=stop)
cells[1].inject(dcsource)
dcsource.record()

noise = sim.NoisyCurrentSource(mean=amp, stdev=0.05, start=start, stop=stop, dt=sim_dt)
cells[2].inject(noise)
noise.record()

step = sim.StepCurrentSource(times=[start, (start+stop)/2, stop], amplitudes=[0.4, 0.6, 0.2])
cells[3].inject(step)
step.record()

cells.record('v')
runtime = 100.0
simtime = 0
# testing for repeated runs
sim.run(runtime)
simtime += runtime
sim.run(runtime)
simtime += runtime

vm = cells.get_data().segments[0].filter(name="v")[0]
sim.end()

v_ac = vm[:, 0]
v_dc = vm[:, 1]
v_noise = vm[:, 2]
v_step = vm[:, 3]

i_t_ac, i_amp_ac = acsource.get_data()
i_t_dc, i_amp_dc = dcsource.get_data()
i_t_noise, i_amp_noise = noise.get_data()
i_t_step, i_amp_step = step.get_data()

# test for length of recorded current traces
assert_true (len(i_t_ac) == len(i_amp_ac) == (int(simtime/sim_dt)+1) == len(v_ac))
assert_true (len(i_t_dc) == len(i_amp_dc) == int(simtime/sim_dt)+1 == len(v_dc))
assert_true (len(i_t_noise) == len(i_amp_noise) == int(simtime/sim_dt)+1 == len(v_noise))
assert_true (len(i_t_step) == len(i_amp_step) == int(simtime/sim_dt)+1 == len(v_step))

# test to check values exist at start and end of simulation
assert_true (i_t_ac[0]==0.0 and numpy.isclose(i_t_ac[-1],simtime))
assert_true (i_t_dc[0]==0.0 and numpy.isclose(i_t_dc[-1],simtime))
assert_true (i_t_noise[0]==0.0 and numpy.isclose(i_t_noise[-1],simtime))
assert_true (i_t_step[0]==0.0 and numpy.isclose(i_t_step[-1],simtime))

# test to check current changes at the expected time instant
assert_true (i_amp_ac[(int(start/sim_dt))-1]==0 and i_amp_ac[int(start/sim_dt)]!=0)
assert_true (i_amp_dc[int(start/sim_dt)-1]==0 and i_amp_dc[int(start/sim_dt)]!=0)
assert_true (i_amp_noise[int(start/sim_dt)-1]==0 and i_amp_noise[int(start/sim_dt)]!=0)
assert_true (i_amp_step[int(start/sim_dt)-1]==0 and i_amp_step[int(start/sim_dt)]!=0)

# test to check vm changes at the time step following current initiation
assert_true (numpy.isclose(v_ac[int(start/sim_dt)].item(),v_rest) and v_ac[int(start/sim_dt)+1]!=v_rest)
assert_true (numpy.isclose(v_dc[int(start/sim_dt)].item(),v_rest) and v_dc[int(start/sim_dt)+1]!=v_rest)
assert_true (numpy.isclose(v_noise[int(start/sim_dt)].item(),v_rest) and v_noise[int(start/sim_dt)+1]!=v_rest)
assert_true (numpy.isclose(v_step[int(start/sim_dt)].item(),v_rest) and v_step[int(start/sim_dt)+1]!=v_rest)


@register()
def issue497(sim):
"""
This is a test to check that the specified phase for the ACSource is valid
at the specified start time (and not, for example, at t=0 as NEST currently does)
NOTE: This test is currently excluded for all the simulators as the final
current recording implementation is currently unavailable on 'master'.
Approach:
> Two signals with different initial specified phases
> 'start' of one signal updated on the fly
Expand Down Expand Up @@ -439,4 +521,5 @@ def issue497(sim):
issue451(sim)
issue483(sim)
issue487(sim)
issue_465_474(sim)
issue497(sim)

0 comments on commit da37e6b

Please sign in to comment.