High quality schematics can be generated from a netlist using Circuitikz for LaTeX diagrams. This is much easier than writing Circuitikz commands directly in LaTeX.

A semi-automatic component placement is used with hints required to designate component orientation and explicit wires to link nodes of the same potential but with different coordinates.

Here’s an example:
>>> from lcapy import Circuit
>>> cct = Circuit()
>>> cct.add('V 1 0 {V(s)}; down')
>>> cct.add('R 1 2; right')
>>> cct.add('C 2 _0_2; down')
>>> cct.add('W 0 _0_2; right')
>>> cct.draw('schematic.pdf')

Note, the orientation hints are appended to the netlist strings with a semicolon delimiter. The drawing direction is with respect to the first node. The component W is a wire. Node names starting with an underscore are not drawn.

The image generated by this netlist is:

Here’s another example, this time loading the netlist from a file:
>>> from lcapy import Circuit
>>> cct = Circuit('voltage-divider.sch')
>>> cct.draw('voltage-divider.pdf')

Here are the contents of the file ‘voltage-divider.sch’:

Vi 1 0_1; down
R1 1 2; right, size=1.5
R2 2 0; down
P1 2_2 0_2; down, v=V_o
W 2 2_2; right
W 0_1 0; right
W 0 0_2; right

Here, P1 defines a port. This is shown as a pair of open blobs. The wires do not need unique names.


Component orientation

Lcapy uses a semi-automated component layout. Each component requires a specified orientation: up, down, left, or right. In addition, attributes can be added to override color, size, etc.

The drawing direction provides a constraint. For example, the nodes of components with a vertical orientation have the same x coordinate, whereas nodes of horizontal components have the same y coordinate.

The component orientation is specified by a rotation angle. This angle is degrees anticlockwise with zero degrees being along the positive x axis. For example,

>>> cct.add('D1 1 2; rotate=45')

The component orientation can also be specified by a direction keyword:

  • right (0 degrees)
  • left (180 degrees)
  • up (90 degrees)
  • down (-90 degrees)

For example:

D1 1 2;right
D1 1 2;down

Note, the drawing direction is from the positive node to the negative node.

Here’s an example of how to draw a diode bridge:

D1 2 1; rotate=225, size=1.5
D2 3 2; rotate=-45, size=1.5
D3 3 4; rotate=225, size=1.5
D4 4 1; rotate=-45, size=1.5

Components can be mirrored about the x-axis using the mirror attribute. For example, to switch the order of the inverting and non-inverting inputs of an opamp use:

>>> cct.add('E1 1 2 opamp 3 0; right, mirror')

Component size

By default each component has a minimum size of 1. This can be stretched to satisfy a node constraint. The minimum size is specified using the size keyword, for example:

>>> cct.add('R1 1 2; right, size=2')

The size argument is used as a scale factor for the component node spacing. The size can also be specified by adding a value to the left, right, up, or down arguments. For example:

>>> cct.add('R1 1 2; right=2')

Here’s a comparison of resistors of different sizes.

R1 1 2; right
R2 2 3; right=2
R3 3 4; right=3

By default, a component with size 1 has its nodes spaced by 2 units. This can be changed using the node_spacing option of the schematic. For example,

R1 1 2; right
R2 2 3; right=2
R3 3 4; right=3
;node_spacing=1.5, help_lines=1

Be default, a component has a length of 1.5 units. This can be changed using the cpt_size option of the schematic. For example,

R1 1 2; right
R2 2 3; right=2
R3 3 4; right=3
;cpt_size=1, help_lines=1
R1 1 2; right
R2 2 3; right=2
R3 3 4; right=3
;cpt_size=1, node_spacing=1, help_lines=1

The size of components can scaled with the scale attribute:

R1 1 2; right
R2 2 3; right=2, scale=2
R3 3 4; right=3, scale=3

The overall schematic can be scaled with the scale option of the schematic:

R1 1 2; right
R2 2 3; right=2
R3 3 4; right=3
;scale=0.5, help_lines=1


Nodes are shown by a blob. By default, only the primary nodes (those not starting with an underscore) are shown by default. This is equivalent to:

>>> cct.draw(draw_nodes='primary')

All nodes can be drawn using:

>>> cct.draw(draw_nodes='all')

Only the nodes where there are more than two branches can be drawn using:

>>> cct.draw(draw_nodes='connections')

No nodes can be drawn using:

>>> cct.draw(draw_nodes=False)

By default, only the primary nodes are labelled. All nodes can be labelled (this is useful for debugging) using:

>>> cct.draw(label_nodes='all')

No nodes can be labelled using:

>>> cct.draw(label_nodes=False)

Only nodes starting with a letter can be labelled using:

>>> cct.draw(label_nodes='alpha')

In this case nodes with names such as in and out will be displayed but not numeric node names.

These options can be stored with the schematic netlist, for example:

C1 1 0 100e-12; down, size=1.5, v={5\,kV}
R1 1 6 1500; right
R2 2 4 1e12; down
C2 3 5 5e-9; down
W 2 3; right
W 0 4; right
W 4 5; right
SW 6 2 no; right, l=, size=1.5
; draw_nodes=connections, label_nodes=False, label_ids=False

Node names

Circuit nodes are usually identified by a number. They can be given arbitrary names provided they do not contain a period (.). By default, nodes with names starting with an underscore are not drawn. The name can contain an underscore to denote a subscript or a caret to denote a superscript. For example, T_123.

Node names starting with a period are a short-hand notation. For example:

R1 1 .2; right
C1 R1.2 3; right

is short-hand for:

R1 1 R1.2; right
C1 R1.2 3; right

Node names not starting with an underscore are considered primary nodes. Node names starting with an underscore are considered secondary nodes (usually they are at the same potential as a primary node and do not need to be labelled). For backward compatibility, nodes with names that contain an underscore and start with a digit are considered secondary.

Node names can also refer to pins of shape and chip components. For example:

U1 regulator; right
W  1; right
W  U1.gnd 0; down


Only linear, time-invariant, components can be analyzed.


XT1 1 2; right

Constant phase elements (CPE)

CPE1 1 0; right


Diodes can be drawn but not simulated. A standard diode is described using:

Dname Np Nm

Different kinds of diodes can be specified by the kind option, for example,

D1 1 2; right, l=diode
D2 2 3; right, kind=schottky, l=schottky
D3 3 4; right, kind=led, l=led
D4 4 5; right, kind=zener, l=zener
D5 5 6; right, kind=zzener, l=zzener
D6 6 7; right, kind=tunnel, l=tunnel
D7 7 8; right, kind=photo, l=photo

The drawn style is controlled by the style option, for example,

D1 1 2; right, l=empty
D2 2 3; right, style=full, l=full
D3 3 4; right, style=stroke, l=stroke


Ferrite beads

FB1 1 2; right


GY1 1 2 3 4 R; right

Integrated circuits

ICs can be drawn but not simulated. Here’s an example:

; draw_nodes=connections, help_lines=1
U1 chip2121; right=2, l={MCU}, pinlabels={r1=PIO1,r2=PIO2}
W U1.vdd VDD; implicit, up=0.2, l=3V3
W U1.vss 0; implicit, down=0.7, l=0V
R1 U1.r2 1; right
D1 1 3 led; down
W 3 0; down=0.1, implicit, l=0V
R2 U1.r1 2; right
W 2 5; right
D2 5 4 led; down
W 4 0; down=0.1, implicit, l=0V

In this example, the chip2121 keyword specifies a block with two pins on the left, one on the bottom, two on the right, and one at the top. The component has pre-defined pinnames, l1, l2, vss, r2, r1, and vdd; these can be modified. Since the pin names start with a dot the associated node names are prefixed by the name of the chip, for example, U1.out1.

The supported chips are:
  • chip1313
  • chip2121
  • chip2222
  • chip3131
  • chip3333
  • chip4141
  • buffer
  • inverter
  • regulator
  • adc
  • dac
  • dff
  • jkff
  • rslatch
_images/Uchip1313.png _images/Uchip2121.png _images/Uchip2222.png _images/Uchip3131.png _images/Uchip3333.png _images/Uchip4141.png _images/Uregulator.png _images/Uadc.png _images/Udac.png _images/Udff.png _images/Ujkff.png _images/Urslatch.png _images/Uinverter.png _images/Ubuffer.png

Chips are subclassed from the shape class and thus the pins can be labelled, renamed, etc. For example:

U1 chip2222; right, pindefs={sda=b1,scl=b2}, pinlabels={sda=SDA,scl=SCL}, pinnodes=all, pinnames=all


Here’s an example using a voltmeter and an ammeter:

