From 003a4a87c7631cb371ca537f248c7c900a364c43 Mon Sep 17 00:00:00 2001 From: liy1shu Date: Tue, 1 Aug 2023 19:46:56 -0400 Subject: [PATCH 1/3] add video --- src/rpad/visualize_3d/html.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/rpad/visualize_3d/html.py b/src/rpad/visualize_3d/html.py index 2934176..d784543 100644 --- a/src/rpad/visualize_3d/html.py +++ b/src/rpad/visualize_3d/html.py @@ -13,25 +13,38 @@ class PlotlyWebsiteBuilder: def __init__(self, title: str): self.title = title self.cats: Dict[str, List[Tuple[str, go.Figure]]] = defaultdict(list) + self.videos: Dict[str, List[Tuple[str, Path]]] = defaultdict(list) def add_plot(self, category: str, id: str, plot: go.Figure): plot.update_layout(margin=dict(l=5, r=5, t=40, b=5)) self.cats[category].append((id, plot)) + def add_video(self, category: str, id: str, video_path: Union[str, Path]): + self.videos[category].append((id, video_path)) + def write_site(self, site_dir: Union[str, Path]): os.makedirs(site_dir, exist_ok=True) # Group all the IDs by category, and then by ID. parsed_ids: Dict[str, Dict[str, List]] = {} + parsed_videos: Dict[str, Dict[str, List]] = {} for cat, plot_list in self.cats.items(): parsed_ids[cat] = defaultdict(list) for id, plot in plot_list: obj_id = id.split("_")[0] parsed_ids[cat][obj_id].append((id, plot)) + + for cat, video_list in self.videos.items(): + parsed_videos[cat] = defaultdict(list) + for id, video in video_list: + obj_id = id.split("_")[0] + parsed_videos[cat][obj_id].append((id, video)) # Create a page for each object, and put all of its articulations on that page. for cat, obj_dict in parsed_ids.items(): + video_dict = parsed_videos[cat] for obj_id, plot_list in obj_dict.items(): + video_list = video_dict[obj_id] sub_doc = dom.document(title=f"{obj_id}: {self.title}") with sub_doc.head: @@ -39,9 +52,11 @@ def write_site(self, site_dir: Union[str, Path]): with sub_doc: with dt.div(id=cat): - dt.h1(f"{id} - {cat}") + dt.h1(f"{obj_id} - {cat}") with dt.table(): - for i, (id, plot) in enumerate(plot_list): + for i, ((pid, plot), (vid, video)) in enumerate(zip(plot_list, video_list)): + assert pid == vid, f"Video {vid} and image {pid} are from different sample." + id = pid if i % 3 == 0: tr = dt.tr() @@ -56,6 +71,10 @@ def write_site(self, site_dir: Union[str, Path]): auto_play=False, ) ) + # Add a video section + video_src = video + with dt.div(): + dt.video(src=video_src, width="640", height="360", controls=True) with open(os.path.join(site_dir, f"{obj_id}.html"), "w") as f: f.write(str(sub_doc)) From 0278b6b2a05369a5a5819d88cbc9a40dc2b8785e Mon Sep 17 00:00:00 2001 From: Ben Eisner Date: Wed, 2 Aug 2023 12:18:11 -0400 Subject: [PATCH 2/3] add a test --- README.md | 3 +++ tests/html_test.py | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/README.md b/README.md index 7d993c6..810ef7b 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,9 @@ doc = html.PlotlyWebsiteBuilder("Evaluation Visualizations") fig = go.Figure() doc.add_plot("Sample Category", "Sample ID", fig) +# Add a video to the page. +doc.add_video("Sample Category", "Sample ID", "./path/to/video.mp4") + # Write the site to disk. doc.write_site("./path/to/desired/output/directory") ``` diff --git a/tests/html_test.py b/tests/html_test.py index 63134cd..c772dc5 100644 --- a/tests/html_test.py +++ b/tests/html_test.py @@ -10,11 +10,19 @@ def test_html(): doc = PlotlyWebsiteBuilder("test_doc") with tempfile.TemporaryDirectory() as tmpdir: + # Make a test video. + video_fn = os.path.join(tmpdir, "test", "test.mp4") + for i in range(10): fig = px.line(x=["a", "b", "c"], y=[i + 1, i + 3, i + 2], title=f"Plot {i}") doc.add_plot("Show", str(i), fig) + + # Add a video. + doc.add_video("Show", str(i), "./test.mp4") doc.write_site(os.path.join(tmpdir, "test")) + os.system(f"ffmpeg -f lavfi -i testsrc=size=640x300:rate=30 -t 5 {video_fn}") + # Check that the files were created. assert os.path.exists(os.path.join(tmpdir, "test/index.html")) for i in range(10): From 2626d7958fadddb472a815c187c7464a11acdcbc Mon Sep 17 00:00:00 2001 From: Ben Eisner Date: Wed, 2 Aug 2023 12:21:36 -0400 Subject: [PATCH 3/3] modify to get everything to pass --- .pre-commit-config.yaml | 2 +- pyproject.toml | 2 +- src/rpad/visualize_3d/html.py | 19 ++++++++++++++----- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f23d977..2cea227 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,6 +27,6 @@ repos: hooks: - id: isort - repo: https://github.com/psf/black - rev: 22.3.0 + rev: 23.7.0 hooks: - id: black diff --git a/pyproject.toml b/pyproject.toml index 43498ed..7ba86a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ build-backend = "setuptools.build_meta" [project.optional-dependencies] develop = [ "autoflake", - "black >= 22.3.0", + "black == 23.7.0", "isort", "jupyterlab", "mypy", diff --git a/src/rpad/visualize_3d/html.py b/src/rpad/visualize_3d/html.py index d784543..a1205b3 100644 --- a/src/rpad/visualize_3d/html.py +++ b/src/rpad/visualize_3d/html.py @@ -13,7 +13,7 @@ class PlotlyWebsiteBuilder: def __init__(self, title: str): self.title = title self.cats: Dict[str, List[Tuple[str, go.Figure]]] = defaultdict(list) - self.videos: Dict[str, List[Tuple[str, Path]]] = defaultdict(list) + self.videos: Dict[str, List[Tuple[str, Union[str, Path]]]] = defaultdict(list) def add_plot(self, category: str, id: str, plot: go.Figure): plot.update_layout(margin=dict(l=5, r=5, t=40, b=5)) @@ -33,7 +33,7 @@ def write_site(self, site_dir: Union[str, Path]): for id, plot in plot_list: obj_id = id.split("_")[0] parsed_ids[cat][obj_id].append((id, plot)) - + for cat, video_list in self.videos.items(): parsed_videos[cat] = defaultdict(list) for id, video in video_list: @@ -54,8 +54,12 @@ def write_site(self, site_dir: Union[str, Path]): with dt.div(id=cat): dt.h1(f"{obj_id} - {cat}") with dt.table(): - for i, ((pid, plot), (vid, video)) in enumerate(zip(plot_list, video_list)): - assert pid == vid, f"Video {vid} and image {pid} are from different sample." + for i, ((pid, plot), (vid, video)) in enumerate( + zip(plot_list, video_list) + ): + assert ( + pid == vid + ), f"Video {vid} and image {pid} are from different sample." id = pid if i % 3 == 0: tr = dt.tr() @@ -74,7 +78,12 @@ def write_site(self, site_dir: Union[str, Path]): # Add a video section video_src = video with dt.div(): - dt.video(src=video_src, width="640", height="360", controls=True) + dt.video( + src=video_src, + width="640", + height="360", + controls=True, + ) with open(os.path.join(site_dir, f"{obj_id}.html"), "w") as f: f.write(str(sub_doc))