/*
* topologymodule.cpp
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEST. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include "integerdatum.h"
#include "booldatum.h"
#include "doubledatum.h"
#include "arraydatum.h"
#include "dictdatum.h"
#include "network.h"
#include "model.h"
#include "genericmodel.h"
#include "communicator.h"
#include "communicator_impl.h"
#include "topologymodule.h"
#include "layer.h"
#include "layer_impl.h"
#include "free_layer.h"
#include "grid_layer.h"
#include "mask.h"
#include "mask_impl.h"
#include "grid_mask.h"
#include "connection_creator_impl.h"
#include "parameter.h"
#include "lockptrdatum_impl.h"
#include "iostreamdatum.h"
namespace nest
{
SLIType TopologyModule::MaskType;
SLIType TopologyModule::ParameterType;
Network *TopologyModule::net_;
TopologyModule::TopologyModule(Network& net)
{
net_ = &net;
MaskType.settypename("masktype");
MaskType.setdefaultaction(SLIInterpreter::datatypefunction);
ParameterType.settypename("parametertype");
ParameterType.setdefaultaction(SLIInterpreter::datatypefunction);
}
TopologyModule::~TopologyModule()
{
}
const std::string TopologyModule::name(void) const
{
return std::string("TopologyModule"); // Return name of the module
}
const std::string TopologyModule::commandstring(void) const
{
return
std::string("/topology /C++ ($Revision: 10398 $) provide-component "
"/topology-interface /SLI (9954) require-component ");
}
GenericFactory<AbstractMask> &TopologyModule::mask_factory_(void)
{
static GenericFactory<AbstractMask> factory;
return factory;
}
GenericFactory<Parameter> &TopologyModule::parameter_factory_(void)
{
static GenericFactory<Parameter> factory;
return factory;
}
MaskDatum TopologyModule::create_mask(const Token & t)
{
// t can be either an existing MaskDatum, or a Dictionary containing
// mask parameters
MaskDatum *maskd = dynamic_cast<MaskDatum*>(t.datum());
if (maskd) {
return *maskd;
} else {
DictionaryDatum *dd = dynamic_cast<DictionaryDatum*>(t.datum());
if (dd==0) {
throw BadProperty("Mask must be masktype or dictionary.");
}
// The dictionary should contain one key which is the name of the
// mask type, and optionally the key 'anchor'. To find the unknown
// mask type key, we must loop through all keys. The value for the
// anchor key will be stored in the anchor_token variable.
Token anchor_token;
bool has_anchor = false;
AbstractMask *mask = 0;
for(Dictionary::iterator dit = (*dd)->begin(); dit != (*dd)->end(); ++dit) {
if (dit->first == names::anchor) {
anchor_token = dit->second;
has_anchor = true;
} else {
if (mask != 0) { // mask has already been defined
throw BadProperty("Mask definition dictionary contains extraneous items.");
}
mask = create_mask(dit->first,getValue<DictionaryDatum>(dit->second));
}
}
if (has_anchor) {
// The anchor may be an array of doubles (a spatial position), or a
// dictionary containing the keys 'column' and 'row' (for grid
// masks only)
try {
std::vector<double_t> anchor = getValue<std::vector<double_t> >(anchor_token);
AbstractMask *amask;
switch(anchor.size()) {
case 2:
amask = new AnchoredMask<2>(dynamic_cast<Mask<2>&>(*mask),anchor);
break;
case 3:
amask = new AnchoredMask<3>(dynamic_cast<Mask<3>&>(*mask),anchor);
break;
default:
throw BadProperty("Anchor must be 2- or 3-dimensional.");
}
delete mask;
mask = amask;
} catch (TypeMismatch e) {
DictionaryDatum ad = getValue<DictionaryDatum>(anchor_token);
int_t dim = 2;
int_t column = getValue<long>(ad, names::column);
int_t row = getValue<long>(ad, names::row);
int_t layer;
if (ad->known(names::layer)) {
layer = getValue<long>(ad,names::layer);
dim = 3;
}
switch(dim) {
case 2:
try {
GridMask<2>& grid_mask_2d = dynamic_cast<GridMask<2>&>(*mask);
grid_mask_2d.set_anchor(Position<2,int_t>(column,row));
} catch (std::bad_cast e) {
throw BadProperty("Mask must be 2-dimensional grid mask.");
}
break;
case 3:
try {
GridMask<3>& grid_mask_3d = dynamic_cast<GridMask<3>&>(*mask);
grid_mask_3d.set_anchor(Position<3,int_t>(column,row,layer));
} catch (std::bad_cast e) {
throw BadProperty("Mask must be 3-dimensional grid mask.");
}
break;
}
}
}
return mask;
}
}
ParameterDatum TopologyModule::create_parameter(const Token & t)
{
// t can be an existing ParameterDatum, a DoubleDatum containing a
// constant value for this parameter, or a Dictionary containing
// parameters
ParameterDatum *pd = dynamic_cast<ParameterDatum*>(t.datum());
if (pd)
return *pd;
// If t is a DoubleDatum, create a ConstantParameter with this value
DoubleDatum *dd = dynamic_cast<DoubleDatum*>(t.datum());
if (dd) {
return new ConstantParameter(*dd);
}
DictionaryDatum *dictd = dynamic_cast<DictionaryDatum*>(t.datum());
if (dictd) {
// The dictionary should only have a single key, which is the name of
// the parameter type to create.
if ((*dictd)->size() != 1) {
throw BadProperty("Parameter definition dictionary must contain one single key only.");
}
Name n = (*dictd)->begin()->first;
DictionaryDatum pdict = getValue<DictionaryDatum>(*dictd,n);
return create_parameter(n, pdict);
} else {
throw BadProperty("Parameter must be parametertype, constant or dictionary.");
}
}
Parameter *TopologyModule::create_parameter(const Name& name, const DictionaryDatum &d)
{
// The parameter factory will create the parameter without regard for
// the anchor
Parameter *param = parameter_factory_().create(name,d);
// Wrap the parameter object created above in an AnchoredParameter if
// the dictionary contains an anchor
if (d->known(names::anchor)) {
std::vector<double_t> anchor = getValue<std::vector<double_t> >(d,names::anchor);
Parameter *aparam;
switch(anchor.size()) {
case 2:
aparam = new AnchoredParameter<2>(*param,anchor);
break;
case 3:
aparam = new AnchoredParameter<3>(*param,anchor);
break;
default:
throw BadProperty("Anchor must be 2- or 3-dimensional.");
}
delete param;
param = aparam;
}
return param;
}
static AbstractMask* create_doughnut(const DictionaryDatum& d) {
// The doughnut (actually an annulus) is created using a DifferenceMask
Position<2> center(0,0);
if (d->known(names::anchor))
center = getValue<std::vector<double_t> >(d, names::anchor);
BallMask<2> outer_circle(center,getValue<double_t>(d, names::outer_radius));
BallMask<2> inner_circle(center,getValue<double_t>(d, names::inner_radius));
return new DifferenceMask<2>(outer_circle, inner_circle);
}
void TopologyModule::init(SLIInterpreter *i)
{
// Register the topology functions as SLI commands.
i->createcommand("CreateLayer_D",
&createlayer_Dfunction);
i->createcommand("GetPosition_i",
&getposition_ifunction);
i->createcommand("Displacement_a_i",
&displacement_a_ifunction);
i->createcommand("Distance_a_i",
&distance_a_ifunction);
i->createcommand("CreateMask_D",
&createmask_Dfunction);
i->createcommand("Inside_a_M",
&inside_a_Mfunction);
i->createcommand("and_M_M",
&and_M_Mfunction);
i->createcommand("or_M_M",
&or_M_Mfunction);
i->createcommand("sub_M_M",
&sub_M_Mfunction);
i->createcommand("mul_P_P",
&mul_P_Pfunction);
i->createcommand("div_P_P",
&div_P_Pfunction);
i->createcommand("add_P_P",
&add_P_Pfunction);
i->createcommand("sub_P_P",
&sub_P_Pfunction);
i->createcommand("GetGlobalChildren_i_M_a",
&getglobalchildren_i_M_afunction);
i->createcommand("ConnectLayers_i_i_D",
&connectlayers_i_i_Dfunction);
i->createcommand("CreateParameter_D",
&createparameter_Dfunction);
i->createcommand("GetValue_a_P",
&getvalue_a_Pfunction);
i->createcommand("DumpLayerNodes_os_i",
&dumplayernodes_os_ifunction);
i->createcommand("DumpLayerConnections_os_i_l",
&dumplayerconnections_os_i_lfunction);
i->createcommand("GetElement_i_ia",
&getelement_i_iafunction);
i->createcommand("cvdict_M",
&cvdict_Mfunction);
// Register layer types as models
Network & net = get_network();
register_model<FreeLayer<2> >(net, "topology_layer_free");
register_model<FreeLayer<3> >(net, "topology_layer_free_3d");
register_model<GridLayer<2> >(net, "topology_layer_grid");
register_model<GridLayer<3> >(net, "topology_layer_grid_3d");
// Register mask types
register_mask<BallMask<2> >();
register_mask<BallMask<3> >();
register_mask<BoxMask<2> >();
register_mask<BoxMask<3> >();
register_mask<BoxMask<3> >("volume"); // For compatibility with topo 2.0
register_mask("doughnut",create_doughnut);
register_mask<GridMask<2> >();
// Register parameter types
register_parameter<ConstantParameter>("constant");
register_parameter<LinearParameter>("linear");
register_parameter<ExponentialParameter>("exponential");
register_parameter<GaussianParameter>("gaussian");
register_parameter<Gaussian2DParameter>("gaussian2D");
register_parameter<UniformParameter>("uniform");
register_parameter<NormalParameter>("normal");
register_parameter<LognormalParameter>("lognormal");
}
/*BeginDocumentation
Name: topology::CreateLayer - create a spatial layer of nodes
Synopsis:
dict CreateLayer -> layer
Parameters:
dict - dictionary with layer specification
Description: The Topology module organizes neuronal networks in
layers. A layer is a special type of subnet which contains information
about the spatial position of its nodes. There are three classes of
layers: grid-based layers, in which each element is placed at a
location in a regular grid; free layers, in which elements can be
placed arbitrarily in space; and random layers, where the elements are
distributed randomly throughout a region in space. Which kind of layer
this command creates depends on the elements in the supplied
specification dictionary.
Author: Håkon Enger, Kittel Austvoll
*/
void TopologyModule::CreateLayer_DFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(1);
DictionaryDatum layer_dict =
getValue<DictionaryDatum>(i->OStack.pick(0));
index layernode = AbstractLayer::create_layer(layer_dict);
i->OStack.pop(1);
i->OStack.push(layernode);
i->EStack.pop();
}
/*
BeginDocumentation
Name: topology::GetPosition - retrieve position of input node
Synopsis: node_gid GetPosition -> [array]
Parameters:
node_gid - gid of layer node
[array] - spatial position of node [x y]
Description: Retrieves spatial 2D position of layer node.
Examples:
topology using
%%Create layer
<< /rows 5
/columns 4
/elements /iaf_neuron
>> /dictionary Set
dictionary CreateLayer /src Set
4 GetPosition
Author: Kittel Austvoll
*/
void TopologyModule::GetPosition_iFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(1);
Network & net = get_network();
index node_gid = getValue<long_t>(i->OStack.pick(0));
if ( not net.is_local_gid(node_gid) )
throw KernelException("GetPosition is currently implemented for local nodes only.");
Node const * const node = net.get_node(node_gid);
AbstractLayer * const layer = dynamic_cast<AbstractLayer*>(node->get_parent());
if ( !layer )
throw LayerExpected();
Token result = layer->get_position_vector(node->get_subnet_index());
i->OStack.pop(1);
i->OStack.push(result);
i->EStack.pop();
}
/*
BeginDocumentation
Name: topology::Displacement - compute displacement vector
Synopsis: from_gid to_gid Displacement -> [double vector]
from_pos to_gid Displacement -> [double vector]
Parameters:
from_gid - int, gid of node in a topology layer
from_pos - double vector, position in layer
to_gid - int, gid of node in a topology layer
Returns:
[double vector] - vector pointing from position "from" to position "to"
Description:
This function returns a vector connecting the position of the "from_gid"
node or the explicitly given "from_pos" position and the position of the
"to_gid" node. Nodes must be parts of topology layers.
The "from" position is projected into the layer of the "to_gid" node. If
this layer has periodic boundary conditions (EdgeWrap is true), then the
shortest displacement vector is returned, taking into account the
periodicity. Fixed grid layers are in this case extended so that the
nodes at the edges of the layer have a distance of one grid unit when
wrapped.
Example:
topology using
<< /rows 5
/columns 4
/elements /iaf_neuron
>> CreateLayer ;
4 5 Displacement
[0.2 0.3] 5 Displacement
Author: Håkon Enger, Hans E Plesser, Kittel Austvoll
See also: Distance, GetPosition
*/
void TopologyModule::Displacement_a_iFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(2);
Network & net = get_network();
std::vector<double_t> point = getValue<std::vector<double_t> >(i->OStack.pick(1));
index node_gid = getValue<long_t>(i->OStack.pick(0));
if ( not net.is_local_gid(node_gid) )
throw KernelException("Displacement is currently implemented for local nodes only.");
Node const * const node = net.get_node(node_gid);
AbstractLayer * const layer = dynamic_cast<AbstractLayer*>(node->get_parent());
if ( !layer )
throw LayerExpected();
Token result = layer->compute_displacement(point, node->get_lid());
i->OStack.pop(2);
i->OStack.push(result);
i->EStack.pop();
}
/*
BeginDocumentation
Name: topology::Distance - compute distance between nodes
Synopsis: from_gid to_gid Distance -> double
from_pos to_gid Distance -> double
Parameters:
from_gid - int, gid of node in a topology layer
from_pos - double vector, position in layer
to_gid - int, gid of node in a topology layer
Returns:
double - distance between nodes or given position and node
Description:
This function returns the distance between the position of the "from_gid"
node or the explicitly given "from_pos" position and the position of the
"to_gid" node. Nodes must be parts of topology layers.
The "from" position is projected into the layer of the "to_gid" node. If
this layer has periodic boundary conditions (EdgeWrap is true), then the
shortest distance is returned, taking into account the
periodicity. Fixed grid layers are in this case extended so that the
nodes at the edges of the layer have a distance of one grid unit when
wrapped.
Example:
topology using
<< /rows 5
/columns 4
/elements /iaf_neuron
>> CreateLayer ;
4 5 Distance
[0.2 0.3] 5 Distance
Author: Hans E Plesser, Kittel Austvoll
See also: Displacement, GetPosition
*/
void TopologyModule::Distance_a_iFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(2);
Network & net = get_network();
std::vector<double_t> point = getValue<std::vector<double_t> >(i->OStack.pick(1));
index node_gid = getValue<long_t>(i->OStack.pick(0));
if ( not net.is_local_gid(node_gid) )
throw KernelException("Displacement is currently implemented for local nodes only.");
Node const * const node = net.get_node(node_gid);
AbstractLayer * const layer = dynamic_cast<AbstractLayer*>(node->get_parent());
if ( !layer )
throw LayerExpected();
Token result = layer->compute_distance(point, node->get_lid());
i->OStack.pop(2);
i->OStack.push(result);
i->EStack.pop();
}
/*BeginDocumentation
Name: topology::CreateMask - create a spatial mask
Synopsis:
<< /type dict >> CreateMask -> mask
Parameters:
/type - mask type
dict - dictionary with mask specifications
Description: Masks are used when creating connections in the Topology
module. A mask describes which area of the pool layer shall be searched
for nodes to connect for any given node in the driver layer. This
command creates a mask object which may be combined with other mask
objects using Boolean operators. The mask is specified in a dictionary.
Author: Håkon Enger
*/
void TopologyModule::CreateMask_DFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(1);
MaskDatum datum( create_mask(i->OStack.pick(0)) );
i->OStack.pop(1);
i->OStack.push(datum);
i->EStack.pop();
}
/*BeginDocumentation
Name: topology::Inside - test if a point is inside a mask
Synopsis:
point mask Inside -> bool
Parameters:
point - array of coordinates
mask - mask object
Returns:
bool - true if the point is inside the mask
*/
void TopologyModule::Inside_a_MFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(2);
std::vector<double_t> point = getValue<std::vector<double_t> >(i->OStack.pick(1));
MaskDatum mask = getValue<MaskDatum>(i->OStack.pick(0));
bool ret = mask->inside(point);
i->OStack.pop(2);
i->OStack.push(Token(BoolDatum(ret)));
i->EStack.pop();
}
void TopologyModule::And_M_MFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(2);
MaskDatum mask1 = getValue<MaskDatum>(i->OStack.pick(1));
MaskDatum mask2 = getValue<MaskDatum>(i->OStack.pick(0));
MaskDatum newmask = mask1->intersect_mask(*mask2);
i->OStack.pop(2);
i->OStack.push(newmask);
i->EStack.pop();
}
void TopologyModule::Or_M_MFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(2);
MaskDatum mask1 = getValue<MaskDatum>(i->OStack.pick(1));
MaskDatum mask2 = getValue<MaskDatum>(i->OStack.pick(0));
MaskDatum newmask = mask1->union_mask(*mask2);
i->OStack.pop(2);
i->OStack.push(newmask);
i->EStack.pop();
}
void TopologyModule::Sub_M_MFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(2);
MaskDatum mask1 = getValue<MaskDatum>(i->OStack.pick(1));
MaskDatum mask2 = getValue<MaskDatum>(i->OStack.pick(0));
MaskDatum newmask = mask1->minus_mask(*mask2);
i->OStack.pop(2);
i->OStack.push(newmask);
i->EStack.pop();
}
void TopologyModule::Mul_P_PFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(2);
ParameterDatum param1 = getValue<ParameterDatum>(i->OStack.pick(1));
ParameterDatum param2 = getValue<ParameterDatum>(i->OStack.pick(0));
ParameterDatum newparam = param1->multiply_parameter(*param2);
i->OStack.pop(2);
i->OStack.push(newparam);
i->EStack.pop();
}
void TopologyModule::Div_P_PFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(2);
ParameterDatum param1 = getValue<ParameterDatum>(i->OStack.pick(1));
ParameterDatum param2 = getValue<ParameterDatum>(i->OStack.pick(0));
ParameterDatum newparam = param1->divide_parameter(*param2);
i->OStack.pop(2);
i->OStack.push(newparam);
i->EStack.pop();
}
void TopologyModule::Add_P_PFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(2);
ParameterDatum param1 = getValue<ParameterDatum>(i->OStack.pick(1));
ParameterDatum param2 = getValue<ParameterDatum>(i->OStack.pick(0));
ParameterDatum newparam = param1->add_parameter(*param2);
i->OStack.pop(2);
i->OStack.push(newparam);
i->EStack.pop();
}
void TopologyModule::Sub_P_PFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(2);
ParameterDatum param1 = getValue<ParameterDatum>(i->OStack.pick(1));
ParameterDatum param2 = getValue<ParameterDatum>(i->OStack.pick(0));
ParameterDatum newparam = param1->subtract_parameter(*param2);
i->OStack.pop(2);
i->OStack.push(newparam);
i->EStack.pop();
}
void TopologyModule::GetGlobalChildren_i_M_aFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(3);
index gid = getValue<long_t>(i->OStack.pick(2));
MaskDatum maskd = getValue<MaskDatum>(i->OStack.pick(1));
std::vector<double_t> anchor = getValue<std::vector<double_t> >(i->OStack.pick(0));
AbstractMask &mask = *maskd;
AbstractLayer *layer = dynamic_cast<AbstractLayer *>(get_network().get_node(gid));
if (layer == NULL)
throw LayerExpected();
std::vector<index> gids = layer->get_global_nodes(mask,anchor,false);
ArrayDatum result;
result.reserve(gids.size());
for(std::vector<index>::iterator it = gids.begin(); it != gids.end(); ++it)
result.push_back(new IntegerDatum(*it));
i->OStack.pop(3);
i->OStack.push(result);
i->EStack.pop();
}
/*
BeginDocumentation
Name: topology::ConnectLayers - connect two layers
Synopsis: sourcelayergid targetlayergid connection_dict
ConnectLayers -> -
Description: Connects nodes in two topological layers.
The parameters set in the input dictionary decides the nature
of the connection pattern being created. Please see parameter
list below for a detailed description of these variables.
The connections are created by iterating through either the
source or the target layer, consecutively connecting each node
to a region in the opposing layer.
Parameters:
sourcelayergid - GID of source layer
targetlayergid - GID of target layer
connection_dict - dictionary containing any of the following
elements:
------------------------------------------------------------------
Connection dictionary parameters:
------------------------------------------------------------------
Parameter name: connection-type
Type: string
Parameter description:
Decides the type of connection pattern being created (i.e.
convergent or divergent topological connection). A convergent
topological connection is a connection between a source region
and a target node. A divergent topological connection is a
connection between a source node and a target region. A convergent
topological connection can also be called a receptive field connection.
A divergent topological connection can also be called a projective
field connection. A one-to-one connection can be created by setting
the size of the source or target region equal to one. The connection
type has particular effect on the connection pattern when used together
with the number_of_connections variable.
Parameter name: mask
Type: dictionary
Parameter description:
The mask defines the region used in the connection type described
above. There exists a selection of many different region sizes and
shapes. Examples are the grid region, the rectangular, circular or
doughnut region.
The grid region takes an optional anchor parameter. The anchor
parameter indicates which node of the grid region is aligned with
the source node.
Parameter name: weights, delays and kernel
Type: dictionary
Parameter description:
These parameters can be initialised in many ways. Either as a constant
value, with the help of a dictionary, or in an array (only for fixed
grid layers). The dictionary can be of type gaussian, 2D gaussian,
linear, exponential and other.
Parameter name: source
Type: dictionary
Parameter description:
The source dictionary enables us to give further detail on
how the nodes in the source layer used in the connection function
should be processed.
Parameters:
model* literal
lid^ integer
*modeltype (i.e. /iaf_neuron) of nodes that should be connected to
in the layer. All nodes are used if this variable isn't set.
^Nesting depth of nodes that should be connected to. All layers are used
if this variable isn't set.
Parameter name: target
Type: dictionary
Parameter description:
See description for source dictionary.
Parameter name: number_of_connections
Type: integer
Parameter description:
Maximum number of connections that each iterating node is allowed.
The actual connections being created are picked at random from all
the candidate connections.
.
Parameter name: allow_autapses
Type: bool
Parameter description: Used together with the number_of_connections option to
indicate if autapses are allowed.
Parameter name: allow_multapses
Type: bool
Parameter description: Used together with the number_of_connections option to
indicate if multapses are allowed.
------------------------------------------------------------------
Example:
topology using
%Create source layer with CreateLayer
<< /rows 15
/columns 43
/extent [1.0 2.0]
/elements /iaf_neuron
>> /src_dictionary Set
src_dictionary CreateLayer /src Set
%Create target layer with CreateLayer
%%Create layer
<< /rows 34
/columns 71
/extent [3.0 1.0]
/elements {/iaf_neuron Create ; /iaf_psc_alpha Create ;}
>> /tgt_dictionary Set
tgt_dictionary CreateLayer /tgt Set
<< /connection_type (convergent)
/mask << /grid << /rows 2 /columns 3 >>
/anchor << /row 4 /column 2 >> >>
/weights 2.3
/delays [2.3 1.2 3.2 1.3 2.3 1.2]
/kernel << /gaussian << /sigma 1.2 /p_center 1.41 >> >>
/sources << /model /iaf_neuron
/lid 1 >>
/targets << /model /iaf_neuron
/lid 2 >>
>> /parameters Set
src tgt parameters ConnectLayers
Author: Håkon Enger, Kittel Austvoll
SeeAlso: topology::CreateLayer
*/
void TopologyModule::ConnectLayers_i_i_DFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(3);
index source_gid = getValue<long_t>(i->OStack.pick(2));
index target_gid = getValue<long_t>(i->OStack.pick(1));
const DictionaryDatum connection_dict = getValue<DictionaryDatum>(i->OStack.pick(0));
AbstractLayer *source = dynamic_cast<AbstractLayer *>(get_network().get_node(source_gid));
AbstractLayer *target = dynamic_cast<AbstractLayer *>(get_network().get_node(target_gid));
if ((source == NULL) || (target == NULL))
throw LayerExpected();
ConnectionCreator connector(connection_dict);
source->connect(*target,connector);
i->OStack.pop(3);
i->EStack.pop();
}
/*BeginDocumentation
Name: topology::CreateParameter - create a spatial function
Synopsis:
<< /type dict >> CreateParameter -> parameter
Parameters:
/type - parameter type
dict - dictionary with parameter specifications
Description: Parameters are spatial functions which are used when
creating connections in the Topology module. A parameter may be used as
a probability kernel when creating connections or as synaptic
parameters (such as weight and delay). This command creates a parameter
object which may be combined with other parameter objects using
arithmetic operators. The parameter is specified in a dictionary.
Author: Håkon Enger
*/
void TopologyModule::CreateParameter_DFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(1);
ParameterDatum datum( create_parameter(i->OStack.pick(0)) );
i->OStack.pop(1);
i->OStack.push(datum);
i->EStack.pop();
}
/*BeginDocumentation
Name: topology::GetValue - compute value of parameter at a point
Synopsis:
point param GetValue -> value
Parameters:
point - array of coordinates
param - parameter object
Returns:
value - the value of the parameter at the point.
Author: Håkon Enger
*/
void TopologyModule::GetValue_a_PFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(2);
std::vector<double_t> point = getValue<std::vector<double_t> >(i->OStack.pick(1));
ParameterDatum param = getValue<ParameterDatum>(i->OStack.pick(0));
librandom::RngPtr rng = get_network().get_grng();
double_t value = param->value(point,rng);
i->OStack.pop(2);
i->OStack.push(value);
i->EStack.pop();
}
/*
BeginDocumentation
Name: topology::DumpLayerNodes - write information about layer nodes to file
Synopsis: ostream layer_gid DumpLayerNodes -> ostream
Parameters:
ostream - open output stream
layer_gid - topology layer
Description:
Write information about each element in the given layer to the
output stream. The file format is one line per element with the
following contents:
GID x-position y-position [z-position]
X and y position are given as physical coordinates in the extent,
not as grid positions. The number of decimals can be controlled by
calling setprecision on the output stream before calling DumpLayerNodes.
Note:
In distributed simulations, this function should only be called for
MPI rank 0. If you call it on several MPI ranks, you must use a
different file name on each.
Examples:
topology using
/my_layer << /rows 5 /columns 4 /elements /iaf_neuron >> CreateLayer def
(my_layer_dump.lyr) (w) file
my_layer DumpLayerNodes
close
Author: Kittel Austvoll, Hans Ekkehard Plesser
SeeAlso: topology::DumpLayerConnections, setprecision, modeldict
*/
void TopologyModule::
DumpLayerNodes_os_iFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(2);
const index layer_gid = getValue<long_t>(i->OStack.pick(0));
OstreamDatum out = getValue<OstreamDatum>(i->OStack.pick(1));
AbstractLayer const * const layer = dynamic_cast<AbstractLayer*>(net_->get_node(layer_gid));
if( layer != 0 && out->good() )
layer->dump_nodes(*out);
i->OStack.pop(1); // leave ostream on stack
i->EStack.pop();
}
/*
BeginDocumentation
Name: topology::DumpLayerConnections - prints a list of the connections of the nodes in the layer to file
Synopsis: ostream source_layer_gid synapse_model DumpLayerConnections -> ostream
Parameters:
ostream - open outputstream
source_layer_gid - topology layer
synapse_model - synapse model (literal)
Description:
Dumps information about all connections of the given type having their source in
the given layer to the given output stream. The data format is one line per connection as follows:
source_gid target_gid weight delay displacement[x,y,z]
where displacement are up to three coordinates of the vector from the source to
the target node. If targets do not have positions (eg spike detectors outside any layer),
NaN is written for each displacement coordinate.
Note:
For distributed simulations
- this function will dump the connections with local targets only.
- the user is responsible for writing to a different output stream (file)
on each MPI process.
Examples:
topology using
...
(out.cnn) (w) file layer_gid /static_synapse PrintLayerConnections close
Author: Kittel Austvoll, Hans Ekkehard Plesser
SeeAlso: topology::DumpLayerNodes
*/
void TopologyModule::
DumpLayerConnections_os_i_lFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(3);
OstreamDatum out_file = getValue<OstreamDatum>(i->OStack.pick(2));
std::ostream& out = *out_file;
const index layer_gid = getValue<long_t>(i->OStack.pick(1));
const std::string synname = getValue<std::string>(i->OStack.pick(0));
const Token synapse = net_->get_synapsedict().lookup(synname);
if ( synapse.empty() )
throw UnknownSynapseType(synname);
const long synapse_id = static_cast<long>(synapse);
AbstractLayer* const layer = dynamic_cast<AbstractLayer*>(net_->get_node(layer_gid));
if (layer == NULL)
throw TypeMismatch("any layer type", "something else");
layer->dump_connections(out, synapse_id);
i->OStack.pop(2); // leave ostream on stack
i->EStack.pop();
}
/*
BeginDocumentation
Name: topology::GetElement - return node GID at specified layer position
Synopsis: layer_gid [array] GetElement -> node_gid
Parameters:
layer_gid - topological layer
[array] - position of node
node_gid - node GID
Description: Retrieves node at the layer grid position
given in [array]. [array] is on the format [column row].
The layer must be of grid type. Returns an array of GIDs
if there are several nodes per grid point.
Examples:
topology using
%%Create layer
<< /rows 5
/columns 4
/elements /iaf_neuron
>> /dictionary Set
dictionary CreateLayer /src Set
src [2 3] GetElement
Author: Kittel Austvoll, Håkon Enger
*/
void TopologyModule::
GetElement_i_iaFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(2);
const index layer_gid = getValue<long_t>(i->OStack.pick(1));
TokenArray array = getValue<TokenArray>(i->OStack.pick(0));
std::vector<index> node_gids;
switch(array.size()) {
case 2:
{
GridLayer<2> *layer =
dynamic_cast<GridLayer<2>*>(net_->get_node(layer_gid));
if (layer==0) {
throw TypeMismatch("grid layer node","something else");
}
node_gids = layer->get_nodes(Position<2,int_t>(static_cast<index>(array[0]),
static_cast<index>(array[1])));
}
break;
case 3:
{
GridLayer<3> *layer =
dynamic_cast<GridLayer<3>*>(net_->get_node(layer_gid));
if (layer==0) {
throw TypeMismatch("grid layer node","something else");
}
node_gids = layer->get_nodes(Position<3,int_t>(static_cast<index>(array[0]),
static_cast<index>(array[1]),
static_cast<index>(array[2])));
}
break;
default:
throw TypeMismatch("array with length 2 or 3", "something else");
}
i->OStack.pop(2);
// For compatibility reasons, return either single node or array
if (node_gids.size()==1) {
i->OStack.push(node_gids[0]);
} else {
i->OStack.push(node_gids);
}
i->EStack.pop();
}
void TopologyModule::Cvdict_MFunction::execute(SLIInterpreter *i) const
{
i->assert_stack_load(1);
MaskDatum mask = getValue<MaskDatum>(i->OStack.pick(0));
DictionaryDatum dict = mask->get_dict();
i->OStack.pop();
i->OStack.push(dict);
i->EStack.pop();
}
std::string LayerExpected::message()
{
return std::string();
}
} // namespace nest