Skip to content

Commit

Permalink
Merge pull request #2955 from HanjiaJiang/connect_astro
Browse files Browse the repository at this point in the history
Add a tripartite connection rule for neuron-astrocyte connectivity
  • Loading branch information
heplesser authored Nov 23, 2023
2 parents 33691e0 + 31e0ce9 commit a5f0d71
Show file tree
Hide file tree
Showing 35 changed files with 3,618 additions and 49 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ option( static-libraries "Build static executable and libraries [default=OFF]" O
set( with-optimize ON CACHE STRING "Enable user defined optimizations [default=ON (uses '-O2')]. When OFF, no '-O' flag is passed to the compiler. Explicit compiler flags can be given; separate multiple flags by ';'." )
set( with-warning ON CACHE STRING "Enable user defined warnings [default=ON (uses '-Wall')]. Separate multiple flags by ';'." )
set( with-debug OFF CACHE STRING "Enable user defined debug flags [default=OFF]. When ON, '-g' is used. Separate multiple flags by ';'." )
set( with-cpp-std "c++11" CACHE STRING "C++ standard to use for compilation [default='c++11']." )
set( with-cpp-std "c++17" CACHE STRING "C++ standard to use for compilation [default='c++17']." )
set( with-intel-compiler-flags OFF CACHE STRING "User defined flags for the Intel compiler [default='-fp-model strict']. Separate multiple flags by ';'." )
set( with-libraries OFF CACHE STRING "Link additional libraries [default=OFF]. Give full path. Separate multiple libraries by ';'." )
set( with-includes OFF CACHE STRING "Add additional include paths [default=OFF]. Give full path without '-I'. Separate multiple include paths by ';'." )
Expand Down
25 changes: 13 additions & 12 deletions build_support/generate_modelsmodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,17 @@ def get_models_from_file(model_file):
"""

model_patterns = {
"neuron": "public ArchivingNode",
"stimulator": "public StimulationDevice",
"recorder": "public RecordingDevice",
"devicelike": "public DeviceNode",
"connection": "public Connection",
"node": "public Node",
"clopath": "public ClopathArchivingNode",
"urbanczik": "public UrbanczikArchivingNode",
"binary": "typedef binary_neuron",
"rate": "typedef rate_",
"public ArchivingNode": "neuron",
"public StructuralPlasticityNode": "neuron",
"public StimulationDevice": "stimulator",
"public RecordingDevice": "recorder",
"public DeviceNode": "devicelike",
"public Connection": "connection",
"public Node": "node",
"public ClopathArchivingNode": "clopath",
"public UrbanczikArchivingNode": "urbanczik",
"typedef binary_neuron": "binary",
"typedef rate_": "rate",
}

fname = Path(srcdir) / "models" / f"{model_file}.h"
Expand All @@ -125,7 +126,7 @@ def get_models_from_file(model_file):
if line.startswith("#ifdef HAVE_"):
guards.append(line.strip().split()[1])
if line.startswith(f"class {model_file} : "):
for mtype, pattern in model_patterns.items():
for pattern, mtype in model_patterns.items():
if pattern in line:
names.append(model_file)
types.append(mtype)
Expand All @@ -138,7 +139,7 @@ def get_models_from_file(model_file):
except (ValueError, KeyError) as e:
types.append("node")
if line.startswith("typedef "):
for mtype, pattern in model_patterns.items():
for pattern, mtype in model_patterns.items():
if pattern in line:
names.append(line.rsplit(" ", 1)[-1].strip()[:-1])
types.append(mtype)
Expand Down
14 changes: 9 additions & 5 deletions doc/htmldoc/examples/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,12 @@ PyNEST examples
* :doc:`../auto_examples/pong/generate_gif`

.. grid-item-card:: Astrocytes
:img-top: ../static/img/astrocyte_tripartite.png
:img-top: ../static/img/astrocyte_interaction.png

* :doc:`../auto_examples/astrocyte_single`
* :doc:`../auto_examples/astrocyte_tripartite`
* :doc:`../auto_examples/astrocytes/astrocyte_single`
* :doc:`../auto_examples/astrocytes/astrocyte_interaction`
* :doc:`../auto_examples/astrocytes/astrocyte_small_network`
* :doc:`../auto_examples/astrocytes/astrocyte_brunel`


.. grid:: 1 1 2 3
Expand Down Expand Up @@ -325,8 +327,10 @@ PyNEST examples
../auto_examples/csa_example
../auto_examples/csa_spatial_example
../auto_examples/hpc_benchmark
../auto_examples/astrocyte_single
../auto_examples/astrocyte_tripartite
../auto_examples/astrocytes/astrocyte_single
../auto_examples/astrocytes/astrocyte_interaction
../auto_examples/astrocytes/astrocyte_small_network
../auto_examples/astrocytes/astrocyte_brunel

.. toctree::
:hidden:
Expand Down
1,278 changes: 1,278 additions & 0 deletions doc/htmldoc/static/img/tripartite_pool_type.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
138 changes: 138 additions & 0 deletions doc/htmldoc/synapses/connection_management.rst
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,144 @@ must be ``True``.
'allow_autapses': False, 'make_symmetric': True}
nest.Connect(A, B, conn_spec_dict)
.. _tripartite_connectivity:

Tripartite connectivity
-----------------------

NEST supports creating connections of three node populations using the
:py:func:`.TripartiteConnect` function:

.. code-block:: python
nest.TripartiteConnect(pre, post, third, conn_spec)
nest.TripartiteConnect(pre, post, third, conn_spec, syn_specs)
``pre``, ``post``, and ``third`` are ``NodeCollections``, defining the nodes of
origin (`sources`) and termination (`targets`) as well as the third
factor population to be included. Connections will be established from ``pre`` to both ``third`` and ``post``, and from ``third`` to ``post``. Details of the connections created depend on
the connection rule used.

``conn_spec`` must be provided and must specify a tripartite
connection rule, e.g., :ref:`tripartite Bernoulli with pool <tripartite_bernoulli_with_pool>`.

``syn_specs`` is a dictionary of the form

.. code-block:: python
{'primary': <syn_spec>,
'third_in': <syn_spec>,
'third_out': <syn_spec>}
where the individual ``syn_spec`` elements follow the same rules as
for the :py:func:`.Connect` function. Any of the three elements can be
left out, in which case the synapse specification defaults to
``'static_synapse'``. The ``'primary'`` synapse specification applies
to connections from ``pre`` to ``post`` nodes, the ``'third_in'``
specification to connections from ``pre`` to ``third`` nodes and
the ``'third_out'`` specification to connections from ``third`` to
``post`` nodes.

.. _tripartite_bernoulli_with_pool:

Tripartite Bernoulli with pool
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For each possible pair of nodes from a source ``NodeCollection`` (e.g., a neuron population ``S``)
and a target ``NodeCollection`` (e.g., a neuron population ``T``), a connection is
created with probability ``p_primary``, and these connections are
called 'primary' connections. For each primary connection, a
third-party connection pair involving a node from a third ``NodeCollection``
(e.g., an astrocyte population ``A``) is created with the conditional probability
``p_third_if_primary``. This connection pair includes a connection
from the ``S`` node to the ``A`` node, and a connection from the ``A`` node to the
``T`` node. The ``A`` node to connect to is chosen
at random from a pool, a subset of the nodes in ``A``. By default,
this pool is all of ``A``.

Pool formation is controlled by parameters ``pool_type``, which can be ``'random'``
(default) or ``'block'``, and ``pool_size``, which must be between 1
and the size of ``A`` (default). For random pools, for each node from
``T``, ``pool_size`` nodes from ``A`` are chosen randomly without
replacement.

For block pools, two variants exist. Let ``N_T`` and ``N_A`` be the number of
nodes in ``T`` and ``A``, respectively. If ``pool_size == 1``, the
first ``N_T/N_A`` nodes in ``T`` are assigned the first node in
``A`` as their pool, the second ``N_T/N_A`` nodes in ``T`` the
second node in ``A`` and so forth. In this case, ``N_T`` must be a
multiple of ``N_A``. If ``pool_size > 1``, the first ``pool_size``
elements of ``A`` are the pool for the first node in ``T``, the
second ``pool_size`` elements of ``A`` are the pool for the second
node in ``T`` and so forth. In this case, ``N_T * pool_size == N_A``
is required.

The following code and figure demonstrate three use case examples with
``pool_type`` being ``'random'`` or ``'block'``:

.. code-block:: python
N_S, N_T, N_A, p_primary, p_third_if_primary = 6, 6, 3, 0.2, 1.0
pool_type, pool_size = 'random', 2
S = nest.Create('aeif_cond_alpha_astro', N_S)
T = nest.Create('aeif_cond_alpha_astro', N_T)
A = nest.Create('astrocyte_lr_1994', N_A)
conn_spec = {'rule': 'tripartite_bernoulli_with_pool',
'p_primary': p_primary,
'p_third_if_primary': p_third_if_primary,
'pool_type': pool_type,
'pool_size': pool_size}
syn_specs = {'third_out': 'sic_connection'}
nest.TripartiteConnect(S, T, A, conn_spec, syn_specs)
.. code-block:: python
N_S, N_T, N_A, p_primary, p_third_if_primary = 6, 6, 3, 0.2, 1.0
pool_type, pool_size = 'block', 1
S = nest.Create('aeif_cond_alpha_astro', N_S)
T = nest.Create('aeif_cond_alpha_astro', N_T)
A = nest.Create('astrocyte_lr_1994', N_A)
conn_spec = {'rule': 'tripartite_bernoulli_with_pool',
'p_primary': p_primary,
'p_third_if_primary': p_third_if_primary,
'pool_type': pool_type,
'pool_size': pool_size}
syn_specs = {'third_out': 'sic_connection'}
nest.TripartiteConnect(S, T, A, conn_spec, syn_specs)
.. code-block:: python
N_S, N_T, N_A, p_primary, p_third_if_primary = 6, 3, 6, 0.2, 1.0
pool_type, pool_size = 'block', 2
S = nest.Create('aeif_cond_alpha_astro', N_S)
T = nest.Create('aeif_cond_alpha_astro', N_T)
A = nest.Create('astrocyte_lr_1994', N_A)
conn_spec = {'rule': 'tripartite_bernoulli_with_pool',
'p_primary': p_primary,
'p_third_if_primary': p_third_if_primary,
'pool_type': pool_type,
'pool_size': pool_size}
syn_specs = {'third_out': 'sic_connection'}
nest.TripartiteConnect(S, T, A, conn_spec, syn_specs)
.. image:: ../static/img/tripartite_pool_type.svg
:align: center

(A) In the example of ``'random'`` pool type, each node in ``T`` can be connected with
up to two randomly selected nodes in ``A`` (given ``pool_size == 2``). (B) In
the first example of ``'block'`` pool type, let ``N_T/N_A`` = 2,
then each node in ``T`` can be connected with one node in ``A``
(``pool_size == 1`` is required because ``N_A < N_T``), and each node in
``A`` can be connected with up to two nodes in ``T``. (C) In the second example
of ``'block'`` pool type, let ``N_A/N_T`` = 2, then each node in
``T`` can be connected with up to two nodes in ``A`` (``pool_size == 2`` is
required because ``N_A/N_T`` = 2), and each node in ``A`` can be
connected to one node in ``T``.


.. _synapse_spec:

Synapse Specification
Expand Down
4 changes: 2 additions & 2 deletions doc/htmldoc/whats_new/v3.6/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ neuron-astrocyte circuits.

See examples using astrocyte models:

* :doc:`../../../auto_examples/astrocyte_single`
* :doc:`../../../auto_examples/astrocyte_tripartite`
* :doc:`../../../auto_examples/astrocytes/astrocyte_single`
* :doc:`../../../auto_examples/astrocytes/astrocyte_interaction`

See model docs:

Expand Down
42 changes: 42 additions & 0 deletions doc/htmldoc/whats_new/v3.7/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.. _release_3.7:

What's new in NEST 3.7
======================

This page contains a summary of important breaking and non-breaking
changes from NEST 3.6 to NEST 3.7. In addition to the `release notes
on GitHub <https://github.com/nest/nest-simulator/releases/>`_, this
page also contains transition information that helps you to update
your simulation scripts when you come from an older version of NEST.

If you transition from an earlier version, please see our extensive
:ref:`transition guide from NEST 2.x to 3.0 <refguide_2_3>` and the
:ref:`list of updates for previous releases in the 3.x series <whats_new>`.


NEST requires C++17
-------------------

From NEST 3.7 on, we use some C++17 features in NEST code. Therefore,
NEST needs to be built with a compiler that supports C++17. Most
recent C++ compilers should do so.

Tripartite connectivity in NEST
-------------------------------

NEST now supports creation of connections involving three populations
of neurons: a pre-synaptic, a post-synaptic and a third-factor
population. At present, as single tripartite connection rule is
available, ``tripartite_bernoulli_with_pool``. Tripartite connections
are created with the new :py:func:`.TripartiteConnect` function. The first
use case for tripartite connections are networks containing astrocyte
populations.

See examples using astrocyte models:

* :doc:`../../../auto_examples/astrocytes/astrocyte_small_network`
* :doc:`../../../auto_examples/astrocytes/astrocyte_brunel`

See connectivity documentation:

* :ref:`tripartite_connectivity`
16 changes: 2 additions & 14 deletions models/astrocyte_lr_1994.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ nest::astrocyte_lr_1994::Buffers_::Buffers_( const Buffers_&, astrocyte_lr_1994&
* ---------------------------------------------------------------- */

nest::astrocyte_lr_1994::astrocyte_lr_1994()
: ArchivingNode()
: StructuralPlasticityNode()
, P_()
, S_( P_ )
, B_( *this )
Expand All @@ -337,7 +337,7 @@ nest::astrocyte_lr_1994::astrocyte_lr_1994()
}

nest::astrocyte_lr_1994::astrocyte_lr_1994( const astrocyte_lr_1994& n )
: ArchivingNode( n )
: StructuralPlasticityNode( n )
, P_( n.P_ )
, S_( n.S_ )
, B_( n.B_, *this )
Expand Down Expand Up @@ -373,8 +373,6 @@ nest::astrocyte_lr_1994::init_buffers_()
B_.sic_values.resize(
kernel().connection_manager.get_min_delay(), 0.0 ); // set size of SIC buffer according to min_delay

ArchivingNode::clear_history();

B_.logger_.reset();

B_.step_ = Time::get_resolution().get_ms();
Expand Down Expand Up @@ -492,16 +490,6 @@ nest::astrocyte_lr_1994::update( Time const& origin, const long from, const long
kernel().event_delivery_manager.send_secondary( *this, sic );
}

/**
* Default implementation of register_stdp_connection( const std::string& name )
* throws IllegalConnection
*/
void
nest::astrocyte_lr_1994::register_stdp_connection( double, double )
{
throw IllegalConnection( "The target node does not support STDP synapses." );
}

void
nest::astrocyte_lr_1994::handle( SpikeEvent& e )
{
Expand Down
9 changes: 3 additions & 6 deletions models/astrocyte_lr_1994.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ EndUserDocs */

void register_astrocyte_lr_1994( const std::string& name );

class astrocyte_lr_1994 : public ArchivingNode
class astrocyte_lr_1994 : public StructuralPlasticityNode
{

public:
Expand Down Expand Up @@ -274,9 +274,6 @@ class astrocyte_lr_1994 : public ArchivingNode
{
}

// disable the use of STDP connections in this model
void register_stdp_connection( double t_first_read, double delay ) override;

void get_status( DictionaryDatum& ) const override;
void set_status( const DictionaryDatum& ) override;

Expand Down Expand Up @@ -469,7 +466,7 @@ astrocyte_lr_1994::get_status( DictionaryDatum& d ) const
{
P_.get( d );
S_.get( d );
ArchivingNode::get_status( d );
StructuralPlasticityNode::get_status( d );

( *d )[ names::recordables ] = recordablesMap_.get_list();
}
Expand All @@ -486,7 +483,7 @@ astrocyte_lr_1994::set_status( const DictionaryDatum& d )
// write them back to (P_, S_) before we are also sure that
// the properties to be set in the parent class are internally
// consistent.
ArchivingNode::set_status( d );
StructuralPlasticityNode::set_status( d );

// if we get here, temporaries contain consistent set of properties
P_ = ptmp;
Expand Down
Loading

0 comments on commit a5f0d71

Please sign in to comment.