diff --git a/Project.toml b/Project.toml index 76ed505..004f8ac 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "WordCloud" uuid = "6385f0a0-cb03-45b6-9089-4e0acc74b26b" authors = ["guoyongzhi "] -version = "0.7.5" +version = "0.8.0" [deps] ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4" diff --git a/examples/compare.jl b/examples/compare.jl index 1f47404..b6d700a 100644 --- a/examples/compare.jl +++ b/examples/compare.jl @@ -24,7 +24,7 @@ wcb = wordcloud( backgroundcolor=:maskcolor, maskcolor=getmaskcolor(wca), font=getparameter(wca, :font), - run=x -> nothing, # turn off the useless initword! and placewords! in advance + state=identity, # turn off the useless initword! and placewords! in advance ) #md# Follow these steps to generate a wordcloud: initword! -> placewords! -> generate! samewords = getwords(wca) ∩ getwords(wcb) diff --git a/examples/compare2.jl b/examples/compare2.jl index fc34cc2..cb7302a 100644 --- a/examples/compare2.jl +++ b/examples/compare2.jl @@ -12,7 +12,7 @@ wca = wordcloud( angles=as, density=dens, backgroundcolor=:maskcolor, - run=x -> nothing, # turn off the initword! and placewords! in advance + state=identity, # turn off the initword! and placewords! in advance ) wcb = wordcloud( processtext(open(pkgdir(WordCloud) * "/res/Donald Trump's Inaugural Address.txt"), stopwords=WordCloud.stopwords_en ∪ stwords), @@ -23,7 +23,7 @@ wcb = wordcloud( backgroundcolor=:maskcolor, maskcolor=getmaskcolor(wca), font=getparameter(wca, :font), - run=x -> nothing, + state=identity, ) #md# ### Make the same words the same style samewords = getwords(wca) ∩ getwords(wcb) diff --git a/examples/custom.jl b/examples/custom.jl index 3633720..2ec0dd8 100644 --- a/examples/custom.jl +++ b/examples/custom.jl @@ -5,7 +5,7 @@ wc = wordcloud( mask=shape(ellipse, 600, 500, color=(0.98, 0.97, 0.99), backgroundcolor=0.97, backgroundsize=(700, 550)), colors=:seaborn_icefire_gradient, angles=-90:90, - run=x -> x, # turn off the useless initword! and placewords! in advance + state=identity, # turn off the useless initword! and placewords! in advance ) setwords!(wc, "Alice", "Alice in Wonderland") # replace the word 'Alice' with 'Alice in Wonderland' diff --git a/examples/gathering.jl b/examples/gathering.jl index 8794cab..43be66c 100644 --- a/examples/gathering.jl +++ b/examples/gathering.jl @@ -4,7 +4,7 @@ wc = wordcloud( processtext(open(pkgdir(WordCloud) * "/res/alice.txt"), stopwords=WordCloud.stopwords_en ∪ ["said"]), angles=0, density=0.55, maskshape=squircle, rt=2.5 * rand(), - run=initwords!) + state=initwords!) placewords!(wc, style=:gathering, level=5, centerlargestword=true) pin(wc, "Alice") do # keep "Alice" in the center generate!(wc, teleporting=0.7) # don't teleport largest 30% words diff --git a/examples/nomask.jl b/examples/nomask.jl index 77dfa67..3562386 100644 --- a/examples/nomask.jl +++ b/examples/nomask.jl @@ -11,7 +11,7 @@ wc = wordcloud( masksize=(1200, 900, 0), backgroundcolor=:maskcolor, angles=rand((0, (0, 90))), - run=identity, + state=identity, ) #md# place words in the center of the background to prevent encountering the mask boundary placewords!(wc, style=:gathering, reorder=WordCloud.shuffle, level=6, rt=1) # a proper level is important, and so is luck diff --git a/examples/pattern.jl b/examples/pattern.jl index be89410..c3511d3 100644 --- a/examples/pattern.jl +++ b/examples/pattern.jl @@ -6,7 +6,7 @@ l = 200 wc = wordcloud( repeat(["placeholder"], l), repeat([1], l), mask=shape(box, 400, 300, color=WordCloud.randommaskcolor(sc)), - run=x -> x) + state=identity) #md# * `words` & `weights` are just placeholders #md# * style arguments like `colors`, `angles` and `density` have no effect #md# diff --git a/examples/semantic.jl b/examples/semantic.jl index 73d6299..d43b130 100644 --- a/examples/semantic.jl +++ b/examples/semantic.jl @@ -36,7 +36,7 @@ wc = wordcloud( density=0.3, colors=0.3, backgroundcolor=:maskcolor, - run=initwords!, + state=initwords!, # angles = (0,45), font = "Helvetica thin", maskcolor=0.98, ) diff --git a/src/artist.jl b/src/artist.jl index 40426f7..fe163f4 100644 --- a/src/artist.jl +++ b/src/artist.jl @@ -79,8 +79,8 @@ end function randommask(sz; kargs...) randommask(sz...; kargs...) end -function randommask(w, h, args...; maskshape=:rand, keepcontent=:auto, kargs...) - keepcontent = keepcontent == :auto ? maskshape == :rand : keepcontent +function randommask(w, h, args...; maskshape=:rand, keeparea=:auto, kargs...) + keeparea = keeparea == :auto ? maskshape == :rand : keeparea ran = Dict(box => 0.2, squircle => 0.7, ellipse => 1, :rand => rand())[maskshape] if ran <= 0.2 return randombox(w, h, args...; kargs...) @@ -90,18 +90,18 @@ function randommask(w, h, args...; maskshape=:rand, keepcontent=:auto, kargs...) return randomellipse(w, h, args...; kargs...) end end -function randombox(w, h, r=:rand; keepcontent=false, kargs...) +function randombox(w, h, r=:rand; keeparea=false, kargs...) if r == :rand r = rand() * 0.5 - 0.05 # up to 0.45 r = r < 0. ? 0. : r # 10% for 0. r = round(Int, h * r) end - sc = keepcontent ? sqrt(w*h/box_area(w, h, r)) : 1 + sc = keeparea ? sqrt(w*h/box_area(w, h, r)) : 1 w = round(Int, w*sc); h = round(Int, h*sc); r = round(Int, r*sc) println("shape(box, $w, $h, $r", join([", $k=$(repr(v))" for (k, v) in kargs]), ")") return shape(box, w, h, r; kargs...) end -function randomsquircle(w, h; rt=:rand, keepcontent=false, kargs...) +function randomsquircle(w, h; rt=:rand, keeparea=false, kargs...) if rt == :rand if rand() < 0.8 rt = rand() @@ -114,13 +114,13 @@ function randomsquircle(w, h; rt=:rand, keepcontent=false, kargs...) end end end - sc = keepcontent ? sqrt(w*h/squircle_area(w, h, rt=rt)) : 1 + sc = keeparea ? sqrt(w*h/squircle_area(w, h, rt=rt)) : 1 w = round(Int, w*sc); h = round(Int, h*sc) println("shape(squircle, $w, $h, rt=$rt", join([", $k=$(repr(v))" for (k, v) in kargs]), ")") return shape(squircle, w, h, rt=rt; kargs...) end -function randomellipse(w, h; keepcontent=false, kargs...) - sc = keepcontent ? sqrt(w*h/ellipse_area(w, h)) : 1 +function randomellipse(w, h; keeparea=false, kargs...) + sc = keeparea ? sqrt(w*h/ellipse_area(w, h)) : 1 w = round(Int, w*sc); h = round(Int, h*sc) println("shape(ellipse, $w, $h", join([", $k=$(repr(v))" for (k, v) in kargs]), ")") return shape(ellipse, w, h; kargs...) diff --git a/src/textprocessing.jl b/src/textprocessing.jl index 9ee7372..81d8ba1 100644 --- a/src/textprocessing.jl +++ b/src/textprocessing.jl @@ -149,8 +149,11 @@ function processtext(counter::AbstractDict{<:AbstractString,<:Real}; m = weights .> maxweight weights[m] .= log1p.(weights[m] .- maxweight) ./ 10 .+ maxweight weights .+= minweight - print("$(sum(m)) huge words, ") - println("keep top $(length(words)) words.") + nhuge = sum(m) + if nhuge > 0 + print("$nhuge huge words, ") + end + println("keep the top $(length(words)) words.") words, weights end diff --git a/src/wc-class.jl b/src/wc-class.jl index 1096af1..0cded52 100644 --- a/src/wc-class.jl +++ b/src/wc-class.jl @@ -47,11 +47,11 @@ Positional arguments are used to specify words and weights, and can be in differ Some arguments depend on whether or not the `mask` is given or the type of the `mask` given. ### other keyword arguments -The keyword argument `run` is a function. It will be called after the `wordcloud` object constructed. -* run = placewords! #default setting, will initialize word's position -* run = generate! #get result directly -* run = initwords! #only initialize resources, such as rendering word images -* run = x->nothing #do nothing +The keyword argument `state` is a function. It will be called after the `wordcloud` object constructed. This will set the object to a specific state. +* state = placewords! #default setting, will initialize word's position +* state = generate! #get result directly +* state = initwords! #only initialize resources, such as rendering word images +* state = identity #do nothing ---NOTE * After getting the `wordcloud` object, these steps are needed to get the result picture: initwords! -> placewords! -> generate! -> paint * You can skip `placewords!` and/or `initwords!`, and the default action will be performed @@ -64,7 +64,7 @@ function wordcloud(words::AbstractVector{<:AbstractString}, weights::AbstractVec colors=:auto, angles=:auto, mask=:auto, font=:auto, transparent=:auto, minfontsize=:auto, maxfontsize=:auto, spacing=1, density=0.5, - run=placewords!, kargs...) + state=placewords!, kargs...) @assert length(words) == length(weights) > 0 params = Dict{Symbol,Any}() colors, angles, mask, svgmask, font, transparent = getstylescheme(words, weights; colors=colors, angles=angles, @@ -106,11 +106,13 @@ function wordcloud(words::AbstractVector{<:AbstractString}, weights::AbstractVec l = length(words) wc = WC(copy(words), float.(weights), Vector(undef, l), Vector{SVGImageType}(undef, l), mask, svgmask, Vector(undef, l), maskqtree, params) - run(wc) + if state != wordcloud + state(wc) + end wc end function getstylescheme(words, weights; colors=:auto, angles=:auto, mask=:auto, - masksize=:default, maskcolor=:default, keepmaskcontent=:auto, + masksize=:default, maskcolor=:default, keepmaskarea=:auto, backgroundcolor=:default, padding=:default, outline=:default, linecolor=:auto, font=:auto, transparent=:auto, params=Dict{Symbol,Any}(), kargs...) @@ -152,7 +154,7 @@ function getstylescheme(words, weights; colors=:auto, angles=:auto, mask=:auto, push!(kg, :linecolor => linecolor) end padding = padding in DEFAULTSYMBOLS ? maximum(masksize) ÷ 10 : padding - mask = randommask(masksize, color=maskcolor; padding=padding, keepcontent=keepmaskcontent, kg..., kargs...) + mask = randommask(masksize, color=maskcolor; padding=padding, keeparea=keepmaskarea, kg..., kargs...) else ms = masksize in DEFAULTSYMBOLS ? () : masksize if maskcolor == :auto && !issvg(loadmask(mask)) diff --git a/test/runtests.jl b/test/runtests.jl index 3691cec..65d9878 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -27,7 +27,7 @@ include("test_textprocessing.jl") end # wordcloud factory - wc = wordcloud(["singleword" => 12], mask=shape(box, 200, 150, 40, color=0.15), density=0.45, run=generate!) # singleword & Pair + wc = wordcloud(["singleword" => 12], mask=shape(box, 200, 150, 40, color=0.15), density=0.45, state=generate!) # singleword & Pair wc = wordcloud("giving a single word is ok. giving several words is ok too", mask=shape(squircle, 200, 150, color=0.15, rt=2.2), density=0.45, transparent=(1, 1, 1, 0)) # String & small mask @test_throws AssertionError wordcloud(["1"], [2,3], density=0.1) |> generate! # length unmatch diff --git a/test/test_textprocessing.jl b/test/test_textprocessing.jl index 198fee1..9b2f9b9 100644 --- a/test/test_textprocessing.jl +++ b/test/test_textprocessing.jl @@ -28,6 +28,7 @@ @test lemmatize("ourselves") == "ourselves" @test lemmatize("loves") == "love" @test lemmatize("lives") in ("life", "live") + @test lemmatize("cos") == "cos" @test lemmatize("中文") == "中文" @test lemmatize!(Dict("dog" => 1, "dogs" => 2)) == Dict("dog" => 3)