Examples

Charge Pump (charge-pump.py)

This example has a transparent background and so all wires terminate at terminals rather than passing underneath components. The labels are intended to be rendered by Latex. It sets line_width to 2 give the schematic a heavier look.

#!/usr/bin/env python3

from svg_schematic import Schematic, Capacitor, Diode, Ground, Pin, Wire, Dot, with_x
from inform import Error, error, os_error

try:
    with Schematic(
        filename = "charge-pump.svg", line_width=2, background='none'):

        vin = Pin(kind='in', name=r'$V_{\rm in}$', w=2)
        p1 = Pin(C=vin.C, yoff=150, kind='in', name=r'$\phi_1$', w=2)
        p2 = Pin(C=p1.C, yoff=50, kind='in', name=r'$\phi_2$', w=2)
        d1 = Diode(a=vin.C, xoff=25, orient='h')
        c1 = Capacitor(p=d1.c, off=(25, 25), orient='v')
        d2 = Diode(a=d1.c, xoff=50, orient='h')
        c2 = Capacitor(p=d2.c, off=(25, 25), orient='v')
        d3 = Diode(a=d2.c, xoff=50, orient='h')
        c3 = Capacitor(p=d3.c, off=(25, 25), orient='v')
        d4 = Diode(a=d3.c, xoff=50, orient='h')
        c4 = Capacitor(p=d4.c, off=(25, 25), orient='v')
        d5 = Diode(a=d4.c, xoff=50, orient='h')
        c5 = Capacitor(p=d5.c, off=(25, 25), orient='v')
        vout = Pin(C=d5.c, xoff=75, kind='out', name=r'$V_{\rm out}$', w=2)
        Ground(t=c5.n)

        Wire([vin.t, d1.a])
        Wire([d1.c, d2.a])
        Wire([d2.c, d3.a])
        Wire([d3.c, d4.a])
        Wire([d4.c, d5.a])
        Wire([d5.c, vout.t])
        Wire([with_x(vin.t, c1.C), c1.p])
        Wire([with_x(vin.t, c2.C), c2.p])
        Wire([with_x(vin.t, c3.C), c3.p])
        Wire([with_x(vin.t, c4.C), c4.p])
        Wire([with_x(vin.t, c5.C), c5.p])
        Wire([p1.t, c1.n], kind='-|')
        Wire([p2.t, c2.n], kind='-|')
        co = Dot(C=with_x(p1.C, c2.C), color='white')     # wire cross over
        Wire([p1.t, c3.n], kind='-|')
        Wire([p2.t, c4.n], kind='-|')

except Error as e:
    e.report()
except OSError as e:
    error(os_error(e))
../../../_images/charge-pump.svg

Inverter (inverter.py)

This example has a transparent background and so all wires terminate at terminals rather than passing underneath components. The labels are intended to be rendered by Latex. It sets line_width to 2 give the schematic a heavier look.

#!/usr/bin/env python3

from svg_schematic import Schematic, MOS, Ground, Gate, Label, Pin, Wire, midpoint
from inform import Error, error, os_error

try:
    with Schematic(filename = 'inverter.svg', line_width=2, background='none'):

        # transistor version
        mp = MOS(kind='p')
        mn = MOS(N=mp.S, kind='n')
        vin = Pin(C=midpoint(mp.g, mn.g), xoff=-50, kind='in', name=r'$V_{\rm in}$', w=2)
        vout = Pin(C=midpoint(mp.d, mn.d), xoff=50, kind='out', name=r'$V_{\rm out}$', w=2)
        Label(C=mp.s, loc='n', name=r'$V_{\rm dd}$')
        Ground(C=mn.s)
        Wire([vin.t, mp.g], kind='-|')
        Wire([vin.t, mn.g], kind='-|')
        Wire([vout.t, mp.d], kind='-|')
        Wire([vout.t, mn.d], kind='-|')

        # gate version
        inv = Gate(N=mn.S, yoff=25, kind='inv')
        vin = Pin(t=inv.i, xoff=-25, kind='in', name=r'$V_{\rm in}$', w=2)
        vout = Pin(t=inv.o, xoff=25, kind='out', name=r'$V_{\rm out}$', w=2)
        Wire([inv.o, vout.t])
        Wire([inv.i, vin.t])

except Error as e:
    e.report()
except OSError as e:
    error(os_error(e))
../../../_images/inverter.svg

Inverting Amplifier (inverting.py)

This schematic uses line_width = 1 give the schematic a lighter look. It uses a 16 point serif font.

