diff --git a/Makefile b/Makefile
index 9d111ec0cd7de5a588b8a09da922c53e163717d1..7989f1bb684584c22f5625e7532217f8e83dab7e 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ SHELL = /bin/bash
 #
 DOCKER_REGISTRY_USER:=tango-example
 PROJECT = lmcbaseclasses
-
+IMAGE_FOR_DIAGRAMS = nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.2.1
 #
 # include makefile to pick up the standard Make targets, e.g., 'make build'
 # build, 'make push' docker push procedure, etc. The other Make targets
@@ -40,10 +40,21 @@ lint: ## lint lmcbaseclasses Python code
 	pylint --output-format=pylint2junit.JunitReporter src/ska > build/reports/linting.xml
 
 test-in-docker: build ## Build the docker image and run tests inside it.
-	@docker run $(IMAGE):$(VERSION) make test
+	@docker run --rm $(IMAGE):$(VERSION) make test
 
 lint-in-docker: build ## Build the docker image and run lint inside it.
-	@docker run $(IMAGE):$(VERSION) make lint
+	@docker run --rm $(IMAGE):$(VERSION) make lint
+
+generate-diagrams-in-docker: ## Build the docker image and generate state machine diagrams inside it.
+	@docker run --rm -v $(PWD):/diagrams $(IMAGE_FOR_DIAGRAMS) bash -c "cd /diagrams && make generate-diagrams-in-docker-internals"
+
+generate-diagrams-in-docker-internals:  ## Generate state machine diagrams (within a container!)
+	test -f /.dockerenv  # ensure running in docker container
+	apt-get update
+	apt-get install --yes graphviz graphviz-dev gsfonts pkg-config
+	python3 -m pip install pygraphviz
+	cd /diagrams/docs/source && python3 draw_state_machines.py
+	ls -lo /diagrams/docs/source/images/
 
 help:  ## show this help.
 	@grep -hE '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
diff --git a/docs/source/State_Machine.rst b/docs/source/State_Machine.rst
index d193e154250d4e4643c190cf7508faa798b96cf1..929d3191c289a8eae7083ee5835e774fa743db59 100644
--- a/docs/source/State_Machine.rst
+++ b/docs/source/State_Machine.rst
@@ -44,15 +44,12 @@ Diagrams of the admin mode state machine are shown below.
 
   Diagram of the admin mode state machine, as designed
 
+.. figure:: images/AdminModeStateMachine_autogenerated.png
+  :alt: Diagram of the admin mode state machine, as implemented
 
-..
-  COMMENTED OUT FOR NOW
-  .. figure:: images/AdminModeStateMachine_autogenerated.png
-    :alt: Diagram of the admin mode state machine, as implemented
-
-    Diagram of the admin mode state machine, automatically generated from
-    the implementation. The equivalence of this diagram to the diagram
-    above demonstrates that the machine has been implemented as designed.
+  Diagram of the admin mode state machine, automatically generated from
+  the implementation. The equivalence of this diagram to the diagram
+  above demonstrates that the machine has been implemented as designed.
 
 
 Operational state state machine
@@ -82,7 +79,7 @@ The operational state state machine allows for:
   STANDBY and OFF.
 * transition between OFF and ON.
 
-.. figure:: images/OperationalStateStateMachine_decoupled.png
+.. figure:: images/OperationStateMachine_decoupled.png
   :alt: Diagram of the operational state state machine, as designed,
         ignoring coupling with admin mode
 
@@ -110,23 +107,21 @@ separately.
 
 Diagrams of the operational state state machine are shown below.
 
-.. figure:: images/OperationalStateStateMachine_coupled.png
+.. figure:: images/OperationStateMachine_coupled.png
   :alt: Diagram of the operational state state machine, as designed,
         showing coupling with admin mode
 
   Diagram of the operational state (opState) state machine, as
   designed, showing coupling with admin mode
 
-..
-  COMMENTED OUT FOR NOW
-  .. figure:: images/OperationalStateStateMachine_coupled_autogenerated.png
-    :width: 80%
-    :alt: Diagram of the admin operational state state machine, as implemented
+.. figure:: images/OperationStateMachine_autogenerated.png
+  :width: 80%
+  :alt: Diagram of the operational state state machine, as implemented
 
-    Diagram of the operational state state machine, automatically
-    generated from the implementation. The equivalence of this diagram
-    to the diagram above demonstrates that the machine has been
-    implemented as designed.
+  Diagram of the operational state state machine, automatically
+  generated from the implementation. The equivalence of this diagram
+  to the diagram above demonstrates that the machine has been
+  implemented as designed.
 
 
 Observation state machine
