-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add the lmorpho utility back to Arbor The original utility was removed because it was a maintenance burden with no users. Now users are requesting the feature, this PR adds the old code, and updates it to work with the new morphology description API.
- Loading branch information
Showing
8 changed files
with
1,045 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -556,3 +556,4 @@ install( | |
cmake/FindUnwind.cmake | ||
DESTINATION "${cmake_config_dir}") | ||
|
||
add_subdirectory(lmorpho) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
add_executable(lmorpho lmorpho.cpp lsystem.cpp lsys_models.cpp) | ||
|
||
target_link_libraries(lmorpho PRIVATE arbor arbor-sup ext-tinyopt arborio) | ||
|
||
# TODO: resolve public headers | ||
target_link_libraries(lmorpho PRIVATE arbor-private-headers) | ||
|
||
install(TARGETS lmorpho RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# `lmporho` — generate random neuron morphologies | ||
|
||
`lmorpho` implements an L-system geometry generator for the purpose of | ||
generating a series of artificial neuron morphologies as described by a set of | ||
stasticial parameters. | ||
|
||
## Method | ||
|
||
The basic algorithm used is that of [Burke (1992)][burke1992], with extensions | ||
for embedding in 3-d taken from [Ascoli (2001)][ascoli2001]. | ||
|
||
A dendritic tree is represented by a piece-wise linear embedding of a rooted | ||
tree into R³×R⁺, describing the position in space and non-negative radius. | ||
Morphologies are represented as a sequence of these trees together with a point | ||
and radius describing a (spherical) soma. | ||
|
||
The generation process for a tree successively grows the terminal points by | ||
some length ΔL each step, changing its orientation each step according to a | ||
random distribution. After growing, there is a radius-dependent probability | ||
that it will bifurcate or terminate. Parameters describing these various | ||
probability distributions constitute the L-system model. | ||
|
||
The distributions used in [Ascoli (2001)][ascoli2001] can be constant (i.e. not | ||
random), uniform over some interval, truncated normal, or a mixture | ||
distribution of these. In the present version of the code, mixture | ||
distributions are not supported. | ||
|
||
## Output | ||
|
||
Generated morphologies can be output either in | ||
[SWC format](http://research.mssm.edu/cnic/swc.html), or as 'parent vectors', | ||
which describe the topology of the associated tree. | ||
|
||
Entry _i_ of the (zero-indexed) parent vector gives the index of the proximal | ||
unbranched section to which it connects. Somata have a parent index of -1. | ||
|
||
Morphology information can be written one each to separate files or | ||
concatenated. If concatenated, the parent vector indices will be shifted as | ||
required to maintain consistency. | ||
|
||
## Models | ||
|
||
Two L-system parameter sets are provided as 'built-in'; if neither model is | ||
selected, a simple, non-biological default model is used. | ||
|
||
As mixture distributions are not yet supported in `lmorpho`, these models are | ||
simplified approximations to those in the literature as described below. | ||
|
||
### Motor neuron model | ||
|
||
The 'motoneuron' model corresponds to the adult cat spinal alpha-motoneuron | ||
model described in [Ascoli (2001)][ascoli2001], based in turn on the model of | ||
[Burke (1992)][burke1992]. | ||
|
||
The model parameters in Ascoli are not complete; missing parameters were taken | ||
from the corresponding ArborVitae model parameters in the same paper, and | ||
somatic diameters were taken from [Cullheim (1987)][cullheim1987]. | ||
|
||
### Purkinke neuron model | ||
|
||
The 'purkinke' model corresponds to the guinea pig Purkinje cell model from | ||
[Ascoli (2001)][ascoli2001], which was fit to data from [Rapp | ||
(1994)][rapp1994]. Somatic diameters are a simple fit to the three measurements | ||
in the original source. | ||
|
||
Some required parameters are not recorded in [Ascoli (2001)][ascoli2001]; | ||
the correlation component `diam_child_a` and the `length_step` ΔL are | ||
taken from the corresponding L-Neuron parameter description in the | ||
[L-Neuron database](l-neuron-database). These should be verified by | ||
fitting against the digitized morphologies as found in the database. | ||
|
||
Produced neurons from this model do not look especially realistic. | ||
|
||
### Other models | ||
|
||
There is not yet support for loading in arbitrary parameter sets, or for | ||
translating or approximating the parameters that can be found in the | ||
[L-Neuron database][l-neuron-database]. Support for parameter estimation | ||
from a population of discretized morphologies would be useful. | ||
|
||
## References | ||
|
||
1. Ascoli, G. A., Krichmar, J. L., Scorcioni, R., Nasuto, S. J., Senft, S. L. | ||
and Krichmar, G. L. (2001). Computer generation and quantitative morphometric | ||
analysis of virtual neurons. _Anatomy and Embryology_ _204_(4), 283–301. | ||
[DOI: 10.1007/s004290100201][ascoli2001] | ||
|
||
2. Burke, R. E., Marks, W. B. and Ulfhake, B. (1992). A parsimonious description | ||
of motoneuron dendritic morphology using computer simulation. | ||
_The Journal of Neuroscience_ _12_(6), 2403–2416. [online][burke1992] | ||
|
||
3. Cullheim, S., Fleshman, J. W., Glenn, L. L., and Burke, R. E. (1987). | ||
Membrane area and dendritic structure in type-identified triceps surae alpha | ||
motoneurons. _The Journal of Comparitive Neurology_ _255_(1), 68–81. | ||
[DOI: 10.1002/cne.902550106][cullheim1987] | ||
|
||
4. Rapp, M., Segev, I. and Yaom, Y. (1994). Physiology, morphology and detailed | ||
passive models of guinea-pig cerebellar Purkinje cells. | ||
_The Journal of Physiology_, _474_, 101–118. | ||
[DOI: 10.1113/jphysiol.1994.sp020006][rapp1994]. | ||
|
||
|
||
[ascoli2001]: http://dx.doi.org/10.1007/s004290100201 | ||
"Ascoli et al. (2001). Computer generation […] of virtual neurons." | ||
|
||
[burke1992]: http://www.jneurosci.org/content/12/6/2403 | ||
"Burke et al. (1992). A parsimonious description of motoneuron dendritic morphology […]" | ||
|
||
[cullheim1987]: http://dx.doi.org/10.1002/cne.902550106 | ||
"Cullheim et al. (1987). Membrane area and dendritic structure in […] alpha motoneurons." | ||
|
||
[rapp1994]: http://dx.doi.org/10.1113/jphysiol.1994.sp020006 | ||
"Rapp et al. (1994). Physiology, morphology […] of guinea-pig cerebellar Purkinje cells." | ||
|
||
[l-neuron-database]: http://krasnow1.gmu.edu/cn3/L-Neuron/database/index.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
#include <algorithm> | ||
#include <iostream> | ||
#include <fstream> | ||
#include <map> | ||
#include <sstream> | ||
#include <vector> | ||
|
||
#include <tinyopt/tinyopt.h> | ||
|
||
#include "lsystem.hpp" | ||
#include "lsys_models.hpp" | ||
|
||
#include <arbor/cable_cell.hpp> | ||
#include <arborio/cableio.hpp> | ||
#include <arborio/label_parse.hpp> | ||
|
||
const char* usage_str = | ||
"[OPTION]...\n" | ||
"\n" | ||
" -n, --count=N Number of morphologies to generate.\n" | ||
" -m, --model=MODEL Use L-system MODEL for generation (see below).\n" | ||
" --acc=FILE Output morphologies as ACC to FILE.\n" | ||
" -h, --help Emit this message and exit.\n" | ||
"\n" | ||
"Generate artificial neuron morphologies based on L-system descriptions.\n" | ||
"\n" | ||
"If a FILE argument contains a '%', then one file will be written for\n" | ||
"each generated morphology, with the '%' replaced by the index of the\n" | ||
"morphology, starting from zero.\n" | ||
"A FILE argument of '-' corresponds to standard output.\n" | ||
"\n" | ||
"Currently supported MODELs:\n" | ||
" motoneuron Adult cat spinal alpha-motoneurons, based on models\n" | ||
" and data in Burke 1992 and Ascoli 2001.\n" | ||
" purkinje Guinea pig Purkinje cells, basd on models and data\n" | ||
" from Rapp 1994 and Ascoli 2001.\n"; | ||
|
||
int main(int argc, char** argv) { | ||
// options | ||
int n_morph = 1; | ||
std::optional<unsigned> rng_seed = 0; | ||
lsys_param P; | ||
bool help = false; | ||
std::optional<std::string> acc_file; | ||
|
||
std::pair<const char*, const lsys_param*> models[] = { | ||
{"motoneuron", &alpha_motoneuron_lsys}, | ||
{"purkinje", &purkinje_lsys} | ||
}; | ||
|
||
|
||
try { | ||
for (auto arg = argv+1; *arg; ) { | ||
bool ok = false; | ||
ok |= (n_morph << to::parse<int>(arg, "--n", "--count")).has_value(); | ||
ok |= (rng_seed << to::parse<int>(arg, "--s", "--seed")).has_value(); | ||
ok |= (acc_file << to::parse<std::string>(arg, "-f", "--acc")).has_value(); | ||
const lsys_param* o; | ||
if((o << to::parse<const lsys_param*>(arg, to::keywords(models), "-m", "--model")).has_value()) { | ||
P = *o; | ||
} | ||
ok |= (help << to::parse(arg, "-h", "--help")).has_value(); | ||
if (!ok) throw to::option_error("unrecognized argument", *arg); | ||
} | ||
|
||
if (help) { | ||
to::usage(argv[0], usage_str); | ||
return 0; | ||
} | ||
|
||
std::minstd_rand g; | ||
if (rng_seed) { | ||
g.seed(rng_seed.value()); | ||
} | ||
|
||
using namespace arborio::literals; | ||
|
||
auto apical = apical_lsys; | ||
auto basal = basal_lsys; | ||
|
||
for (int i = 0; i < n_morph; ++i) { | ||
const arb::segment_tree morph = generate_morphology(P.diam_soma, std::vector<lsys_param>{apical, basal}, g); | ||
|
||
arb::label_dict labels; | ||
labels.set("soma", "(tag 1)"_reg); | ||
labels.set("basal", "(tag 3)"_reg); | ||
labels.set("apical", "(tag 4)"_reg); | ||
arb::decor decor; | ||
|
||
arb::cable_cell cell(morph, labels, decor); | ||
|
||
if(acc_file) { | ||
std::string filename = acc_file.value(); | ||
const std::string toReplace("%"); | ||
auto pos = filename.find(toReplace); | ||
if(pos != std::string::npos) { | ||
filename.replace(pos, toReplace.length(), std::to_string(i)); | ||
} | ||
|
||
if(filename == "-") { | ||
arborio::write_component(std::cout, cell); | ||
} else { | ||
std::ofstream of(filename); | ||
arborio::write_component(of, cell); | ||
} | ||
|
||
} | ||
} | ||
|
||
} catch (to::option_error& e) { | ||
std::cerr << argv[0] << ": " << e.what() << "\n"; | ||
std::cerr << "Try '" << argv[0] << " --help' for more information.\n"; | ||
std::exit(2); | ||
} | ||
catch (std::exception& e) { | ||
std::cerr << "caught exception: " << e.what() << "\n"; | ||
std::exit(1); | ||
} | ||
|
||
} | ||
|
Oops, something went wrong.