#!/usr/bin/env python3

from svg_schematic import (
    Schematic, Amp, Dot, Ground, Label, Pin, Resistor, Source, Wire
)
from inform import Error, error, os_error

try:
    with Schematic(
        filename = "inverting.svg",
        font_size=16,
        font_family='serif'
    ):

        vin = Pin(kind='in', name='in', w=1.5)
        vout = Pin(C=vin.C, xoff=350, kind='out', name='out', w=2)
        Wire([vin.C, vout.C])
        rin = Resistor(W=vin.C, xoff=25, name='Rin')
        vg = Dot(C=rin.E, xoff=25)
        rfb = Resistor(W=vg.C, xoff=25, name='Rfb')
        oj = Dot(C=rfb.E, xoff=25)
        amp = Amp(C=rfb.C, yoff=75, orient='-')
        Wire([oj.C, amp.o], kind='|-')
        gnd = Ground(C=amp.pi, xoff=-25, orient='h|')
        Wire([gnd.C, amp.pi])
        Wire([vg.C, amp.ni], kind='|-')
        Label(C=vg.C, name='Vg', loc='sw')

except Error as e:
    e.report()
except OSError as e:
    error(os_error(e))
../../../_images/inverting.svg

Non-Inverting Amplifier (noninverting.py)

This schematic uses line_width = 1 give the schematic a lighter look.

#!/usr/bin/env python3

from svg_schematic import (
    Schematic, Amp, Dot, Ground, Label, Pin, Resistor, Source, Wire
)
from inform import Error, error, os_error

try:
    with Schematic(filename = "noninverting.svg"):

        vin = Source(kind='sine')
        Label(C=vin.p, name='Vin', loc='n')
        Ground(C=vin.n)
        amp = Amp(pi=vin.p, xoff=100, kind='oa')
        Label(C=amp.ni, xoff=-25, name='Ve', loc='n')
        Wire([vin.p, amp.pi])
        out = Pin(C=amp.o, xoff=50, name='out', w=2)
        Wire([amp.o, out.C])
        oj = Dot(C=amp.o, xoff=25)
        r1 = Resistor(p=amp.ni, off=(-25, 50), name='R1', orient='v')
        Wire([r1.N, amp.ni], kind='|-')
        r2 = Resistor(C=amp.C, yoff=75, name='R2')
        Wire([r1.p, r2.W], kind='|-')
        Wire([oj.C, r2.E], kind='|-')
        fj = Dot(C=r2.W, xoff=-25)
        Ground(C=r1.n)

except Error as e:
    e.report()
except OSError as e:
    error(os_error(e))
../../../_images/noninverting.svg

Oscillator (oscillator.py)

This example has a transparent background and so all wires terminate at terminals rather than passing underneath components. The labels are intended to be rendered by Latex. This schematic uses line_width = 2 give the schematic a heavier look.

#!/usr/bin/env python3

from svg_schematic import (
    Schematic, Capacitor, MOS, Inductor, Label, Source, Wire,
    midpoint, shift, shift_y,
)
from inform import Error, error, os_error

try:
    with Schematic(filename = "oscillator.svg", background='none', line_width=2):

        # resonator
        vdd = Label(loc='n', nudge=10, name=r'$V_{\rm dd}$')
        Wire([vdd.C, shift_y(vdd.C, 25)])
        ll = Inductor(p=shift(vdd.C, -125, 25), orient='v', name=r'$\frac{1}{2} L$')
        lr = Inductor(p=shift(vdd.C, 125, 25), orient='v|', name=r'$\frac{1}{2} L$')
        c = Capacitor(C=midpoint(ll.n, lr.n), orient='h', name='$C$')
        Wire([ll.p, lr.p])
        Wire([ll.n, c.p])
        Wire([lr.n, c.n])

        # gain stage
        ml = MOS(d=ll.n, yoff=50, orient='|')
        mr = MOS(d=lr.n, yoff=50, orient='')
        Wire([ll.n, ml.d])
        Wire([lr.n, mr.d])
        Wire([ml.g, shift_y(ml.g, -25), shift(ml.g, 50, -75), shift_y(mr.d, -25)])
        Wire([mr.g, shift_y(mr.g, -25), shift(mr.g, -50, -75), shift_y(ml.d, -25)])
        Wire([ml.s, mr.s])
        Source(p=midpoint(ml.s, mr.s), kind='idc', value=r'$I_{\rm ss}$')

except Error as e:
    e.report()
