Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spatial bench #30

Merged
merged 10 commits into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ members = [
"nblast-py",
"nblast-rs",
"nblast-js",
"spatial_bench",
]

resolver = "2"

# [profile.release]
# debug = true
2 changes: 1 addition & 1 deletion nblast-js/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ serde = {version = "1", features = ["derive"]}
serde-wasm-bindgen = "0.5"
wasm-bindgen = "0.2"
js-sys = "0.3"
nblast = { path = "../nblast-rs", version = "^0.5.0"}
nblast = { path = "../nblast-rs", version = "^0.5.0", default-features = false, features = ["rstar"]}

[lib]
crate-type = ["cdylib"]
Expand Down
2 changes: 1 addition & 1 deletion nblast-py/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ edition = "2018"
[dependencies]
pyo3 = { version = "0.18.2", features = ["extension-module"] }
neurarbor = "0.2.0"
nblast = { path = "../nblast-rs", version = "^0.5.0", features = ["parallel"] }
nblast = { path = "../nblast-rs", version = "^0.5.0", features = ["parallel", "kiddo"] }
numpy = "0.18"

[lib]
Expand Down
22 changes: 12 additions & 10 deletions nblast-py/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use numpy::{IntoPyArray, PyArray1, PyArray2, PyReadonlyArray1, PyReadonlyArray2}

use nblast::nalgebra::base::{Unit, Vector3};
use nblast::{
BinLookup, NblastArena, Neuron, NeuronIdx, Precision, RangeTable, ScoreCalc,
ScoreMatrixBuilder, Symmetry, TangentAlpha,
neurons::kiddo::ExactKiddoTangentsAlphas as Neuron, BinLookup, NblastArena, NeuronIdx,
Precision, RangeTable, ScoreCalc, ScoreMatrixBuilder, Symmetry, TangentAlpha,
};

use nblast::rayon;
Expand Down Expand Up @@ -67,10 +67,11 @@ impl ArenaWrapper {
.as_array()
.rows()
.into_iter()
.map(|r| [r[0], r[1], r[2]]),
.map(|r| [r[0], r[1], r[2]])
.collect(),
self.k,
)
.map_err(PyErr::new::<exceptions::PyRuntimeError, _>)?;
.map_err(|e| PyErr::new::<PyValueError, _>(e))?;
Ok(self.arena.add_neuron(neuron))
}

Expand Down Expand Up @@ -109,10 +110,11 @@ impl ArenaWrapper {
.as_array()
.rows()
.into_iter()
.map(|r| [r[0], r[1], r[2]]),
.map(|r| [r[0], r[1], r[2]])
.collect(),
tangents_alphas,
)
.map_err(PyErr::new::<exceptions::PyRuntimeError, _>)?;
.map_err(|e| PyErr::new::<PyValueError, _>(e))?;
Ok(self.arena.add_neuron(neuron))
}

Expand Down Expand Up @@ -356,17 +358,17 @@ fn make_neurons_many(
points_list
.into_par_iter()
.map(|ps| {
Neuron::new(ps.into_iter().map(|p| [p[0], p[1], p[2]]), k)
.expect("failed to construct neuron") // todo: error handling
Neuron::new(ps.into_iter().map(|p| [p[0], p[1], p[2]]).collect(), k)
.expect("Invalid neuron")
})
.collect()
})
} else {
points_list
.into_iter()
.map(|ps| {
Neuron::new(ps.into_iter().map(|p| [p[0], p[1], p[2]]), k)
.expect("failed to construct neuron") // todo: error handling
Neuron::new(ps.into_iter().map(|p| [p[0], p[1], p[2]]).collect(), k)
.expect("invalid neuron")
})
.collect()
}
Expand Down
6 changes: 4 additions & 2 deletions nblast-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ categories = ["algorithms", "science"]
[dependencies]

nalgebra = "0.31"
rstar = "0.9"
rstar = {version = "0.9", optional = true}
fastrand = "1.9"
rayon = { version = "1.5", optional = true }
thiserror = "1.0"
nabo = { version = "0.2.1", optional = true }
# fnntw = "0.2"
kiddo = { version = "4.0", optional = true }
cfg-if = "1.0.0"

[dev-dependencies]

Expand All @@ -33,6 +34,7 @@ csv = "1.1"
serde = { version = "1", features = ["derive"] }

