8 个版本 (破坏性)
0.7.1 | 2024年1月23日 |
---|---|
0.6.0 | 2024年1月22日 |
0.5.3 | 2023年3月8日 |
0.4.0 | 2020年5月29日 |
0.1.1 | 2020年4月23日 |
#788 in 算法
每月30次下载
105KB
2.5K SLoC
nblast-rs
NBLAST 神经元形态比较的实现,最初发表在此处 PMC4961245 并在此处实现 nat.nblast。
此包与参考实现兼容,但 API 可能会更改。
基准测试
一些基准测试使用可选功能,因此基准测试者应使用
cargo bench --all-features
lib.rs
:
NBLAST 算法的实现,用于量化神经元形态的相似性。最初发表在 Costa et al. (2016) 中,并作为 NeuroAnatomy Toolbox 的一部分实现。
算法
将每个神经元作为点云样本传递(不需要点之间的链接)。根据每个点的位置及其最近邻的位置,计算每个点的切向向量。此外,还计算一个 alpha
值,描述邻居之间的共线性,介于 0 和 1 之间。
要查询神经元 Q
与神经元 T
的相似性
- 在
Q
中取一个点和其关联的切向量- 在
T
中找到最近的点及其关联的切向量 - 计算两点之间的距离
- 计算两个切向量的绝对点积
- 将一些经验函数应用于(距离,点积)元组
- 如发表所示,这是属于密切相关或无关神经元任何一对的对数概率比
- 在
- 对所有点重复,求和结果
结果不易比较:它高度依赖于点云的大小,并且不是可交换的,即 f(Q, T) != f(T, Q)
。
为了使两个神经元对的查询结果可比较,结果可以通过查询的“自击中”分数进行归一化,即 f(Q, Q)
。
为了使结果具有交换律,可以将正向的 f(Q, T)
和反向的 f(T, Q)
分数以某种方式结合起来。该库支持多种方法(算术、调和和几何),以及最小值和最大值。选择取决于应用。这可以在分数归一化后应用。
神经元的骨架是其形态中最容易采样和最典型化的部分,因此应重点关注该部分进行比较。然而,许多电缆位于树突中,当以高分辨率重建时可能会引起问题。可以通过将每个点匹配的绝对点积乘以两个 alpha 值的几何平均值,将查询加权到更直、分支更少的区域。
有关算法的更多信息,请参阅此处。
用法
QueryNeuron 和 TargetNeuron 特性定义了可以与 NBLAST 进行比较的类型。所有 TargetNeuron
都是 QueryNeuron
。两者都是 Neuron。
PointsTangentsAlphas 和 RstarNeuron 分别实现了这些特性。两者都可以使用预计算的切线和 alpha 值创建,或者在实际创建时计算它们。
NblastArena 包含一组 TargetNeuron
和一个应用于点对点 DistDot 的函数,以生成该点匹配的分数,便于进行方便的多对多比较。预计算的点匹配分数表可以转换为函数,使用 table_to_fn。
use nblast::{NblastArena, ScoreCalc, Neuron, Symmetry};
// Create a lookup table for the point match scores
let smat = ScoreCalc::table_from_bins(
vec![0.0, 0.1, 0.25, 0.5, 1.0, 5.0, f64::INFINITY], // distance thresholds
vec![0.0, 0.2, 0.4, 0.6, 0.8, 1.0], // dot product thresholds
vec![ // table values in dot-major order
0.0, 0.1, 0.2, 0.3, 0.4,
1.0, 1.1, 1.2, 1.3, 1.4,
2.0, 2.1, 2.2, 2.3, 2.4,
3.0, 3.1, 3.2, 3.3, 3.4,
4.0, 4.1, 4.2, 4.3, 4.4,
5.0, 5.1, 5.2, 5.3, 5.4,
],
).expect("could not build score matrix");
// See the ScoreMatrixBuilder for constructing a score matrix from test data.
// Create an arena to hold your neurons with this score function, and
// whether it should scale the dot products by the colinearity value.
let mut arena = NblastArena::new(smat, false);
// if the "parallel" feature is enabled, use e.g. `.with_threads(5)` to set 5 threads for multi-neuron queries
let mut rng = fastrand::Rng::with_seed(1991);
fn random_points(n: usize, rng: &mut fastrand::Rng) -> Vec<[f64; 3]> {
std::iter::repeat_with(|| [
10.0 * rng.f64(),
10.0 * rng.f64(),
10.0 * rng.f64(),
]).take(n).collect()
}
// Add some neurons built from points and a neighborhood size,
// returning their indices in the arena
let idx1 = arena.add_neuron(
Neuron::new(random_points(6, &mut rng), 5).expect("cannot construct neuron")
);
let idx2 = arena.add_neuron(
Neuron::new(random_points(8, &mut rng), 5).expect("cannot construct neuron")
);
// get a raw score (not normalized by self-hit, no symmetry)
let raw = arena.query_target(idx1, idx2, false, &None);
// get all the scores, normalized, made symmetric, and with a centroid distance cut-off
let results = arena.all_v_all(true, &Some(Symmetry::ArithmeticMean), Some(10.0));
依赖项
~7–32MB
~485K SLoC