NEURON
prcellstate.cpp
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 #include <vector>
10 #include <map>
11 
12 #include "coreneuron/nrnconf.h"
20 
21 #define precision 15
22 namespace coreneuron {
23 static std::map<Point_process*, int> pnt2index; // for deciding if NetCon is to be printed
24 static int pntindex; // running count of printed point processes.
25 static std::map<NetCon*, DiscreteEvent*> map_nc2src;
26 static std::vector<int>* inv_permute_;
27 
28 static int permute(int i, NrnThread& nt) {
29  return nt._permute ? nt._permute[i] : i;
30 }
31 
32 static int inv_permute(int i, NrnThread& nt) {
33  nrn_assert(i >= 0 && i < nt.end);
34  if (!nt._permute) {
35  return i;
36  }
37  if (!inv_permute_) {
38  inv_permute_ = new std::vector<int>(nt.end);
39  for (int i = 0; i < nt.end; ++i) {
40  (*inv_permute_)[nt._permute[i]] = i;
41  }
42  }
43  return (*inv_permute_)[i];
44 }
45 
46 static int ml_permute(int i, Memb_list* ml) {
47  return ml->_permute ? ml->_permute[i] : i;
48 }
49 
50 // Note: cellnodes array is in unpermuted order.
51 
52 static void pr_memb(int type, Memb_list* ml, int* cellnodes, NrnThread& nt, FILE* f) {
54  return;
55 
56  bool header_printed = false;
57  int size = corenrn.get_prop_param_size()[type];
58  int psize = corenrn.get_prop_dparam_size()[type];
59  bool receives_events = corenrn.get_pnt_receive()[type];
60  int layout = corenrn.get_mech_data_layout()[type];
61  int cnt = ml->nodecount;
62  for (int iorig = 0; iorig < ml->nodecount; ++iorig) { // original index
63  int i = ml_permute(iorig, ml); // present index
64  int inode = ml->nodeindices[i]; // inode is the permuted node
65  int cix = cellnodes[inv_permute(inode, nt)]; // original index relative to this cell
66  if (cix >= 0) {
67  if (!header_printed) {
68  header_printed = true;
69  fprintf(f, "type=%d %s size=%d\n", type, corenrn.get_memb_func(type).sym, size);
70  }
71  if (receives_events) {
72  fprintf(f, "%d nri %d\n", cix, pntindex);
73  int k = nrn_i_layout(i, cnt, 1, psize, layout);
74  Point_process* pp = (Point_process*) nt._vdata[ml->pdata[k]];
75  pnt2index[pp] = pntindex;
76  ++pntindex;
77  }
78  for (int j = 0; j < size; ++j) {
79  int k = nrn_i_layout(i, cnt, j, size, layout);
80  fprintf(f, " %d %d %.*g\n", cix, j, precision, ml->data[k]);
81  }
82  }
83  }
84 }
85 
86 static void pr_netcon(NrnThread& nt, FILE* f) {
87  if (pntindex == 0) {
88  return;
89  }
90  // pnt2index table has been filled
91 
92  // List of NetCon for each of the NET_RECEIVE point process instances
93  // Also create the initial map of NetCon <-> DiscreteEvent (PreSyn)
94  std::vector<std::vector<NetCon*>> nclist(pntindex);
95  map_nc2src.clear();
96  int nc_cnt = 0;
97  for (int i = 0; i < nt.n_netcon; ++i) {
98  NetCon* nc = nt.netcons + i;
99  Point_process* pp = nc->target_;
100  std::map<Point_process*, int>::iterator it = pnt2index.find(pp);
101  if (it != pnt2index.end()) {
102  nclist[it->second].push_back(nc);
103  map_nc2src[nc] = nullptr;
104  ++nc_cnt;
105  }
106  }
107  fprintf(f, "netcons %d\n", nc_cnt);
108  fprintf(f, " pntindex srcgid active delay weights\n");
109 
110  /// Fill the NetCon <-> DiscreteEvent map with PreSyn-s
111  // presyns can come from any thread
112  for (int ith = 0; ith < nrn_nthread; ++ith) {
113  NrnThread& ntps = nrn_threads[ith];
114  for (int i = 0; i < ntps.n_presyn; ++i) {
115  PreSyn* ps = ntps.presyns + i;
116  for (int j = 0; j < ps->nc_cnt_; ++j) {
118  auto it_nc2src = map_nc2src.find(nc);
119  if (it_nc2src != map_nc2src.end()) {
120  it_nc2src->second = ps;
121  }
122  }
123  }
124  }
125 
126  /// Fill the NetCon <-> DiscreteEvent map with InputPreSyn-s
127  /// Traverse gid <-> InputPreSyn map and loop over NetCon-s of the
128  /// correspondent InputPreSyn. If NetCon is in the nc2src map,
129  /// remember its ips and the gid
130  std::map<NetCon*, int> map_nc2gid;
131  for (const auto& gid: gid2in) {
132  InputPreSyn* ips = gid.second; /// input presyn
133  for (int i = 0; i < ips->nc_cnt_; ++i) {
135  auto it_nc2src = map_nc2src.find(nc);
136  if (it_nc2src != map_nc2src.end()) {
137  it_nc2src->second = ips;
138  map_nc2gid[nc] = gid.first; /// src gid of the input presyn
139  }
140  }
141  }
142 
143  for (int i = 0; i < pntindex; ++i) {
144  for (int j = 0; j < (int) (nclist[i].size()); ++j) {
145  NetCon* nc = nclist[i][j];
146  int srcgid = -3;
147  auto it_nc2src = map_nc2src.find(nc);
148  if (it_nc2src != map_nc2src.end()) { // seems like there should be no NetCon which is
149  // not in the map
150  DiscreteEvent* de = it_nc2src->second;
151  if (de && de->type() == PreSynType) {
152  PreSyn* ps = (PreSyn*) de;
153  srcgid = ps->gid_;
154  Point_process* pnt = ps->pntsrc_;
155  if (srcgid < 0 && pnt) {
156  int type = pnt->_type;
157  fprintf(f,
158  "%d %s %d %.*g",
159  i,
161  nc->active_ ? 1 : 0,
162  precision,
163  nc->delay_);
164  } else if (srcgid < 0 && ps->thvar_index_ > 0) {
165  fprintf(
166  f, "%d %s %d %.*g", i, "v", nc->active_ ? 1 : 0, precision, nc->delay_);
167  } else {
168  fprintf(f,
169  "%d %d %d %.*g",
170  i,
171  srcgid,
172  nc->active_ ? 1 : 0,
173  precision,
174  nc->delay_);
175  }
176  } else {
177  fprintf(f,
178  "%d %d %d %.*g",
179  i,
180  map_nc2gid[nc],
181  nc->active_ ? 1 : 0,
182  precision,
183  nc->delay_);
184  }
185  } else {
186  fprintf(f, "%d %d %d %.*g", i, srcgid, nc->active_ ? 1 : 0, precision, nc->delay_);
187  }
188  int wcnt = corenrn.get_pnt_receive_size()[nc->target_->_type];
189  for (int k = 0; k < wcnt; ++k) {
190  fprintf(f, " %.*g", precision, nt.weights[nc->u.weight_index_ + k]);
191  }
192  fprintf(f, "\n");
193  }
194  }
195  // cleanup
196  nclist.clear();
197 }
198 
199 static void pr_realcell(PreSyn& ps, NrnThread& nt, FILE* f) {
200  // for associating NetCons with Point_process identifiers
201 
202  pntindex = 0;
203 
204  // threshold variable is a voltage
205  printf("thvar_index_=%d end=%d\n", inv_permute(ps.thvar_index_, nt), nt.end);
206  if (ps.thvar_index_ < 0 || ps.thvar_index_ >= nt.end) {
207  hoc_execerror("gid not associated with a voltage", 0);
208  }
209  int inode = ps.thvar_index_;
210 
211  // and the root node is ...
212  int rnode = inode;
213  while (rnode >= nt.ncell) {
214  rnode = nt._v_parent_index[rnode];
215  }
216 
217  // count the number of nodes in the cell
218  // do not assume all cell nodes except the root are contiguous
219  // cellnodes is an unpermuted vector
220  int* cellnodes = new int[nt.end];
221  for (int i = 0; i < nt.end; ++i) {
222  cellnodes[i] = -1;
223  }
224  int cnt = 0;
225  cellnodes[inv_permute(rnode, nt)] = cnt++;
226  for (int i = nt.ncell; i < nt.end; ++i) { // think of it as unpermuted order
227  if (cellnodes[inv_permute(nt._v_parent_index[permute(i, nt)], nt)] >= 0) {
228  cellnodes[i] = cnt++;
229  }
230  }
231  fprintf(f, "%d nodes %d is the threshold node\n", cnt, cellnodes[inv_permute(inode, nt)] - 1);
232  fprintf(f, " threshold %.*g\n", precision, ps.threshold_);
233  fprintf(f, "inode parent area a b\n");
234  for (int iorig = 0; iorig < nt.end; ++iorig)
235  if (cellnodes[iorig] >= 0) {
236  int i = permute(iorig, nt);
237  int ip = nt._v_parent_index[i];
238  fprintf(f,
239  "%d %d %.*g %.*g %.*g\n",
240  cellnodes[iorig],
241  ip >= 0 ? cellnodes[inv_permute(ip, nt)] : -1,
242  precision,
243  nt._actual_area[i],
244  precision,
245  nt._actual_a[i],
246  precision,
247  nt._actual_b[i]);
248  }
249  fprintf(f, "inode v\n");
250  for (int i = 0; i < nt.end; ++i)
251  if (cellnodes[i] >= 0) {
252  fprintf(f, "%d %.*g\n", cellnodes[i], precision, nt._actual_v[permute(i, nt)]);
253  }
254 
255  // each mechanism
256  for (NrnThreadMembList* tml = nt.tml; tml; tml = tml->next) {
257  pr_memb(tml->index, tml->ml, cellnodes, nt, f);
258  }
259 
260  // the NetCon info (uses pnt2index)
261  pr_netcon(nt, f);
262 
263  delete[] cellnodes;
264  pnt2index.clear();
265  if (inv_permute_) {
266  delete inv_permute_;
267  inv_permute_ = nullptr;
268  }
269 }
270 
271 int prcellstate(int gid, const char* suffix) {
272  // search the NrnThread.presyns for the gid
273  for (int ith = 0; ith < nrn_nthread; ++ith) {
274  NrnThread& nt = nrn_threads[ith];
275  for (int ip = 0; ip < nt.n_presyn; ++ip) {
276  PreSyn& ps = nt.presyns[ip];
277  if (ps.output_index_ == gid) {
278  // found it so create a <gid>_<suffix>.corenrn file
279  std::string filename = std::to_string(gid) + "_" + suffix + ".corenrn";
280  FILE* f = fopen(filename.c_str(), "w");
281  assert(f);
282  fprintf(f, "gid = %d\n", gid);
283  fprintf(f, "t = %.*g\n", precision, nt._t);
284  fprintf(f, "celsius = %.*g\n", precision, celsius);
285  if (ps.thvar_index_ >= 0) {
286  pr_realcell(ps, nt, f);
287  }
288  fclose(f);
289  return 1;
290  }
291  }
292  }
293  return 0;
294 }
295 } // namespace coreneuron
auto & get_memb_func(size_t idx)
Definition: coreneuron.hpp:135
union coreneuron::NetCon::@0 u
Point_process * target_
Definition: netcon.hpp:49
Point_process * pntsrc_
Definition: netcon.hpp:113
#define precision
Definition: prcellstate.cpp:21
#define cnt
Definition: tqueue.hpp:44
#define i
Definition: md1redef.h:19
static RNG::key_type k
Definition: nrnran123.cpp:9
#define assert(ex)
Definition: hocassrt.h:24
printf
Definition: extdef.h:5
THIS FILE IS AUTO GENERATED DONT MODIFY IT.
NrnThread * nrn_threads
Definition: multicore.cpp:56
int nrn_i_layout(int icnt, int cnt, int isz, int sz, int layout)
This function return the index in a flat array of a matrix coordinate (icnt, isz).
int prcellstate(int gid, const char *suffix)
int nrn_nthread
Definition: multicore.cpp:55
static void pr_realcell(PreSyn &ps, NrnThread &nt, FILE *f)
static int inv_permute(int i, NrnThread &nt)
Definition: prcellstate.cpp:32
std::map< int, InputPreSyn * > gid2in
Definition: nrn_setup.cpp:160
static std::map< NetCon *, DiscreteEvent * > map_nc2src
Definition: prcellstate.cpp:25
static void pr_memb(int type, Memb_list *ml, int *cellnodes, NrnThread &nt, FILE *f)
Definition: prcellstate.cpp:52
double celsius
void hoc_execerror(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:39
static void pr_netcon(NrnThread &nt, FILE *f)
Definition: prcellstate.cpp:86
CoreNeuron corenrn
Definition: multicore.cpp:53
static int ml_permute(int i, Memb_list *ml)
Definition: prcellstate.cpp:46
static std::vector< int > * inv_permute_
Definition: prcellstate.cpp:26
std::vector< NetCon * > netcon_in_presyn_order_
InputPreSyn.nc_index_ to + InputPreSyn.nc_cnt_ give the NetCon*.
Definition: nrn_setup.cpp:163
static int pntindex
Definition: prcellstate.cpp:24
static std::map< Point_process *, int > pnt2index
Definition: prcellstate.cpp:23
static int permute(int i, NrnThread &nt)
Definition: prcellstate.cpp:28
std::string to_string(const T &obj)
#define PreSynType
Definition: netcon.hpp:26
static char suffix[256]
Definition: nocpout.cpp:135
#define nrn_assert(x)
assert()-like macro, independent of NDEBUG status
Definition: nrn_assert.h:33
size_t j
short type
Definition: cabvars.h:10
virtual int type() const
Definition: netcon.hpp:36
NrnThreadMembList * tml
Definition: multicore.hpp:80
NrnThreadMembList * next
Definition: multicore.hpp:33