Skip to content

Commit

Permalink
Merge pull request #95 from RCagnol/StepCurrentNest
Browse files Browse the repository at this point in the history
 Allowing the use of the models with integrated step current
  • Loading branch information
antolikjan authored Sep 7, 2023
2 parents 7f7cec9 + caab799 commit 997bd7a
Show file tree
Hide file tree
Showing 89 changed files with 6,113 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/fast-model-mpi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ jobs:
run: python setup.py install

- name: Test with pytest
run: pytest -m "mpi and not not_github" ./tests/full_model/test_models_mpi.py --cov=mozaik
run: pytest -v -s -m "mpi and not not_github" ./tests/full_model/test_models_mpi.py --cov=mozaik
63 changes: 63 additions & 0 deletions .github/workflows/fast-model-stepcurrentmodule.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Fast model stepcurrentmodule tests

on: [push, pull_request]

jobs:

pytest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Pytest Unit Tests
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install prerequisites
run: |
sudo apt-get update
sudo apt-get install python3-setuptools subversion git libopenmpi-dev g++ libjpeg8 libjpeg8-dev libfreetype6 libfreetype6-dev zlib1g-dev libpng++-dev libncurses5 libncurses5-dev libreadline-dev liblapack-dev libblas-dev gfortran libgsl0-dev openmpi-bin python-tk cmake
pip3 install pytest pytest-cov pytest-randomly coverage black
# TODO: Remove fixed numpy and pynn versions after the PyNN pull request
# https://github.com/NeuralEnsemble/PyNN/pull/762 is accepted
pip3 install numpy==1.23.5 scipy mpi4py matplotlib quantities lazyarray interval Pillow param==1.5.1 parameters neo cython psutil future requests elephant pytest-xdist pytest-timeout junitparser numba
- name: Download and install imagen
run: |
git clone https://github.com/antolikjan/imagen.git
cd imagen
python setup.py install
cd ..
- name: Download and install PyNN
run: |
git clone https://github.com/RCagnol/PyNN.git
cd PyNN
git checkout PyNNStepCurrentModule
pip install .
cd ..
- name: Install Nest
run: |
wget https://github.com/nest/nest-simulator/archive/v3.4.tar.gz
tar xvfz v3.4.tar.gz
cd nest-simulator-3.4
cmake -Dwith-mpi=ON -Dwith-boost=ON -DCMAKE_INSTALL_PREFIX:PATH=$pythonLocation -Dwith-optimize='-O3' ./
make -j8
make -j8 install
cd ..
python -c 'import nest'
- name: Install stepcurrentmodule
run: |
git clone https://github.com/RCagnol/nest-step-current-module.git
cd nest-step-current-module
cmake -Dwith-mpi=ON -Dwith-boost=ON -Dwith-nest=$pythonLocation/bin/nest-config -Dwith-optimize='-O3' ./
make -j8
make -j8 install
cd ..
- name: Install mozaik
run: python setup.py install

- name: Test with pytest
run: pytest tests --cov=mozaik -m "stepcurrentmodule"
41 changes: 34 additions & 7 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ ____________

Now you can install all other dependencies in this protected environment::

pip3 install numpy==1.23.5 scipy mpi4py matplotlib quantities lazyarray interval Pillow param==1.5.1 parameters neo cython pynn==0.10.0 psutil future requests elephant pytest-xdist pytest-timeout junitparser numba
pip3 install numpy scipy mpi4py matplotlib quantities lazyarray interval Pillow param==1.5.1 parameters neo cython psutil future requests elephant pytest-xdist pytest-timeout junitparser numba
pip3 install numpy==1.23.5 scipy mpi4py matplotlib quantities lazyarray interval Pillow param==1.5.1 parameters neo cython psutil future requests elephant pytest-xdist pytest-timeout junitparser numba

Next we will manually install several packages. It is probably the best if you create a separate directory in an appropriate
place, where you will download and install the packages from.
Expand All @@ -62,16 +63,23 @@ First install the *imagen* package::
cd imagen
python setup.py install

Then install the *PyNN* package from the PyNNStepCurrentModule branch::