BAT 1 0 7.2; down=1.5, l={7.2\,V}
AM 1 2; right=1.5
R 2 3; down
W 0 3; right
W 2 2_1; right
W 3 3_1; right
VM 2_1 3_1; down


Opamps can be drawn using the opamp argument to a VCCS. For example:

E 1 0 opamp 2 3 A; right

The size can be controlled with the scale and size options. The positions of the inverting and non-inverting inputs can be flipped with the mirror option.

E 1 0 opamp 2 3 A; right, scale=0.75, size=0.75
E 1 0 opamp 2 3 A; right, scale=0.75
E 1 0 opamp 2 3 A; right, scale=0.5

Fully differential opamps can be drawn in a similar manner using the fdopamp argument to a VCCS. For example:

E1 1 0 fdopamp 2 3 A; right


RV1 1 2 3; right
; label_nodes=all

Alternatively, a variable resistor can be defined using:

R 1 2; variable


Switches can be drawn but they are ignored for analysis since they make the circuit time-varying.

The general format is:

SWname Np Nm nc|no|push

Here’s an example:

SW1 1 2 no; right
SW2 2 3 nc; right
SW3 3 4 push; right
SW4 4 5 6 spdt; right


TF1 1 2 3 4; right
TF1 1 2 3 4 core; right
TF1 1 2 3 4 tap _5 _6; right
W 5 _5; right=0.5
W _6 6; right=0.5
TF1 1 2 3 4 tapcore _5 _6; right
W 5 _5; right=0.5
W _6 6; right=0.5


Transistors (BJT, JFET, and MOSFET) can be drawn but not analyzed. Both are added to the netlist using a syntax similar to that of SPICE. A BJT is described using:

Qname NC NB NE npn|pnp

where NC, NB, and NE denote the collector, base, and emitter nodes. A MOSFET is described using:

Mname ND NG NS nmos|pmos

where ND, NG, and NS denote the drain, gate, and source nodes.

A JFET is described using:

Jname ND NG NS njf|pjf

where ND, NG, and NS denote the drain, gate, and source nodes.

Here’s an example:

Q1 1 2 3 npn; up
Q2 5 4 3 pnp; up
M1 5 6 7 nmos; up
M2 9 8 7 pmos; up
J1 9 10 11 njf; up
J2 13 12 11 pjf; up

Transmission lines

A transmission line is a two-port device. Here’s an example:

U1 buffer; right
TL1 1 2 U1.out 4; right=2, scale=2, l={50\,$\Omega$}
R 1 2; down
W U1.vdd 9; up=0.1, implicit, l=Vdd
W U1.vss 11; down
W 11 4; right=0.5
W 11 10; down=0.1, implicit, l=Vss
W 5; right=0.5

The ground wires can be removed using the nowires attribute:

U1 buffer; right
TL1 1 2 U1.out 4; right=2, scale=2, l={50\,$\Omega$}, nowires
W 5; right=0.5


Wires are useful for schematic formatting, for example,

W 1 2; right

Here an anonymous wire is created since it has no identifier.

The line style of wires can be changed, such as dashed or dotted (see Line styles).

Wires can be implicitly added using the offset attribute. Here’s an example to draw two parallel resistors:

R1 1 2; right, offset=0.25
R2 1 2; right, offset=-0.25

Stepped wires

Stepped wires can be drawn using the steps attribute. For example:

O 1 2; right=2, rotate=-45
W 1 2; steps=-|, free
O 1 2; right=2, rotate=-45
W 1 2; steps=|-|-, free

In these examples, the free attribute is used so that the wire places no constraints on the node positions. Thus the size and rotate attributes are ignored. The open-circuit component is used to fix the node locations.

The - character represents a horizontal step and the | character represents a vertical step. The shape of the line is controlled by the step pattern. For example –|- represents two steps horizontally, one step vertically, and then one step horizontally. A number before the - or | symbol specifies the number of repeats of the step. For example, steps=-4|- is equivalent to steps=-||||-.

If the step pattern is not specified, a default step pattern -| is chosen if the horizontal extent is longer than the vertical extent and |- is chosen otherwise. For example,

O 1 2; right=2, rotate=-45
W 1 2; steps, free


Arrows can be drawn on wires using the startarrow and endarrow attributes. There are many arrow styles, see the tikz manual. For example,

W 1 2; right, endarrow=tri,
W 2 3; right, endarrow=otri
W 3 4; right, startarrow=open triangle 90, endarrow=open triangle 90
W 4 5; right, startarrow=stealth, endarrow=stealth
; help_lines=1

