NEST main@caf0ae8
 
Loading...
Searching...
No Matches
layer_impl.h
Go to the documentation of this file.
1/*
2 * layer_impl.h
3 *
4 * This file is part of NEST.
5 *
6 * Copyright (C) 2004 The NEST Initiative
7 *
8 * NEST is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * NEST is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#ifndef LAYER_IMPL_H
24#define LAYER_IMPL_H
25
26#include "layer.h"
27
28// Includes from nestkernel:
29#include "node_collection.h"
30
31// Includes from spatial:
32#include "grid_layer.h"
33#include "grid_mask.h"
34
35namespace nest
36{
37
38template < int D >
39std::shared_ptr< Ntree< D, size_t > > Layer< D >::cached_ntree_;
40
41template < int D >
42std::vector< std::pair< Position< D >, size_t > >* Layer< D >::cached_vector_ = 0;
43
44template < int D >
45Position< D >
46Layer< D >::compute_displacement( const Position< D >& from_pos, const Position< D >& to_pos ) const
47{
48 Position< D > displ = to_pos;
49 for ( int i = 0; i < D; ++i )
50 {
51 displ[ i ] -= from_pos[ i ];
52 if ( periodic_[ i ] )
53 {
54 displ[ i ] = -0.5 * extent_[ i ] + std::fmod( displ[ i ] + 0.5 * extent_[ i ], extent_[ i ] );
55 if ( displ[ i ] < -0.5 * extent_[ i ] )
56 {
57 displ[ i ] += extent_[ i ];
58 }
59 }
60 }
61 return displ;
62}
63
64template < int D >
65double
66Layer< D >::compute_displacement( const std::vector< double >& from_pos,
67 const std::vector< double >& to_pos,
68 const unsigned int dimension ) const
69{
70 double displacement = to_pos[ dimension ] - from_pos[ dimension ];
71 if ( periodic_[ dimension ] )
72 {
73 displacement -= extent_[ dimension ] * std::round( displacement * ( 1 / extent_[ dimension ] ) );
74 }
75 return displacement;
76}
77
78template < int D >
79void
81{
82 if ( d.known( names::edge_wrap ) )
83 {
84 if ( d.get< bool >( names::edge_wrap ) )
85 {
86 periodic_ = ( 1 << D ) - 1; // All dimensions periodic
87 }
88 }
89}
90
91template < int D >
92void
94{
95 d[ names::extent ] = std::vector< double >( extent_.get_vector() );
96 d[ names::center ] = std::vector< double >( ( lower_left_ + extent_ / 2 ).get_vector() );
97
98 if ( periodic_.none() )
99 {
100 d[ names::edge_wrap ] = false;
101 }
102 else if ( periodic_.count() == D )
103 {
104 d[ names::edge_wrap ] = true;
105 }
106
107 if ( nc )
108 {
109 // This is for backward compatibility with some tests and scripts
110 // TODO: Rename parameter
111 d[ names::network_size ] = static_cast< long >( nc->size() );
112 }
113}
114
115template < int D >
116void
118 AbstractLayerPTR target_layer,
119 NodeCollectionPTR target_nc,
120 ConnectionCreator& connector )
121{
122 // We need to extract the real pointer here to be able to cast to the
123 // dimension-specific subclass.
124 AbstractLayer* target_abs = target_layer.get();
125 assert( target_abs );
126
127 try
128 {
129 Layer< D >& tgt = dynamic_cast< Layer< D >& >( *target_abs );
130 connector.connect( *this, source_nc, tgt, target_nc );
131 }
132 catch ( std::bad_cast& e )
133 {
134 throw BadProperty( "Target layer must have same number of dimensions as source layer." );
135 }
136}
137
138template < int D >
139std::shared_ptr< Ntree< D, size_t > >
141{
142 if ( cached_ntree_md_ == node_collection->get_metadata() )
143 {
144 assert( cached_ntree_.get() );
145 return cached_ntree_;
146 }
147
148 clear_ntree_cache_();
149
150 cached_ntree_ = std::shared_ptr< Ntree< D, size_t > >(
151 new Ntree< D, size_t >( this->lower_left_, this->extent_, this->periodic_ ) );
152
153 return do_get_global_positions_ntree_( node_collection );
154}
155
156template < int D >
157std::shared_ptr< Ntree< D, size_t > >
158Layer< D >::get_global_positions_ntree( std::bitset< D > periodic,
159 Position< D > lower_left,
160 Position< D > extent,
161 NodeCollectionPTR node_collection )
162{
163 clear_ntree_cache_();
164 clear_vector_cache_();
165
166 // Keep layer geometry for non-periodic dimensions
167 for ( int i = 0; i < D; ++i )
168 {
169 if ( not periodic[ i ] )
170 {
171 extent[ i ] = extent_[ i ];
172 lower_left[ i ] = lower_left_[ i ];
173 }
174 }
175
176 cached_ntree_ =
177 std::shared_ptr< Ntree< D, size_t > >( new Ntree< D, size_t >( this->lower_left_, extent, periodic ) );
178
179 do_get_global_positions_ntree_( node_collection );
180
181 // Do not use cache since the periodic bits and extents were altered.
182 cached_ntree_md_ = NodeCollectionMetadataPTR( nullptr );
183
184 return cached_ntree_;
185}
186
187template < int D >
188std::shared_ptr< Ntree< D, size_t > >
190{
191 if ( cached_vector_md_ == node_collection->get_metadata() )
192 {
193 // Convert from vector to Ntree
194 std::copy( cached_vector_->begin(), cached_vector_->end(), std::back_inserter( *cached_ntree_ ) );
195 }
196 else
197 {
198 insert_global_positions_ntree_( *cached_ntree_, node_collection );
199 }
200
201 clear_vector_cache_();
202
203 cached_ntree_md_ = node_collection->get_metadata();
204
205 return cached_ntree_;
206}
207
208template < int D >
209std::vector< std::pair< Position< D >, size_t > >*
211{
212 if ( cached_vector_md_ == node_collection->get_metadata() )
213 {
214 assert( cached_vector_ );
215 return cached_vector_;
216 }
217
218 clear_vector_cache_();
219
220 cached_vector_ = new std::vector< std::pair< Position< D >, size_t > >;
221
222 if ( cached_ntree_md_ == node_collection->get_metadata() )
223 {
224 // Convert from NTree to vector
225
226 typename std::back_insert_iterator< std::vector< std::pair< Position< D >, size_t > > > to =
227 std::back_inserter( *cached_vector_ );
228
229 for ( typename Ntree< D, size_t >::iterator from = cached_ntree_->begin(); from != cached_ntree_->end(); ++from )
230 {
231 *to = *from;
232 }
233 }
234 else
235 {
236 insert_global_positions_vector_( *cached_vector_, node_collection );
237 }
238
239 clear_ntree_cache_();
240
241 cached_vector_md_ = node_collection->get_metadata();
242
243 return cached_vector_;
244}
245
246template < int D >
247std::vector< std::pair< Position< D >, size_t > >
249 const Position< D >& anchor,
250 bool allow_oversized,
251 NodeCollectionPTR node_collection )
252{
253 MaskedLayer< D > masked_layer( *this, mask, allow_oversized, node_collection );
254 std::vector< std::pair< Position< D >, size_t > > positions;
255
256 for ( typename Ntree< D, size_t >::masked_iterator iter = masked_layer.begin( anchor ); iter != masked_layer.end();
257 ++iter )
258 {
259 positions.push_back( *iter );
260 }
261
262 return positions;
263}
264
265template < int D >
266std::vector< size_t >
268 const std::vector< double >& anchor,
269 bool allow_oversized,
270 NodeCollectionPTR node_collection )
271{
272 MaskedLayer< D > masked_layer( *this, mask, allow_oversized, node_collection );
273 std::vector< size_t > nodes;
274 for ( typename Ntree< D, size_t >::masked_iterator i = masked_layer.begin( anchor ); i != masked_layer.end(); ++i )
275 {
276 nodes.push_back( i->second );
277 }
278 return nodes;
279}
280
281template < int D >
282void
283Layer< D >::dump_nodes( std::ostream& out ) const
284{
285 for ( NodeCollection::const_iterator it = this->node_collection_->rank_local_begin();
286 it < this->node_collection_->end();
287 ++it )
288 {
289 out << ( *it ).node_id << ' ';
290 get_position( ( *it ).nc_index ).print( out );
291 out << std::endl;
292 }
293}
294
295template < int D >
296void
298 NodeCollectionPTR node_collection,
299 AbstractLayerPTR target_layer,
300 const std::string& syn_model )
301{
302 // Find all connections for given sources, targets and synapse model
303 Dictionary conn_filter;
304 conn_filter[ names::source ] = node_collection;
305 conn_filter[ names::target ] = NodeCollectionPTR( target_layer->get_node_collection() );
306 conn_filter[ names::synapse_model ] = syn_model;
307
308 const auto& connectome = kernel().connection_manager.get_connections( conn_filter );
309
310 // Get positions of remote nodes
311 std::vector< std::pair< Position< D >, size_t > >* src_vec = get_global_positions_vector( node_collection );
312
313 // Iterate over connectome and write every connection, looking up source position only if source neuron changes
314 size_t previous_source_node_id = 0; // dummy initial value, cannot be node_id of any node
315 Position< D > source_pos; // dummy value
316 for ( const auto& conn : connectome )
317 {
318 const size_t source_node_id = conn.get_source_node_id();
319
320 // Search source_pos for source node only if it is a different node
321 if ( source_node_id != previous_source_node_id )
322 {
323 const auto it = std::find_if( src_vec->begin(),
324 src_vec->end(),
325 [ source_node_id ]( const std::pair< Position< D >, size_t >& p ) { return p.second == source_node_id; } );
326 assert( it != src_vec->end() ); // internal error if node not found
327
328 source_pos = it->first;
329 previous_source_node_id = source_node_id;
330 }
331
332 const Dictionary& result_dict = kernel().connection_manager.get_synapse_status( source_node_id,
333 conn.get_target_node_id(),
334 conn.get_target_thread(),
335 conn.get_synapse_model_id(),
336 conn.get_port() );
337
338 const auto target_node_id = result_dict.get< long >( names::target );
339 const auto weight = result_dict.get< double >( names::weight );
340 const auto delay = result_dict.get< double >( names::delay );
341
342 const Layer< D >* const tgt_layer = dynamic_cast< Layer< D >* >( target_layer.get() );
343 const long tnode_lid = tgt_layer->node_collection_->get_nc_index( target_node_id );
344 assert( tnode_lid >= 0 );
345
346 // Print source, target, weight, delay, rports
347 out << source_node_id << ' ' << target_node_id << ' ' << weight << ' ' << delay << ' ';
348 tgt_layer->compute_displacement( source_pos, tnode_lid ).print( out );
349 out << '\n';
350 }
351}
352
353template < int D >
354void
355MaskedLayer< D >::check_mask_( Layer< D >& layer, bool allow_oversized )
356{
357 if ( not mask_.get() )
358 {
359 mask_ = MaskPTR( new AllMask< D >() );
360 return;
361 }
362
363 try // Try to cast to GridMask
364 {
365 const GridMask< D >& grid_mask = dynamic_cast< const GridMask< D >& >( *mask_ );
366
367 // If the above cast succeeds, then this is a grid mask
368
369 GridLayer< D >* grid_layer = dynamic_cast< GridLayer< D >* >( &layer );
370 if ( grid_layer == 0 )
371 {
372 throw BadProperty( "Grid masks can only be used with grid layers." );
373 }
374
375 Position< D > ext = grid_layer->get_extent();
376 Position< D, size_t > dims = grid_layer->get_dims();
377
378 if ( not allow_oversized )
379 {
380 bool oversize = false;
381 for ( int i = 0; i < D; ++i )
382 {
383 oversize |= layer.get_periodic_mask()[ i ]
384 and ( grid_mask.get_lower_right()[ i ] - grid_mask.get_upper_left()[ i ] ) > static_cast< int >( dims[ i ] );
385 }
386 if ( oversize )
387 {
388 throw BadProperty(
389 "Mask size must not exceed layer size; set allow_oversized_mask to "
390 "override." );
391 }
392 }
393
394 Position< D > lower_left = ext / dims * grid_mask.get_upper_left() - ext / dims * 0.5;
395 Position< D > upper_right = ext / dims * grid_mask.get_lower_right() - ext / dims * 0.5;
396
397 const double y = lower_left[ 1 ];
398 lower_left[ 1 ] = -upper_right[ 1 ];
399 upper_right[ 1 ] = -y;
400
401 mask_ = MaskPTR( new BoxMask< D >( lower_left, upper_right ) );
402 }
403 catch ( std::bad_cast& )
404 {
405
406 // Not a grid mask
407
408 try // Try to cast to correct dimension Mask
409 {
410 const Mask< D >& mask = dynamic_cast< const Mask< D >& >( *mask_ );
411
412 if ( not allow_oversized )
413 {
414 const Box< D > bb = mask.get_bbox();
415 bool oversize = false;
416 for ( int i = 0; i < D; ++i )
417 {
418 oversize |=
419 layer.get_periodic_mask()[ i ] and bb.upper_right[ i ] - bb.lower_left[ i ] > layer.get_extent()[ i ];
420 }
421 if ( oversize )
422 {
423 throw BadProperty(
424 "Mask size must not exceed layer size; set allow_oversized_mask to "
425 "override." );
426 }
427 }
428 }
429 catch ( std::bad_cast& )
430 {
431 throw BadProperty( "Mask is incompatible with layer." );
432 }
433 }
434}
435
436} // namespace nest
437
438#endif
Dictionary class for interface to Python and C++ API.
Definition dictionary.h:213
T get(const std::string &key) const
Get the value at key in the specified type.
Definition dictionary.h:710
Abstract base class for Layers of unspecified dimension.
Definition layer.h:52
NodeCollectionPTR node_collection_
The NodeCollection to which the layer belongs.
Definition layer.h:182
Mask which covers all of space.
Definition mask.h:155
Exception to be thrown if a status parameter is incomplete or inconsistent.
Definition exceptions.h:680
Mask defining a box region.
Definition mask.h:209
This class is a representation of the dictionary of connection properties given as an argument to the...
Definition connection_creator.h:63
void connect(Layer< D > &source, NodeCollectionPTR source_nc, Layer< D > &target, NodeCollectionPTR target_nc)
Connect two layers.
Definition connection_creator_impl.h:38
Dictionary get_synapse_status(const size_t source_node_id, const size_t target_node_id, const size_t tid, const synindex syn_id, const size_t lcid) const
Definition connection_manager.cpp:235
std::deque< ConnectionID > get_connections(const Dictionary &params)
Return connections between pairs of neurons.
Definition connection_manager.cpp:1081
Layer with neurons placed in a grid.
Definition grid_layer.h:40
Position< D, size_t > get_dims() const
Definition grid_layer.h:169
Mask defined in terms of grid points rather than spacial coordinates.
Definition grid_mask.h:40
Position< D, int > get_lower_right() const
Definition grid_mask.h:95
Position< D, int > get_upper_left() const
Definition grid_mask.h:89
Abstract base class for Layer of given dimension (D=2 or 3).
Definition layer.h:218
std::shared_ptr< Ntree< D, size_t > > get_global_positions_ntree(NodeCollectionPTR node_collection)
Get positions for all nodes in layer, including nodes on other MPI processes.
Definition layer_impl.h:140
Position< D > compute_displacement(const Position< D > &from_pos, const Position< D > &to_pos) const
Returns displacement of a position from another position.
Definition layer_impl.h:46
static std::vector< std::pair< Position< D >, size_t > > * cached_vector_
Definition layer.h:447
std::shared_ptr< Ntree< D, size_t > > do_get_global_positions_ntree_(NodeCollectionPTR node_collection)
Definition layer_impl.h:189
void set_status(const Dictionary &) override
Change properties of the layer according to the entries in the dictionary.
Definition layer_impl.h:80
void connect(NodeCollectionPTR source_nc, AbstractLayerPTR target, NodeCollectionPTR target_nc, ConnectionCreator &connector) override
Connect this layer to the given target layer.
Definition layer_impl.h:117
void dump_nodes(std::ostream &os) const override
Write layer data to stream.
Definition layer_impl.h:283
std::bitset< D > get_periodic_mask() const
Definition layer.h:277
std::vector< size_t > get_global_nodes(const MaskPTR mask, const std::vector< double > &anchor, bool allow_oversized, NodeCollectionPTR node_collection) override
Return a vector with the node IDs of the nodes inside the mask.
Definition layer_impl.h:267
const Position< D > & get_extent() const
Definition layer.h:259
void get_status(Dictionary &, NodeCollection const *const) const override
Retrieve status, slice according to node collection if given.
Definition layer_impl.h:93
static std::shared_ptr< Ntree< D, size_t > > cached_ntree_
Global position information for a single layer.
Definition layer.h:446
void dump_connections(std::ostream &out, NodeCollectionPTR node_collection, AbstractLayerPTR target_layer, const std::string &syn_model) override
Dumps information about all connections of the given type having their source in the given layer to t...
Definition layer_impl.h:297
std::vector< std::pair< Position< D >, size_t > > * get_global_positions_vector(NodeCollectionPTR node_collection)
Definition layer_impl.h:210
Abstract base class for masks with given dimension.
Definition mask.h:101
Class for applying masks to layers.
Definition layer.h:458
void check_mask_(Layer< D > &layer, bool allow_oversized)
Will check that the mask can be applied to the layer.
Definition layer_impl.h:355
Ntree< D, size_t >::masked_iterator begin(const Position< D > &anchor)
Iterate over nodes inside mask.
Definition layer.h:570
Ntree< D, size_t >::masked_iterator end()
Definition layer.h:584
Superclass for NodeCollections.
Definition node_collection.h:565
virtual size_t size() const =0
Get the size of the NodeCollection.
Iterator iterating the nodes in a Quadtree.
Definition ntree.h:69
Iterator iterating the nodes in a Quadtree inside a Mask.
Definition ntree.h:153
A Ntree object represents a subtree or leaf in a Ntree structure.
Definition ntree.h:55
Definition position.h:57
Iterator for NodeCollections.
Definition node_collection.h:415
ConnectionManager connection_manager
Definition kernel_manager.h:239
const std::string delay("delay")
const std::string network_size("network_size")
const std::string center("center")
const std::string edge_wrap("edge_wrap")
const std::string target("target")
const std::string weight("weight")
const std::string extent("extent")
const std::string source("source")
const std::string synapse_model("synapse_model")
Namespace for the NEST simulation kernel.
Definition beta_normalization_factor.h:33
std::shared_ptr< AbstractMask > MaskPTR
Definition mask.h:44
KernelManager & kernel()
Definition kernel_manager.h:311
std::shared_ptr< AbstractLayer > AbstractLayerPTR
Definition layer.h:46
std::shared_ptr< NodeCollectionMetadata > NodeCollectionMetadataPTR
Definition node_collection.h:51
std::vector< std::vector< double > > displacement(NodeCollectionPTR layer_to_nc, NodeCollectionPTR layer_from_nc)
Definition spatial.cpp:137
std::shared_ptr< NodeCollection > NodeCollectionPTR
Definition node_collection.h:50
std::vector< std::vector< double > > get_position(NodeCollectionPTR layer_nc)
Definition spatial.cpp:83
A box is defined by the lower left corner (minimum coordinates) and the upper right corner (maximum c...
Definition position.h:321
Position< D > lower_left
Definition position.h:331
Position< D > upper_right
Definition position.h:332