Skip to content
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
4 changes: 2 additions & 2 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ jobs:
strategy:
matrix:
platform:
- runner: macos-13
- runner: macos-latest
target: x86_64
- runner: macos-14
- runner: macos-latest
target: aarch64
steps:
- uses: actions/checkout@v4
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
"Cargo.toml",
"*.fa",
"*.toml"
]
],
"rust-analyzer.check.command": "clippy"
}
6 changes: 6 additions & 0 deletions generic_a_star/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ pub trait AStarContext: Reset {
}
}

/// The closed list for the A* algorithm.
pub trait AStarClosedList<Identifier: Debug + Clone + Eq + Hash, Cost: AStarCost>: Reset {}

/// The open list for the A* algorithm.
pub trait AStarOpenList<Node: AStarNode>: Reset {}

#[derive(Debug, Default)]
pub struct AStarPerformanceCounters {
pub opened_nodes: usize,
Expand Down
18 changes: 18 additions & 0 deletions lib_ts_chainalign/src/alignment/ts_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,24 @@ impl TsKind {
[Self::TS11, Self::TS12, Self::TS21, Self::TS22].into_iter()
}

/// Index of this [`TsKind`] in the iterator produced by [`Self::iter()`].
///
/// ```rust
/// # use lib_ts_chainalign::alignment::ts_kind::TsKind;
/// assert_eq!(
/// TsKind::iter().enumerate().collect::<Vec<_>>(),
/// TsKind::iter().map(|ts_kind| (ts_kind.index(), ts_kind)).collect::<Vec<_>>()
/// );
/// ```
pub fn index(&self) -> usize {
match (self.ancestor, self.descendant) {
(TsAncestor::Seq1, TsDescendant::Seq1) => 0,
(TsAncestor::Seq1, TsDescendant::Seq2) => 1,
(TsAncestor::Seq2, TsDescendant::Seq1) => 2,
(TsAncestor::Seq2, TsDescendant::Seq2) => 3,
}
}

pub fn digits(&self) -> &'static str {
match (self.ancestor, self.descendant) {
(TsAncestor::Seq1, TsDescendant::Seq1) => "11",
Expand Down
175 changes: 75 additions & 100 deletions lib_ts_chainalign/src/anchors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,25 @@ use crate::{
alignment::{
coordinates::AlignmentCoordinates,
sequences::AlignmentSequences,
ts_kind::{TsAncestor, TsDescendant, TsKind},
ts_kind::{TsDescendant, TsKind},
},
anchors::{
index::AnchorIndex,
kmer_matches::find_kmer_matches,
kmers::{Kmer, KmerStore},
},
};

pub mod index;
pub mod kmer_matches;
pub mod kmers;
#[cfg(test)]
mod tests;

#[derive(Debug, PartialEq, Eq)]
pub struct Anchors {
pub primary: Vec<PrimaryAnchor>,
pub secondary_11: Vec<SecondaryAnchor>,
pub secondary_12: Vec<SecondaryAnchor>,
pub secondary_21: Vec<SecondaryAnchor>,
pub secondary_22: Vec<SecondaryAnchor>,
primary: Vec<PrimaryAnchor>,
secondaries: [Vec<SecondaryAnchor>; 4],
}

#[derive(Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -110,34 +109,35 @@ impl Anchors {
.into_iter()
.map(|(seq1, seq2)| PrimaryAnchor { seq1, seq2 })
.collect();
let mut secondary_11: Vec<_> = find_kmer_matches(&s1_rc_kmers, &s1_kmers)
let secondary_11: Vec<_> = find_kmer_matches(&s1_rc_kmers, &s1_kmers)
.into_iter()
.map(|(ancestor, descendant)| SecondaryAnchor {
ancestor: s1.len() - ancestor,
descendant,
})
.collect();
let mut secondary_12: Vec<_> = find_kmer_matches(&s1_rc_kmers, &s2_kmers)
let secondary_12: Vec<_> = find_kmer_matches(&s1_rc_kmers, &s2_kmers)
.into_iter()
.map(|(ancestor, descendant)| SecondaryAnchor {
ancestor: s1.len() - ancestor,
descendant,
})
.collect();
let mut secondary_21: Vec<_> = find_kmer_matches(&s2_rc_kmers, &s1_kmers)
let secondary_21: Vec<_> = find_kmer_matches(&s2_rc_kmers, &s1_kmers)
.into_iter()
.map(|(ancestor, descendant)| SecondaryAnchor {
ancestor: s2.len() - ancestor,
descendant,
})
.collect();
let mut secondary_22: Vec<_> = find_kmer_matches(&s2_rc_kmers, &s2_kmers)
let secondary_22: Vec<_> = find_kmer_matches(&s2_rc_kmers, &s2_kmers)
.into_iter()
.map(|(ancestor, descendant)| SecondaryAnchor {
ancestor: s2.len() - ancestor,
descendant,
})
.collect();
let mut secondaries = [secondary_11, secondary_12, secondary_21, secondary_22];

// Sort anchors.
primary.sort_unstable_by_key(|primary_anchor| {
Expand All @@ -147,65 +147,67 @@ impl Anchors {
primary_anchor.seq2,
)
});
secondary_11.sort_unstable_by_key(|secondary_anchor| {
(
secondary_anchor.ancestor.min(secondary_anchor.descendant),
secondary_anchor.ancestor,
secondary_anchor.descendant,
)
});
secondary_12.sort_unstable_by_key(|secondary_anchor| {
(
secondary_anchor.ancestor.min(secondary_anchor.descendant),
secondary_anchor.ancestor,
secondary_anchor.descendant,
)
});
secondary_21.sort_unstable_by_key(|secondary_anchor| {
(
secondary_anchor.ancestor.min(secondary_anchor.descendant),
secondary_anchor.ancestor,
secondary_anchor.descendant,
)
});
secondary_22.sort_unstable_by_key(|secondary_anchor| {
(
secondary_anchor.ancestor.min(secondary_anchor.descendant),
secondary_anchor.ancestor,
secondary_anchor.descendant,
)
});
for secondary in &mut secondaries {
secondary.sort_unstable_by_key(|secondary_anchor| {
(
secondary_anchor.ancestor.min(secondary_anchor.descendant),
secondary_anchor.ancestor,
secondary_anchor.descendant,
)
});
}

info!(
"Found {} anchors ({} + {} + {} + {} + {})",
primary.len()
+ secondary_11.len()
+ secondary_12.len()
+ secondary_21.len()
+ secondary_22.len(),
primary.len() + secondaries.iter().map(Vec::len).sum::<usize>(),
primary.len(),
secondary_11.len(),
secondary_12.len(),
secondary_21.len(),
secondary_22.len(),
secondaries[0].len(),
secondaries[1].len(),
secondaries[2].len(),
secondaries[3].len(),
);

Self {
primary,
secondary_11,
secondary_12,
secondary_21,
secondary_22,
secondaries,
}
}

pub fn secondary(&self, ts_kind: TsKind) -> &[SecondaryAnchor] {
match (ts_kind.ancestor, ts_kind.descendant) {
(TsAncestor::Seq1, TsDescendant::Seq1) => &self.secondary_11,
(TsAncestor::Seq1, TsDescendant::Seq2) => &self.secondary_12,
(TsAncestor::Seq2, TsDescendant::Seq1) => &self.secondary_21,
(TsAncestor::Seq2, TsDescendant::Seq2) => &self.secondary_22,
}
pub fn primary(&self, index: AnchorIndex) -> &PrimaryAnchor {
&self.primary[index.as_usize()]
}

pub fn primary_len(&self) -> AnchorIndex {
self.primary.len().into()
}

pub fn enumerate_primaries(&self) -> impl Iterator<Item = (AnchorIndex, &PrimaryAnchor)> {
self.primary
.iter()
.enumerate()
.map(|(index, anchor)| (index.into(), anchor))
}

fn secondary_anchor_vec(&self, ts_kind: TsKind) -> &Vec<SecondaryAnchor> {
&self.secondaries[ts_kind.index()]
}

pub fn secondary(&self, index: AnchorIndex, ts_kind: TsKind) -> &SecondaryAnchor {
&self.secondary_anchor_vec(ts_kind)[index.as_usize()]
}

pub fn secondary_len(&self, ts_kind: TsKind) -> AnchorIndex {
self.secondary_anchor_vec(ts_kind).len().into()
}

pub fn enumerate_secondaries(
&self,
ts_kind: TsKind,
) -> impl Iterator<Item = (AnchorIndex, &SecondaryAnchor)> {
self.secondary_anchor_vec(ts_kind)
.iter()
.enumerate()
.map(|(index, anchor)| (index.into(), anchor))
}
}

Expand Down Expand Up @@ -419,53 +421,26 @@ impl Display for Anchors {
}
writeln!(f, "]")?;

write!(f, "S11: [")?;
let mut once = true;
for secondary_anchor in &self.secondary_11 {
if once {
once = false;
} else {
write!(f, ", ")?;
}
write!(f, "{secondary_anchor}")?;
}
writeln!(f, "]")?;

write!(f, "S12: [")?;
let mut once = true;
for secondary_anchor in &self.secondary_12 {
if once {
once = false;
} else {
write!(f, ", ")?;
}
write!(f, "{secondary_anchor}")?;
}
writeln!(f, "]")?;

write!(f, "S21: [")?;
let mut once = true;
for secondary_anchor in &self.secondary_21 {
if once {
once = false;
let mut ts_kind_once = true;
for ts_kind in TsKind::iter() {
if ts_kind_once {
ts_kind_once = false;
} else {
write!(f, ", ")?;
writeln!(f)?;
}
write!(f, "{secondary_anchor}")?;
}
writeln!(f, "]")?;

write!(f, "S22: [")?;
let mut once = true;
for secondary_anchor in &self.secondary_22 {
if once {
once = false;
} else {
write!(f, ", ")?;
write!(f, "S{}: [", ts_kind.digits())?;
let mut once = true;
for secondary_anchor in self.secondary_anchor_vec(ts_kind) {
if once {
once = false;
} else {
write!(f, ", ")?;
}
write!(f, "{secondary_anchor}")?;
}
write!(f, "{secondary_anchor}")?;
write!(f, "]")?;
}
write!(f, "]")?;

Ok(())
}
Expand Down
77 changes: 77 additions & 0 deletions lib_ts_chainalign/src/anchors/index.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use std::{
fmt::Display,
ops::{Add, Sub},
};

use num_traits::Zero;

type IndexType = u32;

#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub struct AnchorIndex(IndexType);

impl AnchorIndex {
pub fn as_usize(self) -> usize {
self.0.try_into().unwrap()
}
}

impl From<IndexType> for AnchorIndex {
fn from(value: IndexType) -> Self {
Self(value)
}
}

impl From<usize> for AnchorIndex {
fn from(value: usize) -> Self {
Self(value.try_into().unwrap())
}
}

impl Add for AnchorIndex {
type Output = Self;

fn add(self, rhs: Self) -> Self::Output {
Self(self.0.checked_add(rhs.0).unwrap())
}
}

impl Sub for AnchorIndex {
type Output = Self;

fn sub(self, rhs: Self) -> Self::Output {
Self(self.0.checked_sub(rhs.0).unwrap())
}
}

impl Add<IndexType> for AnchorIndex {
type Output = Self;

fn add(self, rhs: IndexType) -> Self::Output {
self + Self::from(rhs)
}
}

impl Sub<IndexType> for AnchorIndex {
type Output = Self;

fn sub(self, rhs: IndexType) -> Self::Output {
self - Self::from(rhs)
}
}

impl Zero for AnchorIndex {
fn zero() -> Self {
Self(0)
}

fn is_zero(&self) -> bool {
self.0.is_zero()
}
}

impl Display for AnchorIndex {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
Loading