except OSError as e:
    error(os_error(e))
../../../_images/oscillator.svg

Passive Low Pass Filter (mfed.py)

This example uses QuantiPhy to compute the values for the components in a low pass filter and then constructs the schematic using those values. It sets line_width to 2 and employs dots at wire junctions to give the schematic a heavier look.

"""
Draw a 5th Order Low Pass Passive Filer with Maximally Flat Envelope Delay

Use the following parameters:
    Fo = 1MHz   -- 3dB corner frequency
    Rref = 50Ω  -- termination impedance

Design equations:
    Omega0 = 2*π*Fo
    Lscale = Rref/Omega0
    Cscale = 1/(Rref*Omega0)

    Rs = 1.0000 * Rref   "Ω"
    C1 = 0.2715 * Cscale "F"
    L2 = 0.6541 * Lscale "H"
    C3 = 0.8892 * Cscale "F"
    L4 = 1.1034 * Lscale "H"
    C5 = 2.2873 * Cscale "F"
"""

from svg_schematic import (
    Schematic, Capacitor, Dot, Ground, Inductor, Label, Resistor, Pin, Source, Wire
)
from inform import Error, error, os_error
from quantiphy import Quantity
from math import pi

Quantity.set_prefs(map_sf=Quantity.map_sf_to_greek, prec=2)
globals().update(
    Quantity.extract(__doc__, predefined={'π': pi})
)

try:
    with Schematic(filename = 'mfed.svg', line_width=2, background = 'none'):

        vin = Source(name='Vin', value='1 V', kind='sine')
        Ground(C=vin.n)
        rs = Resistor(name='Rs', value=Rref, n=vin.p, xoff=25)
        Wire([vin.p, rs.n])
        c1 = Capacitor(name='C1', value=C1, p=rs.p, xoff=25)
        Ground(C=c1.n)
        l2 = Inductor(name='L2', value=L2, n=c1.p, xoff=25)
        Wire([rs.p, l2.n])
        c3 = Capacitor(name='C3', value=C3, p=l2.p, xoff=25)
        Ground(C=c3.n)
        l4 = Inductor(name='L4', value=L4, n=c3.p, xoff=25)
        Wire([l2.p, l4.n])
        c5 = Capacitor(name='C5', value=C5, p=l4.p, xoff=25)
        Ground(C=c5.n)
        rl = Resistor(name='Rl', value=Rref, p=c5.p, xoff=100, orient='v')
        Ground(C=rl.n)
        out = Pin(name='out', C=rl.p, xoff=50, w=2)
        Wire([l4.p, out.t])
        Label(S=c3.N, yoff=-50, name=f'{Fo} LPF', loc='s')
        Dot(C=c1.p)
        Dot(C=c3.p)
        Dot(C=c5.p)
        Dot(C=rl.p)

except Error as e:
    e.report()
except OSError as e:
    error(os_error(e))

../../../_images/mfed1.svg

Pipelined ADC (pipeline-adc.py)

This block diagram has a white background and so could route wires under components rather than wiring to terminals, but it largely does not. It uses line_width = 2 give the diagram a heavier look.

#!/usr/bin/env python3

from svg_schematic import (
    Schematic, Amp, Box, Label, Pin, Source, Wire,
    midpoint, shift_x, shift, with_x, with_y,
)
from inform import Error, error, os_error

