1use crate::GenGraph;
2
3pub trait MergeGraph {
4 fn merge_graph(&mut self, other: &GenGraph);
5}
6
7impl MergeGraph for GenGraph {
8 fn merge_graph(&mut self, other: &GenGraph) {
9 for node in other.nodes() {
10 self.add_node(node);
11 }
12
13 for (source, target, edges) in other.all_edges() {
14 if let Some(existing_edges) = self.edge_weight_mut(source, target) {
15 for edge in edges.iter().copied() {
16 if !existing_edges.contains(&edge) {
17 existing_edges.push(edge);
18 }
19 }
20 } else {
21 self.add_edge(source, target, edges.clone());
22 }
23 }
24 }
25}
26
27#[cfg(test)]
28mod tests {
29 use std::collections::HashSet;
30
31 use gen_core::{HashId, Strand};
32
33 use super::*;
34 use crate::{GraphEdge, GraphNode};
35
36 #[test]
37 fn merges_gen_graphs_and_preserves_distinct_edges() {
38 let start = GraphNode {
39 node_id: HashId::convert_str("merge-start"),
40 sequence_start: 0,
41 sequence_end: 0,
42 };
43 let middle = GraphNode {
44 node_id: HashId::convert_str("merge-middle"),
45 sequence_start: 0,
46 sequence_end: 5,
47 };
48 let end = GraphNode {
49 node_id: HashId::convert_str("merge-end"),
50 sequence_start: 0,
51 sequence_end: 0,
52 };
53 let chrom_index0_edge = GraphEdge {
54 edge_id: HashId::convert_str("merge-edge-ci0"),
55 source_strand: Strand::Forward,
56 target_strand: Strand::Forward,
57 chromosome_index: 0,
58 phased: 0,
59 created_on: 1,
60 };
61 let chrom_index1_edge = GraphEdge {
62 edge_id: HashId::convert_str("merge-edge-ci1"),
63 source_strand: Strand::Forward,
64 target_strand: Strand::Forward,
65 chromosome_index: 1,
66 phased: 1,
67 created_on: 2,
68 };
69
70 let mut graph_a = GenGraph::new();
71 graph_a.add_edge(start, middle, vec![chrom_index0_edge]);
72
73 let mut graph_b = GenGraph::new();
74 graph_b.add_edge(start, middle, vec![chrom_index1_edge]);
75 graph_b.add_edge(middle, end, vec![chrom_index0_edge]);
76
77 graph_a.merge_graph(&graph_b);
78
79 let graph_a_edges = graph_a
80 .edge_weight(start, middle)
81 .unwrap()
82 .iter()
83 .copied()
84 .collect::<HashSet<_>>();
85 assert_eq!(
86 graph_a_edges,
87 HashSet::from([chrom_index0_edge, chrom_index1_edge])
88 );
89 assert_eq!(
90 graph_a.edge_weight(middle, end).unwrap(),
91 &vec![chrom_index0_edge]
92 );
93 }
94
95 #[test]
96 fn merges_gen_graphs_without_duplicating_identical_edges() {
97 let start = GraphNode {
98 node_id: HashId::convert_str("dedup-start"),
99 sequence_start: 0,
100 sequence_end: 0,
101 };
102 let end = GraphNode {
103 node_id: HashId::convert_str("dedup-end"),
104 sequence_start: 0,
105 sequence_end: 0,
106 };
107 let edge = GraphEdge {
108 edge_id: HashId::convert_str("dedup-edge"),
109 source_strand: Strand::Forward,
110 target_strand: Strand::Forward,
111 chromosome_index: 0,
112 phased: 0,
113 created_on: 1,
114 };
115
116 let mut graph_a = GenGraph::new();
117 graph_a.add_edge(start, end, vec![edge]);
118
119 let mut graph_b = GenGraph::new();
120 graph_b.add_edge(start, end, vec![edge]);
121
122 graph_a.merge_graph(&graph_b);
123
124 assert_eq!(graph_a.edge_weight(start, end).unwrap(), &vec![edge]);
125 }
126
127 #[test]
128 fn merges_gen_graphs_by_graph_node_value() {
129 let source_a = GraphNode {
132 node_id: HashId::convert_str("shared-node"),
133 sequence_start: 0,
134 sequence_end: 5,
135 };
136 let target_a = GraphNode {
137 node_id: HashId::convert_str("target-node"),
138 sequence_start: 0,
139 sequence_end: 5,
140 };
141 let source_b = GraphNode {
142 node_id: source_a.node_id,
143 sequence_start: source_a.sequence_start,
144 sequence_end: source_a.sequence_end,
145 };
146 let target_b = GraphNode {
147 node_id: target_a.node_id,
148 sequence_start: target_a.sequence_start,
149 sequence_end: target_a.sequence_end,
150 };
151 let edge_a = GraphEdge {
152 edge_id: HashId::convert_str("logical-edge-a"),
153 source_strand: Strand::Forward,
154 target_strand: Strand::Forward,
155 chromosome_index: 0,
156 phased: 0,
157 created_on: 1,
158 };
159 let edge_b = GraphEdge {
160 edge_id: HashId::convert_str("logical-edge-b"),
161 source_strand: Strand::Forward,
162 target_strand: Strand::Forward,
163 chromosome_index: 1,
164 phased: 0,
165 created_on: 2,
166 };
167
168 let mut graph_a = GenGraph::new();
169 graph_a.add_edge(source_a, target_a, vec![edge_a]);
170
171 let mut graph_b = GenGraph::new();
172 graph_b.add_edge(source_b, target_b, vec![edge_b]);
173
174 graph_a.merge_graph(&graph_b);
175
176 let nodes = graph_a.nodes().collect::<Vec<_>>();
177 let edges = graph_a
178 .edge_weight(source_a, target_a)
179 .unwrap()
180 .iter()
181 .copied()
182 .collect::<HashSet<_>>();
183 assert_eq!(nodes, vec![source_a, target_a]);
184 assert_eq!(edges, HashSet::from([edge_a, edge_b]));
185 }
186}