Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pynest microcircuit #451

Merged
merged 16 commits into from Dec 14, 2016
Merged

Pynest microcircuit #451

merged 16 commits into from Dec 14, 2016

Conversation

@hendrikrth
Copy link
Contributor

@hendrikrth hendrikrth commented Aug 5, 2016

The example files of NEST are lacking a PyNEST version of the microcircuit #450. To compensate this I would like you to include my branch. As reviewers I suggest @jhnnsnk and @mschmidt87.

May 2016

## Description ##
This is a PyNEST implementation of the SLI cortical microcircuit from the microcircuit model by Potjans and Diesmann (2014): The cell-type specific

This comment has been minimized.

@jhnnsnk

jhnnsnk Sep 9, 2016
Contributor

This is a PyNEST implementation of the microcircuit model ...
(no need to mention SLI)


* Files:
* network.py
file which gathers all parameters and connects the different nodes with each other

This comment has been minimized.

@jhnnsnk

jhnnsnk Sep 9, 2016
Contributor

remove 'file which' to be consistent

contains the parameters for the stimuli
* example.py
use this script to try out the microcircuit

This comment has been minimized.

@mschmidt87

mschmidt87 Sep 9, 2016

  • Please put a '.' behind each sentence.
  • Please start the lase sentence with a capital letter: "Use this script..."

How to use the example:

To run the microcircuit on a local machine, adjust the variables N\_scaling and K\_scaling in network_params.py to 0.1 and create an output directory called '/data'. Then run 'example.py' with python. The output will be saved in the directory '/data'.

This comment has been minimized.

@jhnnsnk

jhnnsnk Sep 9, 2016
Contributor

  • give an explanation what N_scaling and K_scaling mean and state that the full network refers to the value 1; mention that 0.1 is the default here
  • the output directory could be generated automatically
  • for running, use 'python example.py'

To run the microcircuit on a local machine, adjust the variables N\_scaling and K\_scaling in network_params.py to 0.1 and create an output directory called '/data'. Then run 'example.py' with python. The output will be saved in the directory '/data'.
The code can be parallelized using OpenMP and MPI, if NEST has been build with these applications. The number of threads (per MPI process) can be chosen by adjusting local\_num\_threads in sim_params.py. The number of MPI process can be set by running the script with the command 'mpirun -n num\_MPI\_processes python example.py'.

This comment has been minimized.

@mschmidt87

mschmidt87 Sep 9, 2016

Please put the variable names and code examples in code blocks to improve the formatting, like so: N_scaling.

How to use the example:

To run the microcircuit on a local machine, adjust the variables N\_scaling and K\_scaling in network_params.py to 0.1 and create an output directory called '/data'. Then run 'example.py' with python. The output will be saved in the directory '/data'.
The code can be parallelized using OpenMP and MPI, if NEST has been build with these applications. The number of threads (per MPI process) can be chosen by adjusting local\_num\_threads in sim_params.py. The number of MPI process can be set by running the script with the command 'mpirun -n num\_MPI\_processes python example.py'.

This comment has been minimized.

@mschmidt87

mschmidt87 Sep 9, 2016

The code can be parallelized using OpenMP and MPI, if NEST has been build with these applications. The number of threads (per MPI process) can be chosen by adjusting local\_num\_threads in sim_params.py. The number of MPI process can be set by running the script with the command 'mpirun -n num\_MPI\_processes python example.py'.

Tested configuration:
This version has been tested with NEST 2.10.0, Python 2.7.12, NumPy 1.11.1

This comment has been minimized.

@mschmidt87

mschmidt87 Sep 9, 2016

Please insert the missing '.' at the end.

Hendrik Rothe, Hannah Bos, Sacha van Albada; May 2016
'''

from network_params import *

This comment has been minimized.

@jhnnsnk

jhnnsnk Sep 9, 2016
Contributor

to avoid import *, use for example from network_params import net_dict (the other import accordingly)

from sim_params import *
from stimulus_params import *
import time
import network as network

This comment has been minimized.

@jhnnsnk

jhnnsnk Sep 9, 2016
Contributor

import network is enough

# connect all nodes
t1 = time.time()
net.connect()
print 'time to create the connections', time.time()-t1

This comment has been minimized.

@jhnnsnk

jhnnsnk Sep 9, 2016
Contributor

  • specify seconds as unit
  • format the number, e.g. 2 decimals
  • 'connections:'
  • for consistency, start all printouts with capital letters
# along with NEST. If not, see <http://www.gnu.org/licenses/>.

'''
pynest microcicuit simulation parameters