try:
    with Schematic(filename = 'pipeline-adc.svg', line_width=2):

        # Stage 1
        i = Pin(kind='in', name='in')
        s1 = Box(NW=i.t, off=(25,-62.5), w=10.5, h=4.5, background='lightgray')
        Label(C=s1.SE, loc='nw', name='Stage 1')
        adc = Box(W=i.t, off=(75,100), name='2 bit', value='Flash')
        dac = Box(i=adc.o, xoff=50, name='2 bit', value='DAC')
        sh = Box(C=with_x(i.t, midpoint(adc.C, dac.C)), name='SAH')
        sum = Source(W=with_x(i.t, dac.E), xoff=25, kind='sum', orient='h|')
        Label(C=sum.W, loc='nw', name='+')
        Label(C=sum.S, loc='se', name='−')
        amp = Amp(i=sum.E, xoff=25, kind='se', name='4×')
        Wire([i.t, sh.i])
        Wire([sh.o, sum.W])
        Wire([sum.E, amp.i])
        Wire([shift_x(i.t, 50), adc.i], kind='|-')
        Wire([adc.o, dac.i])
        Wire([dac.o, sum.S], kind='-|')

        # Stages 2, 3, 4
        s2 = Box(N=dac.S, off=(25,75), name='Stage 2')
        s3 = Box(W=s2.E, xoff=50, name='Stage 3')
        s4 = Box(W=s3.E, xoff=50, name='4 bit', value='Flash')
        Wire([s2.o, s3.i])
        Wire([s3.o, s4.i])
        Wire([
            amp.o,
            shift_x(amp.o, 50),
            shift(s1.SE, 25,25),
            shift(s2.NW, -25, -25),
            shift_x(s2.W, -25),
            s2.W,
        ])

        # Error correction
        ec = Box(NW=s2.SW, off=(-75, 50), name='Digital Error Correction', w=9, h=1)
        out = Pin(t=shift_x(ec.o, 50), kind='out', name='out', w=2)
        Wire([ec.o, out.t])
        Label(C=shift_x(ec.E, 25), kind='slash', loc='s', name='10')

        w1 = Wire([midpoint(adc.o, dac.i), with_y(midpoint(adc.o, dac.i), ec.N)])
        w2 = Wire([s2.S, with_y(s2.S, ec.N)])
        w3 = Wire([s3.S, with_y(s3.S, ec.N)])
        w4 = Wire([s4.S, with_y(s4.S, ec.N)])
        Label(C=w1.e, yoff=-25, kind='slash', loc='w', name='2', nudge=8)
        Label(C=w2.e, yoff=-25, kind='slash', loc='w', name='2', nudge=8)
        Label(C=w3.e, yoff=-25, kind='slash', loc='w', name='2', nudge=8)
        Label(C=w4.e, yoff=-25, kind='slash', loc='w', name='4', nudge=8)

except Error as e:
    e.report()
except OSError as e:
    error(os_error(e))
../../../_images/pipeline-adc.svg

Receiver (receiver.py)

This block diagram has a white background and so could route the wires underneath the components, but does not. It uses line_width = 2 give the diagram a heavier look. It looks small because it is quite wide, and it is scaled to fit the page.

#!/usr/bin/env python3

from svg_schematic import (
    Schematic, shift_x, shift_y, Amp, Box, Ground, Label, Pin, Source, Wire
)

with Schematic(
    filename = 'receiver.svg',
    font_size = 12,
    font_family = 'sans',
    outline = 'none',
    pad = 20,
    line_width = 2,
) as schematic:

    # Input from horn antenna
    rf_in = Pin(kind='in', name='L-band Horn', w=3)
    Label(C=rf_in.C, yoff=15, loc='w', name='fc=1420MHz', w=3.5, nudge=14)
    Label(C=rf_in.C, yoff=30, loc='w', name='BW=15MHz', w=3.5, nudge=14)

    # First preamp
    rf_preamp1 = Amp(i=rf_in.t, xoff=25, kind='se', name='RF Preamp1')
    Label(C=rf_preamp1.S, loc='s', name='A>=26dB')
    Wire([rf_in.t, rf_preamp1.i])

    # Second preamp
    rf_preamp2 = Amp(i=rf_preamp1.o, xoff=25, kind='se', name='RF Preamp2')
    Label(C=rf_preamp2.S, loc='s', name='A>=26dB')
    Wire([rf_preamp1.o, rf_preamp2.i])

    # RF band-pass filter
    rf_bpf = Box(i=rf_preamp2.o, xoff=25, name='RF BPF')
    l = Label(C=rf_bpf.S, loc='s', name='fc=1380MHz')
    Label(C=l.S, name='BW=320MHz')
    Wire([rf_preamp2.o, rf_bpf.i])

    # First RF amplifier
    rf_amp1 = Amp(i=rf_bpf.o, xoff=25, kind='se', name='RF Amp1')
    Label(C=rf_amp1.S, loc='s', name='A<=20dB')
    Wire([rf_bpf.o, rf_amp1.i])

    # Second RF amplifier
    rf_amp2 = Amp(i=rf_amp1.o, xoff=25, kind='se', name='RF Amp2')
    Label(C=rf_amp2.S, loc='s', name='A<=20dB')
    Wire([rf_amp1.o, rf_amp2.i])

    # RF mixer
    rf_mixer = Source(W=rf_amp2.o, xoff=25, kind='mult')
    Label(C=rf_mixer.N, loc='n', name='DSB')
    Wire([rf_amp2.o, rf_mixer.W])

    # RF local oscillator
    rf_lo = Source(
        p=rf_mixer.S, yoff=50, kind='sine',
        name='fo=1230MHz', value='P=10dBm'
    )
    Ground(t=rf_lo.n)
    Wire([rf_mixer.S, rf_lo.N])

    # IF band-pass filter
    if_bpf = Box(i=rf_mixer.E, xoff=25, name='IF BPF')
    l= Label(C=if_bpf.S, loc='s', name='fc=190MHz')
    Label(C=l.S, name='BW=22MHz')
    Wire([rf_mixer.E, if_bpf.i])

    # IF amplifier
    if_amp = Amp(i=if_bpf.o, xoff=25, name='IF Amp')
    Label(C=if_amp.S, loc='s', name='A=20dB')
    Wire([if_bpf.o, if_amp.i])

    # IF mixer
    if_mixer = Source(W=if_amp.o, xoff=20, kind='mult')
    Label(C=if_mixer.N, loc='n', name='SSB')
    Wire([if_amp.o, if_mixer.W])

    # IF local oscillator
    if_lo = Source(
        p=if_mixer.S, yoff=50, kind='sine',
        name='fo=190MHz', value='P=10dBm'
    )
    Ground(t=if_lo.n)
    Wire([if_mixer.S, if_lo.p])

    # Baseband low-pass filter
    bb_lpf = Box(i=if_mixer.E, xoff=25, name='BB LPF')
    Label(C=bb_lpf.S, loc='s', name='BW=2MHz (var)')
    Wire([if_mixer.E, bb_lpf.i])

    # Analog-to-digital converter
    adc = Box(i=bb_lpf.o, xoff=25, name='ADC')
    Label(C=adc.S, loc='s', name='Fclk=var')
    Wire([bb_lpf.o, adc.i])

    # Output
    bb_out = Pin(t=adc.o, xoff=50, kind='out', name='out', w=1.5)
    w = Wire([adc.o, bb_out.t])
    Label(C=w.m, kind='slash', loc='s', name='8')
