gen/
gfa.rs

1use crate::models::strand::Strand;
2use convert_case::{Case, Casing};
3use std::fs::File;
4use std::io::{BufWriter, Write};
5
6#[derive(Clone, Debug, Eq, Hash, PartialEq)]
7pub struct Segment {
8    pub sequence: String,
9    pub node_id: i64,
10    pub sequence_start: i64,
11    pub strand: Strand,
12}
13
14#[derive(Clone, Debug, Eq, Hash, PartialEq)]
15pub struct Link {
16    pub source_segment_id: String,
17    pub source_strand: Strand,
18    pub target_segment_id: String,
19    pub target_strand: Strand,
20}
21
22#[derive(Clone, Debug, Eq, Hash, PartialEq)]
23pub struct Path {
24    pub name: String,
25    pub segment_ids: Vec<String>,
26    pub node_strands: Vec<Strand>,
27}
28
29impl Segment {
30    pub fn segment_id(&self) -> String {
31        format!("{}.{}", self.node_id, self.sequence_start)
32    }
33}
34
35fn segment_line(segment: &Segment) -> String {
36    // NOTE: We encode the node ID and start coordinate in the segment ID
37    format!("S\t{}\t{}\t*\n", segment.segment_id(), segment.sequence)
38}
39
40fn link_line(link: &Link) -> String {
41    format!(
42        "L\t{}\t{}\t{}\t{}\t0M\n",
43        link.source_segment_id, link.source_strand, link.target_segment_id, link.target_strand
44    )
45}
46
47pub fn path_line(path: &Path) -> String {
48    let segments = path
49        .segment_ids
50        .iter()
51        .zip(path.node_strands.iter())
52        .map(|(segment_id, node_strand)| format!("{}{}", segment_id, node_strand))
53        .collect::<Vec<String>>()
54        .join(",");
55    format!("P\t{}\t{}\t*\n", path.name.to_case(Case::Train), segments)
56}
57
58pub fn write_segments(writer: &mut BufWriter<File>, segments: &Vec<Segment>) {
59    for segment in segments {
60        writer
61            .write_all(&segment_line(segment).into_bytes())
62            .unwrap_or_else(|_| {
63                panic!(
64                    "Error writing segment with sequence {} to GFA stream",
65                    segment.sequence,
66                )
67            });
68    }
69}
70
71pub fn write_links(writer: &mut BufWriter<File>, links: &Vec<Link>) {
72    for link in links {
73        writer
74            .write_all(&link_line(link).into_bytes())
75            .unwrap_or_else(|_| {
76                panic!(
77                    "Error writing link from segment {:?} to {:?} to GFA stream",
78                    link.source_segment_id, link.target_segment_id,
79                )
80            });
81    }
82}