Skip to content

Commit e39bc24

Browse files
committed
Updated processing system for current index, and how to obtain results for wasm
1 parent 30f76e1 commit e39bc24

1 file changed

Lines changed: 87 additions & 18 deletions

File tree

src/lib.rs

Lines changed: 87 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,10 @@ use indicatif::ParallelProgressIterator;
159159
use rayon::prelude::*;
160160

161161
pub mod cli;
162-
#[cfg(not(target_family = "wasm"))]
163-
use crate::cli::*;
164162
#[cfg(target_family = "wasm")]
165163
use crate::cli::InvertedQueryType;
164+
#[cfg(not(target_family = "wasm"))]
165+
use crate::cli::*;
166166

167167
#[cfg(not(target_family = "wasm"))]
168168
use crate::hashing::HashType;
@@ -963,10 +963,32 @@ pub fn logw(text: &str, typ: Option<&str>) {
963963
#[wasm_bindgen]
964964
/// Struct to interact with JS when working with WebAssembly
965965
pub struct SketchlibData {
966-
out_probs: Vec<(f64, usize)>,
966+
out_probs: Vec<(u32, usize)>,
967967
index: Inverted,
968968
}
969969

970+
#[cfg(any(target_family = "wasm", test))]
971+
fn select_ranked_matches(matches: &[(u32, usize)], nouts: usize) -> Vec<(u32, usize, usize)> {
972+
let mut selected = Vec::new();
973+
let mut current_rank = 0_usize;
974+
let mut previous_matches: Option<u32> = None;
975+
976+
for (match_count, index) in matches.iter().copied() {
977+
if previous_matches.is_some_and(|prev| match_count != prev) {
978+
current_rank += 1;
979+
}
980+
previous_matches = Some(match_count);
981+
982+
if current_rank >= nouts {
983+
break;
984+
}
985+
986+
selected.push((match_count, index, current_rank));
987+
}
988+
989+
selected
990+
}
991+
970992
#[cfg(target_family = "wasm")]
971993
#[wasm_bindgen]
972994
impl SketchlibData {
@@ -995,7 +1017,11 @@ impl SketchlibData {
9951017
min_qual: u8,
9961018
) {
9971019
let query_type = &InvertedQueryType::MatchCount;
998-
let prop = if proportion_reads >= 1.0 { None } else { Some(proportion_reads) };
1020+
let prop = if proportion_reads >= 1.0 {
1021+
None
1022+
} else {
1023+
Some(proportion_reads)
1024+
};
9991025

10001026
// Get input files
10011027
let (queries, _query_names) =
@@ -1016,17 +1042,13 @@ impl SketchlibData {
10161042
InvertedQueryType::AnyBins => self.index.any_shared_bins(queries[0].as_slice()),
10171043
};
10181044

1019-
let mut outvec: Vec<(f64, usize)> = Vec::with_capacity(dist.len());
1045+
let mut outvec: Vec<(u32, usize)> = Vec::with_capacity(dist.len());
10201046

10211047
for (i, d) in dist.iter().enumerate() {
1022-
outvec.push((
1023-
(*d as f64) / ((2 * self.index.sketch_size()) as f64 - *d as f64),
1024-
i,
1025-
));
1048+
outvec.push((*d, i));
10261049
}
10271050

1028-
outvec.sort_by(|a, b| a.0.partial_cmp(&b.0).expect("NaN obtained!"));
1029-
outvec.reverse();
1051+
outvec.sort_by(|a, b| b.0.cmp(&a.0).then_with(|| a.1.cmp(&b.1)));
10301052

10311053
self.out_probs = outvec;
10321054
}
@@ -1044,17 +1066,27 @@ impl SketchlibData {
10441066
Some("info"),
10451067
);
10461068

1069+
let selected = select_ranked_matches(&self.out_probs, nouts);
1070+
10471071
results["probs"] = json::JsonValue::Array(
1048-
self.out_probs
1072+
selected
10491073
.iter()
1050-
.take(nouts)
1051-
.map(|x| json::JsonValue::Number(x.0.into()))
1074+
.map(|x| {
1075+
let matches = x.0 as f64;
1076+
let similarity = matches / ((2 * self.index.sketch_size()) as f64 - matches);
1077+
json::JsonValue::Number(similarity.into())
1078+
})
1079+
.collect(),
1080+
);
1081+
results["ranks"] = json::JsonValue::Array(
1082+
selected
1083+
.iter()
1084+
.map(|x| json::JsonValue::Number((x.2 + 1).into()))
10521085
.collect(),
10531086
);
10541087
results["names"] = json::JsonValue::Array(
1055-
self.out_probs
1088+
selected
10561089
.iter()
1057-
.take(nouts)
10581090
.map(|x| {
10591091
if let Some(labelsvec) = self.index.get_sample_labels() {
10601092
json::JsonValue::String(labelsvec[x.1].clone())
@@ -1065,9 +1097,8 @@ impl SketchlibData {
10651097
.collect(),
10661098
);
10671099
results["metadata"] = json::JsonValue::Array(
1068-
self.out_probs
1100+
selected
10691101
.iter()
1070-
.take(nouts)
10711102
.map(|x| {
10721103
if let Some(metadatavec) = self.index.get_metadata() {
10731104
json::JsonValue::String(metadatavec[x.1].clone())
@@ -1083,3 +1114,41 @@ impl SketchlibData {
10831114
results.dump()
10841115
}
10851116
}
1117+
1118+
#[cfg(test)]
1119+
mod wasm_result_ranking_tests {
1120+
use super::select_ranked_matches;
1121+
1122+
#[test]
1123+
fn returns_only_requested_rank_groups_without_ties() {
1124+
let matches = vec![(10, 0), (9, 1), (8, 2), (7, 3)];
1125+
assert_eq!(
1126+
select_ranked_matches(&matches, 3),
1127+
vec![(10, 0, 0), (9, 1, 1), (8, 2, 2)]
1128+
);
1129+
}
1130+
1131+
#[test]
1132+
fn includes_all_entries_tied_at_first_rank() {
1133+
let matches = vec![(10, 0), (10, 1), (9, 2), (8, 3), (7, 4)];
1134+
assert_eq!(
1135+
select_ranked_matches(&matches, 3),
1136+
vec![(10, 0, 0), (10, 1, 0), (9, 2, 1), (8, 3, 2)]
1137+
);
1138+
}
1139+
1140+
#[test]
1141+
fn includes_all_entries_tied_at_later_ranks() {
1142+
let matches = vec![(10, 0), (9, 1), (9, 2), (8, 3), (8, 4), (7, 5)];
1143+
assert_eq!(
1144+
select_ranked_matches(&matches, 3),
1145+
vec![(10, 0, 0), (9, 1, 1), (9, 2, 1), (8, 3, 2), (8, 4, 2)]
1146+
);
1147+
}
1148+
1149+
#[test]
1150+
fn get_probs_three_excludes_internal_rank_three() {
1151+
let matches = vec![(10, 0), (9, 1), (8, 2), (7, 3)];
1152+
assert!(!select_ranked_matches(&matches, 3).contains(&(7, 3, 3)));
1153+
}
1154+
}

0 commit comments

Comments
 (0)