/
iterate_graph_detail.rs
148 lines (125 loc) · 4.51 KB
/
iterate_graph_detail.rs
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use anyhow::Result;
fn load_yaml(path: &str) -> Result<demes::Graph> {
let file = std::fs::File::open(path)?;
let graph = demes::load(file)?;
Ok(graph)
}
fn display_graph<T>(graph: &T)
where
T: std::fmt::Display,
{
println!("We can print the Graph as a YAML string:\n");
println!("{graph}");
}
fn graph_api_examples(graph: &demes::Graph) {
println!("Example of the graph API:\n");
println!("Description: {}", graph.description().unwrap_or("None"));
// DOI data are stored in a vector.
// The API provides an iterator
let num_doi = graph.doi().count();
match num_doi {
0 => println!("There is no DOI information for this graph"),
_ => {
println!("DOI:");
graph.doi().for_each(|doi| println!("\t{doi}"));
}
}
println!("The time units are: {}", graph.time_units());
println!("The generation time is: {}", graph.generation_time());
}
fn iterate_demes_and_epochs(graph: &demes::Graph) {
println!("\nIterate over demes and their epochs:\n");
// Get a &[demes::Deme] (slice of demes)
for deme in graph.demes() {
println!("Deme {}: {}", deme.name(), deme.description());
println!("\tstart_time: {}", deme.start_time());
println!("\tend_time: {}", deme.end_time());
println!("\ttime_interval: {}", deme.time_interval());
println!("\tstart_size: {}", deme.start_size());
println!("\tend_size: {}", deme.end_size());
// deme.epochs returns &[demes::Epoch] (slice of epochs),
// which we then enumerate over.
for (i, epoch) in deme.epochs().iter().enumerate() {
println!("\tepoch {i}:");
println!("\t\tstart_time: {}", epoch.start_time());
println!("\t\tend_time: {}", epoch.end_time());
println!("\t\ttime_interval: {}", epoch.time_interval());
println!("\t\tstart_size: {}", epoch.start_size());
println!("\t\tend_size: {}", epoch.end_size());
println!("\t\tsize_function: {}", epoch.size_function());
}
}
}
fn iterate_migrations(graph: &demes::Graph) {
println!("\nIterate over asymmetric migrations:\n");
// Enumerate the &[demes::AsymmetricMigration]
for (i, migration) in graph.migrations().iter().enumerate() {
println!("migration {i}");
println!("\tstart_time: {}", migration.start_time());
println!("\tend_time: {}", migration.end_time());
println!("\ttime_interval: {}", migration.time_interval());
println!("\tsource: {}", migration.source());
println!("\tdest: {}", migration.dest());
}
}
fn iterate_pulses(graph: &demes::Graph) {
// Enumerate the &[demes::Pulse]
for (i, pulse) in graph.pulses().iter().enumerate() {
println!("pulse {i}");
println!("\ttime: {}", pulse.time());
// Slices don't implement Display, so we
// format things manually
print!("\tsources: [");
for s in pulse.sources() {
print!("{s}, ");
}
println!("]");
println!("\tdest: {}", pulse.dest());
print!("\tproportions: [");
for p in pulse.proportions() {
print!("{p}, ");
}
println!("]");
}
}
fn do_work(path: &str) -> Result<()> {
let graph = load_yaml(path)?;
// demes::Graph implements Display, which
// writes out the YAML representation
// of the fully-resolved graph.
// Note: the implementation of Display
// wraps a call to graph.as_string().unwrap(),
// which returns a YAML string. The as_string
// function may return an error from serde_yaml,
// although that is very unlikely to happen
// for a resolved graph.
display_graph(&graph);
// If demes is build with the json feature,
// then we can get a JSON string representation
// of the graph.
// Note that the #[cfg(...)] business is only needed
// here because this file is part of the demes-rs repo.
// See the section in the book on features:
// https://doc.rust-lang.org/cargo/reference/features.html
#[cfg(feature = "json")]
{
println!(
"The graph in JSON format:\n{}",
graph.as_json_string().unwrap()
);
}
graph_api_examples(&graph);
iterate_demes_and_epochs(&graph);
iterate_migrations(&graph);
iterate_pulses(&graph);
Ok(())
}
fn main() {
for input in std::env::args().skip(1) {
do_work(&input).unwrap();
}
}
#[test]
fn test_jouganous_model() {
do_work("examples/jouganous.yaml").unwrap();
}