../../../_images/receiver.svg

Network Map (network-map.py)

This is another block diagram.

from svg_schematic import Schematic, Box, Wire, Label, shift_x, shift_y


with Schematic(filename='network-map.svg', line_width=2):
    # work network
    work = Box(w=6.5, h=4.5, stroke_dasharray="4 2")
    Label(C=work.SW, loc='ne', name='work')
    bastion = Box(S=work.S, yoff=-25, w=5.5, h=2, color='lightgray')
    Wire([bastion.E, shift_x(bastion.E, 75)])
    Label(C=bastion.SW, loc='ne', name='bastion')
    www = Box(NE=bastion.N, off=(-12.5, 25), w=2, h=1, color='white', name='www')
    mail = Box(NW=bastion.N, off=(12.5, 25), w=2, h=1, color='white', name='mail')
    dump = Box(SW=bastion.NW, yoff=-25, w=2.5, h=1, name='dump')
    laptop = Box(SE=bastion.NE, yoff=-25, w=2.5, h=1, name='my laptop', stroke_dasharray="2 2")

    # home network
    home = Box(N=work.S, yoff=50, w=6.5, h=2, stroke_dasharray="4 2")
    Label(C=home.SW, loc='ne', name='home')
    laptop = Box(SW=home.SW, off=(25, -25), w=2.5, h=1, color='lightgray', name='my laptop', stroke_dasharray="2 2")
    media = Box(SE=home.SE, off=(-25, -25), w=2.5, h=1, name='media')
    Wire([media.E, shift_x(media.E, 75)])

    # internet
    internet = Wire([shift_x(work.NE, 50), shift_x(home.SE, 50)], line_width=4)
    Label(C=internet.e, loc='s', name='internet')

    # external network
    github = Box(NW=internet.b, off=(50, 25), w=3, h=1, name='github')
    Wire([github.W, shift_x(github.W, -50)])
    cloud = Box(N=github.S, yoff=25, w=3, h=1, name='vps')
    Wire([cloud.W, shift_x(cloud.W, -50)])
    backups = Box(N=cloud.S, yoff=25, w=3, h=1, name='backups')
    Wire([backups.W, shift_x(backups.W, -50)])
    hotspot = Box(N=backups.S, yoff=25, w=3, h=2, stroke_dasharray="4 2")
    Label(C=hotspot.SW, loc='ne', name='a wifi hotspot')
    laptop = Box(C=hotspot.C, w=2, h=1, name='my laptop', stroke_dasharray="2 2")
../../../_images/network-map1.svg