Auryn simulator  v0.8.1-206-gb56e451
Plastic Spiking Neural Network Simulator
Functions
aube.cpp File Reference
#include "auryn.h"
#include <iostream>
#include <fstream>
#include <vector>
#include "auryn/AurynVersion.h"
Include dependency graph for aube.cpp:

Functions

AurynLong find_frame (std::ifstream *file, AurynTime target)
 
void read_header (std::ifstream *input, double &dt, AurynLong num_events, double &last_time, std::string filename)
 
int main (int ac, char *av[])
 

Function Documentation

◆ find_frame()

AurynLong find_frame ( std::ifstream *  file,
AurynTime  target 
)

Perform binary search on ifstream to extract frame number from a target time reference that should be given in discrete time.

36 {
37  // get number of elements
38  file->seekg (0, file->end);
39  AurynLong num_of_frames = file->tellg()/sizeof(SpikeEvent_type);
40 
41  AurynLong lo = 1; // first frame is used for header
42  AurynLong hi = num_of_frames;
43 
44  while ( lo+1 < hi ) {
45  AurynLong pivot = lo + (hi-lo)/2;
46  file->seekg (pivot*sizeof(SpikeEvent_type), file->beg);
47 
48  SpikeEvent_type spike_data;
49  file->read((char*)&spike_data, sizeof(SpikeEvent_type));
50 
51  if ( spike_data.time < target ) lo = pivot;
52  else hi = pivot;
53  }
54 
55  return lo;
56 }
unsigned long AurynLong
An unsigned long type used to count synapses or similar.
Definition: auryn_definitions.h:154
Auryn spike event for binary monitors.
Definition: auryn_definitions.h:194

◆ main()