Implicit wires

Implicit wires are commonly employed for power supply and ground connections. They have one of the following attributes: - implicit equivalent to signal ground - sground signal ground - ground earth ground - cground chassis ground - nground noiseless ground - pground protected ground - rground reference ground

For example:

# signal ground
W 1 01; down=0.2, sground
W 1 2; right
# earth ground
W 2 02; down=0.2, ground
W 2 3; right
# chassis ground
W 3 03; down=0.2, cground
W 3 4; right
# noiseless ground
W 4 04; down=0.2, nground
W 4 5; right
# protected ground
W 5 05; down=0.2, pground
W 5 6; right
# reference ground
W 6 06; down=0.2, rground

Block diagrams

Block diagrams can be constructed with the following components:
  • TF transfer function
  • SPpp, SPpm, SPppp, SPpmm, SPppm summing points
  • MX mixer
  • box rectangular box
  • circle circle (or ellipse)

Here’s an example showing negative feedback:

W 1 14; right=0.5, endarrow=tri, l=V{in}
SP1 pm 14 9 13; right, l={}
W 13 10; endarrow=tri, l=Vd
TR1 10 11 A; right=1.5, l=Open-loop gain (A)
W 11 2; right, l=V{out}
W 2 3; down
TR2 8 12 B; left=1.5, l=Attenuator $\beta$
W 3 8; left, endarrow=tri
W 12 4; left
W 4 9; up, endarrow=tri
W 2 5; right=0.5, endarrow=tri
; draw_nodes=false, label_nodes=false

Here’s a more complicated example for a causal system:

S1 box; right=1.9, aspect=2.1, draw=white, l={Transfer function\\$H(s)$}
S2 box; right=1.9, aspect=2.1, draw=white, l={Impulse response\\$h(t)$}
S3 box; right=1.9, aspect=2.1, draw=white, l={Frequency response\\$H(\mathrm{j}2\pi f)$ or $H(f)$}
S4 box; right, l={$\mathcal{L}^{-1}\left\{.\right\}$}
S5 box; right, l={$\mathcal{F}\left\{.\right\}$}
S6 box; right, l={$s=\mathrm{j}2\pi f$}
W S1.e S4.w; right=0.4, startarrow=tri, endarrow=tri, color=blue
W S4.e S2.w; right=0.4, startarrow=tri, endarrow=tri, color=black!70!green
W S2.s 4; down, color=black!70!green
W 4 S5.e; left=0.4, endarrow=tri, color=black!70!green
W S5.w S3.e; left=0.4, startarrow=tri, endarrow=tri, color=purple
W S1.s S6.n; down=0.4, endarrow=tri, color=blue
W S6.s S3.n; down=0.4, endarrow=tri, color=purple
O S4.mid S5.mid; down=1.3
; label_nodes=alpha, draw_nodes=none, label_ids=false


Summing points

There are a number of summing point varieties: SPpp, SPpm, SPppp, SPpmm, SPppm. The p suffix stands for plus, the m suffix stands for minus. The other variations can be generated using the mirror attribute.

Here’s an example:

SP1 pp ._1 ._2 ._3; down
W 1 SP1._1; down=0.5, endarrow=tri
W 2 SP1._2; right=0.5, endarrow=tri
W SP1._3 3; down=0.5, endarrow=tri
; draw_nodes=false


Here’s a example of a mixer:

MX1 ._1 ._2 ._3; right
W MX1._1 1; right=0.5, endarrow=tri
W 2 MX1._2; right=0.5, endarrow=tri
W 3 MX1._3; up=0.5, endarrow=tri


Shapes include box, circle, ellipse, triangle.

box, circle, ellipse, and triangle shapes have default anchor nodes based on the centre (c) and sixteen directions of the compass: n, nne, ne, ene, e, ese, se, sse, s, ssw, sw, wsw, w, wnw, nw, nww.

_images/Sbox2.png _images/Scircle2.png _images/Striangle2.png

The aspect ratio of box, circle, and triangle can be controlled with the aspect attribute.

Here’s an example of their use:

W x 1; right
W 1 S1.w; right=0.5, endarrow=tri
S1 box; right=0.5, l=$z^{-1}$
S2 circle; right=0.5, l=$\times$
S3 circle; right=0.5, l=$\times$
S4 circle; right=0.5, l=$+$
W S1.e 2; right=0.5
W 3 S4.w; right=1.25, endarrow=tri
W 1 S2.n; down
W S2.s 3; down
W a0 S2.w; right=0.5, endarrow=tri
W 2 S3.n; down, endarrow=tri
W S3.s S4.n; down, endarrow=tri
W a1 S3.w; right=0.5, endarrow=tri
W S4.e y; right=0.5, endarrow=tri
# Align multipliers
O S2.w S3.w; right
; draw_nodes=false, label_nodes=alpha

triangle is an equilateral triangle. Its shape can be changed with the aspect attribute. It has anchors n, e, s, w, c, c1, c2, c3,

The label of a shape can be replaced by an image, using the image keyword. For example,

S1 box; right=4, image=cmos1.png

Each shape has a number of predefined connection pins. Associated with each pin is an optional label.

The pinlabels option can be specified as:
  • all : the default labels for all the pins are shown
  • connected : the default labels for all the connected pins are shown
  • none : none of the default labels are shown
  • {pin1:label1, pin2:label2, ...} : the labels are specified for the named pins.
The names of the pins can be drawn using the pinnames option. This has a syntax:
  • all : the pin names for all the pins are shown
  • connected : the pin names for all the connected pins are shown
  • none : none of the pin names are shown
  • {pin1, pin2, ...} : the specified pin names are shown.
The nodes of the pins can be drawn using the pinnodes option. This has a syntax:
  • all : the pin nodes for all the pins are shown
  • connected : the pin nodes for all the connected pins are shown
  • none : none of the pin nodes are shown
  • {pin1, pin2, ...} : the specified pin nodes are shown.
The pin names can be redefined by the pindefs option. This has a syntax:
  • pindefs={new1=old1, new2=old2, ...}


Schematics can be annotated using additional tikz commands in the netlist. These are delimited by a line starting with two semicolons, for example:

C1 1 0 100e-12;down
R1 1 6 1500;right
R2 2 4 1e12;down
C2 3 5 5e-12;down
W 2 3;right
W 0 4;right
W 4 5;right
SW 6 2 no;right, l=
;draw_nodes=connections, label_nodes=False, label_ids=False
;;\node[blue,draw,dashed,inner sep=5mm,anchor=north, fit=(1) (6) (0), label=Human body model] {};
;;\node[blue,draw,dashed,inner sep=5mm, fit=(2) (3) (4) (5), label=CMOS input model]{};

This example draws dashed boxes around the nodes 0, 1, and 6 and 2, 3, 4, and 5:


Alternatively, the boxes can be fit around named components, for example:

;;\node[blue,draw,dashed,inner sep=5mm, fit=(R2) (C2), label=CMOS input model]{};

When referring to an anchor of a component it is necessary to use @ instead of ., for example, U1@tl instead of Here’s an example:

U1 chip3333; right, l={MCU}, pinlabels={vss,vdd}
R1 1 1a; down
V_DD 1a 0; down
L1 1 2; right=1
L2 0 0_2; right
W 2 5; right=0.5
W 0_2 0_5; right=0.5
Cbulk 5 0_5; down=2, kind=electrolytic
L3 5 6; right
L4 0_5 0_6; right
W 6 3; right=0.5
W 0_6 0_3; right=0.5
L5 3 4; right, color=blue
L6 0_3 0_4; right, color=blue
W 4 U1.vdd; down=0.25, color=blue
W 0_4 U1.vss; up=0.25, color=blue
Clocal 6 0_6; down, color=blue
; label_nodes=none, draw_nodes=connections, label_values=false, label_ids=false
;;\node[blue,draw,dashed,inner sep=8mm, fit=(Cbulk) (U1@tl) (U1@br), label=PCB]{};


Three component styles are supported: american (default), british, and european. The style is set by a style argument to the draw method or by a schematic option. For example,

Vi 1 0_1; down
Rs 1 2; right=1.5
C 2 0; down
W 0_1 0; right
W 0 0_2; right
Rin 2_2 0_2; down, v=V_{in}
W 2 2_2; right
E1 3 0_3 2 0 A; down, l=A V_{in}
Rout 3 4; right=1.5
RL 4 0_4; down, v=V_o
W 0_2 0_3; size=1.2
W 0_3 0_4
P1 4 0_4; down
; style=european


By default the components are drawn in black. This can be overridden with the color attribute, for example:

>>> cct.add('R1 1 2; right, color=blue')

Line styles

The line style of wires can be changed using the tikz attributes, dashed, dotted, thick, ultra thick, line width, densely dotted, loosely dashed and many others. For example,

W 1 2; right
W 2 3; right, dashed
W 3 4; right, dotted
W 4 5; right, thick
W 5 6; right, ultra thick
W 6 7; right, ultra thick, dashed
W 7 8; right, line width=4pt
; help_lines=1


Each component has a component identifier label and a value label. These can be augmented by explicit voltage and current labels.

  • i=label – annotate current through component with label
  • v=label – annotate voltage across component with label
  • l=label – component label

The label name can be displayed using LaTeX math mode by enclosing the name between dollar signs. Thus superscripts and subscripts can be employed. For example,

>>> cct.add('R1 1 2; right, i=$I_1$, v=$V_{R_1}$')

The label position, current and voltage direction can be controlled with attributes _ ^ < and >, for example i^<=I_1. See the Circuitikz manual for details.

By default, if a component has a value label it is displayed, otherwise the component identifier is displayed. Both can be displayed using:

>>> cct.draw(label_ids=True, label_values=True)

Schematic options are separated using a comma. If you need a comma, say in a label, enclose the field in braces. For example:

>>> C1 1 0 100e-12; down, size=1.5, v={5\,kV}

Math-mode labels need to be enclosed in $...$. There is an experimental feature that is activated when the label starts with a single un-matched $. In this case, Lcapy tries to generate a nice LaTeX label. For example, words in sub- and superscripts are converted into a roman font using mathrm. This feature is also activated if the label is not enclosed in $...$ but includes an ^ or _.

Voltage labels can be annotated between pairs of nodes using an open-circuit component. For example,

>>> O1 1 0; down, v=V_1

Component attributes

  • size: scale factor for distance between component’s nodes
  • scale: scale factor for length of component
  • rotate: angle in degrees to rotate component anti-clockwise
  • mirror: mirror component in x-axis (opamps, transistors)
  • invisible: connect to the other components but do not draw
  • ignore: do not connect to the other components and do not draw (this is useful for simulating multiple mutual inductances but where it it is too hard to show them on a schematic)
  • free: place no constraints on the node positions; this is useful for stepped wires. With this attribute the size and rotate attributes are ignored.
  • color: component color
  • variable: for variable resistors, inductors, and capacitors
  • kind: electrolytic, polar, or variable for capacitors; variable for inductors
  • fixed: do not stretch
  • aspect: set aspect ratio for boxes
  • pins: define pin labels for ICs
  • anchors: specify which anchors to show
  • offset: distance to orthogonally offset component (useful for parallel components)

Here’s an example using the variable attribute:

V 1 0 ac; down=1.5
L 1 2; right=1.5, variable
R 2 3; down, variable
W 0 3; right
W 2 2_1; right
W 3 3_1; right
C 2_1 3_1; down, variable

Here’s an example using the kind attribute to specify the type of capacitor.

C 1 2; right
Celectrolytic 2 3; right, kind=electrolytic
Cpolar 3 4; right, kind=polar
Cvariable 4 5; right, kind=variable
; label_nodes=false, draw_nodes=connections


Schematic attributes

  • node_spacing: scale factor for distance between component nodes (default 2).
  • cpt_size: length of component (default 1.5).
  • scale: scale factor (default 1).
  • help_lines: spacing between help lines (default 0 to disable).
  • draw_nodes: specifies which nodes to draw (default primary). Its argument can either be all, connections (nodes that connect at least two components), none, or primary (node names not starting with an underscore).
  • label_nodes: specifies which nodes to label (default primary). Its argument can either be all, alpha (node names starting with a letter), none, or primary (node names not starting with an underscore).
  • label_ids: specifies whether component ids are drawn (default true).
  • label_values: specifies whether component values are drawn (default true).
  • style: specifies the component style. This is either american, british, or european (default american).
  • dpi: dots per inch (default 150) when converting to a PNG file (as used for displaying Jupyter notebooks). This will change the displayed size of the schematic on the screen.

Schematic attributes apply to the whole schematic. They can be specified by starting a netlist with a semicolon, for example,

;help_lines=1, draw_nodes=connections

The schematic attributes can be overridden using arguments to the draw method. For example,

>>> sch.draw(draw_nodes='alpha')


