diff --git a/share/lib/hoc/mview/mview1.hoc b/share/lib/hoc/mview/mview1.hoc index bdd025484b..c8e849a063 100755 --- a/share/lib/hoc/mview/mview1.hoc +++ b/share/lib/hoc/mview/mview1.hoc @@ -9,6 +9,7 @@ objref this, realcells_, tobj, tobj1, mt, rc_classes, dparm, allsec objref ms, display, storecm, cdis, adis, acview, ncv, appv, pdis, gui objref topcelldis, distinctvalues, tvi, tvi2, kst, ksth, xml objref seclists, pyobj +objref mvncgrapher strdef tstr, tstr1, cond, name in_=0 @@ -112,7 +113,8 @@ proc init() {local i, n, icdis, ntop tobj = new List("NetCon") sprint(tstr, "%d NetCon objects", tobj.count) - display.top.append(new TreeViewItem(nil, tstr)) + mvncgrapher = new ModelViewNetConGrapher(this) + display.top.append(new TreeViewItem(nil, tstr, mvncgrapher, 1.7)) if (tobj.count != 0) { ncv = new ModelViewNetCon(tobj, display.top.object(display.top.count - 1), this) } diff --git a/share/lib/hoc/mview/mviewgui.hoc b/share/lib/hoc/mview/mviewgui.hoc index e15ee67ffc..32495b14e5 100755 --- a/share/lib/hoc/mview/mviewgui.hoc +++ b/share/lib/hoc/mview/mviewgui.hoc @@ -1,15 +1,16 @@ begintemplate ModelViewGUI -public b, sh, selsub, selsec, selpp, selected, grph, pgrph +public b, sh, selsub, selsec, selpp, selected, grph, pgrph, do_netcon_graph external nil, hoc_sf_ -objref modelview, this, b, sh, bsh, g, bg -objref all, svec, xvec, psh, yvec, tobj, xpvec +objref modelview, this, b, sh, bsh, g, bg, netcon_graph, bnetcon_graph +objref all, svec, xvec, psh, yvec, tobj, xpvec, pyobj strdef tstr proc init() { x = 0 j = 0 sh_map_ = 0 + netcon_graph_map_ = 0 g_map_ = 0 spacepl_ = 0 modelview=$o1 @@ -20,6 +21,7 @@ proc init() { proc destroy() { if (sh_map_) { sh_dismiss() } if (g_map_) { g_dismiss() } + if (netcon_graph_map_) {netcon_graph_dismiss() } modelview.destroy() objref modelview, sh, bsh, g, bg objref all, svec, xvec, psh, yvec, xpvec @@ -127,6 +129,30 @@ proc sh_dismiss() { bsh.unmap() } +proc netcon_graph_dismiss() { + netcon_graph_map_ = 0 + netcon_graph.unmap() +} + +proc do_netcon_graph() { + has_python = nrnpython("import neuron") + if (has_python) { + pyobj = new PythonObject() + if (!netcon_graph_map_) { + bnetcon_graph = new VBox() + bnetcon_graph.save("") + bnetcon_graph.ref(this) + bnetcon_graph.intercept(1) + netcon_graph = new Graph() + bnetcon_graph.intercept(0) + bnetcon_graph.map("NetCon connections", 100, 100, 500, 500) + bnetcon_graph.dismiss_action("netcon_graph_dismiss()") + netcon_graph_map_ = 1 + } + pyobj.neuron._show_cell_connectivity_grid(netcon_graph) + } +} + proc selsub() { shape() if (numarg() > 0) { diff --git a/share/lib/hoc/mview/ncview.hoc b/share/lib/hoc/mview/ncview.hoc index 3d2e60d7d0..755a58de07 100755 --- a/share/lib/hoc/mview/ncview.hoc +++ b/share/lib/hoc/mview/ncview.hoc @@ -86,3 +86,15 @@ proc selected() { } endtemplate ModelViewNetCon + + +begintemplate ModelViewNetConGrapher +public selected, mview +objref mview +proc init() { + mview = $o1 +} +proc selected() { + mview.gui.do_netcon_graph() +} +endtemplate ModelViewNetConGrapher diff --git a/share/lib/python/neuron/__init__.py b/share/lib/python/neuron/__init__.py index 6e12cd1e2c..7c161ca44a 100644 --- a/share/lib/python/neuron/__init__.py +++ b/share/lib/python/neuron/__init__.py @@ -1733,3 +1733,105 @@ def _mview_html_tree(hlist, inside_mechanisms_in_use=0): if _get_ipython() is not None: html_formatter = _get_ipython().display_formatter.formatters["text/html"] html_formatter.for_type(hoc.HocObject, _hocobj_html) + + +def _rect(gr, xlo, ylo, xhi, yhi, fill_color=None): + """draw a rectangle from (xlo, ylo) to (xhi, yhi) on Graph gr""" + rectangle = h.Glyph().path().m(0, 0).l(1, 0).l(1, 1).l(0, 1).close() + if fill_color is None: + rectangle.s() + else: + rectangle.fill(fill_color) + gr.glyph(rectangle, xlo, ylo, xhi - xlo, yhi - ylo, 0) + + +def _cell_type(cell): + if isinstance(cell, hoc.HocObject): + return cell.hname().split("[")[0] + return type(cell).__name__ + + +def _show_cell_connectivity_grid(gr): + gr.erase_all() + all_cells = set() + for sec in h.allsec(): + all_cells.add(sec.cell()) + + cell_types = {_cell_type(cell) for cell in all_cells} + + cells_by_type = {cell_type: [] for cell_type in cell_types} + for cell in all_cells: + cells_by_type[_cell_type(cell)].append(cell) + + cell_order = [ + cell + for cell_list in sorted(cells_by_type) + for cell in sorted(cells_by_type[cell_list], key=str) + ] + + # check for artifical cells being used + ncs = h.List("NetCon") + for my_nc in ncs: + if my_nc.precell() is None or my_nc.postcell() is None: + cell_order = [None] + cell_order + break + + # setup graph; hide axes + gr.size(0, 100, 0, 100) + gr.xaxis(3) + gr.yaxis(3) + + labels = [str(cell) for cell in cell_order] + right_edge = 20 + + # labels are relative to scene coordinates + gr.fixed(1) + + # labels going down + + # right justify, vertically center + gr.align(1, 0.5) + + for i, label in enumerate(labels): + if i == 0 and cell_order[0] is None: + label = "(Artifical Cells)" + gr.label(right_edge - 5, (len(labels) - i - 0.5) * 100 / (len(labels)), label) + + # labels going across + across_width = 100 - right_edge + across_each = across_width / len(labels) + y_placement = 105 # (len(labels) + 0.5) * 100 / len(labels) + + # bottom justify, horizontally center + gr.align(0.5, 1) + + for i, label in enumerate(labels): + if i == 0 and cell_order[0] is None: + label = "(Artifical Cells)" + gr.label(right_edge + (i + 0.5) * across_each, y_placement, label) + + ncs = h.List("NetCon") + for my_nc in ncs: + try: + i = cell_order.index(my_nc.precell()) + j = cell_order.index(my_nc.postcell()) + except ValueError: + continue + # we found a netcon; now draw the box + xlo = right_edge + j * across_each + ylo = (len(labels) - i - 1) * 100 / len(labels) + xhi = xlo + across_each + yhi = ylo + 100 / len(labels) + _rect(gr, xlo + 0.5, ylo + 0.5, xhi - 0.5, yhi - 0.5, 1) + + # add pre/post labels and dividing line + gr.beginline() + gr.line(-5, 110) + gr.line(right_edge - 0.5, 100) + gr.flush() + + gr.align(0, 0.5) + gr.label(-5, y_placement - 2, "PreSyn:") + gr.align(0, 1) + gr.label(right_edge - 10, y_placement + 5, "PostSyn:") + return gr