CARLsim  5.0.0
CARLsim: a GPU-accelerated SNN simulator
neuron_monitor_core.cpp
Go to the documentation of this file.
1 /* * Copyright (c) 2016 Regents of the University of California. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * 3. The names of its contributors may not be used to endorse or promote
15 * products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * *********************************************************************************************** *
31 * CARLsim
32 * created by: (MDR) Micah Richert, (JN) Jayram M. Nageswaran
33 * maintained by:
34 * (MA) Mike Avery <averym@uci.edu>
35 * (MB) Michael Beyeler <mbeyeler@uci.edu>,
36 * (KDC) Kristofor Carlson <kdcarlso@uci.edu>
37 * (TSC) Ting-Shuo Chou <tingshuc@uci.edu>
38 * (HK) Hirak J Kashyap <kashyaph@uci.edu>
39 *
40 * CARLsim v1.0: JM, MDR
41 * CARLsim v2.0/v2.1/v2.2: JM, MDR, MA, MB, KDC
42 * CARLsim3: MB, KDC, TSC
43 * CARLsim4: TSC, HK
44 * CARLsim5: HK, JX, KC
45 *
46 * CARLsim available from http://socsci.uci.edu/~jkrichma/CARLsim/
47 * Ver 05/24/2017
48 */
49 
50 #include <neuron_monitor_core.h>
51 
52 #include <snn.h> // CARLsim private implementation
53 #include <snn_definitions.h> // KERNEL_ERROR, KERNEL_INFO, ...
54 
55 #include <algorithm> // std::sort
56 
57 NeuronMonitorCore::NeuronMonitorCore(SNN* snn, int monitorId, int grpId) {
58  snn_ = snn;
59  grpId_= grpId;
60  monitorId_ = monitorId;
61  nNeurons_ = -1;
62  neuronFileId_ = NULL;
63  recordSet_ = false;
64  neuronMonLastUpdated_ = 0;
65 
66  persistentData_ = false;
67  userHasBeenWarned_ = false;
68  needToWriteFileHeader_ = true;
69  neuronFileSignature_ = 206661979;
70  neuronFileVersion_ = 0.1f;
71 
72  // defer all unsafe operations to init function
73  init();
74 }
75 
76 void NeuronMonitorCore::init() {
77  nNeurons_ = snn_->getGroupNumNeurons(grpId_);
78  assert(nNeurons_>0);
79 
80  // so the first dimension is neuron ID
81  vectorV_.resize(nNeurons_);
82  vectorU_.resize(nNeurons_);
83  vectorI_.resize(nNeurons_);
84 
85  clear();
86 
87  // use KERNEL_{ERROR|WARNING|etc} typesetting (const FILE*)
88  fpInf_ = snn_->getLogFpInf();
89  fpErr_ = snn_->getLogFpErr();
90  fpDeb_ = snn_->getLogFpDeb();
91  fpLog_ = snn_->getLogFpLog();
92 }
93 
95  if (neuronFileId_!=NULL) {
96  fclose(neuronFileId_);
97  neuronFileId_ = NULL;
98  }
99 }
100 
102  assert(!isRecording());
103  recordSet_ = false;
104  userHasBeenWarned_ = false;
105  startTime_ = -1;
106  startTimeLast_ = -1;
107  stopTime_ = -1;
108  accumTime_ = 0;
109  totalTime_ = -1;
110 
111  for (int i=0; i<nNeurons_; i++){
112  vectorV_[i].clear();
113  vectorU_[i].clear();
114  vectorI_[i].clear();
115  }
116 }
117 
118 void NeuronMonitorCore::pushNeuronState(int neurId, float V, float U, float I) {
119  assert(isRecording());
120 
121  vectorV_[neurId].push_back(V);
122  vectorU_[neurId].push_back(U);
123  vectorI_[neurId].push_back(I);
124 }
125 
127  assert(!isRecording());
128 
129  if (!persistentData_) {
130  // if persistent mode is off (default behavior), automatically call clear() here
131  clear();
132  }
133 
134  // call updateNeuronMonitor to make sure neuron state file and neuron state vector are up-to-date
135  // Caution: must be called before recordSet_ is set to true!
136  snn_->updateNeuronMonitor(grpId_);
137 
138  recordSet_ = true;
139  long int currentTime = snn_->getSimTimeSec()*1000+snn_->getSimTimeMs();
140 
141  if (persistentData_) {
142  // persistent mode on: accumulate all times
143  // change start time only if this is the first time running it
144  startTime_ = (startTime_<0) ? currentTime : startTime_;
145  startTimeLast_ = currentTime;
146  accumTime_ = (totalTime_>0) ? totalTime_ : 0;
147  }
148  else {
149  // persistent mode off: we only care about the last probe
150  startTime_ = currentTime;
151  startTimeLast_ = currentTime;
152  accumTime_ = 0;
153  }
154 }
155 
157  assert(isRecording());
158  assert(startTime_>-1 && startTimeLast_>-1 && accumTime_>-1);
159 
160  // call updateNeuronMonitor to make sure neuron state file and neuron state vector are up-to-date
161  // Caution: must be called before recordSet_ is set to false!
162  snn_->updateNeuronMonitor(grpId_);
163 
164  recordSet_ = false;
165  userHasBeenWarned_ = false;
166  stopTime_ = snn_->getSimTimeSec()*1000+snn_->getSimTimeMs();
167 
168  // total time is the amount of time of the last probe plus all accumulated time from previous probes
169  totalTime_ = stopTime_-startTimeLast_ + accumTime_;
170  assert(totalTime_>=0);
171 }
172 
173 // returns the total accumulated time.
175  return accumTime_;
176 }
177 
178 void NeuronMonitorCore::setNeuronFileId(FILE* neuronFileId) {
179  assert(!isRecording());
180 
181  // close previous file pointer if exists
182  if (neuronFileId_!=NULL) {
183  fclose(neuronFileId_);
184  neuronFileId_ = NULL;
185  }
186 
187  // set it to new file id
188  neuronFileId_=neuronFileId;
189 
190  if (neuronFileId_==NULL)
191  needToWriteFileHeader_ = false;
192  else {
193  // file pointer has changed, so we need to write header (again)
194  needToWriteFileHeader_ = true;
196  }
197 }
198 
199 // write the header section of the neuron state file
201  if (!needToWriteFileHeader_)
202  return;
203 
204  // write file signature
205  if (!fwrite(&neuronFileSignature_,sizeof(int),1,neuronFileId_))
206  KERNEL_ERROR("NeuronMonitorCore: writeNeuronFileHeader has fwrite error");
207 
208  // write version number
209  if (!fwrite(&neuronFileVersion_,sizeof(float),1,neuronFileId_))
210  KERNEL_ERROR("NeuronMonitorCore: writeNeuronFileHeader has fwrite error");
211 
212  // write grid dimensions
213  Grid3D grid = snn_->getGroupGrid3D(grpId_);
214  int tmpInt = grid.numX;
215  if (!fwrite(&tmpInt,sizeof(int),1,neuronFileId_))
216  KERNEL_ERROR("NeuronMonitorCore: writeNeuronFileHeader has fwrite error");
217 
218  tmpInt = grid.numY;
219  if (!fwrite(&tmpInt,sizeof(int),1,neuronFileId_))
220  KERNEL_ERROR("NeuronMonitorCore: writeNeuronFileHeader has fwrite error");
221 
222  tmpInt = grid.numZ;
223  if (!fwrite(&tmpInt,sizeof(int),1,neuronFileId_))
224  KERNEL_ERROR("NeuronMonitorCore: writeNeuronFileHeader has fwrite error");
225 
226 
227  needToWriteFileHeader_ = false;
228 }
229 
231  long int bufferSize=0; // in bytes
232  for(int i=0; i<vectorV_.size();i++){
233  bufferSize+=vectorV_[i].size()*sizeof(int);
234  }
235  return 3 * bufferSize;
236 }
237 
238 // check if the state vector is getting large. If it is, return true once until
239 // stopRecording is called.
241  if(userHasBeenWarned_)
242  return false;
243  else {
244  //check if buffer is too big
246  userHasBeenWarned_=true;
247  return true;
248  }
249  else {
250  return false;
251  }
252  }
253 }
254 
255 std::vector<std::vector<float> > NeuronMonitorCore::getVectorV(){
256  assert(!isRecording());
257  return vectorV_;
258 }
259 
260 std::vector<std::vector<float> > NeuronMonitorCore::getVectorU(){
261  assert(!isRecording());
262  return vectorU_;
263 }
264 
265 std::vector<std::vector<float> > NeuronMonitorCore::getVectorI(){
266  assert(!isRecording());
267  return vectorI_;
268 }
269 
271  assert(!isRecording());
272 
273  // how many spike times to display per row
274  int dispVoltsPerRow = 7;
275 
276  // spike times only available in AER mode
277  KERNEL_INFO("| Neur ID | volt");
278  KERNEL_INFO("|- - - - -|- - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - -")
279 
280  for (int i=0; i<nNeurons_; i++) {
281  char buffer[100];
282 #if defined(WIN32) || defined(WIN64)
283  _snprintf(buffer, 100, "| %7d | ", i);
284 #else
285  snprintf(buffer, 100, "| %7d | ", i);
286 #endif
287  int nV = vectorV_[i].size();
288  for (int j=0; j<nV; j++) {
289  char volts[10];
290 #if defined(WIN32) || defined(WIN64)
291  _snprintf(volts, 10, "%4.4f ", vectorV_[i][j]);
292 #else
293  snprintf(volts, 10, "%4.4f ", vectorV_[i][j]);
294 #endif
295  strcat(buffer, volts);
296  if (j%dispVoltsPerRow == dispVoltsPerRow-1 && j<nV-1) {
297  KERNEL_INFO("%s",buffer);
298  strcpy(buffer,"| |");
299  }
300  }
301  KERNEL_INFO("%s",buffer);
302  }
303 }
MAX_NEURON_MON_BUFFER_SIZE
#define MAX_NEURON_MON_BUFFER_SIZE
Definition: snn_definitions.h:163
SNN::getSimTimeSec
int getSimTimeSec()
Definition: snn.h:582
SNN::getGroupNumNeurons
int getGroupNumNeurons(int gGrpId)
Definition: snn.h:559
NeuronMonitorCore::~NeuronMonitorCore
~NeuronMonitorCore()
destructor, cleans up all the memory upon object deletion
Definition: neuron_monitor_core.cpp:94
NeuronMonitorCore::NeuronMonitorCore
NeuronMonitorCore(SNN *snn, int monitorId, int grpId)
constructor (called by CARLsim::setNeuronMonitor)
Definition: neuron_monitor_core.cpp:57
NeuronMonitorCore::writeNeuronFileHeader
void writeNeuronFileHeader()
Definition: neuron_monitor_core.cpp:200
NeuronMonitorCore::pushNeuronState
void pushNeuronState(int neurId, float V, float U, float I)
inserts a (time,neurId) tupel into the D Neuron State vector
Definition: neuron_monitor_core.cpp:118
NeuronMonitorCore::stopRecording
void stopRecording()
stops recording Neuron state
Definition: neuron_monitor_core.cpp:156
Grid3D::numX
int numX
Definition: carlsim_datastructures.h:548
NeuronMonitorCore::isRecording
bool isRecording()
returns recording status
Definition: neuron_monitor_core.h:73
SNN::updateNeuronMonitor
void updateNeuronMonitor(int grpId=ALL)
copy required neuron state values from ??? buffer to ??? buffer
Definition: snn_manager.cpp:6590
neuron_monitor_core.h
NeuronMonitorCore::getBufferSize
long int getBufferSize()
returns the approximate size of the state vectors in bytes
Definition: neuron_monitor_core.cpp:230
NeuronMonitorCore::getVectorV
std::vector< std::vector< float > > getVectorV()
returns the Neuron state vector
Definition: neuron_monitor_core.cpp:255
NeuronMonitorCore::setNeuronFileId
void setNeuronFileId(FILE *neuronFileId)
sets pointer to Neuron file
Definition: neuron_monitor_core.cpp:178
snn_definitions.h
NeuronMonitorCore::print
void print()
prints neuron states in human-readable format
Definition: neuron_monitor_core.cpp:270
KERNEL_ERROR
#define KERNEL_ERROR(formatc,...)
Definition: snn_definitions.h:110
KERNEL_INFO
#define KERNEL_INFO(formatc,...)
Definition: snn_definitions.h:114
Grid3D::numY
int numY
Definition: carlsim_datastructures.h:548
SNN::getLogFpErr
const FILE * getLogFpErr()
returns file pointer to error log
Definition: snn.h:516
NeuronMonitorCore::isBufferBig
bool isBufferBig()
returns true if state buffers are close to maxAllowedBufferSize
Definition: neuron_monitor_core.cpp:240
SNN::getSimTimeMs
int getSimTimeMs()
Definition: snn.h:583
SNN::getLogFpInf
const FILE * getLogFpInf()
function writes population weights from gIDpre to gIDpost to file fname in binary.
Definition: snn.h:514
Grid3D
A struct to arrange neurons on a 3D grid (a primitive cubic Bravais lattice with cubic side length 1)
Definition: carlsim_datastructures.h:490
SNN::getLogFpDeb
const FILE * getLogFpDeb()
returns file pointer to debug log
Definition: snn.h:518
NeuronMonitorCore::getVectorU
std::vector< std::vector< float > > getVectorU()
Definition: neuron_monitor_core.cpp:260
NeuronMonitorCore::getVectorI
std::vector< std::vector< float > > getVectorI()
Definition: neuron_monitor_core.cpp:265
snn.h
SNN
Contains all of CARLsim's core functionality.
Definition: snn.h:115
NeuronMonitorCore::getAccumTime
long int getAccumTime()
returns the total accumulated time
Definition: neuron_monitor_core.cpp:174
NeuronMonitorCore::clear
void clear()
deletes data from the neuron state vector
Definition: neuron_monitor_core.cpp:101
Grid3D::numZ
int numZ
Definition: carlsim_datastructures.h:548
SNN::getGroupGrid3D
Grid3D getGroupGrid3D(int grpId)
Definition: snn_manager.cpp:1846
NeuronMonitorCore::startRecording
void startRecording()
starts recording Neuron state
Definition: neuron_monitor_core.cpp:126
SNN::getLogFpLog
const FILE * getLogFpLog()
returns file pointer to log file
Definition: snn.h:520