Skip to content

Commit

Permalink
Merge pull request #870 from VisLab/develop
Browse files Browse the repository at this point in the history
WordCoud allows font_path and EventManager now checks for unsorted onsets.
  • Loading branch information
VisLab authored Feb 25, 2024
2 parents 43ec7fa + 0759e41 commit 4281249
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 8 deletions.
7 changes: 6 additions & 1 deletion hed/tools/analysis/event_manager.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
""" Manager of events of temporal extent. """
import pandas as pd

from hed.errors import HedFileError
from hed.models import HedString
from hed.models.model_constants import DefTagNames
from hed.models.df_util import get_assembled
Expand Down Expand Up @@ -31,7 +33,10 @@ def __init__(self, input_data, hed_schema, extra_defs=None):
self.hed_schema = hed_schema
self.input_data = input_data
self.def_dict = input_data.get_def_dict(hed_schema, extra_def_dicts=extra_defs)
self.onsets = input_data.dataframe['onset'].tolist()
onsets = pd.to_numeric(input_data.dataframe['onset'], errors='coerce')
if not onsets.is_monotonic_increasing:
raise HedFileError("OnsetsNotOrdered", "The onset values must be non-decreasing", "")
self.onsets = onsets.tolist()
self.hed_strings = None # Remaining HED strings copy.deepcopy(hed_strings)
self._create_event_list(input_data)

Expand Down
11 changes: 10 additions & 1 deletion hed/tools/remodeling/operations/summarize_hed_tags_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ class SummarizeHedTagsOp(BaseOp):
"max_font_size": {
"type": "number"
},
"set_font": {
"type": "boolean"
},
"font_path": {
"type": "string"
},
"scale_adjustment": {
"type": "number"
},
Expand Down Expand Up @@ -148,6 +154,8 @@ def __init__(self, parameters):
"prefer_horizontal": wc_params.get("prefer_horizontal", 0.75),
"min_font_size": wc_params.get("min_font_size", 8),
"max_font_size": wc_params.get("max_font_size", 15),
"set_font": wc_params.get("set_font", False),
"font_path": wc_params.get("font_path", ""),
"scale_adjustment": wc_params.get("scale_adjustment", 7),
"contour_width": wc_params.get("contour_width", 3),
"contour_color": wc_params.get("contour_color", 'black'),
Expand Down Expand Up @@ -305,7 +313,8 @@ def save_visualizations(self, save_dir, file_formats=['.svg'], individual_summar
tag_wc = create_wordcloud(word_dict, mask_path=wc["mask_path"], width=wc["width"], height=wc["height"],
prefer_horizontal=wc["prefer_horizontal"], background_color=wc["background_color"],
min_font_size=wc["min_font_size"], max_font_size=wc["max_font_size"],
contour_width=wc["contour_width"], contour_color=wc["contour_color"])
contour_width=wc["contour_width"], contour_color=wc["contour_color"],
set_font=wc["set_font"], font_path=wc["font_path"])
svg_data = word_cloud_to_svg(tag_wc)
cloud_filename = os.path.realpath(os.path.join(save_dir, self.sum_op.summary_name,
self.sum_op.summary_name + '_word_cloud.svg'))
Expand Down
13 changes: 8 additions & 5 deletions hed/tools/visualization/tag_word_cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

import numpy as np
from PIL import Image
from hed.errors import HedFileError
from hed.tools.visualization.word_cloud_util import default_color_func, WordCloud, generate_contour_svg
import matplotlib.font_manager as fm


