diff --git a/b_asic/schedule.py b/b_asic/schedule.py
index 129ce92b3105218596f969d747e21ed3bfcb84fc..1d5a23b6c1a47a26209771677dbbc44315ce9165 100644
--- a/b_asic/schedule.py
+++ b/b_asic/schedule.py
@@ -11,6 +11,8 @@ from typing import Dict, List, Optional, Tuple, cast
 
 import matplotlib.pyplot as plt
 import numpy as np
+from matplotlib.axes import Axes
+from matplotlib.figure import Figure
 from matplotlib.lines import Line2D
 from matplotlib.patches import PathPatch, Polygon
 from matplotlib.path import Path
@@ -40,7 +42,20 @@ _SIGNAL_COLOR = tuple(c / 255 for c in SIGNAL_COLOR)
 
 
 class Schedule:
-    """Schedule of an SFG with scheduled Operations."""
+    """
+    Schedule of an SFG with scheduled Operations.
+
+    Parameters
+    ----------
+    sfg : SFG
+        The signal flow graph to schedule.
+    schedule_time : int, optional
+        The schedule time. If not provided, it will be determined by the scheduling algorithm.
+    cyclic : bool, default: False
+        If the schedule is cyclic.
+    scheduling_alg : {'ASAP'}, optional
+        The scheduling algorithm to use. Currently, only "ASAP" is supported.
+    """
 
     _sfg: SFG
     _start_times: Dict[GraphID, int]
