Skip to content

Commit 50e42b8

Browse files
guoyongzhiguo-yong-zhi
guoyongzhi
authored andcommitted
add example compare2
1 parent a00c4c6 commit 50e42b8

File tree

5 files changed

+136
-27
lines changed

5 files changed

+136
-27
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "WordCloud"
22
uuid = "6385f0a0-cb03-45b6-9089-4e0acc74b26b"
33
authors = ["guoyongzhi <momoshanghan@163.com>"]
4-
version = "0.6.7"
4+
version = "0.6.8"
55

66
[deps]
77
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ paint(wc, "alice.png", ratio=0.5, background=outline(wc.mask, color="purple", li
4545
[![gathering](res/gathering.png)](./examples/gathering.jl)
4646
*Run the command `runexample(:gathering)` or `showexample(:gathering)` to get the result.*
4747
## Recolor
48-
[![recolor](res/recolor.png)](./examples/recolor.jl)![recolor](res/butterfly.png)
48+
[![recolor](res/recolor.png)](./examples/recolor.jl)
4949
*Run the command `runexample(:recolor)` or `showexample(:recolor)` to get the result.*
5050
## Comparison
5151
[![compare](res/compare.png)](./examples/compare.jl)

examples/compare2.jl

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#md# This is a more symmetrical and accurate way to generate comparison wordclouds, but it may be more time consuming.
2+
#md# ### Prepare two wordcloud objects
3+
using WordCloud
4+
5+
stwords = ["us", "will"];
6+
cs = WordCloud.randomscheme() #:Set1_8#
7+
as = WordCloud.randomangles() #(0,90,45,-45)#
8+
dens = 0.5 #not too high
9+
wca = wordcloud(
10+
processtext(open(pkgdir(WordCloud)*"/res/Barack Obama's First Inaugural Address.txt"), stopwords=WordCloud.stopwords_en stwords),
11+
colors = cs,
12+
angles = as,
13+
density = dens,
14+
run = x->nothing, #turn off the initimage! and placement! in advance
15+
)
16+
wcb = wordcloud(
17+
processtext(open(pkgdir(WordCloud)*"/res/Donald Trump's Inaugural Address.txt"), stopwords=WordCloud.stopwords_en stwords),
18+
mask = getsvgmask(wca),
19+
colors = cs,
20+
angles = as,
21+
density = dens,
22+
run = x->nothing,
23+
)
24+
#md# ### Make the same words the same style
25+
samewords = getwords(wca) getwords(wcb)
26+
println(length(samewords), " same words")
27+
for w in samewords
28+
setcolors!(wcb, w, getcolors(wca, w))
29+
setangles!(wcb, w, getangles(wca, w))
30+
end
31+
#md# ### Put the same words at same position
32+
initimages!(wca)
33+
initimages!(wcb)
34+
keep(wca, samewords) do
35+
placement!(wca)
36+
fit!(wca, 1000) #patient=-1 means no teleport; retry=1 means no rescale
37+
end
38+
pin(wca, samewords) do
39+
placement!(wca) #place other words
40+
end
41+
centers = getpositions(wca, samewords, type=getcenter)
42+
setpositions!(wcb, samewords, centers, type=setcenter!) #manually initialize the position,
43+
pin(wcb, samewords) do
44+
placement!(wcb) #place other words
45+
end
46+
#md# ### Fit them all
47+
function syncposition(samewords, pos, wca, wcb)
48+
pos2 = getpositions(wca, samewords, type=getcenter)
49+
if pos != pos2
50+
setpositions!(wcb, samewords, pos2, type=setcenter!)
51+
setstate!(wcb, :placement!)
52+
end
53+
pos2
54+
end
55+
function pinfit!(wc, samewords, ep1, ep2)
56+
pin(wc, samewords) do
57+
fit!(wc, ep1)
58+
end
59+
fit!(wc, ep2, patient=-1) #patient=-1 means no teleport
60+
end
61+
pos = getpositions(wca, samewords, type=getcenter)
62+
while wca.params[:epoch] < 2000
63+
global pos
64+
pinfit!(wca, samewords, 200, 50)
65+
pos = syncposition(samewords, pos, wca, wcb)
66+
pinfit!(wcb, samewords, 200, 50)
67+
pos = syncposition(samewords, pos, wcb, wca)
68+
if getstate(wca) == getstate(wcb) == :fit!
69+
break
70+
end
71+
end
72+
println("Takes $(wca.params[:epoch]) and $(wcb.params[:epoch]) epochs")
73+
WordCloud.printcollisions(wca)
74+
WordCloud.printcollisions(wcb)
75+
#md#
76+
ma = paint(wca)
77+
mb = paint(wcb)
78+
h,w = size(ma)
79+
space = fill(mb[1], (h, w÷20))
80+
try mkdir("address_compare2") catch end
81+
println("results are saved in address_compare2")
82+
WordCloud.save("address_compare2/compare2.png", [ma space mb])
83+
#eval# try rm("address_compare2", force=true, recursive=true) catch end
84+
gif = WordCloud.GIF("address_compare2")
85+
record(wca, "Obama", gif)
86+
record(wcb, "Trump", gif)
87+
WordCloud.Render.generate(gif, framerate=1)
88+
wca, wcb
89+
#eval# runexample(:compare2)
90+
#md# ![](address_compare2/compare2.png)
91+
#md# ![](address_compare2/result.gif)

src/WordCloud.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export wordcloud, processtext, html2text, countwords, lemmatize, casemerge!
33
export parsecolor, rendertext, shape, ellipse, box, loadmask, outline, padding, paint, paintsvg, svgstring
44
export imageof, showmask, showmask!
55
export record, placement!, rescale!, recolor!, take, keep, ignore, pin, runexample, showexample,
6-
generate!, generate_animation!
6+
generate!, generate_animation!, fit!
77
export getcolors, getangles, getwords, getweights, setcolors!, setangles!, setwords!, setweights!,
88
getpositions, setpositions!, getimages, getsvgimages, setimages!, setsvgimages!, getmask, getsvgmask,
99
getfontsizes, setfontsizes!, getfonts, setfonts!, getstate, setstate!, initimage!, initimages!

src/wc-method.jl

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ function initqtree!(wc, i::Integer; backgroundcolor=(0,0,0,0), border=wc.params[
88
end
99
initqtree!(wc, i; kargs...) = initqtree!.(wc, index(wc, i); kargs...)
1010
"Initialize word's images and other resources with specified style"
11-
function initimage!(wc, i::Integer; backgroundcolor=(0,0,0,0), border=wc.params[:border],
11+
function initimages!(wc, i::Integer; backgroundcolor=(0,0,0,0), border=wc.params[:border],
1212
fontsize=getfontsizes(wc, i), color=wc.params[:colors][i],
1313
angle = wc.params[:angles][i], font=getfonts(wc, i))
1414
img, svg = prepareword(wc.words[i], fontsize, color, angle,
@@ -18,8 +18,8 @@ function initimage!(wc, i::Integer; backgroundcolor=(0,0,0,0), border=wc.params[
1818
initqtree!(wc, i, backgroundcolor=backgroundcolor, border=border)
1919
nothing
2020
end
21-
initimage!(wc, i; kargs...) = initimage!.(wc, index(wc, i); kargs...)
22-
function initimage!(wc::WC; maxiter=5, error=0.02)
21+
initimages!(wc, i; kargs...) = initimage!.(wc, index(wc, i); kargs...)
22+
function initimages!(wc::WC; maxiter=5, error=0.02)
2323
params = wc.params
2424
mask = wc.mask
2525

@@ -36,10 +36,10 @@ function initimage!(wc::WC; maxiter=5, error=0.02)
3636
scale = find_weight_scale!(wc, density=params[:density], maxiter=maxiter, error=error)
3737
println("density set to $(params[:density]), with scale=$scale, font minimum is $(getfontsizes(wc, length(wc.words)))")
3838
initimage!.(wc, 1:length(words))
39-
params[:state] = nameof(initimages!)
39+
setstate!(wc, nameof(initimages!))
4040
wc
4141
end
42-
initimages! = initimage!
42+
initimage! = initimages!
4343
"""
4444
* placement!(wc)
4545
* placement!(wc, style=:uniform)
@@ -50,7 +50,7 @@ p=1 produces a rhombus, p=2 produces an ellipse, p>2 produces a rectangle with r
5050
When you have set `style=:gathering`, you should disable teleporting in `generate!` at the same time(`generate!(wc, patient=-1)`).
5151
"""
5252
function placement!(wc::WC; style=:uniform, kargs...)
53-
if getstate(wc) == nameof(wordcloud)
53+
if STATEIDS[getstate(wc)] < STATEIDS[:initimages!]
5454
initimages!(wc)
5555
end
5656
@assert style in [:uniform, :gathering]
@@ -69,7 +69,7 @@ function placement!(wc::WC; style=:uniform, kargs...)
6969
end
7070
if ind === nothing error("no room for placement") end
7171
end
72-
wc.params[:state] = nameof(placement!)
72+
setstate!(wc, nameof(placement!))
7373
wc
7474
end
7575

@@ -151,6 +151,30 @@ function recolor!(wc, args...; style=:average, kargs...)
151151
end
152152
nothing
153153
end
154+
155+
function fit!(wc, args...; krags...)
156+
if STATEIDS[getstate(wc)] < STATEIDS[:placement!]
157+
placement!(wc)
158+
end
159+
qtrees = [wc.maskqtree, wc.qtrees...]
160+
ep, nc = train!(qtrees, args...; krags...)
161+
wc.params[:epoch] += ep
162+
if nc == 0
163+
setstate!(wc, nameof(fit!))
164+
end
165+
wc
166+
end
167+
function printcollisions(wc)
168+
qtrees = [wc.maskqtree, wc.qtrees...]
169+
colllist = first.(batchcollision(qtrees))
170+
get_text(i) = i>1 ? wc.words[i-1] : "#MASK#"
171+
collwords = [(get_text(i), get_text(j)) for (i,j) in colllist]
172+
if length(colllist) > 0
173+
println("have $(length(colllist)) collisions.",
174+
" try setting a larger `nepoch` and `retry`, or lower `density` in `wordcloud` to fix that")
175+
println("$collwords")
176+
end
177+
end
154178
"""
155179
# Positional Args
156180
* wc: the wordcloud to train
@@ -161,10 +185,9 @@ end
161185
* trainer: appoint a training engine
162186
"""
163187
function generate!(wc::WC, args...; retry=3, krags...)
164-
if getstate(wc) != nameof(placement!) && getstate(wc) != nameof(generate!)
188+
if STATEIDS[getstate(wc)] < STATEIDS[:placement!]
165189
placement!(wc)
166190
end
167-
qtrees = [wc.maskqtree, wc.qtrees...]
168191
ep, nc = -1, -1
169192
for r in 1:retry
170193
if r != 1
@@ -175,28 +198,19 @@ function generate!(wc::WC, args...; retry=3, krags...)
175198
else
176199
println("#$r. scale = $(wc.params[:scale])")
177200
end
178-
ep, nc = train!(qtrees, args...; krags...)
179-
wc.params[:epoch] += ep
180-
if nc == 0
201+
fit!(wc, args...; krags...)
202+
if getstate(wc) == :fit!
181203
break
182204
end
183205
end
184-
println("$ep epochs, $nc collisions")
185-
if nc == 0
186-
wc.params[:state] = nameof(generate!)
206+
if STATEIDS[getstate(wc)] >= STATEIDS[:fit!]
207+
println("$(wc.params[:epoch]) epochs")
208+
setstate!(wc, nameof(generate!))
187209
# @assert isempty(outofkernelbounds(wc.maskqtree, wc.qtrees))
188210
# colllist = first.(batchcollision(qtrees))
189211
# @assert length(colllist) == 0
190212
else #check
191-
colllist = first.(batchcollision(qtrees))
192-
get_text(i) = i>1 ? wc.words[i-1] : "#MASK#"
193-
collwords = [(get_text(i), get_text(j)) for (i,j) in colllist]
194-
if length(colllist) > 0
195-
wc.params[:completed] = false
196-
println("have $(length(colllist)) collisions.",
197-
" try setting a larger `nepoch` and `retry`, or lower `density` in `wordcloud` to fix that")
198-
println("$collwords")
199-
end
213+
printcollisions(wc)
200214
end
201215
wc
202216
end
@@ -213,6 +227,10 @@ function generate_animation!(wc::WC, args...; outputdir="gifresult", overwrite=o
213227
re
214228
end
215229

230+
STATES = nameof.([wordcloud, initimages!, placement!, fit!, generate!])
231+
STATEIDS = Dict([s=>i for (i,s) in enumerate(STATES)])
232+
233+
216234
"""
217235
keep some words and ignore the others, then execute the function. It's the opposite of `ignore`.
218236
* keep(fun, wc, ws::String) #keep a word

0 commit comments

Comments
 (0)