git clone https://github.com/CSNG-MFF/PyNN.git
cd PyNN
git checkout PyNNStepCurrentModule
python setup.py install

Next install the *Nest* simulator (always in the virtual environment):

- download the latest version from their `website <http://www.nest-initiative.org/index.php/Software:Download>`_

wget https://github.com/nest/nest-simulator/archive/refs/tags/v3.1.tar.gz
wget https://github.com/nest/nest-simulator/archive/refs/tags/v3.4.tar.gz

- untar and cd into it::

tar xvfz v3.1.tar.gz
cd nest-simulator-3.1
tar xvfz v3.4.tar.gz
cd nest-simulator-3.4
- then configure (change path to wherever you installed your virtual environemnt)::
Expand All @@ -84,16 +92,35 @@ Next install the *Nest* simulator (always in the virtual environment):
- Then::
make installcheck
(mozaik)$ make installcheck

or if you are using Slurm::

salloc -n8 make installcheck
(mozaik)$ salloc -n8 make installcheck
- nest will reside in $HOME/virt_env/mozaik/lib/python3.*/site-packages. Check that the package is seen by python using::

python -c 'import nest'
(mozaik)$ python -c 'import nest'

Then install the *stepcurrentmodule* Nest module:

- get the module from github and cd into it::
git clone https://github.com/CSNG-MFF/nest-step-current-module.git
cd nest-step-current-module

- then configure it relatively to your nest-config installation path (should reside in $HOME/virt_env/mozaik/bin/nest-config)::
(mozaik)$ cmake -Dwith-mpi=ON -Dwith-boost=ON -Dwith-optimize='-O3' -Dwith-nest=NEST_CONFIG_PATH ./

- finally, by launching make and install, it installs the nest module in the activated virtual environment mozaik. If you're using Slurm, run these commands through :code:`srun` ::

(mozaik)$ make
(mozaik)$ make install

- Check that the package is seen by python using::

(mozaik)$ python -c 'import nest; nest.Install("stepcurrentmodule")'

And, finally, Mozaik::
Expand Down
1 change: 1 addition & 0 deletions examples/VogelsAbbott2005/param/exc_layer
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

