/*
* pulsepacket_generator.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 PULSEPACKET_GENERATOR_H
#define PULSEPACKET_GENERATOR_H
#include <vector>
#include <deque>
#include "nest.h"
#include "event.h"
#include "node.h"
#include "stimulating_device.h"
#include "connection.h"
#include "normal_randomdev.h"
namespace nest
{
//! class pulsepacket_generator
/*! Class pulsepacket_generator produces a spike train with
a gaussian distribution of spike times.
*/
/*BeginDocumentation
Name: pulsepacket_generator - Generate sequence of Gaussian pulse packets.
Description:
The pulsepacket_generator produces a spike train contains Gaussian pulse
packets centered about given times. A Gaussian pulse packet is
a given number of spikes with normal distributed random displacements
from the center time of the pulse.
It resembles the output of synfire groups of neurons.
Parameters:
pulse_times double - Times of the centers of pulses in ms
activity int - Number of spikes per pulse
sdev double - Standard deviation of spike times in each pulse in ms
Remarks:
- All targets receive identical spike trains.
- New pulse packets are generated when activity or sdev are changed.
- Gaussian pulse are independently generated for each given
pulse-center time.
- Both standard deviation and number of spikes may be set at any time.
Pulses are then re-generated with the new values.
Sends: SpikeEvent
SeeAlso: spike_generator, StimulatingDevice
*/
class pulsepacket_generator : public Node
{
public:
pulsepacket_generator();
pulsepacket_generator(pulsepacket_generator const&);
// behaves like normal node, since it must provide identical
// output to all targets
bool has_proxies() const {return true;}
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();
void create_pulse();
void update(Time const &, const long_t, const long_t);
struct Buffers_;
// ------------------------------------------------------------
struct Parameters_ {
std::vector<double_t> pulse_times_; //!< times of pulses
long_t a_; //!< number of pulses in a packet
double_t sdev_; //!< standard deviation of the packet
double_t sdev_tolerance_;
Parameters_(); //!< Sets default parameter values
void get(DictionaryDatum&) const; //!< Store current values in dictionary
/**
* Set values from dicitonary.
* @note Buffer is passed so that the position etc can be reset
* parameters have been changed.
*/
void set(const DictionaryDatum&, pulsepacket_generator&);
};
// ------------------------------------------------------------
struct Buffers_ {
std::deque<long_t> spiketimes_;
};
// ------------------------------------------------------------
struct Variables_ {
librandom::NormalRandomDev norm_dev_; //!< random deviate generator
/** Indices into sorted vector of sorted pulse-center times (P_.pulse_times_).
* Spike times to be sent are calculated from pulse-center times
* between 'start' and 'stop'. Times before 'start' are outdated,
* times after 'stop' are not touched yet.
*
* Must be index, not iterator, since we copy pulse times
* out of temporary parameter set.
*/
size_t start_center_idx_;
size_t stop_center_idx_;
double_t tolerance;
Variables_();
};
// ------------------------------------------------------------
StimulatingDevice<SpikeEvent> device_;
Parameters_ P_;
Buffers_ B_;
Variables_ V_;
};
inline
port pulsepacket_generator::check_connection(Connection& c, port receptor_type)
{
SpikeEvent e;
e.set_sender(*this);
c.check_event(e);
return c.get_target()->connect_sender(e, receptor_type);
}
inline
void pulsepacket_generator::get_status(DictionaryDatum &d) const
{
P_.get(d);
device_.get_status(d);
}
inline
void pulsepacket_generator::set_status(const DictionaryDatum &d)
{
Parameters_ ptmp = P_; // temporary copy in case of errors
ptmp.set(d, *this); // 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 nest
#endif