Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
88 changes: 88 additions & 0 deletions examples/mix_fonts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env python
"""
Mix Fonts
=========

English, CJK, and emoji are mixed both across different words and
within each word. Fonts are aligned at their baselines.

"""
import os
import random

import emoji
import matplotlib.pyplot as plt
import regex as re
from fontTools.ttLib import TTFont

from wordcloud import MixedFontPattern
from wordcloud import WordCloud


def get_supported_chars(font_path):
supported_chars = []
with TTFont(font_path, 0, allowVID=0,
ignoreDecompileErrors=True,
fontNumber=-1) as ttf:
for table in ttf["cmap"].tables:
for glyph in list(table.cmap.items()):
try:
char = chr(glyph[0])
supported_chars.append(char)
except Exception:
continue
return supported_chars


font_emoji = "fonts/Symbola/Symbola.ttf"
font_cjk = "fonts/SourceHanSerif/SourceHanSerifK-Light.otf"
font_paths = [
MixedFontPattern(re.compile(pattern), path) for pattern, path in [
(r"[\p{Emoji=Yes}\p{Emoji_Presentation=Yes}]+", font_emoji),
(r"[\p{Han}\p{Katakana}\p{Hiragana}]+", font_cjk),
]
]

# construct word frequency dict.
wordfreq = {}
supported = get_supported_chars(font_emoji)
emojis = list(v for v in emoji.EMOJI_UNICODE.values() if v in supported)
wordfreq.update({random.choice(emojis): random.randint(10, 40)
for _ in range(200)})
wordfreq.update({
emoji.emojize(word, use_aliases=True): n for word, n in {
u"愛Myミィ": 75,
u"I:beating_heart:紐育": 75,
u"We:growing_heart:おんがく": 75,
u"男": 90,
u"女": 90,
u":man_dancing:": 90,
u":woman_dancing:": 90,
u":couple_with_heart:": 90,
u"愛": 90,
u"love": 90,
u"舞": 90,
u"dance": 90,
u":musical_note:": 90,
u":musical_notes:": 90,
u":musical_score:": 45,
}.items()
})

wc = WordCloud(width=600,
height=600,
scale=1.5,
relative_scaling=0.6,
repeat=False,
max_words=len(wordfreq),
font_path=font_paths)
wc.generate_from_frequencies(wordfreq)

# generate an svg outout.
with open(os.path.splitext(os.path.basename(__file__))[0] + ".svg", 'w') as f:
f.write(wc.to_svg(embed_font=True))

plt.figure(figsize=(8, 8))
plt.imshow(wc, interpolation="bilinear")
plt.axis("off")
plt.show()
208 changes: 208 additions & 0 deletions examples/mix_fonts.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions examples/mix_fonts_random.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env python
"""
Mix Fonts with Random Draw Example
==================================

Generating a word cloud from the US constitution. The words are
rendered with a font randomly picked from a list.

"""
import os

import matplotlib.pyplot as plt

from wordcloud import WordCloud


# get data directory (using getcwd() is needed to support running
# example in generated IPython notebook).
d = os.path.dirname(__file__) if "__file__" in locals() else os.getcwd()

# read the whole text.
text = open(os.path.join(d, 'constitution.txt')).read()

# provide paths to fonts for random draw.
font_paths = [
"../wordcloud/DroidSansMono.ttf",
"fonts/Symbola/Symbola.ttf",
"fonts/SourceHanSerif/SourceHanSerifK-Light.otf"
]

# generate a word cloud image.
wc = WordCloud(width=1200, height=600, font_path=font_paths).generate(text)

# generate an svg outout.
with open(os.path.splitext(os.path.basename(__file__))[0] + ".svg", 'w') as f:
f.write(wc.to_svg(embed_font=True))

plt.imshow(wc, interpolation='bilinear')
plt.axis("off")
plt.show()
206 changes: 206 additions & 0 deletions examples/mix_fonts_random.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 60 additions & 0 deletions examples/mix_fonts_random_and_match.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env python
"""
Mix Fonts with Random Draw Example and Match
============================================

Generating a word cloud from the US constitution. The words are
rendered with a font randomly picked from a list except for CJK
characters, to which a CJK font is applied.

"""
import os
import regex as re
from collections import defaultdict

import matplotlib.pyplot as plt

from wordcloud import MixedFontPattern
from wordcloud import STOPWORDS
from wordcloud import WordCloud


