CARLsim  6.1.0
CARLsim: a GPU-accelerated SNN simulator
spikegen_from_file.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 * CARLsim6: LN, JX, KC, KW
46 *
47 * CARLsim available from http://socsci.uci.edu/~jkrichma/CARLsim/
48 * Ver 12/31/2016
49 */
50 #include <spikegen_from_file.h>
51 
52 #include <carlsim.h>
53 //#include <user_errors.h> // fancy user error messages
54 
55 #include <stdio.h> // fopen, fread, fclose
56 #include <string.h> // std::string
57 #include <assert.h> // assert
58 
59 // #define VERBOSE
60 
61 SpikeGeneratorFromFile::SpikeGeneratorFromFile(std::string fileName, int offsetTimeMs) {
62  fileName_ = fileName;
63  fpBegin_ = NULL;
64 
65  nNeur_ = -1;
66  szByteHeader_ = -1;
67  offsetTimeMs_ = offsetTimeMs;
68 
69  // move unsafe operations out of constructor
70  openFile();
71  init();
72 }
73 
75  if (fpBegin_ != NULL) {
76  fclose(fpBegin_);
77  }
78  fpBegin_ = NULL;
79 }
80 
81 void SpikeGeneratorFromFile::loadFile(std::string fileName, int offsetTimeMs) {
82  // close previously opened file (if any)
83  if (fpBegin_ != NULL) {
84  fclose(fpBegin_);
85  }
86  fpBegin_ = NULL;
87 
88  // update file name and open
89  fileName_ = fileName;
90  offsetTimeMs_ = offsetTimeMs;
91  openFile();
92  init();
93 }
94 
95 // rewind file pointers to beginning
96 void SpikeGeneratorFromFile::rewind(int offsetTimeMs) {
97  offsetTimeMs_ = offsetTimeMs;
98 
99  // reset all iterators
100  spikesIt_.clear();
101  for (int i=0; i<nNeur_; i++) {
102  spikesIt_.push_back(spikes_[i].begin());
103  }
104 }
105 
106 void SpikeGeneratorFromFile::openFile() {
107  std::string funcName = "openFile("+fileName_+")";
108  fpBegin_ = fopen(fileName_.c_str(),"rb");
109  UserErrors::assertTrue(fpBegin_!=NULL, UserErrors::FILE_CANNOT_OPEN, funcName, fileName_);
110 
111  // \TODO there should be a common/standard way to read spike files
112  // \FIXME: this is a hack...to get the size of the header section
113  // needs to be updated every time header changes
114  FILE* fp = fpBegin_;
115  szByteHeader_ = 4*sizeof(int)+1*sizeof(float);
116  fseek(fp, sizeof(int)+sizeof(float), SEEK_SET); // skipping signature+version
117 
118  // get number of neurons from header
119  nNeur_ = 1;
120  int grid;
121  for (int i=1; i<=3; i++) {
122  size_t result = fread(&grid, sizeof(int), 1, fp);
123  UserErrors::assertTrue(result == 1, UserErrors::FILE_CANNOT_READ, funcName, fileName_);
124  nNeur_ *= grid;
125  }
126 
127  // make sure number of neurons is now valid
128  assert(nNeur_>0);
129 }
130 
131 void SpikeGeneratorFromFile::init() {
132  assert(nNeur_>0);
133 
134  // allocate spike vector
135  // we organize AER format into a 2D spike vector: first dim=neuron, second dim=spike times
136  // then we just need to maintain an iterator for each neuron to know which spike to schedule next
137  spikes_.clear();
138  for (int i=0; i<nNeur_; i++) {
139  spikes_.push_back(std::vector<int>());
140  }
141 
142  // read spike file
143  FILE* fp = fpBegin_;
144  fseek(fp, szByteHeader_, SEEK_SET); // skip header section
145 
146  std::string funcName = "readFile("+fileName_+")";
147  int tmpTime = -1;
148  int tmpNeurId = -1;
149  size_t result1, result2;
150 
151  while (!feof(fp)) {
152  result1 = fread(&tmpTime, sizeof(int), 1, fp); // i-th time
153  //UserErrors::assertTrue(result == 1, UserErrors::FILE_CANNOT_READ, funcName, fileName_);
154  result2 = fread(&tmpNeurId, sizeof(int), 1, fp); // i-th nid
155  //UserErrors::assertTrue(result == 1, UserErrors::FILE_CANNOT_READ, funcName, fileName_);
156  if (result1 + result2 == 2) // validate the size of reading
157  spikes_[tmpNeurId].push_back(tmpTime); // add spike time to 2D vector
158  }
159 
160 #ifdef VERBOSE
161  for (int neurId=0; neurId<1; neurId++) {
162  printf("[%d]: ",neurId);
163  for (int i=0; i<spikes_[neurId].size(); i++) {
164  printf("%d ",spikes_[neurId][i]);
165  }
166  printf("\n");
167  }
168 #endif
169 
170  // initialize iterators
171  rewind(offsetTimeMs_);
172 }
173 
174 int SpikeGeneratorFromFile::nextSpikeTime(CARLsim* sim, int grpId, int nid, int currentTime, int lastScheduledSpikeTime, int endOfTimeSlice) {
175  assert(nNeur_>0);
176  assert(nid < nNeur_);
177 
178  if (spikesIt_[nid] != spikes_[nid].end()) {
179  // if there are spikes left in the vector ...
180 
181  if (*(spikesIt_[nid])+offsetTimeMs_ < endOfTimeSlice) {
182  // ... and if the next spike time is in the current scheduling time slice:
183 #ifdef VERBOSE
184  if (nid==0) {
185  printf("[%d][%d]: currTime=%u, lastTime=%u, endOfTime=%u, offsetTimeMs=%u, nextSpike=%u\n", grpId, nid,
186  currentTime, lastScheduledSpikeTime, endOfTimeSlice, offsetTimeMs_,
187  (unsigned int) (*(spikesIt_[nid])+offsetTimeMs_));
188  }
189 #endif
190  // return the next spike time and update iterator
191  return (unsigned int)(*(spikesIt_[nid]++)+offsetTimeMs_);
192  }
193  }
194 
195  // if the next spike time is not a valid number, return a large positive number instead
196  // this will signal CARLsim to break the nextSpikeTime loop
197  return -1; // large positive number
198 }
CARLsim User Interface This class provides a user interface to the public sections of CARLsimCore sou...
Definition: carlsim.h:142
could not open file
Definition: user_errors.h:46
void loadFile(std::string fileName, int offsetTimeMs=0)
Loads a new spike file.
SpikeGeneratorFromFile(std::string fileName, int offsetTimeMs=0)
SpikeGeneratorFromFile constructor.
could not read file
Definition: user_errors.h:47
static void assertTrue(bool statement, errorType errorIfAssertionFails, std::string errorFunc, std::string errorMsgPrefix="", std::string errorMsgSuffix="")
simple wrapper for assert statement
Definition: user_errors.cpp:15
int nextSpikeTime(CARLsim *sim, int grpId, int nid, int currentTime, int lastScheduledSpikeTime, int endOfTimeSlice)
schedules the next spike time
~SpikeGeneratorFromFile()
SpikeGeneratorFromFile destructor.
void rewind(int offsetTimeMs)
Rewinds the spike file to beginning of file.