diff --git a/b_asic/operation.py b/b_asic/operation.py
index 0fe66840bcde65e35bb2c24de3b7a9e3ac32b42e..85b3d09c0e01bf15d475feaf172793e9bbb98bca 100644
--- a/b_asic/operation.py
+++ b/b_asic/operation.py
@@ -240,15 +240,27 @@ class Operation(GraphComponent, SignalSourceProvider):
     ) -> Number:
         """
         Evaluate the output at the given index of this operation with the given input values.
-        The *results* parameter will be used to store any results (including intermediate results)
-        for caching.
-        The *delays* parameter will be used to get the current value of any intermediate delays
-        that are encountered, and be updated with their new values.
-        The *prefix* parameter will be used as a prefix for the key string when storing results/delays.
-        The *bits_override* parameter specifies a word length override when truncating inputs
-        which ignores the word length specified by the input signal.
-        The *truncate* parameter specifies whether input truncation should be enabled in the first
-        place. If set to False, input values will be used directly without any bit truncation.
+
+        Parameters
+        ----------
+        index : int
+            Which output to return the value for.
+        input_values : array of float or complex
+            The input values.
+        results : MutableResultMap. optional
+            Used to store any results (including intermediate results)
+            for caching.
+        delays : MutableDelayMap. optional
+            Used to get the current value of any intermediate delay elements
+            that are encountered, and be updated with their new values.
+        prefix : str, optional
+            Used as a prefix for the key string when storing results/delays.
+        bits_override ; int, optional
+            Specifies a word length override when truncating inputs
+            which ignores the word length specified by the input signal.
+        truncate : bool, default: True
+            Specifies whether input truncation should be enabled in the first
+            place. If set to False, input values will be used directly without any bit truncation.
 
         See also
         ========
@@ -263,7 +275,10 @@ class Operation(GraphComponent, SignalSourceProvider):
     ) -> Sequence[Optional[Number]]:
         """
         Get all current outputs of this operation, if available.
-        See current_output for more information.
+
+        See also
+        ========
+        current_output
         """
         raise NotImplementedError
 
@@ -1055,8 +1070,8 @@ class AbstractOperation(Operation, AbstractGraphComponent):
     def get_io_coordinates(
         self,
     ) -> Tuple[List[List[float]], List[List[float]]]:
-        self._check_all_latencies_set()
         # Doc-string inherited
+        self._check_all_latencies_set()
         input_coords = [
             [
                 self.inputs[k].latency_offset,
diff --git a/b_asic/schedule.py b/b_asic/schedule.py
index 129ce92b3105218596f969d747e21ed3bfcb84fc..c74ac5f381115d2bfa12e9391c6d1c053f45d6a7 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"
@@ -181,6 +216,18 @@ class Schedule:
         raise NotImplementedError
 
     def set_schedule_time(self, time: int) -> "Schedule":
+        """
+        Set a new schedule time.
+
+        Parameters
+        ----------
+        time : int
+            The new schedule time. If it is too short, a ValueError will be raised.
+
+        See also
+        --------
+        get_max_time
+        """
         if time < self.get_max_end_time():
             raise ValueError(
                 "New schedule time ({time})to short, minimum:"
@@ -359,6 +406,7 @@ class Schedule:
             delay_list = self._sfg.find_by_type_name(Delay.type_name())
 
     def _schedule_asap(self) -> None:
+        """Schedule the operations using as-soon-as-possible scheduling."""
         pl = self._sfg.get_precedence_list()
 
         if len(pl) < 2:
@@ -479,9 +527,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 +614,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 +627,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 +653,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 +661,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 +684,73 @@ 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..af39c97849a1ff1013a821f969f343bbef537656 100644
--- a/b_asic/signal_flow_graph.py
+++ b/b_asic/signal_flow_graph.py
@@ -78,10 +78,37 @@ 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.
+
+    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.
+
+    Parameters
+    ----------
+    inputs : array of Input, optional
+
+    outputs : array of Output, optional
+
+    input_signals : array of Signal, optional
+
+    output_signals : array of Signal, optional
+
+    id_number_offset : GraphIDNumber, optional
+
+    name : Name, optional
+
+    input_sources :
+
     """
 
     _components_by_id: Dict[GraphID, GraphComponent]
@@ -110,20 +137,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 +324,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 +342,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(
@@ -342,6 +355,7 @@ class SFG(AbstractOperation):
 
     @classmethod
     def type_name(cls) -> TypeName:
+        # doc-string inherited.
         return TypeName("sfg")
 
     def evaluate(self, *args):
@@ -359,6 +373,7 @@ class SFG(AbstractOperation):
         bits_override: Optional[int] = None,
         truncate: bool = True,
     ) -> Number:
+        # doc-string inherited
         if index < 0 or index >= self.output_count:
             raise IndexError(
                 "Output index out of range (expected"
@@ -476,6 +491,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"
@@ -521,7 +548,8 @@ class SFG(AbstractOperation):
 
     @property
     def id_number_offset(self) -> GraphIDNumber:
-        """Get the graph id number offset of the graph id generator for this SFG.
+        """
+        Get the graph id number offset of the graph id generator for this SFG.
         """
         return self._graph_id_generator.id_number_offset
 
@@ -763,7 +791,7 @@ class SFG(AbstractOperation):
 
         return self._precedence_list
 
-    def show_precedence_graph(self) -> None:
+    def show(self) -> None:
         self.precedence_graph().view()
 
     def precedence_graph(self) -> Digraph:
@@ -952,14 +980,32 @@ class SFG(AbstractOperation):
         return self._operations_topological_order
 
     def set_latency_of_type(self, type_name: TypeName, latency: int) -> None:
-        """Set the latency of all components with the given type name."""
+        """
+        Set the latency of all components with the given type name.
+
+        Parameters
+        ----------
+        type_name : TypeName
+            The type name of the operation. For example, obtained as ``Addition.type_name()``.
+        latency : int
+            The latency of the operation.
+
+        """
         for op in self.find_by_type_name(type_name):
             cast(Operation, op).set_latency(latency)
 
     def set_execution_time_of_type(
         self, type_name: TypeName, execution_time: int
     ) -> None:
-        """Set the execution time of all components with the given type name.
+        """
+        Set the execution time of all operations with the given type name.
+
+        Parameters
+        ----------
+        type_name : TypeName
+            The type name of the operation. For example, obtained as ``Addition.type_name()``.
+        execution_time : int
+            The execution time of the operation.
         """
         for op in self.find_by_type_name(type_name):
             cast(Operation, op).execution_time = execution_time
@@ -967,7 +1013,15 @@ class SFG(AbstractOperation):
     def set_latency_offsets_of_type(
         self, type_name: TypeName, latency_offsets: Dict[str, int]
     ) -> None:
-        """Set the latency offset of all components with the given type name.
+        """
+        Set the latency offsets of all operations with the given type name.
+
+        Parameters
+        ----------
+        type_name : TypeName
+            The type name of the operation. For example, obtained as ``Addition.type_name()``.
+        latency_offsets : {"in1": int, ...}
+            The latency offsets of the inputs and outputs.
         """
         for op in self.find_by_type_name(type_name):
             cast(Operation, op).set_latency_offsets(latency_offsets)
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