-
Notifications
You must be signed in to change notification settings - Fork 0
/
Storage.jl
159 lines (115 loc) · 3.6 KB
/
Storage.jl
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
149
150
151
152
153
154
155
156
157
158
159
module Storage
#
# The object managing output storage for the system.
#
# The object has two purposes:
#
# * gather data that arrives per-frame and package it into
# readable output files, one per frame.
#
# * gather data that will be stored in a single file for all
# time points at the end of the simulation
#
# Note: the data may overlap between storage types.
#
#
using Calendar
import Calendar.CalendarTime
# the global storage manager object
global sm = nothing
type StorageManager
output_dir :: String
log_name :: String
frame_prefix :: String
tag_cfg :: Dict
current_frame :: Dict
frame_ndx :: Int
flushed :: Bool
ts_store :: Dict
log_io
StorageManager(out_dir, log_name, frame_prefix) = new(out_dir, log_name, frame_prefix, Dict{String,Any}(), Dict{String,Any}(), 1, false, Dict{String,Any}(), nothing)
end
function sopen(out_dir, log_name, frame_prefix)
global sm
sm = StorageManager(out_dir, log_name, frame_prefix)
log_path = join([out_dir, log_name], "/")
sm.log_io = open(log_path, "w")
println(sm.log_io, "Initialized log at [$log_path]")
end
function sclose()
global sm
close(sm.log_io)
sm = nothing
end
function setup_tag(tag :: String, stdout :: Bool, logout :: Bool)
sm.tag_cfg[tag] = (stdout, logout)
end
function next_frame()
flush_frame()
sm.current_frame = Dict{String,Any}()
sm.flushed = false
end
function flush_frame()
# if the frame is already flushed, don't call again
if sm.flushed == false
f = sm.current_frame
kk = collect(keys(f))
# another construction to avoid "," after last item
if length(kk) > 0
# render the data in python mode
ff_name = join([sm.output_dir, string(sm.frame_prefix, string(sm.frame_ndx))], "/")
io = open(ff_name, "w")
println(io, "{")
python_render_item(io, kk[1], f[kk[1]])
for k in kk[2:]
println(io, ",")
python_render_item(io, k, f[k])
end
println(io)
println(io, "}")
close(io)
end
sm.frame_ndx += 1
# log end of frame to io
println(sm.log_io, "end-of-frame [$ff_name]")
# indicate this frame has been flushed
sm.flushed = true
end
end
function spush(tag :: String, data)
c = sm.tag_cfg[tag]
sm.current_frame[tag] = data
# if stdout requested print it
if c[1] println(string(tag, " : ", data)) end
# if logout is requested
if c[2] println(sm.log_io, string(tag, " : ", data)) end
end
function python_render_item(io::IO, k::String, v::CalendarTime)
show(io,k)
print(io, " : ")
print(io, "datetime($(year(v)), $(month(v)), $(day(v)), $(hour(v)), $(minute(v)), $(second(v)))")
end
function python_render_item(io::IO, k::String, v::Array)
show(io, k)
print(io, " : ")
# construct to avoid "," after last item in list
s = size(v)
print(io, length(s) > 1 ? "np.reshape([" : "[")
if length(v) > 0
python_render_item(io, v[1])
for i in v[2:]
print(io, ", ")
python_render_item(io, i)
end
end
println(io, length(s) > 1 ? "], $s, order = 'F')" : "]")
end
function python_render_item(io::IO, k::String, v::Any)
show(io, k)
print(io, " : ")
python_render_item(io, v)
end
# specialize for floats which are otherwise printed with too many digits
python_render_item(io::IO, f::Float64) = isnan(f) ? @printf(io, "np.nan") : @printf(io, "%f", f)
python_render_item(io::IO, f) = show(io, f)
end