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
use crate::{Monotonicity, RegulatoryGraph};
use std::io::Write;
impl RegulatoryGraph {
pub fn to_dot(&self) -> String {
let mut buffer: Vec<u8> = Vec::new();
self.write_as_dot(&mut buffer)
.expect("I/O error converting `RegulatoryGraph` to `.dot`.");
String::from_utf8(buffer).expect("Invalid UTF formatting in .dot string.")
}
pub fn write_as_dot(&self, output: &mut dyn Write) -> Result<(), std::io::Error> {
writeln!(output, "digraph G {{")?;
for var in self.variables() {
let name = self.get_variable_name(var);
writeln!(
output,
"v{} [shape=box, label=\"{}\", style=filled];",
var.0, name
)?;
}
for reg in self.regulations() {
let line = match reg.observable {
true => "filled",
false => "dashed",
};
let color = match reg.monotonicity {
Some(Monotonicity::Activation) => "#4abd73",
Some(Monotonicity::Inhibition) => "#d05d5d",
None => "#797979",
};
let arrow = match reg.monotonicity {
Some(Monotonicity::Activation) => "normal",
Some(Monotonicity::Inhibition) => "tee",
None => "empty",
};
writeln!(
output,
"v{} -> v{} [style=\"{}\", color=\"{}\", arrowhead=\"{}\"];",
reg.regulator.0, reg.target.0, line, color, arrow,
)?;
}
writeln!(output, "}}")?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::RegulatoryGraph;
#[test]
pub fn test_regulatory_graph_to_dot() {
let mut rg = RegulatoryGraph::new(vec!["a".to_string(), "b".to_string(), "c".to_string()]);
rg.add_string_regulation("a -?? a").unwrap();
rg.add_string_regulation("a -> b").unwrap();
rg.add_string_regulation("b -| c").unwrap();
rg.add_string_regulation("c ->? a").unwrap();
rg.add_string_regulation("a -|? c").unwrap();
rg.add_string_regulation("b -? b").unwrap();
println!("{}", rg.to_dot());
}
}