# get data directory (using getcwd() is needed to support running
# example in generated IPython notebook).
d = os.path.dirname(__file__) if "__file__" in locals() else os.getcwd()

# read the whole text.
text = open(os.path.join(d, 'constitution.txt')).read()

wordfreq = defaultdict(int)
for word in text.split():
word = word.strip('.,')
if word.lower() not in STOPWORDS:
wordfreq[word] += 1

# add some cjk language entries for demonstrating font matching
for phrase, n in {'アメリカ': 40, '憲法': 35, '大統領': 32, '合衆国': 30,
'あめりか': 30, 'けんぽう': 25, 'だいとうりょう': 23,
'がっしゅうこく': 20}.items():
wordfreq[phrase] += n

# provide paths to fonts for random draw plus cjk font when word matches
font_paths = [
"../wordcloud/DroidSansMono.ttf",
"fonts/Symbola/Symbola.ttf",
"fonts/SourceHanSerif/SourceHanSerifK-Light.otf",
MixedFontPattern(re.compile(r"[\p{Han}\p{Katakana}\p{Hiragana}]+"),
"fonts/SourceHanSerif/SourceHanSerifK-Light.otf")
]

# generate a word cloud image.
wc = WordCloud(width=1200, height=600, font_path=font_paths)
wc.generate_from_frequencies(wordfreq)

# generate an svg outout.
with open(os.path.splitext(os.path.basename(__file__))[0] + ".svg", 'w') as f:
f.write(wc.to_svg(embed_font=True))

plt.imshow(wc, interpolation='bilinear')
plt.axis("off")
plt.show()
206 changes: 206 additions & 0 deletions examples/mix_fonts_random_and_match.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 7 additions & 4 deletions test/test_wordcloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,14 +351,17 @@ def test_recolor_too_small_set_default():

def test_small_canvas():
# check font size fallback works on small canvas
WordCloud(max_words=50, width=20, height=20).generate(THIS)
wc = WordCloud(max_words=50, width=21, height=21)
wc.generate(THIS)
assert len(wc.layout_) == 1


def test_tiny_canvas():
# check exception if canvas too small for fallback
w = WordCloud(max_words=50, width=1, height=1)
with pytest.raises(ValueError, match="Couldn't find space to draw"):
w.generate(THIS)
assert len(w.layout_) == 0


def test_coloring_black_works():
Expand All @@ -382,7 +385,7 @@ def test_repeat():
# all frequencies are 1
assert len(wc.words_) == 3
assert_array_equal(list(wc.words_.values()), 1)
frequencies = [w[0][1] for w in wc.layout_]
frequencies = [w.frequency for w in wc.layout_]
assert_array_equal(frequencies, 1)
repetition_text = "Some short text with text"
wc = WordCloud(max_words=52, stopwords=[], repeat=True)
Expand All @@ -392,7 +395,7 @@ def test_repeat():
assert wc.words_['text'] == 1
assert wc.words_['with'] == .5
assert len(wc.layout_), wc.max_words
frequencies = [w[0][1] for w in wc.layout_]
frequencies = [w.frequency for w in wc.layout_]
# check that frequencies are sorted
assert np.all(np.diff(frequencies) <= 0)

Expand All @@ -403,4 +406,4 @@ def test_zero_frequencies():

word_cloud.generate_from_frequencies({'test': 1, 'test1': 0, 'test2': 0})
assert len(word_cloud.layout_) == 1
assert word_cloud.layout_[0][0][0] == 'test'
assert word_cloud.layout_[0].word == 'test'
5 changes: 4 additions & 1 deletion test/test_wordcloud_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
import wordcloud as wc
from wordcloud import wordcloud_cli as cli

from mock import patch
try:
from unittest.mock import patch
except ImportError:
from mock import patch
import pytest

import matplotlib
Expand Down
4 changes: 2 additions & 2 deletions wordcloud/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from .wordcloud import (WordCloud, STOPWORDS, random_color_func,
from .wordcloud import (WordCloud, STOPWORDS, MixedFontPattern, random_color_func,
get_single_color_func)
from .color_from_image import ImageColorGenerator

__all__ = ['WordCloud', 'STOPWORDS', 'random_color_func',
__all__ = ['WordCloud', 'STOPWORDS', 'MixedFontPattern', 'random_color_func',
'get_single_color_func', 'ImageColorGenerator',
'__version__']

Expand Down
Loading