int main ( int  ac,
char *  av[] 
)
97 {
98  std::vector<std::string> input_filenames;
99  std::vector<std::ifstream*> inputs;
100 
101  std::string output_file_name = "";
102  double from_time = 0.0;
103  double to_time = -1.0;
104  double seconds_to_extract_from_end = -1.0; // negative means disabled
105  NeuronID maxid = std::numeric_limits<NeuronID>::max();
106  // one more decimal than neede to show values are not rounded
107  bool debug_output = false;
108 
109  try {
110  po::options_description desc("Allowed options");
111  desc.add_options()
112  ("help,h", "produce help message")
113  ("version,v", "show version information")
114  ("debug,d", "show verbose debug output")
115  ("inputs,i", po::value< std::vector<std::string> >()->multitoken(), "input files")
116  ("output,o", po::value<std::string>(), "output file (output to stout if not given)")
117  ("from,f", po::value<double>(), "'from time' in seconds")
118  ("to,t", po::value<double>(), "'to time' in seconds")
119  ("last,l", po::value<double>(), "last x seconds (overrides from/to)")
120  ("maxid,m", po::value<NeuronID>(), "maximum neuron id to extract")
121  ;
122 
123  po::variables_map vm;
124  po::store(po::parse_command_line(ac, av, desc), vm);
125  po::notify(vm);
126 
127  if (vm.count("help")) {
128  std::cout << desc << "\n";
129  return 1;
130  }
131 
132  if (vm.count("version")) {
133  AurynVersion build;
134  std::cout << "Auryn Binary Extract version "
135  << build.version << "."
136  << build.subversion << "."
137  << build.revision_number << "\n";
138  return EXIT_SUCCESS;
139  }
140 
141  if (vm.count("debug")) {
142  debug_output = true;
143  }
144 
145  if (vm.count("inputs")) {
146  input_filenames = vm["inputs"].as< std::vector<std::string> >();
147  }
148 
149  if (vm.count("output")) {
150  output_file_name = vm["output"].as<std::string>();
151  }
152 
153  if (vm.count("from")) {
154  from_time = vm["from"].as<double>();
155  }
156 
157  if (vm.count("to")) {
158  to_time = vm["to"].as<double>();
159  }
160 
161  if (vm.count("last")) {
162  seconds_to_extract_from_end = vm["last"].as<double>();
163  }
164 
165  if (vm.count("maxid")) {
166  maxid = vm["maxid"].as<NeuronID>();
167  }
168  }
169  catch(std::exception& e) {
170  std::cerr << "error: " << e.what() << "\n";
171  return 1;
172  }
173  catch(...) {
174  std::cerr << "Exception of unknown type!\n";
175  }
176 
177  if ( debug_output )
178  std::cout << "# Number of input files " << input_filenames.size() << std::endl;
179 
180  double last_time = 0.0;
181  double dt = 0.0;
182 
183  if ( input_filenames.size() == 0 ) {
184  std::cerr << "Missing input file." << std::endl;
185  exit(EXIT_FAILURE);
186  }
187 
188  for ( unsigned int i = 0 ; i < input_filenames.size() ; ++i ) {
189  std::ifstream * tmp = new std::ifstream( input_filenames[i].c_str(), std::ios::binary );
190  inputs.push_back(tmp);
191  if (!(*tmp)) {
192  std::cerr << "Unable to open input file "
193  << input_filenames[i]
194  << std::endl;
195  exit(EXIT_FAILURE);
196  }
197 
198  double tmp_last_time = 0;
199  double tmp_dt = 0;
200  AurynLong tmp_num_events = 0;
201  read_header( tmp, tmp_dt, tmp_num_events, tmp_last_time, input_filenames[i] );
202 
203  if ( debug_output ) {
204  std::cerr << "# Last frame in file " << i << ": " << tmp_num_events << std::endl;
205  }
206 
207  if ( dt == 0 ) {
208  dt = tmp_dt;
209  } else {
210  if ( dt != tmp_dt ) { // should not happen
211  std::cerr << "Not all input file headers match." << std::endl;
212  exit(EXIT_FAILURE);
213  }
214  }
215 
216  if ( tmp_last_time > last_time )
217  last_time = tmp_last_time;
218  }
219 
220 
221  if ( to_time < 0 ) {
222  to_time = last_time;
223  }
224 
225  if ( seconds_to_extract_from_end > 0 ) {
226  from_time = to_time-seconds_to_extract_from_end;
227  }
228 
229  if ( from_time < 0 ) from_time = 0.0 ;
230 
231  if ( from_time > to_time || from_time < 0 ) {
232  std::cerr << "Times must be positive and start "
233  "time needs to be < to time." << std::endl;
234  exit(EXIT_FAILURE);
235  }
236 
237  // translate second times into auryn time
238  AurynTime to_auryn_time = to_time/dt;
239 
240 
241  if ( debug_output ) {
242  std::cerr << "# Timestep: " << dt << std::endl;
243  std::cerr << "# Maxid: " << maxid << std::endl;
244  std::cerr << "# Sizeof SpikeEvent struct: " << sizeof(SpikeEvent_type) << std::endl;
245  std::cerr << "# Time of last event in files: " << last_time << std::endl;
246  std::cerr << "# From time: " << from_time << std::endl;
247  std::cerr << "# To time: " << to_time << std::endl;
248  }
249 
250 
251  // set all streams to respetive start frame
252  for ( unsigned int i = 0 ; i < inputs.size() ; ++i ) {
253  // compute start and end frames
254  AurynLong start_frame = find_frame(inputs[i], from_time/dt);
255 
256  // prepare input stream
257  inputs[i]->seekg (start_frame*sizeof(SpikeEvent_type), inputs[i]->beg);
258  inputs[i]->clear();
259  if ( debug_output ) {
260  std::cerr << "# Start frame stream "
261  << i << ": "
262  << start_frame << std::endl;
263  }
264  }
265 
266 
267  // read first frames from all files
268  std::vector<SpikeEvent_type> frames(inputs.size());
269  for ( unsigned int i = 0 ; i < frames.size() ; ++i ) {
270  inputs[i]->read((char*)&frames[i], sizeof(SpikeEvent_type));
271  }
272 
273  AurynTime time_reference = from_time/dt;
274  int decimal_places = -std::log(dt)/std::log(10)+2;
275 
276  // open output filestream if needed
277  std::ofstream of;
278  bool write_to_stdout = true;
279  if( !output_file_name.empty() ) {
280  write_to_stdout = false;
281  of.open( output_file_name.c_str(), std::ofstream::out );
282  of << std::fixed << std::setprecision(decimal_places);
283  }
284  // sets output format to right number of decimal places
285  std::cout << std::fixed << std::setprecision(decimal_places);
286 
287  while ( true ) {
288  // find smallest time reference
289  int current_stream = 0;
290  AurynLong mintime = std::numeric_limits<AurynLong>::max();
291  bool eofs = true;
292  for ( unsigned int i = 0 ; i < frames.size() ; ++i ) {
293  eofs = eofs && inputs[i]->eof();
294  if ( inputs[i]->eof() ) continue;
295  if ( frames[i].time < mintime ) {
296  mintime = frames[i].time;
297  current_stream = i;
298  }
299  }
300 
301  time_reference = mintime;
302  if ( time_reference >= to_auryn_time || eofs ) break;
303 
304  if ( debug_output && false ) {
305  std::cout << "# current_stream " << current_stream << std::endl;
306  std::cout << "# time_reference " << time_reference << std::endl;
307  }
308 
309  // output from next_stream
310  while ( frames[current_stream].time <= time_reference && !inputs[current_stream]->eof() ) {
311  if ( frames[current_stream].neuronID < maxid) {
312  if ( write_to_stdout )
313  std::cout << frames[current_stream].time*dt << " " << frames[current_stream].neuronID << "\n";
314  else
315  of << frames[current_stream].time*dt << " " << frames[current_stream].neuronID << "\n";
316 
317  }
318  inputs[current_stream]->read((char*)&frames[current_stream], sizeof(SpikeEvent_type));
319  }
320  }
321 
322  if ( !write_to_stdout )
323  of.close();
324 
325  // close input streams
326  for ( unsigned int i = 0 ; i < frames.size() ; ++i ) {
327  inputs[i]->close();
328  }
329 
330  return EXIT_SUCCESS;
331 }
void read_header(std::ifstream *input, double &dt, AurynLong num_events, double &last_time, std::string filename)
Definition: aube.cpp:59
Container class providing Auryn version number.
Definition: AurynVersion.h:37
static int revision_number
Definition: AurynVersion.h:41
unsigned long AurynLong
An unsigned long type used to count synapses or similar.
Definition: auryn_definitions.h:154
AurynLong find_frame(std::ifstream *file, AurynTime target)
Definition: aube.cpp:35
static int subversion
Definition: AurynVersion.h:40
static int version
Definition: AurynVersion.h:39
NeuronID AurynTime
Defines Auryns discrete time unit of the System clock. Change to AurynLong if 120h of simtime are not...
Definition: auryn_definitions.h:155
std::string string
Standard library string type which is imported into Auryn namespace.
Definition: auryn_definitions.h:156
unsigned int NeuronID
NeuronID is an unsigned integeger type used to index neurons in Auryn.
Definition: auryn_definitions.h:151
Auryn spike event for binary monitors.
Definition: auryn_definitions.h:194
Here is the call graph for this function:

