Prev TOC Refs Next


No matter how powerful and robust its computational engine may be, the real utility of any software tool depends largely on its ease of use. Therefore a great deal of effort has been invested in the design of the simulation environment provided by NEURON. In this section we first briefly consider general aspects of the high-level language used for writing NEURON programs. Then we turn to an example of a model of a nerve cell to introduce specific aspects of the user environment, after which we cover these features more thoroughly.

4.1 The hoc interpreter

NEURON incorporates a programming language based on hoc, a floating point calculator with C-like syntax described by Kernighan and Pike (1984). This interpreter has been extended by the addition of object-oriented syntax (not including polymorphism or inheritance) that can be used to implement abstract data types and data encapsulation. Other extensions include functions that are specific to the domain of neural simulations, and functions that implement a graphical user interface (see below).
With hoc one can quickly write short programs that meet most problem-specific needs. The interpreter is used to execute simulations, customize the user interface, optimize parameters, analyze experimental data, calculate new variables such as impulse propagation velocity, etc..
NEURON simulations are not subject to the performance penalty often associated with interpreted (as opposed to compiled) languages because computationally intensive tasks are carried out by highly efficient precompiled code. Some of these tasks are related to integration of the cable equation and others are involved in the emulation of biological mechanisms that generate and regulate chemical and electrical signals.
NEURON provides a built-in implementation of the microemacs text editor. Since the choice of a programming editor is highly personal, NEURON will also accept hoc code in the form of straight ASCII files created with any other editor.

4.2 A specific example