Large schematics can be composed by including smaller schematics using the .include directive, for example:

.include part1.sch
.include part2.sch

Each of the smaller schematics can be included into their own namespace to avoid conflicts, for example:

.include LC1.sch as s1
.include LC1.sch as s2
W s1.2 s2.1; right=0.1
W s1.3 s2.0; right=0.1


Hierarchical namespaces are supported, for example:

a.R1 1 2; right
b.R1 1 2; right

This creates two resistors: a.R1 with nodes a.1 and a.2 and b.R1 with nodes b.1 and a.2. They can be joined using:

W a.2 b.1; right

When node names start with a dot, they are defined relative to the name of the component, for example:

R1 .p .m; right
W 1 R1.p; right
W R1.m 2; right


P1 1 0_1; down
R1 1 2; right
R2 2_1 3_1; right
E1 3_2 0_3 opamp 2_0 2 A; mirror
W 0_1 0; right
W 2_0 0; down
W 3_2 3; right
W 0 0_3; right
P2 3 0_3; down
W 2_1 2; down
W 3_1 3_2; down
; draw_nodes=connections
P1 1 0_1; down
W 2_1 2; down
R1 2 0; down
R2 2 3_1; right
W 3_2 3_1; down
E1 3_2 0_3 opamp 1_1 2_1 A;
W 0_1 0; right
W 3_2 3; right
W 0 0_3; right
P2 3 0_3; down
W 1 1_1; right
P1 1 0_1; down
R 1 2; right
C 2_1 3_1; right
E1 3_2 0_3 opamp 2_0 2 A; mirror
W 0_1 0; right
W 2_0 0; down
W 3_2 3; right
W 0 0_3; right
P2 3 0_3; down
W 2_1 2; down
W 3_1 3_2; down
M1 3_c 2_p Vdd pmos P; right
M2 3_c 2_n 0 nmos N; right
W 2_p 2_c; down=0.5
W 2_c 2_n; down=0.5
W in 2_c; right
W 3_c out; right
P1 in 0_2; down
P2 out 0_3; down
W 0_2 0;right
W 0 0_3;right
D1 1 2; left=1.5
D2 3 4; right
D3 1 4; down=1.5
D4 3 2; up
P1 1 0_1
R1 1 3; right
L1 3 2; right
C1 3 4; down
L2 4 0; down
P2 2 0_2
W 0_1 0; right
W 0 0_2; right
L1 1 0 0.1; down
L2 2 3 1; down=1.5
K1 L1 L2; size=1.5
V1 1 0; down
R1 1 2; left=2, i=I_1, v=V_{R_1}
R2 1 3; right=2, i=I_2, v=V_{R_2}
L1 2 0_1; down=2, i=I_1, v=V_{L_1}
L2 3 0_3; down=2, i=I_2, v=V_{L_2}
W 0 0_3; right
W 0 0_1; left
Vi 1 0_1; down
Rs 1 2; right=1.5
C 2 0; down
W 0_1 0; right
W 0 0_2; right
Rin 2_2 0_2; down, v=V_{in}
W 2 2_2; right
E1 3 0_3 2 0 A; down, l=A V_{in}
Rout 3 4; right=1.5
RL 4 0_4; down, v=V_o
W 0_2 0_3; size=1.2
W 0_3 0_4
P1 4 0_4; down
; draw_nodes=connected
P 1 0; down, v=v_{in}(t)
R1 1 2; right
R2 2 3; right
C1 2 4; up
C2 3 9; down
W 4 5; right
W 5 6; right
W 6 7; down=0
W 7 8; right=0.5
E 7 0 opamp 3 11 A; right, mirror, scale=0.75, size=0.75
W 5 11; down=0.5
P 8 10; down, v^=v_{out}(t)
W 0 9; right
W 9 10; right
;draw_nodes=connections, label_nodes=False, help_lines=1
U1 inverter; right=2, l={}
U2 inverter; right=2, l={}
W U1.out; right=1, color=red
W U1.vss 4_2; down=0.3, implicit, l=0V
W U2.vss 4_3; down=0.3, implicit, l=0V
W U1.vdd 3_2; up=0.3, implicit, l=V_{DD1}, color=red
W U2.vdd 3_3; up=0.3, implicit, l=V_{DD2}, color=red
W 7_1; right=0.25, dashed, fixed, color=red
D 7_1 6_1; up=0.25, scale=0.5, l=, color=red
D 6_2 7_1; up=0.25, scale=0.5, l=
W 6_1 U2.vdd; right=0.6, dashed, color=red
W 6_2 U2.vss; right=0.6, dashed
M1 1 2 3 pmos; right=0.25, scale=0.25, l={}, color=red
M2 1 4 5 nmos; right=0.25, scale=0.25, l={}
W 3 3_1; up=0.0, color=red
W 3_1 U1.vdd; right=0.2, dashed, color=red
W 5 5_1; down=0.0
W 5_1 U1.vss; right=0.2, dashed
W 1 U1.out; right, dashed, color=red