'cell': {
'model': 'IF_cond_exp',
'native_nest': False,
'params': {
'v_thresh':-50.0,
'v_rest': -60.0,
Expand Down
128 changes: 84 additions & 44 deletions mozaik/models/vision/spatiotemporalfilter.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from mozaik.sheets.vision import RetinalUniformSheet
from mozaik.sheets.vision import VisualCorticalUniformSheet
from mozaik.tools.mozaik_parametrized import MozaikParametrized
from mozaik.tools.pyNN import *
from parameters import ParameterSet
from builtins import zip
from collections import OrderedDict
Expand Down Expand Up @@ -369,6 +370,7 @@ class SpatioTemporalFilterRetinaLGN(SensoryInputComponent):
'cell': ParameterSet({
'model': str,
'params': ParameterSet,
'native_nest': bool,
'initial_values': ParameterSet,
}),
'gain_control' : {
Expand All @@ -395,16 +397,27 @@ def __init__(self, model, parameters):
self.rf_types = ('X_ON', 'X_OFF')
sim = self.model.sim
self.pops = OrderedDict()
self.scs = OrderedDict()
self.ncs = OrderedDict()

if self.parameters.cell.model[-6:] == '_sc_nc':
self.integrated_cs = True
import copy
cell = copy.deepcopy(self.parameters.cell)
cell.params.update([('mean', self.parameters.noise.mean*1000), ('std', self.parameters.noise.stdev*1000), ('dt', self.model.sim.get_time_step())])
else:
self.integrated_cs = False
self.scs = OrderedDict()
self.ncs = OrderedDict()
cell = self.parameters.cell

self.ncs_rng = OrderedDict()
self.internal_stimulus_cache = OrderedDict()
for rf_type in self.rf_types:

p = RetinalUniformSheet(model,
ParameterSet({'sx': self.parameters.size[0],
'sy': self.parameters.size[1],
'density': self.parameters.density,
'cell': self.parameters.cell,
'cell': cell,
'name': rf_type,
'artificial_stimulators' : OrderedDict(),
'recorders' : self.parameters.recorders,
Expand All @@ -413,25 +426,30 @@ def __init__(self, model, parameters):
self.sheets[rf_type] = p

for rf_type in self.rf_types:
self.scs[rf_type] = []
self.ncs[rf_type] = []
self.ncs_rng[rf_type] = []
seeds=mozaik.get_seeds((self.sheets[rf_type].pop.size,))
for i, lgn_cell in enumerate(self.sheets[rf_type].pop.all_cells):
scs = sim.StepCurrentSource(times=[0.0], amplitudes=[0.0])

if not self.parameters.mpi_reproducible_noise:
ncs = sim.NoisyCurrentSource(**self.parameters.noise)
else:
ncs = sim.StepCurrentSource(times=[0.0], amplitudes=[0.0])

if self.sheets[rf_type].pop._mask_local[i]:
self.ncs_rng[rf_type].append(numpy.random.RandomState(seed=seeds[i]))
self.scs[rf_type].append(scs)
self.ncs[rf_type].append(ncs)
lgn_cell.inject(scs)
lgn_cell.inject(ncs)

if self.integrated_cs:
for i, lgn_cell in enumerate(self.sheets[rf_type].pop.all_cells):
if self.sheets[rf_type].pop._mask_local[i]:
self.ncs_rng[rf_type].append(numpy.random.RandomState(seed=seeds[i]))
else:
self.scs[rf_type] = []
self.ncs[rf_type] = []
for i, lgn_cell in enumerate(self.sheets[rf_type].pop.all_cells):
scs = sim.StepCurrentSource(times=[0.0], amplitudes=[0.0])

if not self.parameters.mpi_reproducible_noise:
ncs = sim.NoisyCurrentSource(**self.parameters.noise)
else:
ncs = sim.StepCurrentSource(times=[0.0], amplitudes=[0.0])

if self.sheets[rf_type].pop._mask_local[i]:
self.ncs_rng[rf_type].append(numpy.random.RandomState(seed=seeds[i]))
self.scs[rf_type].append(scs)
self.ncs[rf_type].append(ncs)
lgn_cell.inject(scs)
lgn_cell.inject(ncs)

P_rf = self.parameters.receptive_field
rf_function = eval(P_rf.func)
Expand Down Expand Up @@ -567,25 +585,36 @@ def process_input(self, visual_space, stimulus, duration=None, offset=0):
(input_currents, retinal_input) = cached

ts = self.model.sim.get_time_step()
# Correcting for nest/PyNN time inconsistency + adding one ts as injected current at the current time is not taken into account
new_offset = convert_time_pyNN_to_nest(self.model.sim,offset) + ts

for rf_type in self.rf_types:
assert isinstance(input_currents[rf_type], list)
for i, (lgn_cell, input_current, scs, ncs) in enumerate(
zip(self.sheets[rf_type].pop,
input_currents[rf_type],
self.scs[rf_type],
self.ncs[rf_type])):
assert isinstance(input_current, dict)
t = input_current['times'] + offset
a = self.parameters.linear_scaler * input_current['amplitudes']
scs.set_parameters(times=t, amplitudes=a,copy=False)
if self.parameters.mpi_reproducible_noise:
t = numpy.arange(0, duration, ts) + offset
amplitudes = (self.parameters.noise.mean
+ self.parameters.noise.stdev
* self.ncs_rng[rf_type][i].randn(len(t)))
ncs.set_parameters(times=t, amplitudes=amplitudes,copy=False)
if self.integrated_cs:
for i, (lgn_cell, input_current) in enumerate(
zip(self.sheets[rf_type].pop,
input_currents[rf_type])):
assert isinstance(input_current, dict)
t = input_current['times'] + new_offset
a = self.parameters.linear_scaler * input_current['amplitudes']
lgn_cell.set_parameters(amplitude_times=t[1:], amplitude_values=a[1:]*1000)

else:
for i, (lgn_cell, input_current, scs, ncs) in enumerate(
zip(self.sheets[rf_type].pop,
input_currents[rf_type],
self.scs[rf_type],
self.ncs[rf_type])):
assert isinstance(input_current, dict)
t = input_current['times'] + offset
a = self.parameters.linear_scaler * input_current['amplitudes']
scs.set_parameters(times=t, amplitudes=a,copy=False)
if self.parameters.mpi_reproducible_noise:
t = numpy.arange(0, duration, ts) + offset
amplitudes = (self.parameters.noise.mean
+ self.parameters.noise.stdev
* self.ncs_rng[rf_type][i].randn(len(t)))
ncs.set_parameters(times=t, amplitudes=amplitudes,copy=False)

# for debugging/testing, doesn't work with MPI !!!!!!!!!!!!
#input_current_array = numpy.zeros((self.shape[1], self.shape[0], len(visual_space.time_points(duration))))
Expand Down Expand Up @@ -634,11 +663,16 @@ def provide_null_input(self, visual_space, duration=None, offset=0):
# Currently, we need to set the start time of stimulation to
# offset + 3*timestep, until the following issue is resolved:
# https://github.com/NeuralEnsemble/PyNN/issues/759.
# TODO: Remove once this gets fixed (hopefully in PyNN 0.11.0)!
ts = self.model.sim.get_time_step()
times = numpy.array([offset + 3 * ts,duration-visual_space.update_interval+offset])
zers = numpy.zeros_like(times)

if self.integrated_cs:
new_offset = convert_time_pyNN_to_nest(self.model.sim,offset) + ts
times = numpy.array([new_offset,duration-visual_space.update_interval+new_offset])
zers = numpy.zeros_like(times)
# TODO: Remove once this gets fixed (hopefully in PyNN 0.11.0)!
else:
times = numpy.array([offset + 3 * ts,duration-visual_space.update_interval+offset])
zers = numpy.zeros_like(times)

input_cells = OrderedDict()
for rf_type in self.rf_types:
input_cells[rf_type] = CellWithReceptiveField(self.sheets[rf_type].pop.positions[0][0],
Expand All @@ -649,12 +683,18 @@ def provide_null_input(self, visual_space, duration=None, offset=0):


for rf_type in self.rf_types:
c = input_cells[rf_type]
nlg = c.gain_control.non_linear_gain
amplitude = visual_space.background_luminance * \
c.receptive_field.kernel_luminance_component.sum()
amplitude = self.parameters.linear_scaler * \
c.gain_function(amplitude, nlg.luminance_gain, nlg.luminance_scaler)
c = input_cells[rf_type]
nlg = c.gain_control.non_linear_gain
amplitude = visual_space.background_luminance * \
c.receptive_field.kernel_luminance_component.sum()
amplitude = self.parameters.linear_scaler * \
c.gain_function(amplitude, nlg.luminance_gain, nlg.luminance_scaler)

if self.integrated_cs:
for i, lgn_cell in enumerate(self.sheets[rf_type].pop):
lgn_cell.set_parameters(amplitude_times=times, amplitude_values=(zers+amplitude)*1000)

else:
for i, (scs, ncs) in enumerate(zip(self.scs[rf_type],self.ncs[rf_type])):
scs.set_parameters(times=times,amplitudes=zers+amplitude,copy=False)
if self.parameters.mpi_reproducible_noise:
Expand Down
6 changes: 5 additions & 1 deletion mozaik/sheets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class Sheet(BaseComponent):
required_parameters = ParameterSet({
'cell': ParameterSet({
'model': str, # the cell type of the sheet
'native_nest': bool,
'params': ParameterSet,
'initial_values': ParameterSet,
}),
Expand Down Expand Up @@ -255,7 +256,10 @@ def get_data(self, stimulus_duration=None):
"""

try:
block = self.pop.get_data(['spikes', 'v', 'gsyn_exc', 'gsyn_inh'],clear=True)
if self.parameters.cell.native_nest:
block = self.pop.get_data(['spikes', 'V_m', 'g_ex', 'g_in'],clear=True)
else:
block = self.pop.get_data(['spikes', 'v', 'gsyn_exc', 'gsyn_inh'],clear=True)
except (NothingToWriteError, errmsg):
logger.debug(errmsg)

Expand Down
Loading

0 comments on commit 997bd7a

Please sign in to comment.