[features]
default = ["kiddo"]

parallel = ["rayon"]

Expand Down
68 changes: 67 additions & 1 deletion nblast-rs/benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use bencher::{benchmark_group, benchmark_main, Bencher};
use csv::ReaderBuilder;
use fastrand::Rng;

#[cfg(feature = "kiddo")]
use nblast::neurons::kiddo::{ExactKiddoTangentsAlphas, KiddoTangentsAlphas};
#[cfg(feature = "nabo")]
use nblast::neurons::nabo::NaboTangentsAlphas;
use nblast::neurons::rstar::RStarTangentsAlphas;
Expand Down Expand Up @@ -264,6 +266,16 @@ fn bench_construction_nabo(b: &mut Bencher) {
b.iter(|| NaboTangentsAlphas::new(points.clone(), N_NEIGHBORS))
}

fn bench_construction_kiddo(b: &mut Bencher) {
let points = read_points(NAMES[0]);
b.iter(|| KiddoTangentsAlphas::new(points.clone(), N_NEIGHBORS))
}

fn bench_construction_exact_kiddo(b: &mut Bencher) {
let points = read_points(NAMES[0]);
b.iter(|| ExactKiddoTangentsAlphas::new(points.clone(), N_NEIGHBORS))
}

fn bench_query_nabo(b: &mut Bencher) {
let score_fn = get_score_fn();
let query = NaboTangentsAlphas::new(read_points(NAMES[0]), N_NEIGHBORS);
Expand All @@ -272,6 +284,22 @@ fn bench_query_nabo(b: &mut Bencher) {
b.iter(|| query.query(&target, false, &score_fn))
}

fn bench_query_kiddo(b: &mut Bencher) {
let score_fn = get_score_fn();
let query = KiddoTangentsAlphas::new(read_points(NAMES[0]), N_NEIGHBORS).unwrap();
let target = KiddoTangentsAlphas::new(read_points(NAMES[1]), N_NEIGHBORS).unwrap();

b.iter(|| query.query(&target, false, &score_fn))
}

fn bench_query_exact_kiddo(b: &mut Bencher) {
let score_fn = get_score_fn();
let query = ExactKiddoTangentsAlphas::new(read_points(NAMES[0]), N_NEIGHBORS).unwrap();
let target = ExactKiddoTangentsAlphas::new(read_points(NAMES[1]), N_NEIGHBORS).unwrap();

b.iter(|| query.query(&target, false, &score_fn))
}

fn bench_construction_with_tangents_rstar(b: &mut Bencher) {
let points = read_points(NAMES[0]);
let neuron = RStarTangentsAlphas::new(&points, N_NEIGHBORS).expect("couldn't parse");
Expand Down Expand Up @@ -375,6 +403,28 @@ fn bench_all_to_all_serial_nabo(b: &mut Bencher) {
b.iter(|| arena.queries_targets(&idxs, &idxs, false, &None, None));
}

fn bench_all_to_all_serial_kiddo(b: &mut Bencher) {
let mut arena = NblastArena::new(get_score_fn(), false);
let mut idxs = Vec::new();
for name in NAMES.iter() {
let points = read_points(name);
idxs.push(arena.add_neuron(KiddoTangentsAlphas::new(points, N_NEIGHBORS).unwrap()));
}

b.iter(|| arena.queries_targets(&idxs, &idxs, false, &None, None));
}

fn bench_all_to_all_serial_exact_kiddo(b: &mut Bencher) {
let mut arena = NblastArena::new(get_score_fn(), false);
let mut idxs = Vec::new();
for name in NAMES.iter() {
let points = read_points(name);
idxs.push(arena.add_neuron(ExactKiddoTangentsAlphas::new(points, N_NEIGHBORS).unwrap()));
}

b.iter(|| arena.queries_targets(&idxs, &idxs, false, &None, None));
}

#[cfg(feature = "parallel")]
fn bench_all_to_all_parallel(b: &mut Bencher) {
let mut arena = NblastArena::new(get_score_fn(), false).with_threads(0);
Expand Down Expand Up @@ -455,6 +505,22 @@ benchmark_group!(
bench_all_to_all_serial_nabo,
);

#[cfg(feature = "kiddo")]
benchmark_group!(
impl_kiddo,
bench_construction_kiddo,
bench_query_kiddo,
bench_all_to_all_serial_kiddo,
);

#[cfg(feature = "kiddo")]
benchmark_group!(
impl_exact_kiddo,
bench_construction_exact_kiddo,
bench_query_exact_kiddo,
bench_all_to_all_serial_exact_kiddo,
);

benchmark_group!(
arena,
bench_arena_query,
Expand All @@ -472,4 +538,4 @@ benchmark_group!(
bench_smatbuild_rstar_quantiles,
);

benchmark_main!(impl_rstar, impl_nabo, arena, smat);
benchmark_main!(impl_rstar, impl_nabo, impl_kiddo, arena, smat);
38 changes: 16 additions & 22 deletions nblast-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
//! ```
//! use nblast::{NblastArena, ScoreCalc, Neuron, Symmetry};
//!
//! // create a lookup table for the point match scores
//! // 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
Expand All @@ -75,7 +75,9 @@
//! ],
//! ).expect("could not build score matrix");
//!
//! // create an arena to hold your neurons with this score function,
//! // See the ScoreMatrixBuilder for constructing a score matrix from test data.
//!
//! // Create an arena to hold your neurons with this score function,
//! // whether it should scale the dot products by the colinearity value,
//! // and how many threads to use (default serial)
//! let mut arena = NblastArena::new(smat, false).with_threads(2);
Expand All @@ -91,7 +93,7 @@
//! }
//!

//! // add some neurons built from points and a neighborhood size,
//! // 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")
Expand Down Expand Up @@ -125,9 +127,11 @@ mod table_lookup;
pub use table_lookup::{BinLookup, NdBinLookup, RangeTable};

pub mod neurons;
use neurons::rstar::points_to_rtree_tangents_alphas;
pub use neurons::{NblastNeuron, Neuron, QueryNeuron, TargetNeuron};

#[cfg(not(any(feature = "nabo", feature = "rstar", feature = "kiddo")))]
compile_error!("one of 'nabo', 'rstar', or 'kiddo' features must be enabled");

/// Floating point precision type used internally
pub type Precision = f64;
/// 3D point type used internally
Expand Down Expand Up @@ -327,17 +331,11 @@ pub struct PointsTangentsAlphas {
}

impl PointsTangentsAlphas {
/// Calculates tangents from the given points.
/// Note that this constructs a spatial index in order to calculate the tangents,
/// and then throws it away: you may as well use a [TargetNeuron](trait.TargetNeuron.html)
/// type, with regards to performance.
/// `k` is the number of points tangents will be calculated with,
/// and includes the point itself.
pub fn new(points: Vec<Point3>, k: usize) -> Result<Self, &'static str> {
points_to_rtree_tangents_alphas(points.iter(), k).map(|(_, tangents_alphas)| Self {
pub fn new(points: Vec<Point3>, tangents_alphas: Vec<TangentAlpha>) -> Self {
Self {
points,
tangents_alphas,
})
}
}
}

Expand Down Expand Up @@ -884,8 +882,7 @@ mod test {
#[test]
fn construct() {
let points = make_points(&[0., 0., 0.], &[1., 0., 0.], 10);
PointsTangentsAlphas::new(points.clone(), N_NEIGHBORS).expect("Query construction failed");
Neuron::new(&points, N_NEIGHBORS).expect("Target construction failed");
Neuron::new(points, N_NEIGHBORS);
}

fn is_close(val1: Precision, val2: Precision) -> bool {
Expand Down Expand Up @@ -1092,13 +1089,10 @@ mod test {
RangeTable::new_from_bins(vec![dist_thresholds, dot_thresholds], cells).unwrap(),
);

let query = Neuron::new(&make_points(&[0., 0., 0.], &[1., 0., 0.], 10), N_NEIGHBORS)
.expect("Construction failed");
let target = Neuron::new(
&make_points(&[0.5, 0., 0.], &[1.1, 0., 0.], 10),
N_NEIGHBORS,
)
.expect("Construction failed");
let query =
Neuron::new(make_points(&[0., 0., 0.], &[1., 0., 0.], 10), N_NEIGHBORS).unwrap();
let target =
Neuron::new(make_points(&[0.5, 0., 0.], &[1.1, 0., 0.], 10), N_NEIGHBORS).unwrap();

let mut arena = NblastArena::new(score_calc, false);
let q_idx = arena.add_neuron(query);
Expand Down
Loading
Loading