U1 inverter; right
W 5; right=0.5
W U1.out 6; right=0.5
W 6 9; right=0.5
R1 7 8; right
W 5 1; down=0.75
W 6 2; down=0.75
W 5 7; up=0.75
W 6 8; up=0.75
XT1 1 2; right
C1  1 4; down=0.8
C2  2 3; down=0.8
W 4 0; down=0.1, implicit, l=GND
W 3 0; down=0.1, implicit, l=GND
; draw_nodes=connections, label_nodes=False


Circuitikz commands (indeed any TikZ/PGF macros) can be embedded in a netlist. Here’s an example that embeds a circuitikz command to change the inductor style:

L1 1 2; right
;; \ctikzset{inductor=american}
L2 2 3; right

File formats

Lcapy uses the filename extension to determine the file format to produce. This must be one of tex, schtex, pgf, png, svg, or pdf. The pgf format is useful for including schematics into LaTeX documents. The tex, schtex, and pgf extension generates a standalone LaTeX file. If no filename is specified, the schematic is displayed on the screen.

By default, the png format is used for interactive drawing. First LaTeX is used to create a temporary pdf file; this is then converted to png format using pdftoppm or convert (ImageMagick); convert does a better job but does not come installed with the required permissions. When using a Jupyter notebook, the svg format can be used with draw(svg=True).


schtex is a Python script that will generate a schematic from a netlist file. For example, here’s how a png file can be generated:

>>> schtex Dbridge.sch Dbridge.png

The generated stand-alone LaTeX file can be obtained using:

>>> schtex Dbridge.sch Dbridge.tex

If you wish to include the schematic into a LaTeX file use:

>>> schtex Dbridge.sch Dbridge.pgf

and then include the file with \input{Dbridge.pgf}.

schtex has many command line options to configure the drawing. These override the options specified in the netlist file. For example:

>>> schtex --draw_nodes=connections --label_nodes=false --cpt-size=1 --help_lines=1 Dbridge.sch Dbridge.pdf

One useful option is to renumber the nodes in a netlist. For example,

>>> schtex --renumber='10:1, 11:2' infile.sch outfile.sch

This will choose small integers for the node numbers, honoring the provided mapping. Equipotential nodes will be distinguished using enumerated subscripts, e.g., 1_1, 1_2, 1_3 etc.

Schematics in LaTeX

Here’s an example of how to include an Lcapy schematic in a LaTeX document.

\documentclass[a4paper, 12pt]{article}


  \caption{RLC network.}


A PDF file can be produced using:

$ schtex pic4.sch pic4.pgf
$ pdflatex pic4-demo

Drawing tips

Lcapy uses a semi-automated approach to component layout. For each component it needs its orientation and size. By default the size is 1. This is the minimum distance between its nodes (for a one-port device). If the component can be stretched, Lcapy will increase but never decrease this distance.

The x and y positions of nodes are computed independently using a graph. An error can occur if components have the wrong orientation since this makes the graph inconsistent. Unfortunately, it is not trivial to find the offending component so it is best to draw a schematic incrementally and to test it as you go. A sketch on a piece of paper showing the nodes is useful.

Problems can occur using components, such as integrated circuits and opamps, that cannot be stretched. Usually this is due to a conflict between constraints. A solution is to reduce the size of the component if it can be stretched, such as a wire or resistor. Sometimes it is necessary to add a short interconnecting wire.

The stretching of components can be prevented by specifying the fixed attribute.

Additional constraints can be supplied by using an open-circuit to align components.

Grid lines can be added to a schematic using some Tikz markup. For example:

;;\draw[help lines] (0,0) grid [xstep=0.1, ystep=0.1] (10,5);

Unfortunately, the drawing quality depends on the installed version of circuitikz due to slight tweakings of component sizes.