/
output.jl
272 lines (220 loc) · 7.19 KB
/
output.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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
defaultOutputFormat(plt::Plot) = "png"
function png(plt::Plot, fn)
fn = addExtension(fn, "png")
open(io -> show(io, MIME("image/png"), plt), fn, "w")
fn
end
png(fn) = png(current(), fn)
png(plt::Plot, io::IO) = show(io, MIME("image/png"), plt)
png(io::IO) = png(current(), io)
function svg(plt::Plot, fn)
fn = addExtension(fn, "svg")
open(io -> show(io, MIME("image/svg+xml"), plt), fn, "w")
fn
end
svg(fn) = svg(current(), fn)
svg(plt::Plot, io::IO) = show(io, MIME("image/svg+xml"), plt)
svg(io::IO) = svg(current(), io)
function pdf(plt::Plot, fn)
fn = addExtension(fn, "pdf")
open(io -> show(io, MIME("application/pdf"), plt), fn, "w")
fn
end
pdf(fn) = pdf(current(), fn)
pdf(plt::Plot, io::IO) = show(io, MIME("application/pdf"), plt)
pdf(io::IO) = pdf(current(), io)
function ps(plt::Plot, fn)
fn = addExtension(fn, "ps")
open(io -> show(io, MIME("application/postscript"), plt), fn, "w")
fn
end
ps(fn) = ps(current(), fn)
ps(plt::Plot, io::IO) = show(io, MIME("application/postscript"), plt)
ps(io::IO) = ps(current(), io)
function eps(plt::Plot, fn)
fn = addExtension(fn, "eps")
open(io -> show(io, MIME("image/eps"), plt), fn, "w")
fn
end
eps(fn) = eps(current(), fn)
eps(plt::Plot, io::IO) = show(io, MIME("image/eps"), plt)
eps(io::IO) = eps(current(), io)
function tex(plt::Plot, fn)
fn = addExtension(fn, "tex")
open(io -> show(io, MIME("application/x-tex"), plt), fn, "w")
fn
end
tex(fn) = tex(current(), fn)
tex(plt::Plot, io::IO) = show(io, MIME("application/x-tex"), plt)
tex(io::IO) = tex(current(), io)
function json(plt::Plot, fn)
fn = addExtension(fn, "json")
open(io -> show(io, MIME("application/vnd.plotly.v1+json"), plt), fn, "w")
fn
end
json(fn) = json(current(), fn)
json(plt::Plot, io::IO) = show(io, MIME("application/vnd.plotly.v1+json"), plt)
json(io::IO) = json(current(), io)
function html(plt::Plot, fn)
fn = addExtension(fn, "html")
open(io -> show(io, MIME("text/html"), plt), fn, "w")
fn
end
html(fn) = html(current(), fn)
html(plt::Plot, io::IO) = show(io, MIME("text/html"), plt)
html(io::IO) = html(current(), io)
function txt(plt::Plot, fn; color::Bool = true)
fn = addExtension(fn, "txt")
open(io -> show(IOContext(io, :color => color), MIME("text/plain"), plt), fn, "w")
fn
end
txt(fn) = txt(current(), fn)
txt(plt::Plot, io::IO) = show(io, MIME("text/plain"), plt)
txt(io::IO) = txt(current(), io)
# ----------------------------------------------------------------
const _savemap = Dict(
"png" => png,
"svg" => svg,
"pdf" => pdf,
"ps" => ps,
"eps" => eps,
"tex" => tex,
"json" => json,
"html" => html,
"tikz" => tex,
"txt" => txt,
)
for out in Symbol.(unique(values(_savemap)))
@eval @doc """
$($out)([plot,], filename)
Save plot as $($out)-file.
""" $out
end
const _extension_map = Dict("tikz" => "tex")
"""
addExtension(filepath, extension)
Change filepath extension according to the extension map
"""
function addExtension(fp, ext::AbstractString)
dn, fn = splitdir(fp)
_, oldext = splitext(fn)
oldext = chop(oldext, head = 1, tail = 0)
get(_extension_map, oldext, oldext) == ext ? fp : joinpath(dn, string(fn, ".", ext))
end
"""
savefig([plot,] filename)
Save a Plot (the current plot if `plot` is not passed) to file. The file
type is inferred from the file extension. All backends support png and pdf
file types, some also support svg, ps, eps, html and tex.
"""
function savefig(plt::Plot, fn) # fn might be an `AbstractString` or an `AbstractPath` from `FilePaths.jl`
fn = abspath(expanduser(fn))
# get the extension
_, ext = splitext(fn)
ext = chop(ext, head = 1, tail = 0)
isempty(ext) && (ext = defaultOutputFormat(plt))
# save it
if haskey(_savemap, ext)
func = _savemap[ext]
return func(plt, fn)
else
error("Invalid file extension: ", fn)
end
end
savefig(fn) = savefig(current(), fn)
# ---------------------------------------------------------
"""
gui([plot])
Display a plot using the backends' gui window
"""
gui(plt::Plot = current()) = display(PlotsDisplay(), plt)
function inline end # for IJulia
function Base.display(::PlotsDisplay, plt::Plot)
prepare_output(plt)
_display(plt)
end
_do_plot_show(plt, showval::Bool) = showval && gui(plt)
function _do_plot_show(plt, showval::Symbol)
showval === :gui && gui(plt)
showval in (:inline, :ijulia) && inline(plt)
end
# ---------------------------------------------------------
const _best_html_output_type =
KW(:pyplot => :png, :unicodeplots => :txt, :plotlyjs => :html, :plotly => :html)
# a backup for html... passes to svg or png depending on the html_output_format arg
function _show(io::IO, ::MIME"text/html", plt::Plot)
output_type = Symbol(plt.attr[:html_output_format])
if output_type === :auto
output_type = get(_best_html_output_type, backend_name(plt.backend), :svg)
end
if output_type === :png
# @info "writing png to html output"
print(
io,
"<img src=\"data:image/png;base64,",
base64encode(show, MIME("image/png"), plt),
"\" />",
)
elseif output_type === :svg
# @info "writing svg to html output"
show(io, MIME("image/svg+xml"), plt)
elseif output_type === :txt
show(io, MIME("text/plain"), plt)
else
error("only png or svg allowed. got: $(repr(output_type))")
end
end
# delegate showable to _show instead
Base.showable(m::M, ::P) where {M<:MIME,P<:Plot} = showable(m, P)
Base.showable(::M, ::Type{P}) where {M<:MIME,P<:Plot} = hasmethod(_show, Tuple{IO,M,P})
_display(plt::Plot) = @warn "_display is not defined for this backend."
Base.show(io::IO, m::MIME"text/plain", plt::Plot) = show(io, plt)
# for writing to io streams... first prepare, then callback
for mime in (
"text/html",
"text/latex",
"image/png",
"image/eps",
"image/svg+xml",
"application/eps",
"application/pdf",
"application/postscript",
"application/x-tex",
"application/vnd.plotly.v1+json",
)
@eval function Base.show(io::IO, m::MIME{Symbol($mime)}, plt::Plot)
if haskey(io, :juno_plotsize)
showjuno(io, m, plt)
else
prepare_output(plt)
Base.invokelatest(_show, io, m, plt)
end
return nothing
end
end
"Close all open gui windows of the current backend"
closeall() = closeall(backend())
# COV_EXCL_START
Base.showable(::MIME"text/html", plt::Plot{UnicodePlotsBackend}) = false # Pluto
Base.show(io::IO, m::MIME"application/prs.juno.plotpane+html", plt::Plot) =
showjuno(io, MIME("text/html"), plt)
# Atom PlotPane
function showjuno(io::IO, m, plt)
dpi = plt[:dpi]
plt[:dpi] = get(io, :juno_dpi_ratio, 1) * Plots.DPI
prepare_output(plt)
try
_showjuno(io, m, plt)
finally
plt[:dpi] = dpi
end
end
_showjuno(io::IO, m::MIME"image/svg+xml", plt) =
if Symbol(plt.attr[:html_output_format]) ≠ :svg
throw(MethodError(show, (typeof(m), typeof(plt))))
else
_show(io, m, plt)
end
Base.showable(::MIME"application/prs.juno.plotpane+html", plt::Plot) = false
_showjuno(io::IO, m, plt) = _show(io, m, plt)
# COV_EXCL_STOP