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. Nodes with an underscore in their name are not drawn with a closed blob.

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 without an underscore in them) 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 indentified by a number. However, they can given arbitrary names with the exception of names containing a period (.) or an underscore (_).

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

Nodes without an underscore in them are considered primary nodes. Nodes 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).

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.


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

Dname Np Nm

Other diodes are specified with an additional argument:

Dname Np Nm schottky|led|zener|tunnel|photo

Here’s an example:

D1 1 2; right
D2 2 3 schottky; right
D3 3 4 led; right
D4 4 5 zener; right
D5 5 6 tunnel; right
D6 6 7 photo; 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


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
;draw_nodes=connections, help_lines=0.1


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


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

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 speficied 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 speficied 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]{};


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)
  • 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
; lable_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 without 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 without 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).

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

File formats

Lcapy uses the filename extension to determine the file format to produce. This must be one of tex, schtex, png, svg, or pdf. The schtex format is useful for including schematics into LaTeX documents. The tex format 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). When using a Jupyter notebook, the svg format can be used with draw(svg=True). is a Python script that will generate a schematic from a netlist file. For example, here’s how a png file can be generated:

>>> Dbridge.sch Dbridge.png

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

>>> Dbridge.sch Dbridge.tex

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

>>> Dbridge.sch Dbridge.schtex

and then include the file with \input{Dbridge.schtex}. has many command line options to configure the drawing. These override the options specified in the netlist file. For example:

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

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.