NEST  2.6.0,not_revisioned_source_dir@0
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 "nest_datums.h"
27 #include "layer.h"
28 #include "grid_layer.h"
29 #include "grid_mask.h"
30 
31 namespace nest {
32 
33  template<int D>
34  lockPTR<Ntree<D,index> > Layer<D>::cached_ntree_;
35 
36  template<int D>
37  std::vector<std::pair<Position<D>,index> > * Layer<D>::cached_vector_ = 0;
38 
39  template<int D>
40  Selector Layer<D>::cached_selector_;
41 
42  template<int D>
44  const Position<D>& to_pos) const
45  {
46  Position<D> displ = to_pos - from_pos;
47  for(int i=0;i<D;++i) {
48  if (periodic_[i]) {
49  displ[i] = -0.5*extent_[i] + std::fmod(displ[i]+0.5*extent_[i], extent_[i]);
50  if (displ[i]<-0.5*extent_[i])
51  displ[i] += extent_[i];
52  }
53  }
54  return displ;
55  }
56 
57  template<int D>
59  {
60  if (d->known(names::extent)) {
61  Position<D> center = get_center();
62  extent_ = getValue<std::vector<double_t> >(d, names::extent);
63  lower_left_ = center - extent_/2;
64  }
65  if (d->known(names::center)) {
66  lower_left_ = getValue<std::vector<double_t> >(d, names::center);
67  lower_left_ -= extent_/2;
68  }
69  if (d->known(names::edge_wrap)) {
71  periodic_ = (1<<D) - 1; // All dimensions periodic
72  }
73  }
74 
76  }
77 
78  template <int D>
80  {
82 
83  DictionaryDatum topology_dict(new Dictionary);
84 
85  (*topology_dict)[names::depth] = depth_;
86  (*topology_dict)[names::extent] = std::vector<double_t>(extent_);
87  (*topology_dict)[names::center] = std::vector<double_t>(lower_left_ + extent_/2);
88 
89  if (periodic_.none())
90  (*topology_dict)[names::edge_wrap] = BoolDatum(false);
91  else if (periodic_.count()==D)
92  (*topology_dict)[names::edge_wrap] = true;
93 
94  (*d)[names::topology] = topology_dict;
95  }
96 
97  template <int D>
98  void Layer<D>::connect(AbstractLayer& target_layer, ConnectionCreator &connector)
99  {
100  try {
101  Layer<D> &tgt = dynamic_cast<Layer<D>&>(target_layer);
102  connector.connect(*this, tgt);
103  } catch (std::bad_cast e) {
104  throw BadProperty("Target layer must have same number of dimensions as source layer.");
105  }
106  }
107 
108  template <int D>
110  {
111  lockPTR<Ntree<D,index> > ntree(new Ntree<D,index>(this->lower_left_, this->extent_, this->periodic_));
112 
113  insert_local_positions_ntree_(*ntree, filter);
114 
115  return ntree;
116  }
117 
118  template <int D>
120  {
121  if ((cached_ntree_layer_ == get_gid()) and (cached_selector_ == filter)) {
122  assert(cached_ntree_.valid());
123  return cached_ntree_;
124  }
125 
126  clear_ntree_cache_();
127 
128  cached_ntree_ = lockPTR<Ntree<D,index> >(new Ntree<D,index>(this->lower_left_, this->extent_, this->periodic_));
129 
130  return do_get_global_positions_ntree_(filter);
131  }
132 
133  template <int D>
135  {
136  clear_ntree_cache_();
137  clear_vector_cache_();
138 
139  // Keep layer geometry for non-periodic dimensions
140  for(int i=0;i<D;++i) {
141  if (not periodic[i]) {
142  extent[i] = extent_[i];
143  lower_left[i] = lower_left_[i];
144  }
145  }
146 
147  cached_ntree_ = lockPTR<Ntree<D,index> >(new Ntree<D,index>(this->lower_left_, extent, periodic));
148 
149  do_get_global_positions_ntree_(filter);
150 
151  cached_ntree_layer_ = -1; // Do not use cache since the periodic bits and extents were altered.
152 
153  return cached_ntree_;
154  }
155 
156  template <int D>
158  {
159  if ((cached_vector_layer_ == get_gid()) and (cached_selector_ == filter)) {
160  // Convert from vector to Ntree
161 
162  typename std::insert_iterator<Ntree<D,index> > to = std::inserter(*cached_ntree_, cached_ntree_->end());
163 
164  for(typename std::vector<std::pair<Position<D>,index> >::iterator from=cached_vector_->begin();
165  from != cached_vector_->end(); ++from) {
166  *to = *from;
167  }
168 
169  } else {
170 
171  insert_global_positions_ntree_(*cached_ntree_, filter);
172 
173  }
174 
175  clear_vector_cache_();
176 
177  cached_ntree_layer_ = get_gid();
178  cached_selector_ = filter;
179 
180  return cached_ntree_;
181  }
182 
183  template <int D>
184  std::vector<std::pair<Position<D>,index> >* Layer<D>::get_global_positions_vector(Selector filter)
185  {
186  if ((cached_vector_layer_ == get_gid()) and (cached_selector_ == filter)) {
187  assert(cached_vector_);
188  return cached_vector_;
189  }
190 
191  clear_vector_cache_();
192 
193  cached_vector_ = new std::vector<std::pair<Position<D>,index> >;
194 
195  if ((cached_ntree_layer_ == get_gid()) and (cached_selector_ == filter)) {
196  // Convert from NTree to vector
197 
198  typename std::back_insert_iterator<std::vector<std::pair<Position<D>,index> > > to = std::back_inserter(*cached_vector_);
199 
200  for(typename Ntree<D,index>::iterator from=cached_ntree_->begin();
201  from != cached_ntree_->end(); ++from) {
202  *to = *from;
203  }
204 
205  } else {
206 
207  insert_global_positions_vector_(*cached_vector_, filter);
208 
209  }
210 
211  clear_ntree_cache_();
212 
213  cached_vector_layer_ = get_gid();
214  cached_selector_ = filter;
215 
216  return cached_vector_;
217  }
218 
219  template <int D>
220  std::vector<std::pair<Position<D>,index> > Layer<D>::get_global_positions_vector(Selector filter, const MaskDatum& mask, const Position<D>& anchor, bool allow_oversized)
221  {
222  MaskedLayer<D> masked_layer(*this,filter,mask,true,allow_oversized);
223  std::vector<std::pair<Position<D>,index> > positions;
224 
225  for(typename Ntree<D,index>::masked_iterator iter=masked_layer.begin(anchor);iter!=masked_layer.end();++iter) {
226  positions.push_back(*iter);
227  }
228 
229  return positions;
230  }
231 
232  template <int D>
233  std::vector<index> Layer<D>::get_global_nodes(const MaskDatum &mask, const std::vector<double_t> &anchor, bool allow_oversized)
234  {
235  MaskedLayer<D> masked_layer(*this,Selector(),mask,true,allow_oversized);
236  std::vector<index> nodes;
237  for(typename Ntree<D,index>::masked_iterator i=masked_layer.begin(anchor); i != masked_layer.end(); ++i) {
238  nodes.push_back(i->second);
239  }
240  return nodes;
241  }
242 
243  template <int D>
244  void Layer<D>::dump_nodes(std::ostream & out) const
245  {
246  for(index i=0;i<nodes_.size();++i) {
247  const index gid = nodes_[i]->get_gid();
248  out << gid << ' ';
249  get_position(i).print(out);
250  out << std::endl;
251  }
252  }
253 
254  template <int D>
255  void Layer<D>::dump_connections(std::ostream & out, const Token & syn_model)
256  {
257  std::vector<std::pair<Position<D>,index> >* src_vec = get_global_positions_vector();
258 
259  // Dictionary with parameters for get_connections()
260  DictionaryDatum gcdict(new Dictionary);
261  def(gcdict,names::synapse_model,syn_model);
262 
263  // Avoid setting up new array for each iteration of the loop
264  std::vector<index> source_array(1);
265 
266  for(typename std::vector<std::pair<Position<D>,index> >::iterator src_iter=src_vec->begin();
267  src_iter != src_vec->end(); ++src_iter) {
268 
269  const index source_gid = src_iter->second;
270  const Position<D> source_pos = src_iter->first;
271 
272  source_array[0] = source_gid;
273  def(gcdict,names::source,source_array);
274  ArrayDatum connectome = net_->get_connections(gcdict);
275 
276  // Print information about all local connections for current source
277  for( size_t i = 0; i < connectome.size(); ++i ) {
278  ConnectionDatum con_id= getValue<ConnectionDatum>(connectome.get(i));
279  DictionaryDatum result_dict = net_->get_synapse_status(
280  con_id.get_source_gid(),
281  con_id.get_synapse_model_id(),
282  con_id.get_port(),
283  con_id.get_target_thread());
284 
285  long_t target_gid = getValue<long_t>(result_dict, names::target);
286  double_t weight = getValue<double_t>(result_dict, names::weight);
287  double_t delay = getValue<double_t>(result_dict, names::delay);
288 
289  Node const * const target = net_->get_node(target_gid);
290  assert(target);
291 
292  // Print source, target, weight, delay, rports
293  out << source_gid << ' ' << target_gid << ' '
294  << weight << ' ' << delay;
295 
296  Layer<D>* tgt_layer = dynamic_cast<Layer<D>*>(target->get_parent());
297  if (tgt_layer==0) {
298 
299  // Happens if target does not belong to layer, eg spike_detector.
300  // We then print NaNs for the displacement.
301  for ( int n = 0 ; n < D ; ++n )
302  out << " NaN";
303 
304  } else {
305 
306  out << ' ';
307  tgt_layer->compute_displacement(source_pos, target->get_subnet_index()).print(out);
308 
309  }
310 
311  out << '\n';
312 
313  }
314  }
315  }
316 
317  template<int D>
318  void MaskedLayer<D>::check_mask_(Layer<D>& layer, bool allow_oversized)
319  {
320  if (not mask_.valid()) {
321  mask_ = new AllMask<D>();
322  }
323 
324  try // Try to cast to GridMask
325  {
326  const GridMask<D>& grid_mask = dynamic_cast<const GridMask<D>&>(*mask_);
327 
328  // If the above cast succeeds, then this is a grid mask
329 
330  GridLayer<D>* grid_layer = dynamic_cast<GridLayer<D>*>(&layer);
331  if (grid_layer==0) {
332  throw BadProperty("Grid masks can only be used with grid layers.");
333  }
334 
335  Position<D> ext = grid_layer->get_extent();
336  Position<D,index> dims = grid_layer->get_dims();
337 
338  if (not allow_oversized) {
339  bool oversize = false;
340  for(int i=0;i<D;++i)
341  oversize |= layer.get_periodic_mask()[i] and (grid_mask.get_lower_right()[i]-grid_mask.get_upper_left()[i])>(int)dims[i];
342 
343  if (oversize)
344  throw BadProperty("Mask size must not exceed layer size; set allow_oversized_mask to override.");
345  }
346 
347  Position<D> lower_left = ext/dims * grid_mask.get_upper_left() - ext/dims * 0.5;
348  Position<D> upper_right = ext/dims * grid_mask.get_lower_right() - ext/dims * 0.5;
349 
350  double_t y = lower_left[1];
351  lower_left[1] = -upper_right[1];
352  upper_right[1] = -y;
353 
354  mask_ = new BoxMask<D>(lower_left, upper_right);
355 
356  }
357  catch (std::bad_cast&)
358  {
359 
360  // Not a grid mask
361 
362  try // Try to cast to correct dimension Mask
363  {
364  const Mask<D>& mask = dynamic_cast<const Mask<D>&>(*mask_);
365 
366  if (not allow_oversized) {
367  const Box<D> bb = mask.get_bbox();
368  bool oversize = false;
369  for(int i=0;i<D;++i)
370  oversize |= layer.get_periodic_mask()[i] and (bb.upper_right[i]-bb.lower_left[i])>layer.get_extent()[i];
371 
372  if (oversize)
373  throw BadProperty("Mask size must not exceed layer size; set allow_oversized_mask to override.");
374  }
375  }
376  catch (std::bad_cast&)
377  {
378  throw BadProperty("Mask is incompatible with layer.");
379  }
380 
381  }
382  }
383 
384 } // namespace nest
385 
386 #endif
size_t index
Unsigned long type for enumerations.
Definition: nest.h:109
This class is a representation of the dictionary of connection properties given as an argument to the...
Definition: connection_creator.h:65
double_t weight
Weight of a connection.
Definition: nest.h:170
const Name edge_wrap("edge_wrap")
Definition: topology_names.h:49
const Name delay("delay")
Connection parameters.
Definition: nest_names.h:92
Ntree< D, index >::masked_iterator begin(const Position< D > &anchor)
Iterate over nodes inside mask.
Definition: layer.h:506
lockPTR< Ntree< D, index > > get_local_positions_ntree(Selector filter=Selector())
Get positions for local nodes in layer.
Definition: layer_impl.h:109
void set_status(const DictionaryDatum &)
Definition: subnet.cpp:57
const Name d("d")
Specific to Izhikevich 2003.
Definition: nest_names.h:83
Iterator iterating the nodes in a Quadtree inside a Mask.
Definition: ntree.h:128
Layer with neurons placed in a grid.
Definition: grid_layer.h:34
const Name layer("layer")
Definition: topology_names.h:82
Ntree< D, index >::masked_iterator end()
Definition: layer.h:517
void get_status(DictionaryDatum &) const
Definition: subnet.cpp:63
const Name weight("weight")
Connection parameters.
Definition: nest_names.h:344
void get_status(DictionaryDatum &) const
Export properties of the layer by setting entries in the status dictionary.
Definition: layer_impl.h:79
lockPTR< Ntree< D, index > > do_get_global_positions_ntree_(const Selector &filter)
Definition: layer_impl.h:157
const Name extent("extent")
Definition: topology_names.h:47
const Position< D > & get_extent() const
Definition: layer.h:235
const Name lower_left("lower_left")
Definition: topology_names.h:66
Contains rules for selecting nodes from a layer when connecting.
Definition: selector.h:36
Mask which covers all of space.
Definition: mask.h:141
Position< D, int_t > get_upper_left() const
Definition: grid_mask.h:76
void connect(Layer< D > &source, Layer< D > &target)
Connect two layers.
Definition: connection_creator_impl.h:38
const Name depth("depth")
Definition: topology_names.h:46
Class for applying masks to layers.
Definition: connection_creator.h:42
assert(pNet!=0)
Position< D, int_t > get_lower_right() const
Definition: grid_mask.h:79
Mask defining a box region.
Definition: mask.h:182
Abstract base class for masks with given dimension.
Definition: mask.h:90
A Ntree object represents a subtree or leaf in a Ntree structure.
Definition: ntree.h:49
A class that associates names and tokens.
Definition: dict.h:45
const Name anchor("anchor")
Definition: topology_names.h:50
void connect(AbstractLayer &target, ConnectionCreator &connector)
Connect this layer to the given target layer.
Definition: layer_impl.h:98
const Name y("y")
Definition: topology_names.h:52
const Name center("center")
Definition: topology_names.h:48
Abstract base class for Layer of given dimension (D=2 or 3).
Definition: connection_creator.h:39
bool getValue< bool >(const Token &t)
Definition: tokenutils.cc:124
Iterator iterating the nodes in a Quadtree.
Definition: ntree.h:64
const Name source("source")
Connection parameters.
Definition: nest_names.h:260
A box is defined by the lower left corner (minimum coordinates) and the upper right corner (maximum c...
Definition: position.h:289
const Name target("target")
Connection parameters.
Definition: nest_names.h:282
const Name positions("positions")
Definition: topology_names.h:53
Abstract base class for Layers of unspecified dimension.
Definition: layer.h:44
virtual 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:43
void def(DictionaryDatum &d, Name const n, FT const &value)
Define a new dictionary entry from a fundamental type.
Definition: dictutils.h:196
const Name topology("topology")
Definition: topology_names.h:54
Exception to be thrown if a status parameter is incomplete or inconsistent.
Definition: exceptions.h:420
Position< D > upper_right
Definition: position.h:297
size_t size(void) const
Return number of elements in the array.
Definition: tokenarray.h:142
Position< D, index > get_dims() const
Definition: grid_layer.h:155
const Token & get(long i) const
Definition: tokenarray.h:172
double double_t
Double precision floating point numbers.
Definition: nest.h:93
Mask defined in terms of grid points rather than spacial coordinates.
Definition: grid_mask.h:41
void dump_nodes(std::ostream &os) const
Write layer data to stream.
Definition: layer_impl.h:244
void dump_connections(std::ostream &out, const Token &syn_model)
Dumps information about all connections of the given type having their source in the given layer to t...
Definition: layer_impl.h:255
const Name n("n")
Number of synaptic release sites (int >=0) (Tsodyks2_connection)
Definition: nest_names.h:202
long_t delay
Delay of a connection.
Definition: nest.h:178
Definition: booldatum.h:35
Position< D > lower_left
Definition: position.h:296
const Name mask("mask")
Definition: topology_names.h:57
This template is the standard safe-pointer implementation of SYNOD.
Definition: lockptr.h:84
void set_status(const DictionaryDatum &)
Change properties of the layer according to the entries in the dictionary.
Definition: layer_impl.h:58
Base class for all NEST network objects.
Definition: node.h:96
virtual Box< D > get_bbox() const =0
The whole mask is inside (i.e., false everywhere outside) the bounding box.
std::bitset< D > get_periodic_mask() const
Definition: layer.h:247
A type-independent container for C++-types.
Definition: token.h:68
std::vector< std::pair< Position< D >, index > > * get_global_positions_vector(Selector filter=Selector())
Definition: layer_impl.h:184
lockPTR< Ntree< D, index > > get_global_positions_ntree(Selector filter=Selector())
Get positions for all nodes in layer, including nodes on other MPI processes.
Definition: layer_impl.h:119
const Name synapse_model("synapse_model")
Connection parameters.
Definition: nest_names.h:272
long long_t
Integer number with at least 32 bit.
Definition: nest.h:96
const Name upper_right("upper_right")
Definition: topology_names.h:67
const double e
Definition: numerics.cpp:62
void check_mask_(Layer< D > &layer, bool allow_oversized)
Will check that the mask can be applied to the layer.
Definition: layer_impl.h:318
std::vector< index > get_global_nodes(const MaskDatum &mask, const std::vector< double_t > &anchor, bool allow_oversized)
Return a vector with the GIDs of the nodes inside the mask.
Definition: layer_impl.h:233