Architecture of CNModel ======================= CNModel is built in a layered architecture that provides both high-level tools for constructing and simulating networks, as well as low-level access to the individual components. The model consists of three major pieces: *cell types*, which describe the morphology and membrane physiology of the various cell types in the cochlear nucleus; *synapse types*, which describe the strength, kinetics, and short-term plasticity of the many synaptic connections; and *populations*, which describe the aggregate organization of cell types, including their distribution within the nucleus and their patterns of connectivity. .. figure:: architecture.svg Cells ----- The cell types found in the cochlear nucleus (bushy, t-stellate, etc.) are each represented in CNModel as classes that inherit from the base `Cell` class. One instance of any of these classes represents exactly one neuron, and internally manages any number of NEURON sections and mechanisms. Each class is responsible for determining the morphology and intrinsic membrane properties of the cell it represents. Additionally, cell classes define the properties of their synapses in a cooperative manner: the pre- snd postsynaptic cells each create half of the synapse. Morphology can be procedurally generated (usually a single somatic section, perhaps with another for a dendrite and/or axon), or it can be loaded from an SWC file. After the cell morphology is established, the membrane is "decorated" with channels using a `ChannelDecorator` object. Cell classes may be further divided into a class hierarchy. For example, the base `DStellate` class is further inherited by `DStellateRothman` and `DStellateEager` classes that each implement different D-stellate models that have been published previously. To simplify (and in many cases to automate) the creation of cells each base cell class (`Bushy`, `SGC`, `TStellate`, etc.) implements a `create` method that can be used to generate instances from any of the subclasses. Synapses -------- Every synapse in CNModel is represented by an instance of the `Synapse` class. This class contains two objects: a `Terminal`, and a `PSD`. Synapses are created by calling the `connect` method of the presynaptic cell with the postsynaptic cell as an argument:: pre_cell.connect(post_cell) When `connect` is called, the presynaptic terminal is created by calling ``pre_cell.make_terminal()``, and the postsynaptic receptors are created by calling ``post_cell.make_psd()``. In this way, both pre- and postsynaptic cells are given a chance to influence the creation of the synapse. CNModel implements most synapses in two different ways. The first is a simple synapse that implements variable amplitude, short-term plasticity, and double- exponential rise/fall kinetics. This synapse is relatively efficient to compute and simple to configure. The second synapse implementation is a much more physiologically detailed model that includes stochastic release from multiple release zones per terminal, synaptic cleft diffusion, and state models of postsynaptic receptors. This synapse is computationally expensive but may capture important behaviors that are not possible with the simpler implementation. Populations ----------- Populations are objects that encapsulate a group of cells sharing a common cell class. Each base `Cell` class has a corresponding `Population` class that implements the organization of many cells within the nucleus and the patterns of connectivity between populations. Conceptually, a `Population` represents *all* cells of a particular type within the nucleus. When a population is created, it initially decides how many cells is will represent and how to distribute properties across those cells. For example, an `SGC` population describes 10k cells distributed uniformly across the tonotopic axis. Initially, none of these 10k cells are created; rather, each cell is simply represented as a virtual placeholder, and only instantiated when it is explicitly requested or when it is required to satisfy the input requirements for another cell. Populations are connected to each other in much the same way cells are:: pre_pop.connect(post_pop) Like the virtual cells, however, this connection does not create any synapses, but instead merely records the fact that one population of cells projects to another. Once the populations of interest are created and connected, the user then manually instantiates only the cells that they wish to record from, and finally the entire network of presynaptic inputs is automatically instantiated. Because populations manage the creation of synaptic connections between large groups of neurons, they are also responsible for ensuring that the appropriate patterns of connectivity are followed. For example, this allows us to ensure that bushy cells are automatically connected to auditory nerve fibers coming from a relatively narrow window across the tonotopic axis, whereas D-stellate cells integrate the same inputs across a broader window. Physiological parameters ------------------------ Throughout the model we use physiological parameters (channel kinetics, synaptic strengths, convergence ratios, etc.) that are often derived from published reports. In an attempt to make the provenance of these parameters clear, we have separated them from the source code and embedded them in annotated tables. These tables are found in `cnmodel/data`, and are automatically parsed by the model as they are needed. Morphology ---------- The model implements the ability to use morphological reconstructions of cells, as rendered in hoc files, the native NEURON format. These reconstructions can be decorated with ion channels and synapses according to pre-specified tables or pre-defined rules. Unit testing ------------ CNModel attempts to reproduce several specific published observations. The complexity of the model makes it quite fragile--small modifications to one physiological parameter may have unexpected (and sometimes unnoticed) consequences in the output of the model. To combat this unavoidable fragility, CNModel includes a large battery of unit tests that are used to ensure the model output is stable across modifications and platforms, and that it does reproduce our target observations within reasonable limits. As such, any modification to the model should usually be followed soon after by running the unit tests (these depend on the py.test package and may be invoked by running the included `test.py` script). Auditory nerve input -------------------- CNModel builds from the auditory periphery model developed by Zilany et al. (2014). The periphery model converts auditory stimuli into spike trains for auditory nerve fibers of a specific CF and SR group. CNModel uses the Python version of the auditory periphery model as implemented by Rudnicki and Hemmert (available from https://github.com/mrkrd/cochlea). This version does not require MATLAB, and in some simulations may run slightly faster because there is no delay associated with loading (and unloading) MATLAB. The interface is otherwise exactly the same, and the model type can be selected at runtime. An alternative approach is to use the original auditory periphery model. Because this model was developed in MATLAB, CNModel uses a Python-to-MATLAB bridge that transparently invokes the periphery model in a background process. When using CNModel, is is generally not necessary to manually interact with MATLAB in any way; this interaction is wrapped within functions in the `cnmodel/an_model` subpackage. At present, there is no mechanism for feedback from the cochlear nucleus model back into the auditory periphery model. As such, the output of the periphery model is a convenient place to do some caching--we can precompute auditory nerve spike trains in response to various sound stimuli and reuse those spike trains to improve the computational performance of the nucleus model. This caching is performed automatically, but relies on the use of `Sound` objects (described below) as a mechanism for storing and retrieving cached spike trains. Generating sound stimuli ------------------------ Sound stimuli are defined as subclasses of `cnmodel.util.sound.Sound`. Each subclass (for example, `TonePip` and `NoisePip`) defines the function for generating a sound waveform, but also provides a unique key that is used to store and retrieve auditory nerve spike trains that were generated with a particular stimulus. `Sound` objects may be passed directly to `SGC` cells or populations, and the necessary spike trains will be automatically computed (or read from cache).