Circuits

The Circuit class is designed to make building circuits easier, in particular by handling as much wiring as possible (including the pesky attaching and detaching).

Note

If you haven’t read the guide on wiring, I recommend you read that first — the Wire is what Circuit uses under the bonnet to do component connection, and won’t repeat the coverage of how those connections are plotted.

Adding and removing components

Adding and removing components is very simple, and mirrors the API for Manim manim.scene.scene.Scenes: add() is used to add one or more components, and remove() removes one or more components.

Adding wires

Wires are added using the connect() method. This mirrors the signature of the Wire constructor; the first parameter is the terminal to go from, the second is the terminal to go to. One caveat here is that all terminals passed to connect() must belong to components in the circuit, i.e. they must have been added first.

Tip

If you want to connect a component in a given circuit to one not in that circuit, you can use either a Wire or a ManualWire, which work regardless of what any given components’ parents are — see here for more info.

class CircuitExample(Scene):
    def construct(self):
        r1 = Resistor(label="R_1").shift(UP)
        r2 = Resistor(label="R_2")
        r3 = Resistor(label="R_3").shift(DOWN)
        c = Circuit(r1, r2, r3)

        c.connect(r1.right, r2.right)
        c.connect(r2.right, r3.right)
        c.connect(r1.left, r2.left)
        c.connect(r2.left, r3.left)

        self.add(c)
../_images/CircuitExample-1.png

Note

You’d normally add some Nodes to have solder blobs either side of R2, but I’ve omitted these here to keep the example short.

Removing wires

There are two ways of removing wires from a circuit: disconnect() and isolate(). These vary slightly in how they decide if a wire is to be removed, but otherwise work identically. They take an arbitrarily long list of end specifiers, which can be either Components or Terminals (passing a component is shorthand for passing all of its terminals).

Disconnection

The disconnect() method will only remove a wire if both the start and end of the wire are passed as arguments. In the example below, we disconnect R1 and R2, with the result we expect.

class CircuitExample(Scene):
    def construct(self):
        r1 = Resistor(label="R_1").shift(UP)
        r2 = Resistor(label="R_2")
        r3 = Resistor(label="R_3").shift(DOWN)
        c = Circuit(r1, r2, r3)

        c.connect(r1.right, r2.right)
        c.connect(r2.right, r3.right)
        c.connect(r1.left, r2.left)
        c.connect(r2.left, r3.left)

        c.disconnect(r1, r2)

        self.add(c)
../_images/CircuitExample-2.png

To drive the point about needing to pass both ends home, if we just one end specifier (say r1.left), nothing will happen.

class CircuitExample(Scene):
    def construct(self):
        r1 = Resistor(label="R_1").shift(UP)
        r2 = Resistor(label="R_2")
        r3 = Resistor(label="R_3").shift(DOWN)
        c = Circuit(r1, r2, r3)

        c.connect(r1.right, r2.right)
        c.connect(r2.right, r3.right)
        c.connect(r1.left, r2.left)
        c.connect(r2.left, r3.left)

        c.disconnect(r1.left)

        self.add(c)
../_images/CircuitExample-3.png

Isolate

You may have been able to guess from our treatment of disconnect() how isolate() differs. Isolation will remove all wires connected to the passed end points. If we use the example above, but isolate r1.left rather than disconnecting it, we see that the wire between R1 and R2’s left terminals is removed.

class CircuitExample(Scene):
    def construct(self):
        r1 = Resistor(label="R_1").shift(UP)
        r2 = Resistor(label="R_2")
        r3 = Resistor(label="R_3").shift(DOWN)
        c = Circuit(r1, r2, r3)

        c.connect(r1.right, r2.right)
        c.connect(r2.right, r3.right)
        c.connect(r1.left, r2.left)
        c.connect(r2.left, r3.left)

        c.isolate(r1.left)

        self.add(c)
../_images/CircuitExample-4.png

We could also have passed just r1 to remove all wires going to R1, or even r2 to remove all wires full stop (as all wires are connected at one end to one of R2’s terminals.

Animations

Like everything else in manim-eng, Circuit provides hand-crafted animation overrides for its methods. An example showcasing this and combining the various capabilities outlined on this page is below.

class CircuitExample(Scene):
    def construct(self):
        r1 = Resistor(label="R_1").shift(UP)
        r2 = Resistor(label="R_2")
        r3 = Resistor(label="R_3").shift(DOWN)
        c = Circuit(r1, r2, r3)
        self.add(c)

        self.play(
            c.animate.connect(r1.right, r2.right),
            c.animate.connect(r1.left, r2.left),
        )
        self.play(
            c.animate.connect(r2.right, r3.right),
            c.animate.connect(r2.left, r3.left),
        )
        self.wait()
        self.play(
            c.animate.disconnect(r1, r2.left)
        )
        self.wait()
        self.play(
            c.animate.isolate(r3)
        )
        self.wait()