def create_wordcloud(word_dict, mask_path=None, background_color=None, width=400, height=300, font_path=None, **kwargs):
def create_wordcloud(word_dict, mask_path=None, background_color=None, width=400, height=300, set_font=False, **kwargs):
""" Takes a word dict and returns a generated word cloud object.
Parameters:
Expand Down Expand Up @@ -45,10 +46,12 @@ def create_wordcloud(word_dict, mask_path=None, background_color=None, width=400
kwargs.setdefault('relative_scaling', 1)
kwargs.setdefault('max_font_size', height / 20)
kwargs.setdefault('min_font_size', 8)
if font_path and not font_path.endswith(".ttf") and not font_path.endswith(".otf"):
font_path = fm.findfont(font_path)
if not set_font or 'font_path' not in kwargs:
kwargs['font_path'] = None
elif kwargs['font_path'] and not kwargs['font_path'].endswith((".ttf", ".otf", ".TTF", ".OTF")):
raise HedFileError("InvalidFontPath", f"Font {kwargs['font_path']} not valid on this system", "")

wc = WordCloud(font_path=font_path, background_color=background_color, mask=mask_image,
wc = WordCloud(background_color=background_color, mask=mask_image,
width=width, height=height, mode="RGBA", **kwargs)

wc.generate_from_frequencies(word_dict)
Expand Down Expand Up @@ -111,4 +114,4 @@ def load_and_resize_mask(mask_path, width=None, height=None):
(mask_image_array[:, :, 1] > 127) &
(mask_image_array[:, :, 2] > 127)), 255, 0)

return mask_image_array.astype(np.uint8)
return mask_image_array.astype(np.uint8)
35 changes: 35 additions & 0 deletions tests/tools/analysis/test_event_manager.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import os
import unittest
import numpy as np
import pandas as pd

from hed.errors import HedFileError
from hed.models.sidecar import Sidecar, HedString
from hed.models.tabular_input import TabularInput
from hed.schema.hed_schema_io import load_schema_version
Expand Down Expand Up @@ -77,6 +80,38 @@ def test_get_type_defs(self):
self.assertIsInstance(def_names, list)
self.assertEqual(11, len(def_names))

def test_onset_ordering_mixed(self):
df = pd.DataFrame({'onset': [1, 2, '3', 3.24, 5],
'HED': ['(Duration/4.0 s, Black)', '(Duration/2 s, Red)', 'Blue', 'Green', 'Label/1']})
manager = EventManager(TabularInput(df), self.schema)
self.assertIsInstance(manager, EventManager)
hed, base, context = manager.unfold_context()

def test_onset_ordering_bad(self):
df = pd.DataFrame({'onset': [1, 2, '3', 'n/a', 5],
'HED': ['(Duration/4.0 s, Black)', '(Duration/2 s, Red)', 'Blue', 'n/a', 'Label/1']})
with self.assertRaises(HedFileError) as ex:
EventManager(TabularInput(df), self.schema)
self.assertEqual(ex.args(0), "OnsetsNotOrdered")
df1 = pd.DataFrame({'onset': [1, 2, 1.4, 6, 5],
'HED': ['(Duration/4.0 s, Black)', '(Duration/2 s, Red)', 'Blue', 'n/a', 'Label/1']})
with self.assertRaises(HedFileError) as ex1:
EventManager(TabularInput(df1), self.schema)
self.assertEqual(ex1.args(0), "OnsetsNotOrdered")

df2 = pd.DataFrame({'onset': [1, np.nan, 1.4, 6, 5],
'HED': ['(Duration/4.0 s, Black)', '(Duration/2 s, Red)', 'Blue', 'n/a', 'Label/1']})
with self.assertRaises(HedFileError) as ex2:
EventManager(TabularInput(df2), self.schema)
self.assertEqual(ex2.args(0), "OnsetsNotOrdered")

def test_duration_context(self):
df = pd.DataFrame({'onset': [1, 2, 3, 4, 5],
'HED': ['(Duration/4.0 s, Black)', '(Duration/2 s, Red)', 'Blue', 'n/a', 'Label/1']})
manager = EventManager(TabularInput(df), self.schema)
hed, base, context = manager.unfold_context()
pass


if __name__ == '__main__':
unittest.main()
3 changes: 2 additions & 1 deletion tests/tools/visualization/test_tag_word_cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ def test_create_wordcloud_font_direct(self):

fonts = fm.findSystemFonts()
first_font = fonts[0]

x = '/C/Windows/Fonts/timesi.ttf'
#y = 'C:\\Windows\\Fonts\\arialbd.ttf'
wc = tag_word_cloud.create_wordcloud(word_dict, width=width, height=height, font_path=first_font)

self.assertIsInstance(wc, wordcloud.WordCloud)
Expand Down

0 comments on commit 4281249

Please sign in to comment.