@@ -82,7 +97,7 @@ class Schedule:
 
     def start_time_of_operation(self, graph_id: GraphID) -> int:
         """
-        Get the start time of the operation with the specified by *graph_id*.
+        Return the start time of the operation with the specified by *graph_id*.
         """
         if graph_id not in self._start_times:
             raise ValueError(
@@ -91,7 +106,7 @@ class Schedule:
         return self._start_times[graph_id]
 
     def get_max_end_time(self) -> int:
-        """Returns the current maximum end time among all operations."""
+        """Return the current maximum end time among all operations."""
         max_end_time = 0
         for graph_id, op_start_time in self._start_times.items():
             op = cast(Operation, self._sfg.find_by_id(graph_id))
@@ -103,6 +118,16 @@ class Schedule:
         return max_end_time
 
     def forward_slack(self, graph_id: GraphID) -> int:
+        """
+
+        Parameters
+        ----------
+        graph_id
+
+        Returns
+        -------
+            The number of time steps the operation with *graph_id* can ba moved forward in time.
+        """
         if graph_id not in self._start_times:
             raise ValueError(
                 f"No operation with graph_id {graph_id} in schedule"
@@ -137,6 +162,16 @@ class Schedule:
         return ret
 
     def backward_slack(self, graph_id: GraphID) -> int:
+        """
+
+        Parameters
+        ----------
+        graph_id
+
+        Returns
+        -------
+            The number of time steps the operation with *graph_id* can ba moved backward in time.
+        """
         if graph_id not in self._start_times:
             raise ValueError(
                 f"No operation with graph_id {graph_id} in schedule"
@@ -479,9 +514,11 @@ class Schedule:
         return operation_gap + y_location * (operation_height + operation_gap)
 
     def _plot_schedule(self, ax, operation_gap=None):
+        """Draw the schedule."""
         line_cache = []
 
         def _draw_arrow(start, end, name="", laps=0):
+            """Draw an arrow from *start* to *end*."""
             if end[0] < start[0] or laps > 0:  # Wrap around
                 if start not in line_cache:
                     line = Line2D(
@@ -564,6 +601,7 @@ class Schedule:
         def _draw_offset_arrow(
             start, end, start_offset, end_offset, name="", laps=0
         ):
+            """Draw an arrow from *start* to *end*, but with an offset."""
             _draw_arrow(
                 [start[0] + start_offset[0], start[1] + start_offset[1]],
                 [end[0] + end_offset[0], end[1] + end_offset[1]],
@@ -576,7 +614,7 @@ class Schedule:
         ax.set_axisbelow(True)
         ax.grid()
         for graph_id, op_start_time in self._start_times.items():
-            ypos = -self._get_y_position(graph_id, operation_gap=operation_gap)
+            ypos = self._get_y_position(graph_id, operation_gap=operation_gap)
             op = self._sfg.find_by_id(graph_id)
             # Rewrite to make better use of NumPy
             latency_coords, execution_time_coords = op.get_plot_coordinates()
@@ -602,7 +640,7 @@ class Schedule:
         for graph_id, op_start_time in self._start_times.items():
             op = self._sfg.find_by_id(graph_id)
             _, out_coords = op.get_io_coordinates()
-            source_ypos = -self._get_y_position(
+            source_ypos = self._get_y_position(
                 graph_id, operation_gap=operation_gap
             )
 
@@ -610,7 +648,7 @@ class Schedule:
                 for output_signal in output_port.signals:
                     dest_op = output_signal.destination.operation
                     dest_start_time = self._start_times[dest_op.graph_id]
-                    dest_ypos = -self._get_y_position(
+                    dest_ypos = self._get_y_position(
                         dest_op.graph_id, operation_gap=operation_gap
                     )
                     (
@@ -633,35 +671,72 @@ class Schedule:
 
         # Get operation with maximum position
         max_pos_graph_id = max(self._y_locations, key=self._y_locations.get)
-        yposmin = -self._get_y_position(
-            max_pos_graph_id, operation_gap=operation_gap
-        ) - (OPERATION_GAP if operation_gap is None else operation_gap)
-        ax.axis([-1, self._schedule_time + 1, yposmin, 1])
+        yposmax = (
+            self._get_y_position(max_pos_graph_id, operation_gap=operation_gap)
+            + 1
+            + (OPERATION_GAP if operation_gap is None else operation_gap)
+        )
+        ax.axis([-1, self._schedule_time + 1, yposmax, 0])  # Inverted y-axis
         ax.xaxis.set_major_locator(MaxNLocator(integer=True))
         ax.add_line(
-            Line2D([0, 0], [yposmin, 1], linestyle="--", color="black")
+            Line2D([0, 0], [0, yposmax], linestyle="--", color="black")
         )
         ax.add_line(
             Line2D(
                 [self._schedule_time, self._schedule_time],
-                [yposmin, 1],
+                [0, yposmax],
                 linestyle="--",
                 color="black",
             )
         )
 
     def _reset_y_locations(self):
+        """Reset all the y-locations in the schedule to None"""
         self._y_locations = self._y_locations = defaultdict(lambda: None)
 
-    def plot_schedule(self, operation_gap=None) -> None:
+    def plot_in_axes(self, ax: Axes, operation_gap: float = None) -> None:
+        """
+        Plot the schedule in a :class:`matplotlib.axes.Axes` or subclass.
+
+        Parameters
+        ----------
+        ax : matplotlib.axes.Axes
+            The :class:`matplotlib.axes.Axes` to plot in.
+        operation_gap : float, optional
+            The vertical distance between operations in the schedule. The height of the operation is always 1.
+        """
+
+    def plot(self, operation_gap: float = None) -> None:
+        """
+        Plot the schedule. Will display based on the current Matplotlib backend.
+
+        Parameters
+        ----------
+        operation_gap : float, optional
+            The vertical distance between operations in the schedule. The height of the operation is always 1.
+        """
         self._get_figure(operation_gap=operation_gap).show()
 
-    def _get_figure(self, operation_gap=None) -> None:
+    def _get_figure(self, operation_gap: float = None) -> Figure:
+        """
+        Create a Figure and an Axes and plot schedule in the Axes.
+
+        Parameters
+        ----------
+        operation_gap : float, optional
+            The vertical distance between operations in the schedule. The height of the operation is always 1.
+
+        Returns
+        -------
+            The Matplotlib Figure.
+        """
         fig, ax = plt.subplots()
         self._plot_schedule(ax, operation_gap=operation_gap)
         return fig
 
     def _repr_svg_(self):
+        """Generate an SVG of the schedule. This is automatically displayed in e.g. Jupyter Qt console.
+        """
         fig, ax = plt.subplots()
         self._plot_schedule(ax)
         f = io.StringIO()
diff --git a/b_asic/scheduler_gui/main_window.py b/b_asic/scheduler_gui/main_window.py
index 41b59263cfce8a3657f464b97a05d850503495aa..cdea2fb88cf890f51cd0a733fa5c47c6a7fd1516 100644
--- a/b_asic/scheduler_gui/main_window.py
+++ b/b_asic/scheduler_gui/main_window.py
@@ -170,7 +170,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
         # TODO: remove
         if self.schedule is None:
             return
-        self.schedule.plot_schedule()
+        self.schedule.plot()
         if self._graph is not None:
             print(f"filtersChildEvents(): {self._graph.filtersChildEvents()}")
         # self._printButtonPressed('callback_pushButton()')
diff --git a/b_asic/signal_flow_graph.py b/b_asic/signal_flow_graph.py
index 5a42494b57a79eaf4b289d23e510c6732aca496b..5e49ec1c6146b418218a5a82ba32f1f4e92e1d35 100644
--- a/b_asic/signal_flow_graph.py
+++ b/b_asic/signal_flow_graph.py
@@ -78,10 +78,30 @@ class GraphIDGenerator:
 
 class SFG(AbstractOperation):
     """
-    Signal flow graph.
+    Construct an SFG given its inputs and outputs.
 
     Contains a set of connected operations, forming a new operation.
     Used as a base for simulation, scheduling, etc.
+
+    Parameters
+    ----------
+    inputs
+    outputs
+    input_signals
+    output_signals
+    id_number_offset
+    name
+    input_sources
+
+    Inputs/outputs may be specified using either Input/Output operations
+    directly with the inputs/outputs parameters, or using signals with the
+    input_signals/output_signals parameters. If signals are used, the
+    corresponding Input/Output operations will be created automatically.
+
+    The id_number_offset parameter specifies what number graph IDs will be
+    offset by for each new graph component type. IDs start at 1 by default,
+    so the default offset of 0 will result in IDs like "c1", "c2", etc.
+    while an offset of 3 will result in "c4", "c5", etc.
     """
 
     _components_by_id: Dict[GraphID, GraphComponent]
@@ -110,20 +130,6 @@ class SFG(AbstractOperation):
             Sequence[Optional[SignalSourceProvider]]
         ] = None,
     ):
-        """
-        Construct an SFG given its inputs and outputs.
-
-        Inputs/outputs may be specified using either Input/Output operations
-        directly with the inputs/outputs parameters, or using signals with the
-        input_signals/output_signals parameters. If signals are used, the
-        corresponding Input/Output operations will be created automatically.
-
-        The id_number_offset parameter specifies what number graph IDs will be
-        offset by for each new graph component type. IDs start at 1 by default,
-        so the default offset of 0 will result in IDs like "c1", "c2", etc.
-        while an offset of 3 will result in "c4", "c5", etc.
-        """
-
         input_signal_count = 0 if input_signals is None else len(input_signals)
         input_operation_count = 0 if inputs is None else len(inputs)
         output_signal_count = (
@@ -311,7 +317,7 @@ class SFG(AbstractOperation):
                     )
 
     def __str__(self) -> str:
-        """Get a string representation of this SFG."""
+        """Return a string representation of this SFG."""
         string_io = StringIO()
         string_io.write(super().__str__() + "\n")
         string_io.write("Internal Operations:\n")
@@ -329,7 +335,7 @@ class SFG(AbstractOperation):
         self, *src: Optional[SignalSourceProvider], name: Name = Name("")
     ) -> "SFG":
         """
-        Get a new independent SFG instance that is identical to this SFG
+        Return a new independent SFG instance that is identical to this SFG
         except without any of its external connections.
         """
         return SFG(
@@ -359,6 +365,19 @@ class SFG(AbstractOperation):
         bits_override: Optional[int] = None,
         truncate: bool = True,
     ) -> Number:
+        """
+
+        Parameters
+        ----------
+        index
+        input_values
+        results
+        delays
+        prefix
+        bits_override
+        truncate
+
+        """
         if index < 0 or index >= self.output_count:
             raise IndexError(
                 "Output index out of range (expected"
@@ -476,6 +495,18 @@ class SFG(AbstractOperation):
         return self
 
     def inputs_required_for_output(self, output_index: int) -> Iterable[int]:
+        """
+        Return which inputs that the output depends on.
+
+        Parameters
+        ----------
+        output_index : int
+            The output index.
+
+        Returns
+        -------
+            A  list of inputs that are required to compute the output with the given *output_index*.
+        """
         if output_index < 0 or output_index >= self.output_count:
             raise IndexError(
                 "Output index out of range (expected"
diff --git a/b_asic/signal_generator.py b/b_asic/signal_generator.py
index 466e1f1e94a6bd988fe0f444cbd1aa5705331c98..be4543eb04b6d275e65560442a05fad3688e5dc0 100644
--- a/b_asic/signal_generator.py
+++ b/b_asic/signal_generator.py
@@ -10,6 +10,12 @@ from typing import Callable, Sequence
 
 
 class SignalGenerator:
+    """
+    Base class for signal generators.
+
+    Handles operator overloading and defined the ``__call__`` method that should be overridden.
+    """
+
     def __call__(self, time: int) -> complex:
         raise NotImplementedError
 
diff --git a/examples/secondorderdirectformiir.py b/examples/secondorderdirectformiir.py
index 2f2536cfcf70ccaf59f1c3b3337108ff96d024ec..f6aefffe3a8f84b005af7d0e154c0519b67d6262 100644
--- a/examples/secondorderdirectformiir.py
+++ b/examples/secondorderdirectformiir.py
@@ -42,4 +42,4 @@ sfg.set_execution_time_of_type(Addition.type_name(), 1)
 # Create schedule
 
 schedule = Schedule(sfg, cyclic=True)
-schedule.plot_schedule()
+schedule.plot()
diff --git a/examples/threepointwinograddft.py b/examples/threepointwinograddft.py
index 2d6614678f947a6f2c531b968e66d432fc97cde9..7e1fd5378b72e5c55ccfdef77a9cda8d93cb742f 100644
--- a/examples/threepointwinograddft.py
+++ b/examples/threepointwinograddft.py
@@ -53,4 +53,4 @@ sfg.set_execution_time_of_type(Subtraction.type_name(), 1)
 # %%
 # Generate schedule
 schedule = Schedule(sfg, cyclic=True)
-schedule.plot_schedule()
+schedule.plot()
diff --git a/logo.svg b/logo.svg
index 1133f65086fbc045ef7ee4a0f444a7e6530c756c..6d43369e921a58c0dc4deb10264192b40e628b22 100644
--- a/logo.svg
+++ b/logo.svg
@@ -10,8 +10,8 @@
    inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
    sodipodi:docname="logo.svg"
    inkscape:export-filename="icon_logo.png"
-   inkscape:export-xdpi="5.3303123"
-   inkscape:export-ydpi="5.3303123"
+   inkscape:export-xdpi="5.1594224"
+   inkscape:export-ydpi="5.1594224"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns="http://www.w3.org/2000/svg"
@@ -28,7 +28,7 @@
      inkscape:document-units="mm"
      showgrid="false"
      inkscape:zoom="0.4204826"
-     inkscape:cx="1055.9295"
+     inkscape:cx="511.31723"
      inkscape:cy="709.89857"
      inkscape:window-width="1200"
      inkscape:window-height="1896"
diff --git a/test/baseline/test__get_figure_no_execution_times.png b/test/baseline/test__get_figure_no_execution_times.png
index b68cadd183a9638a0596a4a58dd3b331d58e2332..329b3064a06dd922b83dfaa873fd8da2bc9021d6 100644
Binary files a/test/baseline/test__get_figure_no_execution_times.png and b/test/baseline/test__get_figure_no_execution_times.png differ