Esempio n. 1
0
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 ) );
  }
}
Esempio n. 5
0
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, &params[ 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();
  }
}
Esempio n. 6
0
  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;
  }