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
use {
    crate::*,
    anyhow::{bail, Result},
};

/// this table is garanteed to contain at least 2 sequences.
#[derive(Debug)]
pub struct Tbl {
    seqs: Vec<Seq>,
}

impl Tbl {
    pub fn from_raw(mut raw_tbl: RawTbl) -> Result<Self> {
        if raw_tbl.row_count() < 2 {
            bail!("two rows needed for a graph");
        }
        let mut seqs = Vec::new();
        for (col_idx, raw_col) in raw_tbl.cols.drain(..).enumerate() {
            match Seq::new(raw_col) {
                Ok(seq) => {
                    seqs.push(seq);
                }
                Err(e) => {
                    info!("column {} can't be used: {}", col_idx, e);
                }
            }
        }
        if seqs.len() < 2 {
            bail!("not enough usable columns")
        }
        Ok(Self { seqs })
    }
    pub fn from_seqs(seqs: Vec<Seq>) -> Result<Self> {
        if seqs.len() < 2 {
            bail!("not enough columns");
        }
        if !seqs[0].is_full_and_increasing() {
            bail!("first sequence must be full and increasing");
        }
        Ok(Self { seqs })
    }
    pub fn seqs_count(&self) -> usize {
        self.seqs.len()
    }
    pub fn y_seqs_count(&self) -> usize {
        self.seqs.len() - 1
    }
    pub fn dim(&self) -> (usize, usize) {
        (self.seqs_count(), self.seqs[0].len())
    }
    pub fn x_seq(&self) -> &Seq {
        &self.seqs[0]
    }
    pub fn y_seqs(&self) -> std::iter::Skip<std::slice::Iter<'_, seq::Seq>> {
        self.seqs.iter().skip(1)
    }
    pub fn y_min_max(&self) -> (i64, i64) {
        let mut y_seqs = self.y_seqs();
        let first_y = y_seqs.next().unwrap();
        y_seqs.fold((first_y.min, first_y.max), |(min, max), seq| {
            (min.min(seq.min), max.max(seq.max))
        })
    }
}