1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::gfa::gfa::GFAtk;
use crate::gfa::graph::{segments_subgraph, GFAdigraph};
use crate::load::{load_gfa, load_gfa_stdin};
use crate::utils::{self, GFAGraphLookups};
use anyhow::{bail, Result};
use indexmap::IndexMap;
pub fn linear(matches: &clap::ArgMatches) -> Result<()> {
let gfa_file = matches.value_of("GFA");
let include_node_coverage = matches.is_present("include-node-coverage");
let evaluate_subgraphs = matches.is_present("evaluate-subgraphs");
let gfa: GFAtk = match gfa_file {
Some(f) => {
if !f.ends_with(".gfa") {
bail!("Input file is not a GFA.")
}
GFAtk(load_gfa(f)?)
}
None => match utils::is_stdin() {
true => GFAtk(load_gfa_stdin(std::io::stdin().lock())?),
false => bail!("No input from STDIN. Run `gfatk extract -h` for help."),
},
};
let (graph_indices, gfa_graph) = gfa.into_digraph()?;
if gfa_graph.node_count() == 1 {
eprintln!("[+]\tOnly a single segment detected. Printing sequence and exiting.");
gfa.print_sequences()?;
return Ok(())
}
let subgraphs = gfa_graph.weakly_connected_components(graph_indices.clone())?;
if subgraphs.len() > 1 {
eprintln!(
"[-]\tThe input GFA has multiple subgraphs ({}).",
subgraphs.len()
)
}
match evaluate_subgraphs {
true => {
for id_set in &subgraphs {
let gfa = gfa.clone();
let subgraph_gfa = GFAtk(segments_subgraph(&gfa.0, id_set.to_vec()));
let (graph_indices_subgraph, subgraph) = subgraph_gfa.into_digraph()?;
linear_inner(gfa, include_node_coverage, graph_indices_subgraph, subgraph)?;
}
}
false => {
linear_inner(gfa, include_node_coverage, graph_indices, gfa_graph)?;
}
}
Ok(())
}
fn linear_inner(
gfa: GFAtk,
include_node_coverage: bool,
graph_indices: GFAGraphLookups,
gfa_graph: GFAdigraph,
) -> Result<()> {
let rel_coverage_map = match include_node_coverage {
true => Some(gfa.gen_cov_hash(&graph_indices)?),
false => None,
};
let (chosen_path, chosen_path_ids, segments_not_in_path, fasta_header) =
gfa_graph.all_paths_all_node_pairs(&graph_indices, rel_coverage_map.as_ref())?;
let sorted_chosen_path_overlaps =
gfa.determine_path_overlaps(&chosen_path, graph_indices, &chosen_path_ids)?;
let mut merged_sorted_chosen_path_overlaps = IndexMap::new();
for (id, orientation, overlap, side) in sorted_chosen_path_overlaps {
merged_sorted_chosen_path_overlaps
.entry(id)
.or_insert(Vec::new())
.push((orientation, overlap, side));
}
gfa.print_path_to_fasta(
merged_sorted_chosen_path_overlaps,
&fasta_header,
segments_not_in_path,
)?;
Ok(())
}