Prev TOC Refs Next

4.7 Graphical interface

The user is not limited to operating within the traditional "code-based command-mode environment." Among its many extensions to hoc, NEURON includes functions for implementing a fully graphical, windowed interface. Through this interface, and without having to write any code at all, the user can effortlessly create and arrange displays of menus, parameter value editors, graphs of parameters and state variables, and views of the model neuron. Anatomical views, called "space plots," can be explored, revealing what mechanisms and point processes are present and where they are located.
The purpose of NEURON's graphical interface is to promote a match between what the user thinks is inside the computer, and what is actually there. These visualization enhancements are a major aid to maintaining conceptual control over the simulation because they provide immediate answers to questions about what is being represented in the computer.
The interface has no provision for constructing neuronal topology, a conscious design choice based on the strong likelihood that a graphical toolbox for building neuronal topologies would find little use. Small models with simple topology are so easily created in hoc that a graphical topology editor is unnecessary. More complex models are too cumbersome to deal with using a graphical editor. It is best to express the topological specifications of complex stereotyped models through algorithms, written in hoc, that generate the topology automatically. Biologically realistic models often involve hundreds or thousands of sections, whose dimensions and interconnections are contained in large data tables generated by hours of painstaking quantitative morphometry. These tables are commonly read by hoc procedures that in turn create and connect the required sections without operator intervention.
The basic features of the graphical interface and how to use it to monitor and control simulations are discussed elsewhere (Moore and Hines 1996). However, several sophisticated analyis and simulation tools that have special utility for nerve simulation are worthy of mention.
  • The "Function Fitter" optimizes a parameterized mathematical expression to minimize the least squared difference between the expression and data.
  • The "Run Fitter" allows one to optimize several parameters of a complete neuron model to experimental data. This is most useful in the context of voltage clamp data which is contaminated by incomplete space clamp or models that cannot be expressed in closed form, such as kinetic schemes for channel conductance.
  • The "Electrotonic Workbench" plots small signal input and transfer impedance and voltage attenuation as functions of space and frequency (Carnevale et al. 1996a, b). These plots include the neuromorphic (Carnevale et al. 1995) and L vs. x (O'Boyle et al. 1996) renderings of the electrotonic transformation (Brown et al. 1992; Tsai et al. 1994b; Zador et al. 1995). By revealing the effectiveness of signal transfer, the Workbench quickly provides insight into the "functional shape" of a neuron.
All interaction with these and other tools takes place in the graphical interface and no interpreter programming is needed to use them. However, they are constructed entirely within the interpreter and can be modified when special needs require.

4.8 Object-oriented syntax

4.8.1 Neurons

It is often convenient to deal with groups of sections that are related. Therefore NEURON provides a data class called a SectionList that can be used to identify subsets of sections. Section lists fit nicely with the "regular expression" method of selecting sections, used in earlier implementations of NEURON, in that
  1. the section list is easily constructed by using regular expressions to add and delete sections
  2. after the list is constructed it is available for reuse
  3. it is much more efficient to loop over the sections in a section list than to pick out the sections accepted by a combination of regular expressions
This code
  objref alldend
  alldend = new SectionList()
  forsec "dend" alldend.append()
  forsec alldend print secname()
forms a list of all the sections whose names contain the string "dend" and then iterates over the list, printing the name of each section in it. For the example program presented in this report, this would generate the following output in the NEURON interpreter window
  dendrite[0]
  dendrite[1]
  dendrite[2]
although in this very simple example it would clearly have been easy enough to loop over the array of dendrites directly, e.g.
  for i = 0,2 {
    dendrite[i] print secname()
  }
4.8.2 Networks

To help the user manage very large simulations, the interpreter syntax has been extended to facilitate the construction of hierarchical objects. This is illustrated by the following code fragment, which specifies a pattern for a simple stylized neuron consisting of three dendrites connected to one end of a soma and an axon connected to the other end.
begintemplate Cell1 
  public soma, dendrite, axon
  create soma, dendrite[3], axon
  proc init() {
    for i=0,2 connect dendrite[i](0), soma(0)
    connect axon(0), soma(1)
    axon insert hh
  }
endtemplate Cell1

Whenever a new instance of this pattern is created, the init() procedure automatically connects the soma, dendrite, and axon sections together. A complete pattern would also specify default membrane properties as well as the number of segments for each section.
Names that can be referenced outside the pattern are listed in the public statement. In this case, since init is not in the list, the user could not re-initialize by calling the init() procedure. Public names are referenced through a dot notation.
The particular benefit of using templates ("classes" in standard object oriented terminology) is the fact that they can be employed to create any number of instances of a pattern. For example,
  objref cell[10][10]
  for i=0,9 for j=0,9 cell[i][j]=new Cell1()

creates an array of 100 objects of type Cell1 that can be referenced individually via the object variable cell. In this example, cell[4][5].axon.gnabar_hh(0.5) is the value of the maximum HH sodium conductance in the middle of the axon of cell[4][5].
As this example implies, templates offer a natural syntax for the creation of networks. However it is entirely up to the user to logically organize the templates in such a way that they appropriately reflect the structure of the problem. Generally, any given structural organization can be viewed as a hierarchy of container classes, such as cells, microcircuits, layers, or networks. The important issue is how much effort is required for the concrete network representation to support a range of logical views of the same abstract network. A logical view that organizes the cells differently may not be easy to compute if the network is built as an elaborate hierarchy. This kind of pressure tends to encourage relatively flat organizations that make it easier to implement functions that search for specific information. The bottom line is that network simulation design remains an ad hoc process that requires careful programming judgement.
One very important class of logical views that are not generally organizable as a hierarchy are those of synaptic organization. In connecting cells with synapses, one is often driven to deal with general graphs, which is to say, no structure at all.
In addition to the notions of classes and objects (a synapse is an object with a pre- and a postsynaptic logical connection) the interpreter offers one other fundamental language feature that can be useful in dealing with objects that are collections of other objects. This is the notion of "iterators," taken from the Sather programming language (Murer et al. 1996). This is a separation of the process of iteration from that of "what is to be done for each item." If a programmer implements one or more iterators in a collection class, the user of the class does not need to know how the class indexes its items. Instead the class will return each item in turn for execution in the context of the loop body. This allows the user to write
  for layer1.synapses(syn, type) {
    // statements that manipulate the object 
    // reference named "syn" (The iterator 
    // causes "syn" to refer, in turn, 
    // to each synapse of a certain type 
    // in the layer1 object)
  }

without being aware of the possibly complicated process of picking out these synapses from the layer (that is the responsibility of the author of the class of which layer1 is an instance).
It is to be sadly emphasized that these kinds of language features, though very useful, do not impose any policy with regard to the design decisions users must make in building their networks. Different programmers express very different designs on the same language base, with the consequence that it is more often than not infeasible to reconcile slightly different representations of even very similar concepts.
An example of a useful way to deal uniformly with the issue of synaptic connectivity is the policy implemented in NEURON by Lytton (1996). This implementation uses the normal NMODL methodology to define a synaptic conductance model and enclose it within a framework that manages network connectivity.


Prev TOC Refs Next


Address questions and inquiries to
Michael Hines or Ted Carnevale

Digital preprint of "The NEURON Simulation Environment" by M.L. Hines and N.T. Carnevale, Neural Computation, Volume 9, Number 6 (August 15, 1997), pp. 1179-1209. Copyright © 1997 by the Massachusetts Institute of Technology, all rights reserved.
HTML formatting and graphics for page navigation copyright © 1997 by N.T. Carnevale amd M.L. Hines.