NEURON
nrn_filehandler.hpp
Go to the documentation of this file.
1 /*
2 # =============================================================================
3 # Copyright (c) 2016 - 2021 Blue Brain Project/EPFL
4 #
5 # See top-level LICENSE file for details.
6 # =============================================================================.
7 */
8 
9 #pragma once
10 
11 #include <iostream>
12 #include <fstream>
13 #include <vector>
14 #include <cmath>
15 #include <sys/stat.h>
16 
19 
20 namespace coreneuron {
21 /** Encapsulate low-level reading of coreneuron input data files.
22  *
23  * Error handling is simple: abort()!
24  *
25  * Reader will abort() if native integer size is not 4 bytes.
26  *
27  * All automatic allocations performed by read_int_array()
28  * and read_dbl_array() methods use new [].
29  */
30 
31 // @todo: remove this static buffer
32 const int max_line_length = 1024;
33 
34 class FileHandler {
35  std::fstream F; //!< File stream associated with reader.
36  std::ios_base::openmode current_mode; //!< File open mode (not stored in fstream)
37  int chkpnt; //!< Current checkpoint number state.
38  int stored_chkpnt; //!< last "remembered" checkpoint number state.
39  /** Read a checkpoint line, bump our chkpnt counter, and assert equality.
40  *
41  * Checkpoint information is represented by a sequence "checkpt %d\n"
42  * where %d is a scanf-compatible representation of the checkpoint
43  * integer.
44  */
46 
47  // FileHandler is not copyable.
48  FileHandler(const FileHandler&) = delete;
49  FileHandler& operator=(const FileHandler&) = delete;
50 
51  public:
53  : chkpnt(0)
54  , stored_chkpnt(0) {}
55 
56  explicit FileHandler(const std::string& filename);
57 
58  /** Preserving chkpnt state, move to a new file. */
59  void open(const std::string& filename, std::ios::openmode mode = std::ios::in);
60 
61  /** Is the file not open */
62  bool fail() const {
63  return F.fail();
64  }
65 
66  static bool file_exist(const std::string& filename);
67 
68  /** nothing more to read */
69  bool eof();
70 
71  /** Query chkpnt state. */
72  int checkpoint() const {
73  return chkpnt;
74  }
75 
76  /** Explicitly override chkpnt state. */
77  void checkpoint(int c) {
78  chkpnt = c;
79  }
80 
81  /** Record current chkpnt state. */
84  }
85 
86  /** Restored last recorded chkpnt state. */
89  }
90 
91  /** Parse a single integer entry.
92  *
93  * Single integer entries are represented by their standard
94  * (C locale) text representation, followed by a newline.
95  * Extraneous characters following the integer but preceding
96  * the newline are ignore.
97  */
98  int read_int();
99 
100  /** Parse a neuron mapping count entries
101  *
102  * Reads neuron mapping info which is represented by
103  * gid, #sections, #segments, #section lists
104  */
105  void read_mapping_count(int* gid, int* nsec, int* nseg, int* nseclist);
106 
107  /** Reads number of cells in parsing file */
108  void read_mapping_cell_count(int* count);
109 
110  /** Parse a neuron section segment mapping
111  *
112  * Read count no of mappings for section to segment
113  */
114  template <typename T>
116  int nsec, nseg, n_scan;
117  size_t total_lfp_factors;
118  int num_electrodes;
119  char line_buf[max_line_length], name[max_line_length];
120 
121  F.getline(line_buf, sizeof(line_buf));
122  n_scan = sscanf(
123  line_buf, "%s %d %d %zd %d", name, &nsec, &nseg, &total_lfp_factors, &num_electrodes);
124 
125  nrn_assert(n_scan == 5);
126 
127  mapinfo->name = std::string(name);
128 
129  if (nseg) {
130  auto sec = read_vector<int>(nseg);
131  auto seg = read_vector<int>(nseg);
132 
133  std::vector<double> lfp_factors;
134  if (total_lfp_factors > 0) {
135  lfp_factors = read_vector<double>(total_lfp_factors);
136  }
137 
138  int factor_offset = 0;
139  for (int i = 0; i < nseg; i++) {
140  mapinfo->add_segment(sec[i], seg[i]);
141  ntmapping->add_segment_id(seg[i]);
142  int factor_offset = i * num_electrodes;
143  if (total_lfp_factors > 0) {
144  // Abort if the factors contains a NaN
145  nrn_assert(count_if(lfp_factors.begin(), lfp_factors.end(), [](double d) {
146  return std::isnan(d);
147  }) == 0);
148  std::vector<double> segment_factors(lfp_factors.begin() + factor_offset,
149  lfp_factors.begin() + factor_offset +
150  num_electrodes);
151  cmap->add_segment_lfp_factor(seg[i], segment_factors);
152  }
153  }
154  }
155  return nseg;
156  }
157 
158  /** Defined flag values for parse_array() */
159  enum parse_action { read, seek };
160 
161  /** Generic parse function for an array of fixed length.
162  *
163  * \tparam T the array element type: may be \c int or \c double.
164  * \param p pointer to the target in memory for reading into.
165  * \param count number of items of type \a T to parse.
166  * \param action whether to validate and skip (\c seek) or
167  * copy array into memory (\c read).
168  * \return the supplied pointer value.
169  *
170  * Error if \a count is non-zero, \a flag is \c read, and
171  * the supplied pointer \p is null.
172  *
173  * Arrays are represented by a checkpoint line followed by
174  * the array items in increasing index order, in the native binary
175  * representation of the writing process.
176  */
177  template <typename T>
178  inline T* parse_array(T* p, size_t count, parse_action flag) {
179  if (count > 0 && flag != seek)
180  nrn_assert(p != 0);
181 
183  switch (flag) {
184  case seek:
185  F.seekg(count * sizeof(T), std::ios_base::cur);
186  break;
187  case read:
188  F.read((char*) p, count * sizeof(T));
189  break;
190  }
191 
192  nrn_assert(!F.fail());
193  return p;
194  }
195 
196  // convenience interfaces:
197 
198  /** Read an integer array of fixed length. */
199  template <typename T>
200  inline T* read_array(T* p, size_t count) {
201  return parse_array(p, count, read);
202  }
203 
204  /** Allocate and read an integer array of fixed length. */
205  template <typename T>
206  inline T* read_array(size_t count) {
207  return parse_array(new T[count], count, read);
208  }
209 
210  template <typename T>
211  inline std::vector<T> read_vector(size_t count) {
212  std::vector<T> vec(count);
213  parse_array(vec.data(), count, read);
214  return vec;
215  }
216 
217  /** Close currently open file. */
218  void close();
219 
220  /** Write an 1D array **/
221  template <typename T>
222  void write_array(T* p, size_t nb_elements) {
223  nrn_assert(F.is_open());
224  nrn_assert(current_mode & std::ios::out);
226  F.write((const char*) p, nb_elements * (sizeof(T)));
227  nrn_assert(!F.fail());
228  }
229 
230  /** Write a padded array. nb_elements is number of elements to write per line,
231  * line_width is full size of a line in nb elements**/
232  template <typename T>
233  void write_array(T* p,
234  size_t nb_elements,
235  size_t line_width,
236  size_t nb_lines,
237  bool to_transpose = false) {
238  nrn_assert(F.is_open());
239  nrn_assert(current_mode & std::ios::out);
241  T* temp_cpy = new T[nb_elements * nb_lines];
242 
243  if (to_transpose) {
244  for (size_t i = 0; i < nb_lines; i++) {
245  for (size_t j = 0; j < nb_elements; j++) {
246  temp_cpy[i + j * nb_lines] = p[i * line_width + j];
247  }
248  }
249  } else {
250  memcpy(temp_cpy, p, nb_elements * sizeof(T) * nb_lines);
251  }
252  // AoS never use padding, SoA is translated above, so one write
253  // operation is enought in both cases
254  F.write((const char*) temp_cpy, nb_elements * sizeof(T) * nb_lines);
255  nrn_assert(!F.fail());
256  delete[] temp_cpy;
257  }
258 
259  template <typename T>
260  FileHandler& operator<<(const T& scalar) {
261  nrn_assert(F.is_open());
262  nrn_assert(current_mode & std::ios::out);
263  F << scalar;
264  nrn_assert(!F.fail());
265  return *this;
266  }
267 
268  private:
269  /* write_checkpoint is callable only for our internal uses, making it accesible to user, makes
270  * file format unpredictable */
272  F << "chkpnt " << chkpnt++ << "\n";
273  }
274 };
275 } // namespace coreneuron
T * read_array(size_t count)
Allocate and read an integer array of fixed length.
std::ios_base::openmode current_mode
File open mode (not stored in fstream)
void read_checkpoint_assert()
Read a checkpoint line, bump our chkpnt counter, and assert equality.
void write_array(T *p, size_t nb_elements, size_t line_width, size_t nb_lines, bool to_transpose=false)
Write a padded array.
void write_array(T *p, size_t nb_elements)
Write an 1D array.
parse_action
Defined flag values for parse_array()
T * read_array(T *p, size_t count)
Read an integer array of fixed length.
FileHandler(const FileHandler &)=delete
std::vector< T > read_vector(size_t count)
int stored_chkpnt
last "remembered" checkpoint number state.
void read_mapping_cell_count(int *count)
Reads number of cells in parsing file.
FileHandler & operator=(const FileHandler &)=delete
void record_checkpoint()
Record current chkpnt state.
bool eof()
nothing more to read
void checkpoint(int c)
Explicitly override chkpnt state.
bool fail() const
Is the file not open.
int read_mapping_info(T *mapinfo, NrnThreadMappingInfo *ntmapping, CellMapping *cmap)
Parse a neuron section segment mapping.
FileHandler & operator<<(const T &scalar)
void open(const std::string &filename, std::ios::openmode mode=std::ios::in)
Preserving chkpnt state, move to a new file.
void read_mapping_count(int *gid, int *nsec, int *nseg, int *nseclist)
Parse a neuron mapping count entries.
void restore_checkpoint()
Restored last recorded chkpnt state.
int chkpnt
Current checkpoint number state.
int checkpoint() const
Query chkpnt state.
void close()
Close currently open file.
std::fstream F
File stream associated with reader.
static bool file_exist(const std::string &filename)
T * parse_array(T *p, size_t count, parse_action flag)
Generic parse function for an array of fixed length.
int read_int()
Parse a single integer entry.
#define sec
Definition: md1redef.h:20
#define i
Definition: md1redef.h:19
static int c
Definition: hoc.cpp:169
const char * name
Definition: init.cpp:16
THIS FILE IS AUTO GENERATED DONT MODIFY IT.
const int max_line_length
Encapsulate low-level reading of coreneuron input data files.
#define nrn_assert(x)
assert()-like macro, independent of NDEBUG status
Definition: nrn_assert.h:33
NrnMappingInfo mapinfo
mapping information
size_t p
size_t j
Compartment mapping information for a cell.
void add_segment_lfp_factor(const int segment_id, std::vector< double > &factors)
add the lfp electrode factors of a segment_id
Compartment mapping information for NrnThread.
void add_segment_id(const int segment_id)
add a new segment