1 /*
2  *  spin_detector.h
3  *
4  *  This file is part of NEST.
5  *
6  *  Copyright (C) 2004 The NEST Initiative
7  *
8  *  NEST is free software: you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation, either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  NEST is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with NEST.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #ifndef SPIN_DETECTOR_H
24 #define SPIN_DETECTOR_H
25 
26 
27 // C++ includes:
28 #include <vector>
29 
30 // Includes from nestkernel:
31 #include "device_node.h"
32 #include "event.h"
33 #include "exceptions.h"
34 #include "nest_types.h"
35 #include "recording_device.h"
36 #include "nest_timeconverter.h"
37 
38 namespace nest
39 {
40 
41 /* BeginUserDocs: device, detector
42 
43 Short description
44 +++++++++++++++++
45 
46 Device for detecting binary states in neurons
47 
48 Description
49 +++++++++++
50 
51 The spin_detector is a recording device. It is used to decode and
52 record binary states from spiking activity from a single neuron, or
53 from multiple neurons at once. A single spike signals the 0 state, two
54 spikes at the same time signal the 1 state. If a neuron is in the 0 or
55 1 state and emits the spiking activity corresponding to the same
56 state, the same state is recorded again.  Therefore, it is not only
57 the transitions that are recorded. Data is recorded in memory or to
58 file as for all RecordingDevices. By default, node ID, time, and binary
59 state (0 or 1) for each decoded state is recorded. The state can be
60 accessed from ['events']['weight'].
61 
62 The spin_detector will record binary state times with full
63 precision from neurons emitting precisely timed spikes.
64 
65 Any node from which binary states are to be recorded, must be
66 connected to the spin_detector using the Connect command. Any
67 connection weight and delay will be ignored for that connection.
68 
69 Simulations progress in cycles defined by the minimum delay. During
70 each cycle, the spin_detector records (stores in memory or writes to
71 screen/file) the states during the previous cycle. As a consequence,
72 any state information that was decoded during the cycle immediately
73 preceding the end of the simulation time will not be recorded. Setting
74 the /stop parameter to at the latest one min_delay period before the
75 end of the simulation time ensures that all binary states desired to
76 be recorded, are recorded.
77 
78 states are not necessarily written to file in chronological order.
79 
80 Receives
81 ++++++++
82 
83 SpikeEvent
84 
85 EndUserDocs */
86 
87 /**
88  * Spin detector class.
89  *
90  * This class decodes binary states based on incoming spikes. It receives
91  * spikes via its handle(SpikeEvent&) method, decodes the state, and
92  * stores them via its RecordingDevice.
93  *
94  */
95 class spin_detector : public RecordingDevice
96 {
97 
98 public:
99   spin_detector();
100   spin_detector( const spin_detector& );
101 
102   bool
has_proxies()103   has_proxies() const
104   {
105     return false;
106   }
107   bool
local_receiver()108   local_receiver() const
109   {
110     return true;
111   }
112 
113   Name
get_element_type()114   get_element_type() const
115   {
116     return names::recorder;
117   }
118 
119   /**
120    * Import sets of overloaded virtual functions.
121    * @see Technical Issues / Virtual Functions: Overriding, Overloading, and
122    * Hiding
123    */
124   using Node::handle;
125   using Node::handles_test_event;
126   using Node::receives_signal;
127 
128   void handle( SpikeEvent& );
129 
130   port handles_test_event( SpikeEvent&, rport );
131 
132   Type get_type() const;
133   SignalType receives_signal() const;
134 
135   void get_status( DictionaryDatum& ) const;
136   void set_status( const DictionaryDatum& );
137 
138   void calibrate_time( const TimeConverter& tc );
139 
140 private:
141   void init_buffers_();
142   void calibrate();
143 
144   /**
145    * Update detector by recording spikes.
146    *
147    * All spikes in the read_toggle() half of the spike buffer are
148    * used to detect binary states.
149    *
150    * @see RecordingDevice
151    */
152   void update( Time const&, const long, const long );
153 
154   index last_in_node_id_;
155   SpikeEvent last_event_;
156   Time t_last_in_spike_;
157 };
158 
159 inline port
handles_test_event(SpikeEvent &,rport receptor_type)160 spin_detector::handles_test_event( SpikeEvent&, rport receptor_type )
161 {
162   if ( receptor_type != 0 )
163   {
164     throw UnknownReceptorType( receptor_type, get_name() );
165   }
166   return 0;
167 }
168 
169 inline SignalType
receives_signal()170 spin_detector::receives_signal() const
171 {
172   return BINARY;
173 }
174 
175 inline void
calibrate_time(const TimeConverter & tc)176 nest::spin_detector::calibrate_time( const TimeConverter& tc )
177 {
178   t_last_in_spike_ = tc.from_old_tics( t_last_in_spike_.get_tics() );
179 }
180 
181 } // namespace
182 
183 #endif /* #ifndef SPIN_DETECTOR_H */
184