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