This comment has been minimized.

@mschmidt87

mschmidt87 Sep 9, 2016

--> microcircuit

sim_dict = {
# Simulation time (in ms)
't_sim': 1000.0,
# sim_resolution = Resolution of the simulation (in ms)

This comment has been minimized.

@mschmidt87

mschmidt87 Sep 9, 2016

Please make the explanations consistent, so remove the 'sim_resolution = ' here.


import os
current_dir = os.getcwd()
full_path = current_dir + '/data/'

This comment has been minimized.

@mschmidt87

mschmidt87 Sep 9, 2016

  • Please use os.path.join to concatenate the paths.
  • Here, you can place a command to create the actual data path if it does not exist.
'master_seed': 55,
# Number of threads run by NEST
'local_num_threads': 1,
# Recording intervall of the membrane potential (in ms)

This comment has been minimized.

'local_num_threads': 1,
# Recording intervall of the membrane potential (in ms)
'rec_V_int': 1.0,
# If True data will be overwritten, if False it won't

This comment has been minimized.

@mschmidt87

mschmidt87 Sep 9, 2016

should be: "If True, data will be overwritten. If False, a NESTError is raised if the files already exist."

'data_path': full_path,
# Masterseed for NEST and NumPy
'master_seed': 55,
# Number of threads run by NEST

This comment has been minimized.

@mschmidt87

mschmidt87 Sep 9, 2016

--> "Number of threads per MPI process"

def get_std_delays(std_delay_exc, std_delay_inh, number_of_pop):
"""Creates matrix containing the standard deviations of all delays.
Arguments

This comment has been minimized.

evoked postsynaptic potential.
Arguements:
PSP_rel: standard deviation of the evoked synaptiv potential

This comment has been minimized.

inh = PSP_e * g
weights[:, 0:dim:2] = exc
weights[:, 1:dim:2] = inh
# The weight of the connection L23E to L4E is doubled.

This comment has been minimized.

@mschmidt87

mschmidt87 Sep 9, 2016

This comment should be contained in the docsctrings of the function.
And the connection from 4E onto 23E is doubled.



def get_mean_delays(mean_delay_exc, mean_delay_inh, number_of_pop):
"""Creates matrix containing the delay of all connections.

This comment has been minimized.

@jhnnsnk

jhnnsnk Sep 9, 2016
Contributor

docstring conventions, e.g., as used by topology (compare numpy); be also consistent with the other files

std_value_normal = PSP_rel
std_value_exception = 0.05
std_mat[:, :] = std_value_normal
std_mat[0, 2] = std_value_exception

This comment has been minimized.

@mschmidt87

mschmidt87 Sep 9, 2016

What is the reason for setting the relative standard deviation here different than in the other connections? We find this neither in the SLI implementation nor in the paper.

"""This function creates a matrix of the standard deviation of the
evoked postsynaptic potential.
Arguements:

This comment has been minimized.

# The default recording device is the spike_detector. If you also
# want to record the membrane potentials of the neurons, add
# 'voltmeter' to the list.
'rec_dev': ['spike_detector', 'voltmeter'],

This comment has been minimized.

@jhnnsnk

jhnnsnk Sep 9, 2016
Contributor

either remove 'voltmeter' from the list or adapt the documentation

'N_scaling': 0.1,
# Amplitude of excitatory postsynaptic potential.
'PSP_e': 0.15,
# Standard deviation of the postsynaptic potential.

This comment has been minimized.

@mschmidt87

mschmidt87 Sep 9, 2016

Should be "Relative standard deviation.."

'Seeds for random number generators of virtual processes: %r'
% rng_seeds
)
print('Global random number generator seed:%i' % grng_seed)

This comment has been minimized.

@jhnnsnk

jhnnsnk Nov 8, 2016
Contributor

Add a space in front of %i for being consistent.

This comment has been minimized.

@hendrikrth

hendrikrth Nov 17, 2016
Author Contributor

Done


def connect_devices(self):
""" Connects the recording devices to the microcircuit."""
print('%s of 2 Devices connected' % (len(self.net_dict['rec_dev'])))

This comment has been minimized.

@jhnnsnk

jhnnsnk Nov 8, 2016
Contributor

It prints "1 of 2 Devices connected" if only a spike detector is used which sounds as if something was missing. I suggest to be specific and print "Spike Detector connected" or/and "Voltmeter connected".

This comment has been minimized.

@hendrikrth

hendrikrth Nov 17, 2016
Author Contributor

fixed



# Initialize the network and pass parameters to it.
net = network.Network(sim_dict, net_dict, stim_dict)

This comment has been minimized.

@jhnnsnk

jhnnsnk Nov 8, 2016
Contributor

It would be nice to time also the network initialization.

This comment has been minimized.

@hendrikrth

hendrikrth Nov 17, 2016
Author Contributor

Done

t1 = time.time()
net.setup()
time_con = time.time()-t1
print("Time to create the connections: %.2f seconds" % time_con)

This comment has been minimized.

@jhnnsnk

jhnnsnk Nov 8, 2016
Contributor

Since the units ms and Hz are printed as well, why not just writing s instead of seconds?

This comment has been minimized.

@hendrikrth

hendrikrth Nov 17, 2016
Author Contributor

Done


How to use the example:

To run the microcircuit on a local machine, adjust the variables `N_scaling` and `K_scaling` in `network_params.py` to 0.1 and create an output directory called `data`. `N_scaling` adjusts the number of neurons and `K_scaling` the number of connections to be simulated. The full network can be run by adjusting these values to 1. If this is done, the option to print the time progress should be set to False in the file `sim_params.py`. For running, use `python example.py`. The output will be saved in the directory `data`.

This comment has been minimized.

@jhnnsnk

jhnnsnk Nov 8, 2016
Contributor

Remove

and create an output directory called data.

since this is now done automatically.

This comment has been minimized.

@hendrikrth

hendrikrth Nov 17, 2016
Author Contributor

Fixed

""" This function simulates the microcircuit."""
nest.Simulate(self.sim_dict['t_sim'])

def evaluate(self, raster_plot_time_idx, fire_rate_time_idx):

This comment has been minimized.

@jhnnsnk

jhnnsnk Nov 8, 2016
Contributor

You could save the generated plots directly in the output directory together with the raw data.

This comment has been minimized.

@hendrikrth

hendrikrth Nov 17, 2016
Author Contributor

Done

# Standard deviation of the postsynaptic potential (in relative units).
'PSP_sd': 0.1,
# Start of the thalamic input (in ms).
'th_start': 700.0,

This comment has been minimized.

@jhnnsnk

jhnnsnk Nov 8, 2016
Contributor

It would be nice to set the default stimulus intervals somewhere into the default plotting interval so that their effect is directly visible by eye.

This comment has been minimized.

@hendrikrth

hendrikrth Nov 17, 2016
Author Contributor

I kept the thalamus stimulus interval, since this is the stimulus interval of the sli version. I therefore changed the interval of the spike raster plot.

This comment has been minimized.

@jhnnsnk

jhnnsnk Nov 21, 2016
Contributor

Ok. Please update the comment on the plotting interval accordingly.

else:
os.mkdir(self.sim_dict['data_path'])
print('data directory created')
print('Data will be written to %s' % self.data_path)

This comment has been minimized.

@jhnnsnk

jhnnsnk Nov 8, 2016
Contributor

If used with MPI such statements are currently printed once per process. Please print them only on Rank 0 unless you want to print something specific to a process.

This comment has been minimized.

@hendrikrth

hendrikrth Nov 17, 2016
Author Contributor

Done

'0 << /model /%s >> GetLocalNodes' % self.net_dict['neuron_model']
)
local_nodes = nest.sli_pop()
vp = nest.GetStatus(local_nodes)[0]['vp']

This comment has been minimized.

@jhnnsnk

jhnnsnk Nov 8, 2016
Contributor

If run with both MPI and threads, taking the vp of the first local node is not correct. For example, with 2 MPI processes and 2 threads, one gets the MPI ranks 0 and 1, but the vps 0,1,2 and 3. For accessing the right pyrngs, I think we cannot avoid to extract all vps correponding to the local nodes. I will give a suggestion soon.

This comment has been minimized.

@jhnnsnk

jhnnsnk Nov 9, 2016
Contributor

This might be a possible solution to the problem:

for thread in np.arange(nest.GetKernelStatus('local_num_threads')):
    local_nodes = nest.GetNodes([0], {'model': self.net_dict['neuron_model'], 'thread': thread}, local_only=True)[0]
    vp = nest.GetStatus(local_nodes)[0]['vp'] # same thread on MPI proc -> same vp
    nest.SetStatus(
        local_nodes, 'V_m', self.pyrngs[vp].normal(
        self.net_dict['neuron_params']['V0_mean'],
        self.net_dict['neuron_params']['V0_sd'],
            len(local_nodes)))

This comment has been minimized.

@hendrikrth

hendrikrth Nov 17, 2016
Author Contributor

I fixed this, using your solution.

self.DC_amp_e = compute_DC(self.net_dict, self.w_ext)

print(
'The Number of neurons is scaled by a factor of: %.2f'

This comment has been minimized.

@jhnnsnk

jhnnsnk Nov 9, 2016
Contributor

Number -> number

This comment has been minimized.

@hendrikrth

hendrikrth Nov 17, 2016
Author Contributor

Done

@jhnnsnk
Copy link
Contributor

@jhnnsnk jhnnsnk commented Nov 9, 2016

Hi, during testing with both MPI and threads, I noticed that the initialization of membrane voltages did not work correctly. I made a suggestion inline how this could be solved. Apart from this, I made some other minor comments for improvement.

hendrikrth added 2 commits Nov 17, 2016
fixed initialization of membrane potentials, with provided solution
Copy link

@mschmidt87 mschmidt87 left a comment

Hi, thanks to @albada , I took another look at the code and discovered some typos. Please fix them.

# along with NEST. If not, see <http://www.gnu.org/licenses/>.

'''
pynest microcicuit example

This comment has been minimized.

@mschmidt87

mschmidt87 Nov 24, 2016

Please correct to microcircuit. Also in All other files that have this typo.

This comment has been minimized.

@hendrikrth

hendrikrth Nov 30, 2016
Author Contributor

fixed this and all other typos



def get_weight(PSP_val, net_dict):
""" Function computes weight to elicit a change in the membrane potential.

This comment has been minimized.

@mschmidt87

mschmidt87 Nov 24, 2016

Please change to "Computes" in accordance to the documentation of other functions.

This comment has been minimized.

@hendrikrth

hendrikrth Nov 30, 2016
Author Contributor

Changes this and adapted this style in all other functions

)
# If the network is scaled the indegrees are calculated in the same
# fashion as in the original version of the circuit, which is
# written in sli