diff --git a/docs/source/draw_state_machines.py b/docs/source/draw_state_machines.py
new file mode 100644
index 0000000000000000000000000000000000000000..4823b887cf2cd3839ac43099e7b65224c2fc2a63
--- /dev/null
+++ b/docs/source/draw_state_machines.py
@@ -0,0 +1,50 @@
+"""
+This module draws diagrams of the state machines.
+
+Usage:
+    ~/ska-src/lmc-base-classes$ docker run --rm -ti -v $PWD:/app continuumio/miniconda3 bash
+
+    (base) root@293f3b699c9b:/opt/project/src/ska/base# history
+    $ conda install --yes pygraphviz
+    $ pip install transitions
+    $ apt-get update && apt-get install gsfonts
+    $ cd /app/docs/source
+    $ python draw_state_machines.py
+
+(Or see the top level Makefile)
+
+"""
+import importlib
+import sys
+
+from unittest import mock
+from transitions.extensions import GraphMachine
+
+# local import, so we can run this without installing the whole package
+sys.path.append("../../src/ska/base")
+import state_machine
+
+
+def patch_in_graph_machine():
+    with mock.patch("transitions.Machine", GraphMachine):
+        mod = sys.modules["state_machine"]
+        importlib.reload(mod)
+
+
+def draw(machine_class):
+    machine_name = machine_class.__name__
+    graphing_options = {
+        "title": f"\n{machine_name}",
+        "show_conditions": True,
+        "show_state_attributes": True,
+        "show_auto_transitions": False,
+    }
+    machine = machine_class(None, **graphing_options)
+    machine.get_graph().draw(f"images/{machine_name}_autogenerated.png", prog='dot')
+
+
+if __name__ == "__main__":
+    patch_in_graph_machine()
+    draw(state_machine.OperationStateMachine)
+    draw(state_machine.AdminModeStateMachine)
+    draw(state_machine.ObservationStateMachine)
diff --git a/docs/source/images/AdminModeStateMachine_autogenerated.png b/docs/source/images/AdminModeStateMachine_autogenerated.png
new file mode 100644
index 0000000000000000000000000000000000000000..6c761f570cdbdeb0fa41b6a157ffea9736bf19ed
Binary files /dev/null and b/docs/source/images/AdminModeStateMachine_autogenerated.png differ
diff --git a/docs/source/images/ObservationStateMachine_autogenerated.png b/docs/source/images/ObservationStateMachine_autogenerated.png
index 8a06b18e1a03ac15f1664557b64f49c0f5a6fa65..2299fbbe566219224e8f7b7179828c03298d6115 100644
Binary files a/docs/source/images/ObservationStateMachine_autogenerated.png and b/docs/source/images/ObservationStateMachine_autogenerated.png differ
diff --git a/docs/source/images/OperationStateMachine_autogenerated.png b/docs/source/images/OperationStateMachine_autogenerated.png
new file mode 100644
index 0000000000000000000000000000000000000000..a9845db4166b4727af342d486079e2453676e091
Binary files /dev/null and b/docs/source/images/OperationStateMachine_autogenerated.png differ
diff --git a/docs/source/images/OperationalStateStateMachine_coupled.png b/docs/source/images/OperationStateMachine_coupled.png
similarity index 100%
rename from docs/source/images/OperationalStateStateMachine_coupled.png
rename to docs/source/images/OperationStateMachine_coupled.png
diff --git a/docs/source/images/OperationalStateStateMachine_decoupled.png b/docs/source/images/OperationStateMachine_decoupled.png
similarity index 100%
rename from docs/source/images/OperationalStateStateMachine_decoupled.png
rename to docs/source/images/OperationStateMachine_decoupled.png
diff --git a/src/ska/base/state_machine.py b/src/ska/base/state_machine.py
index 46ebf7741ca6063552579b4906de78a942919323..4096d8a1a11f3a250f3d9fa86c684af531edfde0 100644
--- a/src/ska/base/state_machine.py
+++ b/src/ska/base/state_machine.py
@@ -17,13 +17,15 @@ class OperationStateMachine(Machine):
     administratively disabled.
     """
 
-    def __init__(self, callback=None):
+    def __init__(self, callback=None, **extra_kwargs):
         """
         Initialises the state model.
 
         :param callback: A callback to be called when a transition
             implies a change to op state
         :type callback: callable
+        :param extra_kwargs: Additional keywords arguments to pass to super class
+            initialiser (useful for graphing)
         """
         self._callback = callback
 
@@ -203,6 +205,7 @@ class OperationStateMachine(Machine):
             initial="UNINITIALISED",
             transitions=transitions,
             after_state_change=self._state_changed,
+            **extra_kwargs,
         )
 
     def _state_changed(self):
@@ -219,13 +222,15 @@ class AdminModeStateMachine(Machine):
     The state machine governing admin modes
     """
 
-    def __init__(self, callback=None):
+    def __init__(self, callback=None, **extra_kwargs):
         """
         Initialises the admin mode state machine model.
 
         :param callback: A callback to be called whenever there is a transition
             to a new admin mode value
         :type callback: callable
+        :param extra_kwargs: Additional keywords arguments to pass to super class
+            initialiser (useful for graphing)
         """
         self._callback = callback
 
@@ -263,6 +268,7 @@ class AdminModeStateMachine(Machine):
             initial="MAINTENANCE",
             transitions=transitions,
             after_state_change=self._state_changed,
+            **extra_kwargs,
         )
         self._state_changed()
 
@@ -281,12 +287,14 @@ class ObservationStateMachine(Machine):
     ADR-8.
     """
 
-    def __init__(self, callback=None):
+    def __init__(self, callback=None, **extra_kwargs):
         """
         Initialises the model.
 
         :param callback: A callback to be called when the state changes
         :type callback: callable
+        :param extra_kwargs: Additional keywords arguments to pass to super class
+            initialiser (useful for graphing)
         """
         self._callback = callback
 
@@ -442,6 +450,7 @@ class ObservationStateMachine(Machine):
             initial="EMPTY",
             transitions=transitions,
             after_state_change=self._state_changed,
+            **extra_kwargs,
         )
         self._state_changed()