From d3ccf421dc98b85d246e271b96143bbac9807b20 Mon Sep 17 00:00:00 2001
From: Oscar Gustafsson <oscar.gustafsson@gmail.com>
Date: Wed, 10 May 2023 09:44:44 +0200
Subject: [PATCH] Add content property to resource

---
 b_asic/architecture.py        | 24 ++++++++++++++++++++----
 b_asic/mpl_utils.py           | 18 ++++++++++++++++++
 docs_sphinx/api/index.rst     |  1 +
 docs_sphinx/api/mpl_utils.rst |  7 +++++++
 4 files changed, 46 insertions(+), 4 deletions(-)
 create mode 100644 b_asic/mpl_utils.py
 create mode 100644 docs_sphinx/api/mpl_utils.rst

diff --git a/b_asic/architecture.py b/b_asic/architecture.py
index 28f44d96..2d17dd76 100644
--- a/b_asic/architecture.py
+++ b/b_asic/architecture.py
@@ -8,6 +8,7 @@ from typing import Dict, Iterable, Iterator, List, Optional, Set, Tuple, Union,
 import matplotlib.pyplot as plt
 from graphviz import Digraph
 
+from b_asic.mpl_utils import FigureWrapper
 from b_asic.port import InputPort, OutputPort
 from b_asic.process import MemoryVariable, OperatorProcess, PlainMemoryVariable
 from b_asic.resources import ProcessCollection
@@ -174,19 +175,34 @@ class Resource(HardwareBlock):
         # doc-string inherited
         return self._collection.schedule_time
 
-    def show_content(self):
+    def plot_content(self, ax: plt.Axes) -> None:
         if not self.is_assigned:
-            self._collection.show()
+            self._collection.plot(ax)
         else:
-            fig, ax = plt.subplots()
             for i, pc in enumerate(self._assignment):  # type: ignore
                 pc.plot(ax=ax, row=i)
-            fig.show()  # type: ignore
+
+    def show_content(self):
+        fig, ax = plt.subplots()
+        self.plot_content(ax)
+        fig.show()  # type: ignore
 
     @property
     def is_assigned(self) -> bool:
         return self._assignment is not None
 
+    @property
+    def content(self) -> FigureWrapper:
+        """
+        Return a graphical representation of the content.
+
+        This is visible in enriched shells, but the object in itself has no further
+        meaning.
+        """
+        fig, ax = plt.subplots()
+        self.plot_content(ax)
+        return FigureWrapper(fig)
+
 
 class ProcessingElement(Resource):
     """
diff --git a/b_asic/mpl_utils.py b/b_asic/mpl_utils.py
new file mode 100644
index 00000000..f0213df8
--- /dev/null
+++ b/b_asic/mpl_utils.py
@@ -0,0 +1,18 @@
+"""
+B-ASIC utilities for Matplotlib integration.
+"""
+import io
+
+from matplotlib.figure import Figure
+
+
+class FigureWrapper:
+    """Simple wrapper to display a figure inline in enriched shells."""
+
+    def __init__(self, figure: Figure):
+        self._figure = figure
+
+    def _repr_svg_(self):
+        buffer = io.StringIO()
+        self._figure.savefig(buffer, format="svg")
+        return buffer.getvalue()
diff --git a/docs_sphinx/api/index.rst b/docs_sphinx/api/index.rst
index 484dfd3b..e0cf7ef3 100644
--- a/docs_sphinx/api/index.rst
+++ b/docs_sphinx/api/index.rst
@@ -8,6 +8,7 @@ API
     architecture.rst
     core_operations.rst
     graph_component.rst
+    mpl_utils.rst
     operation.rst
     port.rst
     process.rst
diff --git a/docs_sphinx/api/mpl_utils.rst b/docs_sphinx/api/mpl_utils.rst
new file mode 100644
index 00000000..2a528cc0
--- /dev/null
+++ b/docs_sphinx/api/mpl_utils.rst
@@ -0,0 +1,7 @@
+********************
+``b_asic.mpl_utils``
+********************
+
+.. automodule:: b_asic.mpl_utils
+   :members:
+   :undoc-members:
-- 
GitLab