void nest::spike_generator::Parameters_::set(const DictionaryDatum& d, State_& s, const Time& origin, const Time& now) { const bool flags_changed = updateValue<bool>(d, names::precise_times, precise_times_) || updateValue<bool>(d, "allow_offgrid_spikes", allow_offgrid_spikes_) || updateValue<bool>(d, "shift_now_spikes", shift_now_spikes_); if ( precise_times_ && ( allow_offgrid_spikes_ || shift_now_spikes_ ) ) throw BadProperty("Option precise_times cannot be set to true when either allow_offgrid_spikes " "or shift_now_spikes is set to true."); const bool updated_spike_times = d->known(names::spike_times); if ( flags_changed && !(updated_spike_times || spike_stamps_.empty()) ) throw BadProperty("Options can only be set together with spike times or if no " "spike times have been set."); if ( updated_spike_times ) { const std::vector<double_t> d_times = getValue<std::vector<double> >(d->lookup(names::spike_times)); const size_t n_spikes = d_times.size(); spike_stamps_.clear(); spike_stamps_.reserve(n_spikes); spike_offsets_.clear(); if ( precise_times_ ) spike_offsets_.reserve(n_spikes); // Check spike times for ordering and grid compatibility and insert them if ( !d_times.empty() ) { // handle first spike time, no predecessor to compare with std::vector<double_t>::const_iterator prev = d_times.begin(); assert_valid_spike_time_and_insert_(*prev, origin, now); // handle all remaining spike times, compare to predecessor for ( std::vector<double_t>::const_iterator next = prev + 1; next != d_times.end() ; ++next, ++prev ) if ( *prev > *next ) throw BadProperty("Spike times must be sorted in non-descending order."); else assert_valid_spike_time_and_insert_(*next, origin, now); } } // spike_weights can be the same size as spike_times, or can be of size 0 to // only use the spike_times array bool updated_spike_weights = d->known("spike_weights"); if (updated_spike_weights) { std::vector<double> spike_weights = getValue<std::vector<double> >(d->lookup("spike_weights")); if (spike_weights.empty()) spike_weights_.clear(); else { if (spike_weights.size() != spike_stamps_.size()) throw BadProperty("spike_weights must have the same number of elements as spike_times," " or 0 elements to clear the property."); spike_weights_.swap(spike_weights); } } // Set position to start if something changed if ( updated_spike_times || updated_spike_weights || d->known(names::origin) ) s.position_ = 0; }
void nest::RNGManager::set_status( const DictionaryDatum& d ) { // have those two for later asking, whether threads have changed: long n_threads; bool n_threads_updated = updateValue< long >( d, "local_num_threads", n_threads ); // set RNGs --- MUST come after n_threads_ is updated if ( d->known( "rngs" ) ) { // this array contains pre-seeded RNGs, so they can be used // directly, no seeding required ArrayDatum* ad = dynamic_cast< ArrayDatum* >( ( *d )[ "rngs" ].datum() ); if ( ad == 0 ) throw BadProperty(); // n_threads_ is the new value after a change of the number of // threads if ( ad->size() != ( size_t )( kernel().vp_manager.get_num_virtual_processes() ) ) { LOG( M_ERROR, "RNGManager::set_status", "Number of RNGs must equal number of virtual processes " "(threads*processes). RNGs " "unchanged." ); throw DimensionMismatch( ( size_t )( kernel().vp_manager.get_num_virtual_processes() ), ad->size() ); } // delete old generators, insert new generators this code is // robust under change of thread number in this call to // set_status, as long as it comes AFTER n_threads_ has been // upated rng_.clear(); for ( index i = 0; i < ad->size(); ++i ) if ( kernel().vp_manager.is_local_vp( i ) ) rng_.push_back( getValue< librandom::RngDatum >( ( *ad )[ kernel().vp_manager.suggest_vp( i ) ] ) ); } else if ( n_threads_updated && kernel().node_manager.size() == 0 ) { LOG( M_WARNING, "RNGManager::set_status", "Equipping threads with new default RNGs" ); create_rngs_(); } if ( d->known( "rng_seeds" ) ) { ArrayDatum* ad = dynamic_cast< ArrayDatum* >( ( *d )[ "rng_seeds" ].datum() ); if ( ad == 0 ) throw BadProperty(); if ( ad->size() != ( size_t )( kernel().vp_manager.get_num_virtual_processes() ) ) { LOG( M_ERROR, "RNGManager::set_status", "Number of seeds must equal number of virtual processes " "(threads*processes). RNGs unchanged." ); throw DimensionMismatch( ( size_t )( kernel().vp_manager.get_num_virtual_processes() ), ad->size() ); } // check if seeds are unique std::set< ulong_t > seedset; for ( index i = 0; i < ad->size(); ++i ) { long s = ( *ad )[ i ]; // SLI has no ulong tokens if ( !seedset.insert( s ).second ) { LOG( M_WARNING, "RNGManager::set_status", "Seeds are not unique across threads!" ); break; } } // now apply seeds, resets generators automatically for ( index i = 0; i < ad->size(); ++i ) { long s = ( *ad )[ i ]; if ( kernel().vp_manager.is_local_vp( i ) ) rng_[ kernel().vp_manager.vp_to_thread( kernel().vp_manager.suggest_vp( i ) ) ]->seed( s ); rng_seeds_[ i ] = s; } } // if rng_seeds // set GRNG if ( d->known( "grng" ) ) { // pre-seeded grng that can be used directly, no seeding required updateValue< librandom::RngDatum >( d, "grng", grng_ ); } else if ( n_threads_updated && kernel().node_manager.size() == 0 ) { LOG( M_WARNING, "RNGManager::set_status", "Equipping threads with new default GRNG" ); create_grng_(); } if ( d->known( "grng_seed" ) ) { const long gseed = getValue< long >( d, "grng_seed" ); // check if grng seed is unique with respect to rng seeds // if grng_seed and rng_seeds given in one SetStatus call std::set< ulong_t > seedset; seedset.insert( gseed ); if ( d->known( "rng_seeds" ) ) { ArrayDatum* ad_rngseeds = dynamic_cast< ArrayDatum* >( ( *d )[ "rng_seeds" ].datum() ); if ( ad_rngseeds == 0 ) throw BadProperty(); for ( index i = 0; i < ad_rngseeds->size(); ++i ) { const long vpseed = ( *ad_rngseeds )[ i ]; // SLI has no ulong tokens if ( !seedset.insert( vpseed ).second ) { LOG( M_WARNING, "RNGManager::set_status", "Seeds are not unique across threads!" ); break; } } } // now apply seed, resets generator automatically grng_seed_ = gseed; grng_->seed( gseed ); } // if grng_seed }
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 > anchor = getValue< std::vector< double > >( 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 dim = 2; int column = getValue< long >( ad, names::column ); int row = getValue< long >( ad, names::row ); int 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 >( 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 >( column, row, layer ) ); } catch ( std::bad_cast e ) { throw BadProperty( "Mask must be 3-dimensional grid mask." ); } break; } } } return mask; } }
void nest::Archiving_Node::set_status( const DictionaryDatum& d ) { // We need to preserve values in case invalid values are set double_t new_tau_minus = tau_minus_; double_t new_tau_minus_triplet = tau_minus_triplet_; double_t new_tau_Ca = tau_Ca_; double_t new_beta_Ca = beta_Ca_; updateValue< double_t >( d, names::tau_minus, new_tau_minus ); updateValue< double_t >( d, names::tau_minus_triplet, new_tau_minus_triplet ); updateValue< double_t >( d, names::tau_Ca, new_tau_Ca ); updateValue< double_t >( d, names::beta_Ca, new_beta_Ca ); if ( new_tau_minus <= 0.0 || new_tau_minus_triplet <= 0.0 ) { throw BadProperty( "All time constants must be strictly positive." ); } tau_minus_ = new_tau_minus; tau_minus_triplet_ = new_tau_minus_triplet; if ( new_tau_Ca <= 0.0 ) { throw BadProperty( "All time constants must be strictly positive." ); } tau_Ca_ = new_tau_Ca; if ( new_beta_Ca <= 0.0 ) { throw BadProperty( "For Ca to function as an integrator of the electrical activity, beta_ca needs to be greater " "than 0." ); } beta_Ca_ = new_beta_Ca; // check, if to clear spike history and K_minus bool clear = false; updateValue< bool >( d, names::clear, clear ); if ( clear ) { clear_history(); } if ( not d->known( names::synaptic_elements ) ) { return; } // we replace the existing synaptic_elements_map_ by the new one DictionaryDatum synaptic_elements_d; std::pair< std::map< Name, SynapticElement >::iterator, bool > insert_result; synaptic_elements_map_ = std::map< Name, SynapticElement >(); synaptic_elements_d = getValue< DictionaryDatum >( d, "synaptic_elements" ); for ( Dictionary::const_iterator i = synaptic_elements_d->begin(); i != synaptic_elements_d->end(); ++i ) { insert_result = synaptic_elements_map_.insert( std::pair< Name, SynapticElement >( i->first, SynapticElement() ) ); ( insert_result.first->second ) .set( getValue< DictionaryDatum >( synaptic_elements_d, i->first ) ); } }
void cg_connect( ConnectionGeneratorDatum& cg, RangeSet& sources, std::vector< long >& source_gids, RangeSet& targets, std::vector< long >& target_gids, DictionaryDatum params_map, index syn ) { cg_set_masks( cg, sources, targets ); cg->start(); int source, target, num_parameters = cg->arity(); if ( num_parameters == 0 ) { // connect source to target while ( cg->next( source, target, NULL ) ) { if ( ConnectionGeneratorModule::get_network().is_local_gid( target_gids.at( target ) ) ) { Node* const target_node = ConnectionGeneratorModule::get_network().get_node( target_gids.at( target ) ); const thread target_thread = target_node->get_thread(); ConnectionGeneratorModule::get_network().connect( source_gids.at( source ), target_node, target_thread, syn ); } } } else if ( num_parameters == 2 ) { if ( !params_map->known( names::weight ) || !params_map->known( names::delay ) ) throw BadProperty( "The parameter map has to contain the indices of weight and delay." ); long w_idx = ( *params_map )[ names::weight ]; long d_idx = ( *params_map )[ names::delay ]; std::vector< double > params( 2 ); // connect source to target with weight and delay while ( cg->next( source, target, ¶ms[ 0 ] ) ) { if ( ConnectionGeneratorModule::get_network().is_local_gid( target_gids.at( target ) ) ) { Node* const target_node = ConnectionGeneratorModule::get_network().get_node( target_gids.at( target ) ); const thread target_thread = target_node->get_thread(); ConnectionGeneratorModule::get_network().connect( source_gids.at( source ), target_node, target_thread, syn, params[ d_idx ], params[ w_idx ] ); } } } else { ConnectionGeneratorModule::get_network().message( SLIInterpreter::M_ERROR, "Connect", "Either two or no parameters in the Connection Set expected." ); throw DimensionMismatch(); } }
index AbstractLayer::create_layer(const DictionaryDatum & layer_dict) { index length = 0; const char *layer_model_name = 0; std::vector<long_t> element_ids; std::string element_name; Token element_model; const Token& t = layer_dict->lookup(names::elements); ArrayDatum* ad = dynamic_cast<ArrayDatum *>(t.datum()); if (ad) { for (Token* tp = ad->begin(); tp != ad->end(); ++tp) { element_name = std::string(*tp); element_model = net_->get_modeldict().lookup(element_name); if ( element_model.empty() ) throw UnknownModelName(element_name); // Creates several nodes if the next element in // the elements variable is a number. if ((tp+1 != ad->end()) && dynamic_cast<IntegerDatum*>((tp+1)->datum())) { // Select how many nodes that should be created. const long_t number = getValue<long_t>(*(++tp)); for(long_t i=0;i<number;++i) element_ids.push_back(static_cast<long>(element_model)); } else { element_ids.push_back(static_cast<long>(element_model)); } } } else { element_name = getValue<std::string>(layer_dict, names::elements); element_model = net_->get_modeldict().lookup(element_name); if ( element_model.empty() ) throw UnknownModelName(element_name); element_ids.push_back(static_cast<long>(element_model)); } if (layer_dict->known(names::positions)) { if (layer_dict->known(names::rows) or layer_dict->known(names::columns) or layer_dict->known(names::layers)) throw BadProperty("Can not specify both positions and rows or columns."); TokenArray positions = getValue<TokenArray>(layer_dict, names::positions); if (positions.size() == 0) { throw BadProperty("Empty positions array."); } std::vector<double_t> pos = getValue<std::vector<double_t> >(positions[0]); if (pos.size() == 2) layer_model_name = "topology_layer_free"; else if (pos.size() == 3) layer_model_name = "topology_layer_free_3d"; else throw BadProperty("Positions must have 2 or 3 coordinates."); length = positions.size(); } else if (layer_dict->known(names::columns)) { if (not layer_dict->known(names::rows)) { throw BadProperty("Both columns and rows must be given."); } length=getValue<long_t>(layer_dict, names::columns) * getValue<long_t>(layer_dict, names::rows); if (layer_dict->known(names::layers)) { layer_model_name = "topology_layer_grid_3d"; length *= getValue<long_t>(layer_dict, names::layers); } else { layer_model_name = "topology_layer_grid"; } } else { throw BadProperty("Unknown layer type."); } assert(layer_model_name != 0); Token layer_model = net_->get_modeldict().lookup(layer_model_name); if ( layer_model.empty() ) throw UnknownModelName(layer_model_name); index layer_node = net_->add_node(layer_model); // Remember original subnet const index cwnode = net_->get_cwn()->get_gid(); net_->go_to(layer_node); // Create layer nodes. for ( size_t i = 0 ; i < element_ids.size() ; ++i ) { for ( index n = 0 ; n < length ; ++n ) { net_->add_node(element_ids[i]); } } // Return to original subnet net_->go_to(cwnode); //Set layer parameters according to input dictionary. AbstractLayer *layer = dynamic_cast<AbstractLayer *>(net_->get_node(layer_node)); layer->depth_ = element_ids.size(); layer->set_status(layer_dict); return layer_node; }