biodivine_lib_param_bn/_impl_regulatory_graph/
_impl_dot_export.rs

1use crate::{Monotonicity, RegulatoryGraph};
2use std::io::Write;
3
4impl RegulatoryGraph {
5    /// Export this regulatory graph to a `.dot` format.
6    ///
7    /// In the representation, we use red and green color to distinguish positive and negative
8    /// regulations. Dashed edges show regulations without observability requirement.
9    pub fn to_dot(&self) -> String {
10        let mut buffer: Vec<u8> = Vec::new();
11        self.write_as_dot(&mut buffer)
12            .expect("I/O error converting `RegulatoryGraph` to `.dot`.");
13        String::from_utf8(buffer).expect("Invalid UTF formatting in .dot string.")
14    }
15
16    pub fn write_as_dot(&self, output: &mut dyn Write) -> Result<(), std::io::Error> {
17        writeln!(output, "digraph G {{")?;
18        for var in self.variables() {
19            let name = self.get_variable_name(var);
20            writeln!(
21                output,
22                "v{} [shape=box, label=\"{}\", style=filled];",
23                var.0, name
24            )?;
25        }
26        for reg in self.regulations() {
27            let line = match reg.observable {
28                true => "filled",
29                false => "dashed",
30            };
31            let color = match reg.monotonicity {
32                Some(Monotonicity::Activation) => "#4abd73",
33                Some(Monotonicity::Inhibition) => "#d05d5d",
34                None => "#797979",
35            };
36            let arrow = match reg.monotonicity {
37                Some(Monotonicity::Activation) => "normal",
38                Some(Monotonicity::Inhibition) => "tee",
39                None => "empty",
40            };
41            writeln!(
42                output,
43                "v{} -> v{} [style=\"{}\", color=\"{}\", arrowhead=\"{}\"];",
44                reg.regulator.0, reg.target.0, line, color, arrow,
45            )?;
46        }
47        writeln!(output, "}}")?;
48        Ok(())
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use crate::RegulatoryGraph;
55
56    #[test]
57    pub fn test_regulatory_graph_to_dot() {
58        let mut rg = RegulatoryGraph::new(vec!["a".to_string(), "b".to_string(), "c".to_string()]);
59
60        rg.add_string_regulation("a -?? a").unwrap();
61        rg.add_string_regulation("a -> b").unwrap();
62        rg.add_string_regulation("b -| c").unwrap();
63        rg.add_string_regulation("c ->? a").unwrap();
64        rg.add_string_regulation("a -|? c").unwrap();
65        rg.add_string_regulation("b -? b").unwrap();
66
67        println!("{}", rg.to_dot());
68    }
69}