Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/fix/circular-new-pos' into rust
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-aksamentov committed Jan 13, 2025
2 parents 07d89dc + 4dfce17 commit 7d28b1b
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 14 deletions.
3 changes: 2 additions & 1 deletion packages/pangraph/src/pangraph/pangraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ impl Pangraph {
let block_id = BlockId(fasta.index);
let block = PangraphBlock::from_consensus(fasta.seq, block_id, node_id);
let path_id = PathId(fasta.index);
let node = PangraphNode::new(Some(node_id), block.id(), path_id, strand, (0, 0));
let node_position = if circular { (0, 0) } else { (0, tot_len) }; // path wraps around if circular
let node = PangraphNode::new(Some(node_id), block.id(), path_id, strand, node_position);
let path = PangraphPath::new(Some(path_id), [node.id()], tot_len, circular, Some(fasta.seq_name));
Self {
blocks: btreemap! {block.id() => block},
Expand Down
12 changes: 6 additions & 6 deletions packages/pangraph/src/pangraph/reweave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,9 +528,9 @@ mod tests {
},
);

let p1 = PangraphPath::new(Some(PathId(100)), [nid1], 2000, false, None);
let p2 = PangraphPath::new(Some(PathId(200)), [nid2], 2000, false, None);
let p3 = PangraphPath::new(Some(PathId(300)), [nid3], 200, false, None);
let p1 = PangraphPath::new(Some(PathId(100)), [nid1], 2000, true, None);
let p2 = PangraphPath::new(Some(PathId(200)), [nid2], 2000, true, None);
let p3 = PangraphPath::new(Some(PathId(300)), [nid3], 200, true, None);

let G = Pangraph {
paths: btreemap! {
Expand Down Expand Up @@ -683,9 +683,9 @@ mod tests {
};

let paths = btreemap! {
PathId(100) => PangraphPath::new(Some(PathId(100)), [NodeId(1), NodeId(2)], 1000, false, None),
PathId(200) => PangraphPath::new(Some(PathId(200)), [NodeId(3), NodeId(4), NodeId(5)], 1000, false, None),
PathId(300) => PangraphPath::new(Some(PathId(300)), [NodeId(6), NodeId(7), NodeId(8)], 1000, false, None),
PathId(100) => PangraphPath::new(Some(PathId(100)), [NodeId(1), NodeId(2)], 1000, true, None),
PathId(200) => PangraphPath::new(Some(PathId(200)), [NodeId(3), NodeId(4), NodeId(5)], 1000, true, None),
PathId(300) => PangraphPath::new(Some(PathId(300)), [NodeId(6), NodeId(7), NodeId(8)], 1000, true, None),
};

#[rustfmt::skip]
Expand Down
74 changes: 67 additions & 7 deletions packages/pangraph/src/pangraph/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ pub fn new_strandedness(old_strandedness: Strand, orientation: Strand, is_anchor
}
}

pub fn new_position(
// given the old position of a node, the coordinates of the node in the new block,
// the length of the path and the strandedness of the node, return the new node position.
// Accounts for circular paths.
// Nb: a node that spans the whole path [0, L] will have position [0, 0]
pub fn new_position_circular(
old_position: (usize, usize),
node_coords: (usize, usize),
path_L: usize,
Expand All @@ -77,6 +81,24 @@ pub fn new_position(
}
}

// given the old position of a node, the coordinates of the node in the new block,
// and the strandedness of the node, return the new node position.
// Does not account for circular paths.
// Nb: a node that spans the whole path [0, L] will have position [0, L]
pub fn new_position_non_circular(
old_position: (usize, usize),
node_coords: (usize, usize),
old_strandedness: Strand,
) -> (usize, usize) {
let (old_s, old_e) = old_position;
let (new_s_in_node, new_e_in_node) = node_coords;
if old_strandedness.is_forward() {
(old_s + new_s_in_node, old_s + new_e_in_node)
} else {
(old_e - new_e_in_node, old_e - new_s_in_node)
}
}

pub fn interval_node_coords(i: &PangraphInterval, edits: &Edit, block_L: usize) -> (usize, usize) {
let (mut s, mut e) = (i.interval.start, i.interval.end);
for d in &edits.dels {
Expand Down Expand Up @@ -134,7 +156,12 @@ pub fn block_slice(

let path_L = G.paths[&old_node.path_id()].tot_len;
let node_coords = interval_node_coords(i, edits, block_L);
let new_pos = new_position(old_node.position(), node_coords, path_L, old_strandedness);
let circular = G.paths[&old_node.path_id()].circular();
let new_pos = if circular {
new_position_circular(old_node.position(), node_coords, path_L, old_strandedness)
} else {
new_position_non_circular(old_node.position(), node_coords, old_strandedness)
};

let new_node = PangraphNode::new(None, i.new_block_id, old_node.path_id(), new_strand, new_pos);
node_updates.insert(*old_node_id, new_node.clone());
Expand Down Expand Up @@ -315,27 +342,60 @@ mod tests {
}

#[test]
fn test_new_position() {
fn test_new_position_circular() {
let path_L = 100;

let strandedness = Forward;
let node_coords = (10, 20);
let old_position = (10, 40);
let new_pos = new_position(old_position, node_coords, path_L, strandedness);
let new_pos = new_position_circular(old_position, node_coords, path_L, strandedness);
assert_eq!(new_pos, (20, 30));

let old_position = (95, 20);
let new_pos = new_position(old_position, node_coords, path_L, strandedness);
let new_pos = new_position_circular(old_position, node_coords, path_L, strandedness);
assert_eq!(new_pos, (5, 15));

let strandedness = Reverse;
let old_position = (10, 50);
let new_pos = new_position(old_position, node_coords, path_L, strandedness);
let new_pos = new_position_circular(old_position, node_coords, path_L, strandedness);
assert_eq!(new_pos, (30, 40));

let old_position = (40, 5);
let new_pos = new_position(old_position, node_coords, path_L, strandedness);
let new_pos = new_position_circular(old_position, node_coords, path_L, strandedness);
assert_eq!(new_pos, (85, 95));

let strandedness = Forward;
let old_position = (0, 100);
let node_coords = (0, 100);
let new_pos = new_position_circular(old_position, node_coords, path_L, strandedness);
assert_eq!(new_pos, (0, 0));
}

#[test]
fn test_new_position_non_circular() {
let strandedness = Forward;
let node_coords = (10, 20);
let old_position = (10, 40);
let new_pos = new_position_non_circular(old_position, node_coords, strandedness);
assert_eq!(new_pos, (20, 30));

let strandedness = Reverse;
let node_coords = (10, 20);
let old_position = (10, 50);
let new_pos = new_position_non_circular(old_position, node_coords, strandedness);
assert_eq!(new_pos, (30, 40));

let strandedness = Forward;
let node_coords = (0, 10);
let old_position = (0, 20);
let new_pos = new_position_non_circular(old_position, node_coords, strandedness);
assert_eq!(new_pos, (0, 10));

let strandedness = Forward;
let node_coords = (0, 100);
let old_position = (0, 100);
let new_pos = new_position_non_circular(old_position, node_coords, strandedness);
assert_eq!(new_pos, (0, 100));
}

#[test]
Expand Down

0 comments on commit 7d28b1b

Please sign in to comment.