|
1 | | -export @import_model, @export_model |
| 1 | +export @import_network, @export_network |
| 2 | +export @load_models |
2 | 3 | export @import_solution, @export_solution |
3 | | -export @export_as_table, @export_csv |
| 4 | +export @export_solution_as_table, @export_solution_as_csv |
4 | 5 | export @export, @import |
5 | 6 |
|
6 | 7 | using TOML, JLD2, CSV |
7 | 8 | using DataFrames |
8 | 9 |
|
9 | 10 | const objects_aliases = Dict(:S => "spec", :T => "trans", :P => "prm", :M => "meta", |
10 | 11 | :E => "event", :obs => "obs") |
| 12 | + |
11 | 13 | const RN_attrs = string.(propertynames(ReactionNetwork().subparts)) |
12 | 14 |
|
13 | 15 | function get_attrs(object) |
14 | | - (object = object isa Symbol ? objects_aliases[object] : object; |
15 | | - filter(x -> occursin(object, |
16 | | - x), |
17 | | - RN_attrs)) |
| 16 | + object = object isa Symbol ? objects_aliases[object] : object |
| 17 | + |
| 18 | + filter(x -> occursin(object, x), RN_attrs) |
18 | 19 | end |
19 | 20 |
|
20 | | -function serialize_to_toml(acs::ReactionNetwork, io::IO = stdout) |
21 | | - data = Dict() |
| 21 | +function export_network(acs::ReactionNetwork) |
| 22 | + dict = Dict() |
22 | 23 | for (key, val) in objects_aliases |
23 | | - push!(data, val => []) |
| 24 | + push!(dict, val => []) |
24 | 25 | for i in 1:nparts(acs, key) |
25 | | - data_ = Dict() |
| 26 | + dict_ = Dict() |
26 | 27 | for attr in get_attrs(val) |
27 | 28 | attr_val = acs[i, Symbol(attr)] |
28 | 29 | ismissing(attr_val) && continue |
29 | 30 | attr_val = attr_val isa Number ? attr_val : string(attr_val) |
30 | | - push!(data_, string(attr) => attr_val) |
| 31 | + push!(dict_, string(attr) => attr_val) |
31 | 32 | end |
32 | | - push!(data[val], data_) |
| 33 | + push!(dict[val], dict_) |
33 | 34 | end |
34 | 35 | end |
35 | 36 |
|
36 | | - TOML.print(io, data) |
| 37 | + dict |
37 | 38 | end |
38 | 39 |
|
39 | | -function deserialize_from_dict(data::Dict) |
| 40 | +function load_network(dict::Dict) |
40 | 41 | acs = ReactionNetwork() |
41 | 42 | for (key, val) in objects_aliases |
42 | | - for row in data[val] |
| 43 | + val == "prm" && continue |
| 44 | + for row in get(dict, val, []) |
43 | 45 | i = add_part!(acs, key) |
44 | 46 | for (attr, attrval) in row |
45 | 47 | set_subpart!(acs, i, Symbol(attr), attrval) |
46 | 48 | end |
47 | 49 | end |
48 | 50 | end |
49 | 51 |
|
50 | | - for row in get(data, "registered", []) |
| 52 | + for row in get(dict, "prm", []) |
| 53 | + i = add_part!(acs, :P) |
| 54 | + for (attr, attrval) in row |
| 55 | + if attr == "prmVal" |
| 56 | + attrval = attrval isa String ? eval(Meta.parseall(attrval)) : attrval |
| 57 | + end |
| 58 | + set_subpart!(acs, i, Symbol(attr), attrval) |
| 59 | + end |
| 60 | + end |
| 61 | + |
| 62 | + for row in get(dict, "registered", []) |
51 | 63 | eval(Meta.parseall(row["body"])) |
52 | 64 | end |
53 | 65 |
|
54 | 66 | assign_defaults!(acs) |
55 | 67 | end |
56 | 68 |
|
57 | | -export_model(acs::ReactionNetwork, path::AbstractString) = |
58 | | - open(path, "w") do io |
59 | | - serialize_to_toml(acs, io) |
| 69 | +function import_network_csv(pathmap) |
| 70 | + dict = Dict(); for (key, paths) in pathmap |
| 71 | + push!(dict, key => []) |
| 72 | + for path in paths |
| 73 | + data = DataFrame(CSV.File(path; delim=";;", types=String, stripwhitespace=true, comment="#")) |
| 74 | + for row in eachrow(data) |
| 75 | + object = Dict(); for (attr, val) in Iterators.zip(keys(row), values(row)) |
| 76 | + !ismissing(val) && push!(object, string(attr) => val) |
| 77 | + end |
| 78 | + push!(dict[key], object) |
| 79 | + end |
| 80 | + end |
| 81 | + end |
| 82 | + |
| 83 | + load_network(dict) |
| 84 | +end |
| 85 | + |
| 86 | +function import_network(path::AbstractString) |
| 87 | + if splitext(path)[2] == ".csv" |
| 88 | + pathmap = Dict(val => [] for val in [collect(values(objects_aliases)); "registered"]) |
| 89 | + for row in CSV.File(path; delim=";;", stripwhitespace=true, comment="#") |
| 90 | + push!(pathmap[row.type], joinpath(dirname(path), row.path)) |
| 91 | + end |
| 92 | + |
| 93 | + import_network_csv(pathmap) |
| 94 | + else |
| 95 | + load_network(TOML.parsefile(path)) |
60 | 96 | end |
61 | | -function import_model(path::AbstractString) |
62 | | - (dict = TOML.parsefile(path); deserialize_from_dict(dict)) |
63 | 97 | end |
64 | 98 |
|
65 | | -function load_models(io::IO) |
66 | | - for line in eachline(io) |
67 | | - name, path = split(line, ';') |
68 | | - name = isempty(name) ? gensym() : name |
| 99 | + |
| 100 | +function export_network(acs::ReactionNetwork, path::AbstractString) |
| 101 | + if splitext(path)[2] == ".csv" |
| 102 | + exported_network = export_network(acs) |
| 103 | + paths = DataFrame(type = [], path = []) |
| 104 | + for (key, objs) in exported_network |
| 105 | + push!(paths, (key, "export-$key.csv")) |
| 106 | + objs_exported = DataFrame(Dict(attr => [] for attr in get_attrs(key))) |
| 107 | + for obj in objs |
| 108 | + push!(objs_exported, [get(obj, key, missing) for key in names(objs_exported)]) |
| 109 | + end |
| 110 | + |
| 111 | + CSV.write(joinpath(dirname(path), "export-$key.csv"), objs_exported, delim=";;") |
| 112 | + end |
| 113 | + CSV.write(path, paths, delim=";;") |
| 114 | + else |
| 115 | + open(io -> TOML.print(io, export_network(acs)), path, "w+") |
69 | 116 | end |
70 | 117 | end |
71 | 118 |
|
| 119 | + |
72 | 120 | """ |
73 | | -Export model to a file. |
| 121 | +Export model to a file: this can be either a single TOML file encoding the entire model, |
| 122 | +or a batch of CSV files (a root file and a number of files, each per a class of objects). |
| 123 | +
|
| 124 | +See `tutorials/loadsave` for an example. |
74 | 125 |
|
75 | 126 | # Examples |
76 | 127 | ```julia |
77 | | -@export_model acs "acs_data.toml" |
| 128 | +@export_network acs "acs_data.toml" # as a TOML |
| 129 | +@export_network acs "csv/model.csv" # as a CSV |
78 | 130 | ``` |
79 | 131 | """ |
80 | | -macro export_model(acsex, pathex) |
81 | | - :(export_model($(esc(acsex)), $(string(pathex)))) |
| 132 | +macro export_network(acsex, pathex) |
| 133 | + :(export_network($(esc(acsex)), $(string(pathex)))) |
82 | 134 | end |
83 | 135 |
|
84 | 136 | """ |
85 | | -Import a model from a file. |
| 137 | +Import a model from a file: this can be either a single TOML file encoding the entire model, |
| 138 | +or a batch of CSV files (a root file and a number of files, each per a class of objects). |
| 139 | +
|
| 140 | +See `tutorials/loadsave` for an example. |
86 | 141 |
|
87 | 142 | # Examples |
88 | 143 | ```julia |
89 | | -@import_model "model.toml" |
| 144 | +@import_network "model.toml" |
| 145 | +@import_network "csv/model.toml" |
90 | 146 | ``` |
91 | 147 | """ |
92 | | -macro import_model(pathex, name = gensym()) |
93 | | - :($(esc(name)) = import_model($(string(pathex)))) |
| 148 | +macro import_network(pathex, name = gensym()) |
| 149 | + :($(esc(name)) = import_network($(string(pathex)))) |
94 | 150 | end |
95 | 151 |
|
96 | 152 | macro load_models(pathex) |
97 | 153 | callex = :(begin end) |
98 | 154 | for line in readlines(string(pathex)) |
99 | 155 | name, pathex = split(line, ';') |
100 | 156 | name = isempty(name) ? gensym() : Symbol(name) |
101 | | - push!(callex.args, :($(esc(name)) = import_model($(string(pathex))))) |
| 157 | + push!(callex.args, :($(esc(name)) = import_network($(string(pathex))))) |
102 | 158 | end |
103 | 159 |
|
104 | 160 | callex |
@@ -133,30 +189,30 @@ macro export_solution(solex, pathex = "sol.jld2") |
133 | 189 | end |
134 | 190 |
|
135 | 191 | """ |
136 | | - @export_as_table sol |
| 192 | + @export_solution_as_table sol |
137 | 193 | Export a solution as a `DataFrame`. |
138 | 194 |
|
139 | 195 | # Examples |
140 | 196 | ```julia |
141 | | -@export_as_table sol |
| 197 | +@export_solution_as_table sol |
142 | 198 | ``` |
143 | 199 | """ |
144 | | -macro export_as_table(solex, pathex = "sol.jld2") |
| 200 | +macro export_solution_as_table(solex, pathex = "sol.jld2") |
145 | 201 | :(DataFrame($(esc(solex)))) |
146 | 202 | end |
147 | 203 |
|
148 | 204 | get_DataFrame(sol) = sol isa EnsembleSolution ? DataFrame(sol)[!, [:u, :t]] : DataFrame(sol) |
149 | 205 |
|
150 | 206 | """ |
151 | | - @export_csv sol |
152 | | - @export_csv sol "sol.csv" |
| 207 | + @export_solution_as_csv sol |
| 208 | + @export_solution_as_csv sol "sol.csv" |
153 | 209 | Export a solution to a file. |
154 | 210 |
|
155 | 211 | # Examples |
156 | 212 | ```julia |
157 | | -@export_csv sol "sol.csv" |
| 213 | +@export_solution_as_csv sol "sol.csv" |
158 | 214 | ``` |
159 | 215 | """ |
160 | | -macro export_csv(solex, pathex = "sol.csv") |
| 216 | +macro export_solution_as_csv(solex, pathex = "sol.csv") |
161 | 217 | :(CSV.write($(string(pathex)), get_DataFrame($(esc(solex))))) |
162 | 218 | end |
0 commit comments