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