NEURON
datapath.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include <map>
3 #include <cstdio>
4 #include <InterViews/resource.h>
5 #include "hoclist.h"
6 #if HAVE_IV
7 #include "graph.h"
8 #endif
9 #include "datapath.h"
10 #include "ivocvect.h"
11 
12 #include "nrnoc2iv.h"
13 #include "membfunc.h"
14 
15 #include "parse.hpp"
19 
20 /*static*/ class PathValue {
21  public:
22  PathValue();
23  ~PathValue() = default;
24  std::string path{};
26  double original;
27  char* str;
28 };
30  str = NULL;
31  sym = NULL;
32 }
33 
35  private:
36  friend class HocDataPaths;
37  HocDataPathImpl(int, int);
39 
40  void search();
41  void found(double*, const char*, Symbol*);
42  void found(char**, const char*, Symbol*);
43  PathValue* found_v(void*, const char*, Symbol*);
44 
45  void search(Objectdata*, Symlist*);
46  void search_vectors();
47  void search_pysec();
48  void search(Section*);
49  void search(Node*, double x);
50  void search(Point_process*, Symbol*);
51  void search(Prop*, double x);
52 
53  private:
54  std::map<void*, PathValue*> table_;
55  std::vector<std::string> strlist_;
58 };
59 
60 #define sentinal 123456789.e15
61 
63 
64 HocDataPaths::HocDataPaths(int size, int pathstyle) {
65  if (!sym_vec) {
72  }
73  impl_ = new HocDataPathImpl(size, pathstyle);
74 }
75 
77  delete impl_;
78 }
79 
81  return impl_->pathstyle_;
82 }
83 
84 void HocDataPaths::append(double* pd) {
85  // printf("HocDataPaths::append\n");
86  if (pd && impl_->table_.find((void*) pd) == impl_->table_.end()) {
87  impl_->table_.emplace((void*) pd, new PathValue);
88  ++impl_->count_;
89  }
90 }
91 
93  // printf("HocDataPaths::search\n");
94  impl_->search();
95  if (impl_->count_ > impl_->found_so_far_) {
96  // printf("HocDataPaths:: didn't find paths to all the pointers\n");
97  // this has proved to be too often a false alarm since most panels are
98  // in boxes controlled by objects which have no reference but are
99  // deleted when the window is closed
100  }
101 }
102 
103 std::string HocDataPaths::retrieve(double* pd) const {
104  assert(impl_->pathstyle_ != 2);
105  // printf("HocDataPaths::retrieve\n");
106  auto const it = impl_->table_.find(pd);
107  if (it != impl_->table_.end()) {
108  return it->second->path;
109  }
110  return {};
111 }
112 
113 Symbol* HocDataPaths::retrieve_sym(double* pd) const {
114  // printf("HocDataPaths::retrieve\n");
115  auto const it = impl_->table_.find(pd);
116  if (it != impl_->table_.end()) {
117  return it->second->sym;
118  }
119  return nullptr;
120 }
121 
122 void HocDataPaths::append(char** pd) {
123  // printf("HocDataPaths::append\n");
124  if (*pd && impl_->table_.find((void*) pd) == impl_->table_.end()) {
125  PathValue* pv = new PathValue;
126  pv->str = *pd;
127  impl_->table_.emplace((void*) pd, pv);
128  ++impl_->count_;
129  }
130 }
131 
132 std::string HocDataPaths::retrieve(char** pd) const {
133  // printf("HocDataPaths::retrieve\n");
134  auto const it = impl_->table_.find(pd);
135  if (it != impl_->table_.end()) {
136  return it->second->path;
137  }
138  return {};
139 }
140 
141 /*------------------------------*/
142 HocDataPathImpl::HocDataPathImpl(int size, int pathstyle) {
143  pathstyle_ = pathstyle;
144  size_ = size;
145  count_ = 0;
146  found_so_far_ = 0;
147 }
148 
150  for (auto& kv: table_) {
151  PathValue* pv = kv.second;
152  delete pv;
153  }
154 }
155 
157  found_so_far_ = 0;
158  for (auto& it: table_) {
159  PathValue* pv = it.second;
160  if (pv->str) {
161  char** pstr = (char**) it.first;
162  *pstr = nullptr;
163  } else {
164  double* pd = (double*) it.first;
165  pv->original = *pd;
166  *pd = sentinal;
167  }
168  }
169  if (pathstyle_ > 0) {
172  } else {
175  }
176  if (found_so_far_ < count_) {
177  search_pysec();
178  }
179  if (found_so_far_ < count_) {
180  search_vectors();
181  }
182  for (auto& it: table_) {
183  PathValue* pv = it.second;
184  if (pv->str) {
185  char** pstr = (char**) it.first;
186  *pstr = pv->str;
187  } else {
188  double* pd = (double*) it.first;
189  *pd = pv->original;
190  }
191  }
192 }
193 
194 PathValue* HocDataPathImpl::found_v(void* v, const char* buf, Symbol* sym) {
195  PathValue* pv;
196  if (pathstyle_ != 2) {
197  char path[500];
198  std::string cs{};
199  for (const auto& str: strlist_) {
200  Sprintf(path, "%s%s.", cs.c_str(), str.c_str());
201  cs = path;
202  }
203  Sprintf(path, "%s%s", cs.c_str(), buf);
204  const auto& it = table_.find(v);
205  if (it == table_.end()) {
206  hoc_warning("table lookup failed for pointer for-", path);
207  return nullptr;
208  }
209  pv = it->second;
210  if (pv->path.empty()) {
211  pv->path = path;
212  pv->sym = sym;
213  ++found_so_far_;
214  }
215  // printf("HocDataPathImpl::found %s\n", path);
216  } else {
217  const auto& it = table_.find(v);
218  if (it == table_.end()) {
219  hoc_warning("table lookup failed for pointer for-", sym->name);
220  return nullptr;
221  }
222  pv = it->second;
223  if (!pv->sym) {
224  pv->sym = sym;
225  ++found_so_far_;
226  }
227  }
228  return pv;
229 }
230 
231 void HocDataPathImpl::found(double* pd, const char* buf, Symbol* sym) {
232  PathValue* pv = found_v((void*) pd, buf, sym);
233  if (pv) {
234  *pd = pv->original;
235  }
236 }
237 
238 void HocDataPathImpl::found(char** pstr, const char* buf, Symbol* sym) {
239  PathValue* pv = found_v((void*) pstr, buf, sym);
240  if (pv) {
241  *pstr = pv->str;
242  } else {
243  hoc_assign_str(pstr, "couldn't find");
244  }
245 }
246 
248  Symbol* sym;
249  int i, total;
250  char buf[200];
251  std::string cs{};
252  if (sl)
253  for (sym = sl->first; sym; sym = sym->next) {
254  if (sym->cpublic != 2) {
255  switch (sym->type) {
256  case VAR: {
257  double* pd;
258  if (sym->subtype == NOTUSER) {
259  pd = object_pval(sym, od);
260  total = hoc_total_array_data(sym, od);
261  } else if (sym->subtype == USERDOUBLE) {
262  pd = sym->u.pval;
263  total = 1;
264  } else {
265  break;
266  }
267  for (i = 0; i < total; ++i) {
268  if (pd[i] == sentinal) {
269  Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od));
270  cs = buf;
271  found(pd + i, cs.c_str(), sym);
272  }
273  }
274  } break;
275  case STRING: {
276  char** pstr = object_pstr(sym, od);
277  if (*pstr == NULL) {
278  Sprintf(buf, "%s", sym->name);
279  cs = buf;
280  found(pstr, cs.c_str(), sym);
281  }
282  } break;
283  case OBJECTVAR: {
284  if (pathstyle_ > 0) {
285  break;
286  }
287  Object** obp = object_pobj(sym, od);
288  total = hoc_total_array_data(sym, od);
289  for (i = 0; i < total; ++i)
290  if (obp[i] && !obp[i]->recurse) {
291  cTemplate* t = (obp[i])->ctemplate;
292  if (!t->constructor) {
293  // not the this pointer
294  if (obp[i]->u.dataspace != od) {
295  Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od));
296  cs = buf;
297  strlist_.push_back(cs);
298  obp[i]->recurse = 1;
299  search(obp[i]->u.dataspace, obp[i]->ctemplate->symtable);
300  obp[i]->recurse = 0;
301  strlist_.pop_back();
302  }
303  } else {
304  /* point processes */
305  if (t->is_point_) {
306  Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od));
307  cs = buf;
308  strlist_.push_back(cs);
309  search((Point_process*) obp[i]->u.this_pointer, sym);
310  strlist_.pop_back();
311  }
312  /* seclists, object lists */
313  }
314  }
315  } break;
316  case SECTION: {
317  total = hoc_total_array_data(sym, od);
318  for (i = 0; i < total; ++i) {
319  hoc_Item** pitm = object_psecitm(sym, od);
320  if (pitm[i]) {
321  Sprintf(buf, "%s%s", sym->name, hoc_araystr(sym, i, od));
322  cs = buf;
323  strlist_.push_back(cs);
324  search(hocSEC(pitm[i]));
325  strlist_.pop_back();
326  }
327  }
328  } break;
329  case TEMPLATE: {
330  cTemplate* t = sym->u.ctemplate;
331  hoc_Item* q;
332  ITERATE(q, t->olist) {
333  Object* obj = OBJ(q);
334  Sprintf(buf, "%s[%d]", sym->name, obj->index);
335  cs = buf;
336  strlist_.push_back(cs);
337  if (!t->constructor) {
338  search(obj->u.dataspace, t->symtable);
339  } else {
340  if (t->is_point_) {
341  search((Point_process*) obj->u.this_pointer, sym);
342  }
343  }
344  strlist_.pop_back();
345  }
346  } break;
347  }
348  }
349  }
350 }
351 
353  char buf[200];
354  std::string cs{};
356  hoc_Item* q;
357  ITERATE(q, t->olist) {
358  Object* obj = OBJ(q);
359  Sprintf(buf, "%s[%d]", sym_vec->name, obj->index);
360  cs = buf;
361  strlist_.push_back(cs);
362  Vect* vec = (Vect*) obj->u.this_pointer;
363  int size = vec->size();
364  double* pd = vector_vec(vec);
365  for (size_t i = 0; i < size; ++i) {
366  if (pd[i] == sentinal) {
367  Sprintf(buf, "x[%zu]", i);
368  found(pd + i, buf, sym_vec);
369  }
370  }
371  strlist_.pop_back();
372  }
373 }
374 
376 #if USE_PYTHON
377  std::string cs{};
378  hoc_Item* qsec;
379  // ForAllSections(sec)
380  ITERATE(qsec, section_list) {
381  Section* sec = hocSEC(qsec);
382  if (sec->prop && sec->prop->dparam[PROP_PY_INDEX].get<void*>()) {
383  cs = secname(sec);
384  strlist_.push_back(cs);
385  search(sec);
386  strlist_.pop_back();
387  }
388  }
389 #endif
390 }
391 
393  if (sec->prop->dparam[2].get<double>() == sentinal) {
394  found(&(sec->prop->dparam[2].literal_value<double>()), "L", sym_L);
395  }
396  if (sec->prop->dparam[4].get<double>() == sentinal) {
397  found(&(sec->prop->dparam[4].literal_value<double>()), "rallbranch", sym_rallbranch);
398  }
399  if (sec->prop->dparam[7].get<double>() == sentinal) {
400  found(&(sec->prop->dparam[7].literal_value<double>()), "Ra", sym_Ra);
401  }
402  if (!sec->parentsec && sec->parentnode) {
403  search(sec->parentnode, sec->prop->dparam[1].get<double>());
404  }
405  for (int i = 0; i < sec->nnode; ++i) {
406  search(sec->pnode[i], nrn_arc_position(sec, sec->pnode[i]));
407  }
408 }
409 void HocDataPathImpl::search(Node* nd, double x) {
410  char buf[100];
411  if (NODEV(nd) == sentinal) {
412  Sprintf(buf, "v(%g)", x);
413  // the conversion below yields a pointer that is potentially invalidated
414  // by almost any Node operation
415  found(static_cast<double*>(nd->v_handle()), buf, sym_v);
416  }
417 
418 #if EXTRACELLULAR
419  if (nd->extnode) {
420  int i;
421  for (i = 0; i < nlayer; ++i) {
422  if (nd->extnode->v[i] == sentinal) {
423  if (i == 0) {
424  Sprintf(buf, "vext(%g)", x);
425  } else {
426  Sprintf(buf, "vext[%d](%g)", i, x);
427  }
428  found(&(nd->extnode->v[i]), buf, sym_vext);
429  }
430  }
431  }
432 #endif
433 
434  Prop* p;
435  for (p = nd->prop; p; p = p->next) {
436  if (!memb_func[p->_type].is_point) {
437  search(p, x);
438  }
439  }
440 }
441 
443  if (pp->prop) {
444  search(pp->prop, -1);
445  }
446 }
447 
449  char buf[200];
450  int type = prop->_type;
451  Symbol* sym = memb_func[type].sym;
452  Symbol* psym;
453  double* pd;
454  int i, imax, k = 0, ir, kmax = sym->s_varn;
455 
456  for (k = 0; k < kmax; ++k) {
457  psym = sym->u.ppsym[k];
458  if (psym->subtype == NRNPOINTER) {
459  continue;
460  }
461  ir = psym->u.rng.index;
462  if (memb_func[type].hoc_mech) {
463  pd = prop->ob->u.dataspace[ir].pval;
464  } else {
466  // skip as it was handled by caller
467  continue;
468  } else {
469  pd = static_cast<double*>(prop->param_handle_legacy(ir));
470  }
471  }
472  imax = hoc_total_array_data(psym, 0);
473  for (i = 0; i < imax; ++i) {
474  if (pd[i] == sentinal) {
475  if (x < 0) {
476  Sprintf(buf, "%s%s", psym->name, hoc_araystr(psym, i, 0));
477  } else {
478  Sprintf(buf, "%s%s(%g)", psym->name, hoc_araystr(psym, i, 0), x);
479  }
480  found(pd + i, buf, psym);
481  }
482  }
483  }
484 }
#define STRING
Definition: bbslsrv.cpp:9
const char * secname(Section *sec)
name of section (for use in error messages)
Definition: cabcode.cpp:1674
double nrn_arc_position(Section *sec, Node *node)
Definition: cabcode.cpp:1755
HocDataPathImpl(int, int)
Definition: datapath.cpp:142
PathValue * found_v(void *, const char *, Symbol *)
Definition: datapath.cpp:194
std::map< void *, PathValue * > table_
Definition: datapath.cpp:54
void search_vectors()
Definition: datapath.cpp:352
std::vector< std::string > strlist_
Definition: datapath.cpp:55
void search_pysec()
Definition: datapath.cpp:375
void found(double *, const char *, Symbol *)
Definition: datapath.cpp:231
virtual ~HocDataPaths()
Definition: datapath.cpp:76
int style()
Definition: datapath.cpp:80
HocDataPathImpl * impl_
Definition: datapath.h:24
void append(double *)
Definition: datapath.cpp:84
Symbol * retrieve_sym(double *) const
Definition: datapath.cpp:113
HocDataPaths(int=1000, int pathstyle=0)
Definition: datapath.cpp:64
std::string retrieve(double *) const
Definition: datapath.cpp:103
void search()
Definition: datapath.cpp:92
size_t size() const
Definition: ivocvect.h:42
char * str
Definition: datapath.cpp:27
Symbol * sym
Definition: datapath.cpp:25
~PathValue()=default
double original
Definition: datapath.cpp:26
std::string path
Definition: datapath.cpp:24
Symbol * hoc_table_lookup(const char *, Symlist *)
Definition: symbol.cpp:48
#define v
Definition: md1redef.h:11
#define sec
Definition: md1redef.h:20
#define i
Definition: md1redef.h:19
#define prop
Definition: md1redef.h:38
#define sentinal
Definition: datapath.cpp:60
static Symbol * sym_L
Definition: datapath.cpp:62
Symlist * hoc_top_level_symlist
Definition: symdir.cpp:16
static Symbol * sym_Ra
Definition: datapath.cpp:62
static Symbol * sym_vext
Definition: datapath.cpp:62
static Symbol * sym_v
Definition: datapath.cpp:62
static Symbol * sym_rallbranch
Definition: datapath.cpp:62
static Symbol * sym_vec
Definition: datapath.cpp:62
Objectdata * hoc_top_level_data
Definition: hoc_oop.cpp:123
Symlist * hoc_built_in_symlist
Definition: symbol.cpp:28
static RNG::key_type k
Definition: nrnran123.cpp:9
char buf[512]
Definition: init.cpp:13
size_t hoc_total_array_data(const Symbol *s, Objectdata *obd)
Definition: hoc_oop.cpp:95
void hoc_assign_str(char **cpp, const char *buf)
Definition: code.cpp:2263
char * hoc_araystr(Symbol *sym, int index, Objectdata *obd)
Definition: code.cpp:2281
#define assert(ex)
Definition: hocassrt.h:24
#define USERDOUBLE
Definition: hocdec.h:84
#define NOTUSER
Definition: hocdec.h:82
#define hocSEC(q)
Definition: hoclist.h:87
#define OBJ(q)
Definition: hoclist.h:88
#define NRNPOINTER
Definition: membfunc.hpp:83
#define EXTRACELL
Definition: membfunc.hpp:61
#define ITERATE(itm, lst)
Definition: model.h:18
double * vector_vec(IvocVect *v)
Definition: ivocvect.cpp:19
void hoc_warning(const char *s1, const char *s2)
Definition: nrnoc_aux.cpp:44
std::size_t vext_pseudoindex()
Definition: membfunc.h:150
int Sprintf(char(&buf)[N], const char *fmt, Args &&... args)
Redirect sprintf to snprintf if the buffer size can be deduced.
Definition: wrap_sprintf.h:14
size_t q
size_t p
std::vector< Memb_func > memb_func
Definition: init.cpp:145
short type
Definition: cabvars.h:10
hoc_List * section_list
Definition: init.cpp:113
char ** object_pstr(Symbol *sym, Objectdata *od)
Definition: oc2iv.h:76
Object ** object_pobj(Symbol *sym, Objectdata *od)
Definition: oc2iv.h:79
hoc_Item ** object_psecitm(Symbol *sym, Objectdata *od)
Definition: oc2iv.h:82
double * object_pval(Symbol *sym, Objectdata *od)
Definition: oc2iv.h:70
#define PROP_PY_INDEX
Definition: section.h:230
#define NODEV(n)
Definition: section_fwd.hpp:60
#define nlayer
Definition: section_fwd.hpp:31
#define NULL
Definition: spdefs.h:105
double * v
Definition: section_fwd.hpp:40
Definition: section.h:105
auto v_handle()
Definition: section.h:153
Extnode * extnode
Definition: section.h:199
Prop * prop
Definition: section.h:190
Definition: hocdec.h:173
void * this_pointer
Definition: hocdec.h:178
Objectdata * dataspace
Definition: hocdec.h:177
int index
Definition: hocdec.h:175
cTemplate * ctemplate
Definition: hocdec.h:180
union Object::@47 u
short recurse
Definition: hocdec.h:186
A point process is computed just like regular mechanisms.
Definition: section_fwd.hpp:77
Definition: section.h:231
Definition: model.h:47
Symbol * next
Definition: hocdec.h:133
union Symbol::@28 u
short cpublic
Definition: hocdec.h:107
Symbol ** ppsym
Definition: hocdec.h:125
struct Symbol::@45::@46 rng
short type
Definition: model.h:48
long subtype
Definition: model.h:49
cTemplate * ctemplate
Definition: hocdec.h:126
unsigned s_varn
Definition: hocdec.h:129
char * name
Definition: model.h:61
double * pval
Definition: hocdec.h:112
Definition: hocdec.h:75
Symbol * first
Definition: hocdec.h:76
Symlist * symtable
Definition: hocdec.h:148