This comment has been minimized.

@mschmidt87

mschmidt87 Nov 24, 2016

insert '.' at the end.

This comment has been minimized.

@hendrikrth

hendrikrth Nov 30, 2016
Author Contributor

Done

def adj_w_ext_to_K(K_full, K_scaling, w, w_from_PSP, DC, net_dict, stim_dict):
""" Adjustment of weights to scaling is dine in this function.
With this funtion the recurrent and external weights are adjusted

This comment has been minimized.

This comment has been minimized.

@hendrikrth

hendrikrth Nov 30, 2016
Author Contributor

Done



def load_spike_times(path, name, begin, end):
""" This function loads spike times of each spike detector.

This comment has been minimized.

@mschmidt87

mschmidt87 Nov 24, 2016

Change to "Loads..."

This comment has been minimized.

@hendrikrth

hendrikrth Nov 30, 2016
Author Contributor

Done

# along with NEST. If not, see <http://www.gnu.org/licenses/>.

'''
microcicuit simulation parameters

This comment has been minimized.

microcicuit simulation parameters
---------------------------------
Simulation Parameters for the microcircuit.

This comment has been minimized.

@mschmidt87

mschmidt87 Nov 24, 2016

Simulation parameters

'local_num_threads': 1,
# Recording interval of the membrane potential (in ms).
'rec_V_int': 1.0,
# If True data will be overwritten,

This comment has been minimized.

@mschmidt87

mschmidt87 Nov 24, 2016

If True, data...

# Recording interval of the membrane potential (in ms).
'rec_V_int': 1.0,
# If True data will be overwritten,
# if False a NESTError is raised if the files already exist.

This comment has been minimized.

# along with NEST. If not, see <http://www.gnu.org/licenses/>.

'''
microcicuit stimulus parameters

This comment has been minimized.

some typos were fixed and a comment about the initialization
of the membrane potentials was changed
@jhnnsnk
Copy link
Contributor

@jhnnsnk jhnnsnk commented Dec 14, 2016

👍

@heplesser
Copy link
Contributor

@heplesser heplesser commented Dec 14, 2016

@hendrikrth Thank you for porting this important model to PyNEST! @jhnnsnk @mschmidt87 Thank you for your thorough review!

@heplesser heplesser merged commit 102e338 into nest:master Dec 14, 2016
1 check passed
1 check passed
continuous-integration/travis-ci/pr The Travis CI build passed
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

5 participants
You can’t perform that action at this time.