CARLsim  4.1.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 *
45 * CARLsim available from http://socsci.uci.edu/~jkrichma/CARLsim/
46 * Ver 05/24/2017
47 */
48 
49 #include <neuron_monitor_core.h>
50 
51 #include <snn.h> // CARLsim private implementation
52 #include <snn_definitions.h> // KERNEL_ERROR, KERNEL_INFO, ...
53 
54 #include <algorithm> // std::sort
55 
56 NeuronMonitorCore::NeuronMonitorCore(SNN* snn, int monitorId, int grpId) {
57  snn_ = snn;
58  grpId_= grpId;
59  monitorId_ = monitorId;
60  nNeurons_ = -1;
61  neuronFileId_ = NULL;
62  recordSet_ = false;
63  neuronMonLastUpdated_ = 0;
64 
65  persistentData_ = false;
66  userHasBeenWarned_ = false;
67  needToWriteFileHeader_ = true;
68  neuronFileSignature_ = 206661979;
69  neuronFileVersion_ = 0.1f;
70 
71  // defer all unsafe operations to init function
72  init();
73 }
74 
75 void NeuronMonitorCore::init() {
76  nNeurons_ = snn_->getGroupNumNeurons(grpId_);
77  assert(nNeurons_>0);
78 
79  // so the first dimension is neuron ID
80  vectorV_.resize(nNeurons_);
81  vectorU_.resize(nNeurons_);
82  vectorI_.resize(nNeurons_);
83 
84  clear();
85 
86  // use KERNEL_{ERROR|WARNING|etc} typesetting (const FILE*)
87  fpInf_ = snn_->getLogFpInf();
88  fpErr_ = snn_->getLogFpErr();
89  fpDeb_ = snn_->getLogFpDeb();
90  fpLog_ = snn_->getLogFpLog();
91 }
92 
94  if (neuronFileId_!=NULL) {
95  fclose(neuronFileId_);
96  neuronFileId_ = NULL;
97  }
98 }
99 
101  assert(!isRecording());
102  recordSet_ = false;
103  userHasBeenWarned_ = false;
104  startTime_ = -1;
105  startTimeLast_ = -1;
106  stopTime_ = -1;
107  accumTime_ = 0;
108  totalTime_ = -1;
109 
110  for (int i=0; i<nNeurons_; i++){
111  vectorV_[i].clear();
112  vectorU_[i].clear();
113  vectorI_[i].clear();
114  }
115 }
116 
117 void NeuronMonitorCore::pushNeuronState(int neurId, float V, float U, float I) {
118  assert(isRecording());
119 
120  vectorV_[neurId].push_back(V);
121  vectorU_[neurId].push_back(U);
122  vectorI_[neurId].push_back(I);
123 }
124 
126  assert(!isRecording());
127 
128  if (!persistentData_) {
129  // if persistent mode is off (default behavior), automatically call clear() here
130  clear();
131  }
132 
133  // call updateNeuronMonitor to make sure neuron state file and neuron state vector are up-to-date
134  // Caution: must be called before recordSet_ is set to true!
135  snn_->updateNeuronMonitor(grpId_);
136 
137  recordSet_ = true;
138  long int currentTime = snn_->getSimTimeSec()*1000+snn_->getSimTimeMs();
139 
140  if (persistentData_) {
141  // persistent mode on: accumulate all times
142  // change start time only if this is the first time running it
143  startTime_ = (startTime_<0) ? currentTime : startTime_;
144  startTimeLast_ = currentTime;
145  accumTime_ = (totalTime_>0) ? totalTime_ : 0;
146  }
147  else {
148  // persistent mode off: we only care about the last probe
149  startTime_ = currentTime;
150  startTimeLast_ = currentTime;
151  accumTime_ = 0;
152  }
153 }
154 
156  assert(isRecording());
157  assert(startTime_>-1 && startTimeLast_>-1 && accumTime_>-1);
158 
159  // call updateNeuronMonitor to make sure neuron state file and neuron state vector are up-to-date
160  // Caution: must be called before recordSet_ is set to false!
161  snn_->updateNeuronMonitor(grpId_);
162 
163  recordSet_ = false;
164  userHasBeenWarned_ = false;
165  stopTime_ = snn_->getSimTimeSec()*1000+snn_->getSimTimeMs();
166 
167  // total time is the amount of time of the last probe plus all accumulated time from previous probes
168  totalTime_ = stopTime_-startTimeLast_ + accumTime_;
169  assert(totalTime_>=0);
170 }
171 
172 // returns the total accumulated time.
174  return accumTime_;
175 }
176 
177 void NeuronMonitorCore::setNeuronFileId(FILE* neuronFileId) {
178  assert(!isRecording());
179 
180  // close previous file pointer if exists
181  if (neuronFileId_!=NULL) {
182  fclose(neuronFileId_);
183  neuronFileId_ = NULL;
184  }
185 
186  // set it to new file id
187  neuronFileId_=neuronFileId;
188 
189  if (neuronFileId_==NULL)
190  needToWriteFileHeader_ = false;
191  else {
192  // file pointer has changed, so we need to write header (again)
193  needToWriteFileHeader_ = true;
195  }
196 }
197 
198 // write the header section of the neuron state file
200  if (!needToWriteFileHeader_)
201  return;
202 
203  // write file signature
204  if (!fwrite(&neuronFileSignature_,sizeof(int),1,neuronFileId_))
205  KERNEL_ERROR("NeuronMonitorCore: writeNeuronFileHeader has fwrite error");
206 
207  // write version number
208  if (!fwrite(&neuronFileVersion_,sizeof(float),1,neuronFileId_))
209  KERNEL_ERROR("NeuronMonitorCore: writeNeuronFileHeader has fwrite error");
210 
211  // write grid dimensions
212  Grid3D grid = snn_->getGroupGrid3D(grpId_);
213  int tmpInt = grid.numX;
214  if (!fwrite(&tmpInt,sizeof(int),1,neuronFileId_))
215  KERNEL_ERROR("NeuronMonitorCore: writeNeuronFileHeader has fwrite error");
216 
217  tmpInt = grid.numY;
218  if (!fwrite(&tmpInt,sizeof(int),1,neuronFileId_))
219  KERNEL_ERROR("NeuronMonitorCore: writeNeuronFileHeader has fwrite error");
220 
221  tmpInt = grid.numZ;
222  if (!fwrite(&tmpInt,sizeof(int),1,neuronFileId_))
223  KERNEL_ERROR("NeuronMonitorCore: writeNeuronFileHeader has fwrite error");
224 
225 
226  needToWriteFileHeader_ = false;
227 }
228 
230  long int bufferSize=0; // in bytes
231  for(int i=0; i<vectorV_.size();i++){
232  bufferSize+=vectorV_[i].size()*sizeof(int);
233  }
234  return 3 * bufferSize;
235 }
236 
237 // check if the state vector is getting large. If it is, return true once until
238 // stopRecording is called.
240  if(userHasBeenWarned_)
241  return false;
242  else {
243  //check if buffer is too big
245  userHasBeenWarned_=true;
246  return true;
247  }
248  else {
249  return false;
250  }
251  }
252 }
253 
254 std::vector<std::vector<float> > NeuronMonitorCore::getVectorV(){
255  assert(!isRecording());
256  return vectorV_;
257 }
258 
259 std::vector<std::vector<float> > NeuronMonitorCore::getVectorU(){
260  assert(!isRecording());
261  return vectorU_;
262 }
263 
264 std::vector<std::vector<float> > NeuronMonitorCore::getVectorI(){
265  assert(!isRecording());
266  return vectorI_;
267 }
268 
270  assert(!isRecording());
271 
272  // how many spike times to display per row
273  int dispVoltsPerRow = 7;
274 
275  // spike times only available in AER mode
276  KERNEL_INFO("| Neur ID | volt");
277  KERNEL_INFO("|- - - - -|- - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - -")
278 
279  for (int i=0; i<nNeurons_; i++) {
280  char buffer[100];
281 #if defined(WIN32) || defined(WIN64)
282  _snprintf(buffer, 100, "| %7d | ", i);
283 #else
284  snprintf(buffer, 100, "| %7d | ", i);
285 #endif
286  int nV = vectorV_[i].size();
287  for (int j=0; j<nV; j++) {
288  char volts[10];
289 #if defined(WIN32) || defined(WIN64)
290  _snprintf(volts, 10, "%4.4f ", vectorV_[i][j]);
291 #else
292  snprintf(volts, 10, "%4.4f ", vectorV_[i][j]);
293 #endif
294  strcat(buffer, volts);
295  if (j%dispVoltsPerRow == dispVoltsPerRow-1 && j<nV-1) {
296  KERNEL_INFO("%s",buffer);
297  strcpy(buffer,"| |");
298  }
299  }
300  KERNEL_INFO("%s",buffer);
301  }
302 }
MAX_NEURON_MON_BUFFER_SIZE
#define MAX_NEURON_MON_BUFFER_SIZE
Definition: snn_definitions.h:162
SNN::getSimTimeSec
int getSimTimeSec()
Definition: snn.h:581
SNN::getGroupNumNeurons
int getGroupNumNeurons(int gGrpId)
Definition: snn.h:558
NeuronMonitorCore::~NeuronMonitorCore
~NeuronMonitorCore()
destructor, cleans up all the memory upon object deletion
Definition: neuron_monitor_core.cpp:93
NeuronMonitorCore::NeuronMonitorCore
NeuronMonitorCore(SNN *snn, int monitorId, int grpId)
constructor (called by CARLsim::setNeuronMonitor)
Definition: neuron_monitor_core.cpp:56
NeuronMonitorCore::writeNeuronFileHeader
void writeNeuronFileHeader()
Definition: neuron_monitor_core.cpp:199
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:117
NeuronMonitorCore::stopRecording
void stopRecording()
stops recording Neuron state
Definition: neuron_monitor_core.cpp:155
Grid3D::numX
int numX
Definition: carlsim_datastructures.h:547
NeuronMonitorCore::isRecording
bool isRecording()
returns recording status
Definition: neuron_monitor_core.h:72
SNN::updateNeuronMonitor
void updateNeuronMonitor(int grpId=ALL)
copy required neuron state values from ??? buffer to ??? buffer
Definition: snn_manager.cpp:6589
neuron_monitor_core.h
NeuronMonitorCore::getBufferSize
long int getBufferSize()
returns the approximate size of the state vectors in bytes
Definition: neuron_monitor_core.cpp:229
NeuronMonitorCore::getVectorV
std::vector< std::vector< float > > getVectorV()
returns the Neuron state vector
Definition: neuron_monitor_core.cpp:254
NeuronMonitorCore::setNeuronFileId
void setNeuronFileId(FILE *neuronFileId)
sets pointer to Neuron file
Definition: neuron_monitor_core.cpp:177
snn_definitions.h
NeuronMonitorCore::print
void print()
prints neuron states in human-readable format
Definition: neuron_monitor_core.cpp:269
KERNEL_ERROR
#define KERNEL_ERROR(formatc,...)
Definition: snn_definitions.h:109
KERNEL_INFO
#define KERNEL_INFO(formatc,...)
Definition: snn_definitions.h:113
Grid3D::numY
int numY
Definition: carlsim_datastructures.h:547
SNN::getLogFpErr
const FILE * getLogFpErr()
returns file pointer to error log
Definition: snn.h:515
NeuronMonitorCore::isBufferBig
bool isBufferBig()
returns true if state buffers are close to maxAllowedBufferSize
Definition: neuron_monitor_core.cpp:239
SNN::getSimTimeMs
int getSimTimeMs()
Definition: snn.h:582
SNN::getLogFpInf
const FILE * getLogFpInf()
function writes population weights from gIDpre to gIDpost to file fname in binary.
Definition: snn.h:513
Grid3D
A struct to arrange neurons on a 3D grid (a primitive cubic Bravais lattice with cubic side length 1)
Definition: carlsim_datastructures.h:489
SNN::getLogFpDeb
const FILE * getLogFpDeb()
returns file pointer to debug log
Definition: snn.h:517
NeuronMonitorCore::getVectorU
std::vector< std::vector< float > > getVectorU()
Definition: neuron_monitor_core.cpp:259
NeuronMonitorCore::getVectorI
std::vector< std::vector< float > > getVectorI()
Definition: neuron_monitor_core.cpp:264
snn.h
SNN
Contains all of CARLsim's core functionality.
Definition: snn.h:114
NeuronMonitorCore::getAccumTime
long int getAccumTime()
returns the total accumulated time
Definition: neuron_monitor_core.cpp:173
NeuronMonitorCore::clear
void clear()
deletes data from the neuron state vector
Definition: neuron_monitor_core.cpp:100
Grid3D::numZ
int numZ
Definition: carlsim_datastructures.h:547
SNN::getGroupGrid3D
Grid3D getGroupGrid3D(int grpId)
Definition: snn_manager.cpp:1845
NeuronMonitorCore::startRecording
void startRecording()
starts recording Neuron state
Definition: neuron_monitor_core.cpp:125
SNN::getLogFpLog
const FILE * getLogFpLog()
returns file pointer to log file
Definition: snn.h:519