void nest::mip_generator::event_hook( DSSpikeEvent& e ) { // note: event_hook() receives a reference of the spike event that // was originally created in the update function. there we set // the multiplicty to store the number of mother spikes. the *same* // reference will be delivered multiple times to the event hook, // once for every receiver. when calling handle() of the receiver // above, we need to change the multiplicty to the number of copied // child process spikes, so afterwards it needs to be reset to correctly // store the number of mother spikes again during the next call of event_hook(). // reichert librandom::RngPtr rng = net_->get_rng( get_thread() ); ulong_t n_mother_spikes = e.get_multiplicity(); ulong_t n_spikes = 0; for ( ulong_t n = 0; n < n_mother_spikes; n++ ) { if ( rng->drand() < P_.p_copy_ ) n_spikes++; } if ( n_spikes > 0 ) { e.set_multiplicity( n_spikes ); e.get_receiver().handle( e ); } e.set_multiplicity( n_mother_spikes ); }
void nest::poisson_generator::event_hook( DSSpikeEvent& e ) { librandom::RngPtr rng = kernel().rng_manager.get_rng( get_thread() ); long n_spikes = V_.poisson_dev_.ldev( rng ); if ( n_spikes > 0 ) // we must not send events with multiplicity 0 { e.set_multiplicity( n_spikes ); e.get_receiver().handle( e ); } }
void nest::sinusoidal_gamma_generator::event_hook( DSSpikeEvent& e ) { // get port number --- see #737 const port tgt_idx = e.get_port(); assert( 0 <= tgt_idx && static_cast< size_t >( tgt_idx ) < B_.t0_ms_.size() ); if ( V_.rng_->drand() < hazard_( tgt_idx ) ) { e.get_receiver().handle( e ); B_.t0_ms_[ tgt_idx ] = V_.t_ms_; B_.Lambda_t0_[ tgt_idx ] = 0; } }
void nest::ppd_sup_generator::event_hook( DSSpikeEvent& e ) { // get port number const port prt = e.get_port(); // we handle only one port here, get reference to vector element assert( 0 <= prt && static_cast< size_t >( prt ) < B_.age_distributions_.size() ); // age_distribution object propagates one time step and returns number of spikes ulong_t n_spikes = B_.age_distributions_[ prt ].update( V_.hazard_step_t_, net_->get_rng( get_thread() ) ); if ( n_spikes > 0 ) // we must not send events with multiplicity 0 { e.set_multiplicity( n_spikes ); e.get_receiver().handle( e ); } }
void nest::mip_generator::update(Time const & T, const long_t from, const long_t to) { assert(to >= 0 && (delay) from < Scheduler::get_min_delay()); assert(from < to); for ( long_t lag = from ; lag < to ; ++lag ) { if ( !device_.is_active(T) || P_.rate_ <= 0 ) return; // no spikes to be generated // generate spikes of mother process for each time slice ulong_t n_mother_spikes = V_.poisson_dev_.uldev(P_.rng_); if ( n_mother_spikes ) { DSSpikeEvent se; se.set_multiplicity(n_mother_spikes); network()->send(*this, se, lag); } } }
void nest::spike_dilutor::update( Time const& T, const long_t from, const long_t to ) { assert( to >= 0 && ( delay ) from < Scheduler::get_min_delay() ); assert( from < to ); for ( long_t lag = from; lag < to; ++lag ) { if ( !device_.is_active( T ) ) return; // no spikes to be repeated // generate spikes of mother process for each time slice ulong_t n_mother_spikes = static_cast< ulong_t >( B_.n_spikes_.get_value( lag ) ); if ( n_mother_spikes ) { DSSpikeEvent se; se.set_multiplicity( n_mother_spikes ); network()->send( *this, se, lag ); } } }
void Node::event_hook( DSSpikeEvent& e ) { e.get_receiver().handle( e ); }
void nest::spike_generator::event_hook(DSSpikeEvent& e) { e.set_weight(P_.spike_weights_[S_.position_] * e.get_weight()); e.get_receiver().handle(e); }
void nest::poisson_generator_ps::event_hook( DSSpikeEvent& e ) { // get port number const port prt = e.get_port(); // we handle only one port here, get reference to vector elem assert( 0 <= prt && static_cast< size_t >( prt ) < B_.next_spike_.size() ); // obtain rng librandom::RngPtr rng = net_->get_rng( get_thread() ); // introduce nextspk as a shorthand Buffers_::SpikeTime& nextspk = B_.next_spike_[ prt ]; if ( nextspk.first.is_neg_inf() ) { // need to initialize relative to t_min_active_ // first spike is drawn from backward recurrence time to initialize the process in equilibrium. // In the case of the Poisson process with dead time, this has two domains: // one with uniform probability (t<dead_time) and one // with exponential probability (t>=dead_time). // First we draw a uniform number to choose the case according to the associated probability // mass. // If dead_time==0 we do not want to draw addtional random numbers (keeps old functionality). double spike_offset = 0; if ( P_.dead_time_ > 0 and rng->drand() < P_.dead_time_ * P_.rate_ / 1000.0 ) { // uniform case: spike occurs with uniform probability in [0, dead_time]. spike_offset = rng->drand() * P_.dead_time_; } else { // exponential case: spike occurs with exponential probability in [dead_time, infinity] spike_offset = V_.inv_rate_ms_ * V_.exp_dev_( rng ) + P_.dead_time_; } // spike_offset is now time from t_min_active_ til first spike. // Split into stamp+offset, then add t_min_active. nextspk.first = Time::ms_stamp( spike_offset ); nextspk.second = nextspk.first.get_ms() - spike_offset; nextspk.first += V_.t_min_active_; } // as long as there are spikes in active period, emit and redraw while ( nextspk.first <= V_.t_max_active_ ) { // std::cerr << nextspk.first << '\t' << nextspk.second << '\n'; e.set_stamp( nextspk.first ); e.set_offset( nextspk.second ); e.get_receiver().handle( e ); // Draw time of next spike // Time of spike relative to current nextspk.first stamp const double new_offset = -nextspk.second + V_.inv_rate_ms_ * V_.exp_dev_( rng ) + P_.dead_time_; if ( new_offset < 0 ) // still in same stamp nextspk.second = -new_offset; // stamps always 0 < stamp <= h else { // split into stamp and offset, then add to old stamp const Time delta_stamp = Time::ms_stamp( new_offset ); nextspk.first += delta_stamp; nextspk.second = delta_stamp.get_ms() - new_offset; } } // std::cerr << "********************************\n"; }