Here we show how NEURON might be used to model the cell in the top of Fig. 4.1. Comments in the hoc code are preceded by double slashes (//), and code blocks are enclosed in curly brackets ({}).

4.2.1 First step: establish model topology

One very important feature of NEURON is that it allows the user to think about models in terms that are familiar to the neurophysiologist, keeping numerical issues (e.g. number of spatial segments) entirely separate from the specification of morphology and biophysical properties. As noted in a previous section (3.2 Spatial discretization . . . ), this separation is achieved through the use of one-dimensional cable "sections" as the basic building block from which model cells are constructed. These sections can be connected together to form any kind of branched cable and endowed with properties which may vary with position along their length.

Figure 4.1. Top: cartoon of a neuron with a soma, three dendrites, and an unmyelinated axon (not to scale). The diameter of the spherical soma is 50 um. Each dendrite is 200 um long and tapers uniformly along its length from 10 um diameter at its site of origin on the soma, to 3 um at its distal end. The unmyelinated cylindrical axon is 1000 um long and has a diameter of 1 um. An electrode (not shown) is inserted into the soma for intracellular injection of a stimulating current. Bottom: topology of a NEURON model that represents this cell.

The idealized neuron in Fig. 4.1 has several anatomical features whose existence and spatial relationships we want the model to include: a cell body (soma), three dendrites, and an unmyelinated axon. The following hoc code sets up the basic topology of the model:
create soma, axon, dendrite[3]
connect axon(0), soma(0)
for i=0,2 { connect dendrite[i](0), soma(1) }

The program starts by creating named sections that correspond to the important anatomical features of the cell. These sections are attached to each other using connect statements. As noted previously, each section has a normalized position parameter x which ranges from 0 at one end to 1 at the other. Because the axon and dendrites arise from opposite sides of the cell body, they are connected to the 0 and 1 ends of the soma section (see bottom of Fig. 4.1). A child section can be attached to any location on the parent, but attachment at locations other than 0 or 1 is generally employed only in special cases such as spines on dendrites.

4.2.2 Second step: assign anatomical and biophysical properties

Next we set the anatomical and biophysical properties of each section. Each section has its own segmentation, length, and diameter parameters, so it is necessary to indicate which section is being referenced. There are several ways to declare which is the currently accessed section, but here the most convenient is to precede blocks of statements with the appropriate section name.
// specify anatomical and biophysical properties
soma {
  nseg = 1   // compartmentalization parameter
  L = 50     // [um] length
  diam = 50  // [um] diameter
  insert hh  // standard Hodgkin-Huxley currents
  gnabar_hh = 0.5*0.120  // max HH sodium conductance
axon {
  nseg = 20
  L = 1000
  diam = 1
  insert hh
for i = 0,2  dendrite[i] {
  nseg = 5
  L = 200
  diam(0:1) = 10:3  // dendritic diameter tapers
  insert pas     // standard passive current
  e_pas = -65    // [mv] equilibrium potential 
                 //   for passive current
  g_pas = 0.001  // [siemens/cm2]
                 //   conductance for passive current

The fineness of the spatial grid is determined by the compartmentalization parameter nseg (see 3.2 Spatial discretization . . . ). Here the soma is lumped into a single compartment (nseg = 1), while the axon and each of the dendrites are broken into several subcompartments (nseg = 20 and 5, respectively).
In this example, we specify the geometry of each section by assigning values directly to section length and diameter. This creates a "stylized model." Alternatively, one can use the "3-D method," in which NEURON computes section length and diameter from a list of (x, y, z, diam) measurements (see 4.5 Specifying geometry: stylized vs. 3-D).
Since the axon is a cylinder, the corresponding section has a fixed diameter along its entire length. The spherical soma is represented by a cylinder with the same surface area as the sphere. The dimensions and electrical properties of the soma are such that its membrane will be nearly isopotential, so the cylinder approximation is not a significant source of error. If chemical signals such as intracellular ion concentrations were important in this model, it would be necessary to approximate not only the surface area but also the volume of the soma.
Unlike the axon, the dendrites become progressively narrower with distance from the soma. Furthermore, unlike the soma, they are too long to be lumped into a single compartment with constant diameter. The taper of the dendrites is accommodated by assigning a sequence of decreasing diameters to their segments. This is done through the use of "range variables," which are discussed later (4.4 Range variables).
In this model the soma and axon contain Hodgkin-Huxley (HH) sodium, potassium, and leak channels (Hodgkin and Huxley 1952), while the dendrites have constant, linear ("passive") ionic conductances . The insert statement assigns the biophysical mechanisms that govern electrical signals in each section. Particular values are set for the density of sodium channels on the soma (gnabar_hh) and for the ionic conductance and equilibrium potential of the passive current in the dendrites (g_pas and e_pas). More information about membrane mechanisms is presented in 4.6 Density mechanisms and point processes.

4.2.3 Third step: attach stimulating electrodes

This code emulates the use of an electrode to inject a stimulating current into the soma by placing a current pulse stimulus in the middle of the soma section. The stimulus starts at t = 1 ms, lasts for 0.1 ms, and has an amplitude of 60 nA.
objref stim
soma stim = new IClamp(0.5)  // put it in middle of soma
stim.del = 1    // [ms] delay
stim.dur = 0.1  // [ms] duration
stim.amp = 60   // [nA] amplitude

The stimulating electrode is an example of a point process. Point processes are discussed in 4.6 Density mechanisms and point processes.

4.2.4 Fourth step: control simulation time course

At this point all model parameters have been specified. All that remains is to define the simulation parameters, which govern the time course of the simulation, and write some code that executes the simulation.
This is generally done in two procedures. The first procedure initializes the membrane potential and the states of the inserted mechanisms (channel states, ionic concentrations, extracellular potential next to the membrane). The second procedure repeatedly calls the built-in single step integration function fadvance() and saves, plots, or computes functions of the desired output variables at each step. In this procedure it is possible to change the values of model parameters during a run.
dt = 0.05  // [ms] integration time step
tstop = 5  // [ms]
finitialize(-65)  // initialize membrane potential, 
                  //   state variables, and time

proc integrate() {
  print t, soma.v(0.5)   // show starting time 
                         //   and initial somatic 
                         //   membrane potential
  while (t < tstop) {
    fadvance()  // advance solution by dt
    // function calls to save or plot results 
    //   would go here
    print t, soma.v(0.5) // show present time
                         //   and somatic 
                         //   membrane potential
    // statements that change model parameters 
    //   would go here

The built-in function finitialize() initializes time t to 0, membrane potential v to - 65 mv throughout the model, and the HH state variables m, n and h to their steady state values at v = - 65 mv. Initialization can also be performed with a user-written routine if there are special requirements that finitialize() cannot accommodate, such as nonuniform membrane potential.
Both the integration time step dt and the solution time t are global variables. For this example dt = 50 us. The while(){} statement repeatedly calls fadvance(), which integrates the model equations over the interval dt and increments t by dt on each call. For this example, the time and somatic membrane potential are displayed at each step. This loop exits when t > = tstop.
When this program is first processed by the NEURON interpreter, the model is set up and initiated but the integrate() procedure is not executed. When the user enters an integrate() statement in the NEURON interpreter window, the simulation advances for 5 ms using 50 us time steps.

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.