◆ read_header()

void read_header ( std::ifstream *  input,
double &  dt,
AurynLong  num_events,
double &  last_time,
std::string  filename 
)
60 {
61  // get length of the file
62  SpikeEvent_type spike_data;
63  input->seekg (0, input->end);
64  num_events = input->tellg()/sizeof(SpikeEvent_type)-1;
65 
66  // read first entry to infer dt
67  input->seekg (0, input->beg);
68  input->read((char*)&spike_data, sizeof(SpikeEvent_type));
69  dt = 1.0/spike_data.time;
70 
71  // do some version checking
72  AurynVersion build;
73  NeuronID tag = spike_data.neuronID;
74  if ( tag/1000 != build.tag_binary_spike_monitor/1000 ) {
75  std::cerr << "Header not recognized. "
76  "Not a binary Auryn monitor file?"
77  << std::endl;
78  exit(EXIT_FAILURE);
79  }
80 
81  if ( tag != build.tag_binary_spike_monitor ) {
82  std::cerr << "# Warning: Either the Auryn version does not match "
83  "the version of this tool or this is not a spike "
84  "raster file." << std::endl;
85  // TODO tell user if it is a state file
86  }
87 
88  // read out last time
89  input->seekg (num_events*sizeof(SpikeEvent_type), input->beg);
90  input->read((char*)&spike_data, sizeof(SpikeEvent_type));
91  last_time = (spike_data.time+1)*dt;
92  // places last_time _behind_ the last time because we are the
93  // exclusive interval end
94 }
AurynTime time
Definition: auryn_definitions.h:196
Container class providing Auryn version number.
Definition: AurynVersion.h:37
static NeuronID tag_binary_spike_monitor
file signature for BinarySpikeMonitor files
Definition: AurynVersion.h:42
unsigned int NeuronID
NeuronID is an unsigned integeger type used to index neurons in Auryn.
Definition: auryn_definitions.h:151
Auryn spike event for binary monitors.
Definition: auryn_definitions.h:194