/*
* poisson_generator_ps.h
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEST. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef POISSON_GENERATOR_PS_H
#define POISSON_GENERATOR_PS_H
#include <vector>
#include "nest.h"
#include "event.h"
#include "node.h"
#include "stimulating_device.h"
#include "scheduler.h"
#include "exp_randomdev.h"
#include "connection.h"
/*BeginDocumentation
Name: poisson_generator_ps - simulate neuron firing with Poisson processes
(with arbitrary dead time) statistics and exact timing
Description:
The poisson_generator_ps generator simulates a neuron firing with Poisson
statistics (with dead time), ie, exponentially distributed interspike
intervals plus constant dead time, spike events have exact timing
(i.e. not binned).
Parameters:
The following parameters appear in the element's status dictionary:
rate - mean firing rate. (double, var)
dead_time - minimal time between two spikes. (double, var)
Note:
- This generator must be connected to all its targets using the
same synapse model. Failure to do so will only be detected at
runtime.
- This generator has only been validated in a very basic manner.
Sends: SpikeEvent
SeeAlso: poisson_generator, spike_generator, Device, StimulatingDevice
*/
namespace nest{
/**
* Poisson generator (with dead time) with precisely timed spikes.
*
* This Poisson process (with dead time) generator sends different spike
* trains to all its targets.
* All spikes are sent individually with offsets identifying their precise
* times.
*
* @ingroup Devices
*/
class poisson_generator_ps: public Node
{
public:
typedef Node base;
poisson_generator_ps();
poisson_generator_ps(const poisson_generator_ps&);
bool has_proxies() const {return false;}
bool is_off_grid() const {return true;} // uses off_grid events
using Node::event_hook;
port check_connection(Connection&, port);
void get_status(DictionaryDatum &) const;
void set_status(const DictionaryDatum &);
private:
void init_state_(const Node&);
void init_buffers_();
void calibrate();
/**
* Update state.
* Update cannot send spikes directly, since we need to identify each
* target to know the time of the most recent spike sent. Since target
* information is in the Connectors, we send a DSSpikeEvent to all
* targets, which is reflected to this->event_hook() with target
* information.
* @see event_hook, DSSpikeEvent
*/
void update(Time const &, const long_t, const long_t);
/**
* Send out spikes.
* Called once per target to dispatch actual output spikes.
* @param contains target information.
*/
void event_hook(DSSpikeEvent&);
// ------------------------------------------------------------
/**
* Store independent parameters of the model.
*/
struct Parameters_ {
double_t rate_; //!< process rate [Hz]
double_t dead_time_; //!< dead time [ms]
/**
* Number of targets.
* This is a hidden parameter; must be placed in parameters,
* even though it is an implementation detail, since it
* concerns the connections and must not be affected by resets.
*/
size_t num_targets_;
Parameters_(); //!< Sets default parameter values
void get(DictionaryDatum&) const; //!< Store current values in dictionary
void set(const DictionaryDatum&); //!< Set values from dicitonary
};
// ------------------------------------------------------------
struct Buffers_ {
typedef std::pair<Time, double_t> SpikeTime;
/**
* Time of next spike represented as time stamp and offset, for each target.
* - first: time stamp
* - second: offset (<=0)
* @note first == Time::neg_inf() marks that no spike has been generated yet
* and that an initial interval needs to be drawn.
*/
std::vector<SpikeTime> next_spike_;
//! Map port to target GID
typedef std::map<port,index> PortGIDMap;
/**
* Map sender port to target GID.
* This is a kludge to solve #482, i.e., to protect against several senders
* using the same port.
* Entries are added when a DSSpikeEvent is received through a new port.
* For subsequent DSSpikeEvents through the same port, they must be
* for the same target.
* @see assert_unique_port
*/
PortGIDMap port_targets_;
};
// ------------------------------------------------------------
struct Variables_ {
double_t inv_rate_ms_; //!< 1000.0 / Parameters_.rate_
librandom::ExpRandomDev exp_dev_; //!< random deviate generator
/**
* @name update-hook communication.
* The following variables are used for direct communication from
* update() to event_hook(). They rely on the fact that event_hook()
* is called instantaneuously from update().
* Spikes are sent at times t that fulfill
*
* t_min_active_ < t <= t_max_active_
*/
//@{
Time t_min_active_; //!< start of generator activity in slice
Time t_max_active_; //!< end of generator activity in slice
//@}
};
// ------------------------------------------------------------
StimulatingDevice<CurrentEvent> device_;
Parameters_ P_;
Variables_ V_;
Buffers_ B_;
};
inline
port poisson_generator_ps::check_connection(Connection& c, port receptor_type)
{
DSSpikeEvent e;
e.set_sender(*this);
c.check_event(e);
port receptor = c.get_target()->connect_sender(e, receptor_type);
++P_.num_targets_; // count number of targets
return receptor;
}
inline
void poisson_generator_ps::get_status(DictionaryDatum &d) const
{
P_.get(d);
device_.get_status(d);
}
inline
void poisson_generator_ps::set_status(const DictionaryDatum &d)
{
Parameters_ ptmp = P_; // temporary copy in case of errors
ptmp.set(d); // throws if BadProperty
// We now know that ptmp is consistent. We do not write it back
// to P_ before we are also sure that the properties to be set
// in the parent class are internally consistent.
device_.set_status(d);
// if we get here, temporaries contain consistent set of properties
P_ = ptmp;
}
} // namespace
#endif //POISSON_GENERATOR_PS_H