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
use crate::sbml::import::{child_tags, read_unique_child, SBML_LAYOUT};
use roxmltree::Node;
use std::collections::HashMap;
#[derive(Clone, Debug, PartialEq)]
pub struct SbmlLayout {
pub dimensions: (f64, f64),
pub glyphs: HashMap<String, (f64, f64)>,
}
pub fn read_sbml_layout(model: Node) -> Result<SbmlLayout, String> {
let layout_list = read_unique_child(model, (SBML_LAYOUT, "listOfLayouts"))?;
let layouts = child_tags(layout_list, (SBML_LAYOUT, "layout"));
if layouts.is_empty() {
return Err("No layout found.".to_string());
}
let mut result = SbmlLayout {
dimensions: (0.0, 0.0),
glyphs: HashMap::new(),
};
let layout = layouts[0];
let dimensions = read_unique_child(layout, (SBML_LAYOUT, "dimensions")).ok();
if let Some(dimensions) = dimensions {
if let Some(width) = dimensions.attribute((SBML_LAYOUT, "width")) {
result.dimensions.0 = str_to_f64(width)?;
}
if let Some(height) = dimensions.attribute((SBML_LAYOUT, "height")) {
result.dimensions.1 = str_to_f64(height)?;
}
}
let glyph_list =
read_unique_child(layout, (SBML_LAYOUT, "listOfAdditionalGraphicalObjects")).ok();
if let Some(glyph_list) = glyph_list {
let glyphs = child_tags(glyph_list, (SBML_LAYOUT, "generalGlyph"));
for glyph in glyphs {
if let Some(reference) = glyph.attribute((SBML_LAYOUT, "reference")) {
let bounding_box = read_unique_child(glyph, (SBML_LAYOUT, "boundingBox")).ok();
if let Some(bounding_box) = bounding_box {
let position = read_unique_child(bounding_box, (SBML_LAYOUT, "position")).ok();
if let Some(position) = position {
let mut coordinates = (0.0, 0.0);
if let Some(x) = position.attribute((SBML_LAYOUT, "x")) {
coordinates.0 = str_to_f64(x)?;
}
if let Some(y) = position.attribute((SBML_LAYOUT, "y")) {
coordinates.1 = str_to_f64(y)?;
}
result.glyphs.insert(reference.to_string(), coordinates);
}
}
}
}
}
Ok(result)
}
fn str_to_f64(str: &str) -> Result<f64, String> {
if let Ok(value) = str.parse::<f64>() {
Ok(value)
} else {
Err(format!("Invalid numeric value: {}.", str))
}
}