CARLsim  6.1.0
CARLsim: a GPU-accelerated SNN simulator
visual_stimulus.cpp
Go to the documentation of this file.
1 #include "visual_stimulus.h"
2 
3 #include <poisson_rate.h>
4 #include <string>
5 #include <cassert> // assert
6 #include <stdio.h> // fopen, fread, fclose
7 #include <stdlib.h> // exit
8 
10 public:
11  // +++++ PUBLIC METHODS +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
12 
13  Impl(std::string fileName, bool wrapAroundEOF) {
14  _fileId = NULL;
15  _fileName = fileName;
16  _wrapAroundEOF = wrapAroundEOF;
17 
18  _frame = NULL;
19  _frameNum = -1;
20 
21  _width = -1;
22  _height = -1;
23  _length = -1;
24 
25  _framePoisson = NULL;
26 
27  _channels = -1;
28  _type = UNKNOWN_STIM;
29 
30  _version = 1.0f;
31  _fileSignature = 293390619; // v1.0 file signature
32 
33  // read the header section of the binary file
34  readHeader();
35  }
36 
37  ~Impl() {
38  if (_frame!=NULL)
39  delete[] _frame;
40  _frame=NULL;
41 
42  if (_framePoisson!=NULL)
43  delete _framePoisson;
44  _framePoisson=NULL;
45 
46  if (_fileId!=NULL)
47  fclose(_fileId);
48  }
49 
50  // reads the next frame and returns the char array
51  unsigned char* readFrameChar() {
52  readFramePrivate();
53  return _frame;
54  }
55 
56  // reads the next frame and returns the PoissonRate object
57  PoissonRate* readFramePoisson(float maxPoisson, float minPoisson) {
58  assert(maxPoisson>0);
59  assert(maxPoisson>minPoisson);
60 
61  // read next frame
62  readFramePrivate();
63 
64  // create new Poisson object, assign
65  _framePoisson = new PoissonRate(_width*_height*_channels);
66  for (int i=0; i<_width*_height*_channels; i++) {
67  _framePoisson->setRate(i, _frame[i]*(maxPoisson-minPoisson)/255.0f + minPoisson); // scale firing rates
68  }
69 
70  return _framePoisson;
71  }
72 
73  // rewind position of file stream to first frame
74  void rewind() {
75  fseek(_fileId, _fileHeaderSizeBytes, SEEK_SET);
76  }
77 
78  void print() {
79  fprintf(stdout, "VisualStimulus loaded (\"%s\", Type %d, Size %dx%dx%dx%d).\n", _fileName.c_str(), _type,
80  _width, _height, _channels, _length);
81  }
82 
83  int getWidth() { return _width; }
84  int getHeight() { return _height; }
85  int getLength() { return _length; }
86  int getChannels() { return _channels; }
87  stimType_t getType() { return _type; }
88 
89  unsigned char* getCurrentFrameChar() { return _frame; }
90  PoissonRate* getCurrentFramePoisson() { return _framePoisson; }
91  int getCurrentFrameNumber() { return _frameNum; }
92 
93 
94 private:
95  // +++++ PRIVATE METHODS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
96 
97  // reads next frame and assigns char array and Poisson Rate
98  void readFramePrivate() {
99  // make sure type is set
100  assert(_type!=UNKNOWN_STIM);
101 
102  // keep at most one frame in memory
103  if (_frame!=NULL)
104  delete[] _frame;
105  if (_framePoisson!=NULL)
106  delete _framePoisson;
107  _frame = NULL; _framePoisson = NULL;
108 
109  // have we reached EOF?
110  if (feof(_fileId) || (_frameNum==_length-1)) {
111  // reset frame index
112  _frameNum = -1;
113 
114  if (!_wrapAroundEOF) {
115  // we've reached end of file, print a warning
116  fprintf(stderr,"WARNING: End of file reached, starting from the top\n");
117  }
118 
119  // rewind position of file stream to first frame
120  rewind();
121  }
122 
123  // read new frame
124  _frame = new unsigned char[_width*_height*_channels];
125  size_t result = fread(_frame, sizeof(unsigned char), _width*_height*_channels, _fileId);
126  if (result!=(size_t) (_width*_height*_channels)) {
127  fprintf(stderr,"VisualStimulus Error: Error while reading stimulus frame (expected %d elements, found %d\n",
128  _width*_height*_channels, (int)result);
129  exit(1);
130  }
131 
132  // initialized as -1, so after reading first frame this sits at 0
133  _frameNum++;
134  }
135 
136  // reads the header section of the binary file
137  void readHeader() {
138  _fileId = fopen(_fileName.c_str(),"rb");
139  if (_fileId==NULL) {
140  fprintf(stderr,"VisualStimulus Error: Could not open stimulus file %s\n",_fileName.c_str());
141  exit(1);
142  }
143 
144  bool readErr = false; // keep track of reading Errors
145  size_t result;
146  int tmpInt;
147  float tmpFloat;
148  char tmpChar;
149 
150  // read signature
151  result = fread(&tmpInt, sizeof(int), 1, _fileId);
152  readErr |= (result!=1);
153  if (tmpInt != _fileSignature) {
154  fprintf(stderr,"VisualStimulus Error: Unknown file signature\n");
155  exit(1);
156  }
157 
158  // read version number
159  result = fread(&tmpFloat, sizeof(float), 1, _fileId);
160  readErr |= (result!=1);
161  if (tmpFloat != _version) {
162  fprintf(stderr,"VisualStimulus Error: Unknown file version (%1.1f), must have 1.0\n",tmpFloat);
163  exit(1);
164  }
165 
166  // read stimulus type
167  result = fread(&tmpInt, sizeof(int), 1, _fileId);
168  readErr |= (result!=1);
169  if (tmpInt < UNKNOWN_STIM || tmpInt > COMPOUND_STIM) {
170  fprintf(stderr,"VisualStimulus Error: Unknown stimulus type found (%d)\n",tmpInt);
171  exit(1);
172  }
173  _type = static_cast<stimType_t>(tmpInt);
174 
175  // read number of channels
176  result = fread(&tmpChar, sizeof(char), 1, _fileId);
177  readErr |= (result!=1);
178  _channels = (int)tmpChar;
179 
180  // read stimulus dimensions
181  result = fread(&tmpInt, sizeof(int), 1, _fileId); readErr |= (result!=1);
182  _width = tmpInt;
183  result = fread(&tmpInt, sizeof(int), 1, _fileId); readErr |= (result!=1);
184  _height = tmpInt;
185  result = fread(&tmpInt, sizeof(int), 1, _fileId); readErr |= (result!=1);
186  _length = tmpInt;
187 
188  // any reading Errors encountered?
189  if (readErr) {
190  fprintf(stderr,"VisualStimulus Error: Error while reading file %s\n",_fileName.c_str());
191  exit(1);
192  }
193 
194  // store the size of the header section (in bytes)
195  _fileHeaderSizeBytes = ftell(_fileId);
196  }
197 
198 
199  // +++++ PRIVATE MEMBERS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
200 
201  FILE* _fileId;
202  std::string _fileName;
203 
204  int _version;
205  int _fileSignature;
206 
207  long _fileHeaderSizeBytes;
208  bool _wrapAroundEOF;
209 
210  unsigned char* _frame;
211  int _frameNum;
212 
213  PoissonRate* _framePoisson;
214 
215  int _width;
216  int _height;
217  int _length;
218 
219  int _channels;
220  stimType_t _type;
221 };
222 
223 
224 // ****************************************************************************************************************** //
225 // VISUALSTIMULUS API IMPLEMENTATION
226 // ****************************************************************************************************************** //
227 
228 // create and destroy a pImpl instance
229 VisualStimulus::VisualStimulus(std::string fileName, bool wrapAroundEOF) : _impl( new Impl(fileName, wrapAroundEOF) ) {}
231 
232 unsigned char* VisualStimulus::readFrameChar() { return _impl->readFrameChar(); }
233 PoissonRate* VisualStimulus::readFramePoisson(float maxPoisson, float minPoisson) {
234  return _impl->readFramePoisson(maxPoisson, minPoisson);
235 }
236 void VisualStimulus::rewind() { _impl->rewind(); }
237 void VisualStimulus::print() { _impl->print(); }
238 
239 int VisualStimulus::getWidth() { return _impl->getWidth(); }
240 int VisualStimulus::getHeight() { return _impl->getHeight(); }
241 int VisualStimulus::getLength() { return _impl->getLength(); }
242 int VisualStimulus::getChannels() { return _impl->getChannels(); }
244 unsigned char* VisualStimulus::getCurrentFrameChar() { return _impl->getCurrentFrameChar(); }
Class for generating Poisson spike trains.
Definition: poisson_rate.h:88
PoissonRate * readFramePoisson(float maxPoisson, float minPoisson)
int getHeight()
returns the stimulus height (number of pixels)
Impl(std::string fileName, bool wrapAroundEOF)
VisualStimulus(std::string fileName, bool wrapAroundEOF=true)
Default constructor.
PoissonRate * readFramePoisson(float maxPoisson, float minPoisson=0.0f)
Reads the next image frame and returns a pointer to a PoissonRate object.
PoissonRate * getCurrentFramePoisson()
returns PoissonRate object of current frame
unsigned char * getCurrentFrameChar()
int getLength()
returns the stimulus length (number of frames)
int getChannels()
returns the number of channels (1=grayscale, 3=RGB)
void rewind()
Rewinds the file pointer to the top.
unsigned char * readFrameChar()
Reads the next image frame and returns a pointer to the char array.
~VisualStimulus()
default destructor
stimType_t
List of stimulus file types.
void setRate(int neurId, float rate)
Sets the mean firing rate of a particular neuron ID.
unsigned char * getCurrentFrameChar()
returns char array of current frame
unsigned char * readFrameChar()
stimType_t getType()
returns the stimulus type (STIM_GRAY, STIM_RGB, etc.)
int getWidth()
returns the stimulus width (number of pixels)
PoissonRate * getCurrentFramePoisson()