# Modules¶

Lcapy is a Python library for linear circuit analysis. It uses SymPy for symbolic mathematics.

Lcapy can analyse circuits described with netlists using modified nodal analysis. See lcapy.netlist

Alternatively, Lcapy can analyse networks and circuits formed by combining one, two, and three port networks. See lcapy.oneport

For more detailed documentation see http://lcapy.elec.canterbury.ac.nz

lcapy.show_version()

Show versions of Lcapy, SymPy, NumPy, MatplotLib, SciPy, and Python.

## Circuit analysis¶

### Circuit¶

This module provides circuit analysis using modified nodal analysis (MNA).

The circuit is described using netlists, similar to SPICE, but with arbitrary node names (except for the ground node which is labelled 0). The netlists can be loaded from a file or created at run-time. For example:

>>> from lcapy import Circuit
>>> cct = Circuit('''
V_s fred 0
R_a fred 1
R_b 1 0''')


Branch currents and branch voltage differences can be found using the component name as an attribute, for example,

>>> cct.V_s.V.pprint()
>>> cct.R_a.I.pprint()


Nodal voltages (with respect to the ground node) can be found using the node name or number as index, for example,

>>> cct['fred'].V.pprint()
>>> cct[1].V.pprint()


class lcapy.circuit.Circuit(filename=None, netlist=None, allow_anon=False)

The Circuit class is used for describing networks using netlists. Despite the name, it does not require a closed path.

Here’s an example of using the Circuit class:

cct = Circuit(‘’’ V1 1 0 V; down R1 1 2 R; right C1 2 0_2 C; down W 0 0_2; right’‘’)

The directions after the semicolon are hints for drawing the schematic and are ignored for the circuit analysis. The last net is a wire to make the schematic look nice; it is not needed for circuit analysis. Indeed the capacitor could be connected directly to nodes 2 and 0.

The nodes are usually numbers but can be any alphanumeric name including underscores. By default, nodes with underscores are not drawn.

The circuit components are also usually numbered but again they can be any alphanumeric name. They can also have anonymous names, as for the wire in the example. Internally they are enumerated sequentially for each component type: W#1, W#2, etc.

The circuit can be displayed using: cct.draw()

The schematic can be saved to a file using: cct.draw(‘schematic.pdf’)

The transform domain voltages across a component can be found using: cct.V1.V

This is found using modified nodal analysis for each type of independent source in the circuit (AC, DC, transient, noise). Once this is performed, the results are cached until the network is modified.

The transform domain currents through a component can be found using: cct.R1.I

The transform domain nodal voltages with respect to the ground node (0) can be found using: cct[2].V

The time domain voltages and currents are displayed using lowercase attributes v and i. For example, cct.C1.v

Note that the answer assumes that all the dependent sources are zero for t < 0 and that all the inductors and capacitors have no initial currents and voltages. Thus the Heaviside(t) factor should be ignored and replaced with the condition t >= 0.

The impedance between nodes 2 and 0 can be found using: Z = cct.impedance(2, 0)

The open-circuit voltage between nodes 2 and 0 can be found using: Z = cct.Voc(2, 0)

The Thevenin equivalent circuit between nodes 2 and 0 can be found using: thevenin = cct.Thevenin(2, 0)

The s-domain model can be drawn using: cct.s_model().draw()

### Netlist¶

This module provides support for the common aspects of Circuit and Network classes.

class lcapy.netlist.Netlist(filename=None, context=None, allow_anon=False)

This class handles a generic netlist with multiple sources. During analysis, subnetlists are created for each source kind (dc, ac, transient, etc). Since linearity is assumed, superposition is employed.

Idict

Return dictionary of branch currents for each transform domain

Vdict

Return dictionary of node voltages for each transform domain

ac()

Return subnetlist for ac components of independent sources for angular frequency omega.

dc()

Return subnetlist for dc components of independent sources.

get_I(name)

Current through component

get_Vd(Np, Nm=None)

Voltage drop between nodes

get_i(name)

Time-domain current through component

get_vd(Np, Nm=None)

Time-domain voltage drop between nodes

kinds

Return list of transform domain kinds.

laplace()

Return subnetlist for Laplace representations of independent source values.

sub

Return dictionary of subnetlists keyed by transform domain kind. Note, the subnetlists are not created until a specific one is selected.

subcircuits
transient()

Return subnetlist for transient components of independent sources. Note, unlike the similar laplace method, dc and ac components are ignored.

class lcapy.netlist.NetlistMixin(filename=None, context=None, allow_anon=False)

Bases: object

Aparams(N1p, N1m, N2p, N2m)

Create A-parameters for two-port defined by nodes N1p, N1m, N2p, and N2m, where: I1 is the current flowing into N1p and out of N1m I2 is the current flowing into N2p and out of N2m V1 is V[N1p] - V[N1m] V2 is V[N2p] - V[N2m]

Bparams(N1p, N1m, N2p, N2m)

Create B-parameters for two-port defined by nodes N1p, N1m, N2p, and N2m, where: I1 is the current flowing into N1p and out of N1m I2 is the current flowing into N2p and out of N2m V1 is V[N1p] - V[N1m] V2 is V[N2p] - V[N2m]

Gparams(N1p, N1m, N2p, N2m)

Create G-parameters for two-port defined by nodes N1p, N1m, N2p, and N2m, where: I1 is the current flowing into N1p and out of N1m I2 is the current flowing into N2p and out of N2m V1 is V[N1p] - V[N1m] V2 is V[N2p] - V[N2m]

Hparams(N1p, N1m, N2p, N2m)

Create H-parameters for two-port defined by nodes N1p, N1m, N2p, and N2m, where: I1 is the current flowing into N1p and out of N1m I2 is the current flowing into N2p and out of N2m V1 is V[N1p] - V[N1m] V2 is V[N2p] - V[N2m]

Iname(name)
Isc(Np, Nm=None)

Return short-circuit transform-domain current between nodes Np and Nm.

Sparams(N1p, N1m, N2p, N2m)

Create S-parameters for two-port defined by nodes N1p, N1m, N2p, and N2m, where: I1 is the current flowing into N1p and out of N1m I2 is the current flowing into N2p and out of N2m V1 is V[N1p] - V[N1m] V2 is V[N2p] - V[N2m]

Tparams(N1p, N1m, N2p, N2m)

Create T-parameters for two-port defined by nodes N1p, N1m, N2p, and N2m, where: I1 is the current flowing into N1p and out of N1m I2 is the current flowing into N2p and out of N2m V1 is V[N1p] - V[N1m] V2 is V[N2p] - V[N2m]

Vname(name)
Voc(Np, Nm=None)

Return open-circuit transform-domain voltage between nodes Np and Nm.

Yparams(N1p, N1m, N2p, N2m)

Create Y-parameters for two-port defined by nodes N1p, N1m, N2p, and N2m, where: I1 is the current flowing into N1p and out of N1m I2 is the current flowing into N2p and out of N2m V1 is V[N1p] - V[N1m] V2 is V[N2p] - V[N2m]

Zparams(N1p, N1m, N2p, N2m)

Create Z-parameters for two-port defined by nodes N1p, N1m, N2p, and N2m, where: I1 is the current flowing into N1p and out of N1m I2 is the current flowing into N2p and out of N2m V1 is V[N1p] - V[N1m] V2 is V[N2p] - V[N2m]

ac_model(var=omegaExpr(omega))

“Create AC model for specified angular frequency (default omega).

admittance(Np, Nm=None)

Return driving-point admittance between nodes Np and Nm with independent sources killed and initial conditions ignored. Since the result is causal, the frequency domain admittance can be found by substituting j * omega for s.

all_symbols

Return dictionary of symbols defined in the circuit and global symbols.

analyse()
analysis
annotate_current(cpts, var=None, flow=False, pos='')

Annotate specified list of component names cpts with current (or flow). pos specifies where to position the labels.

annotate_voltage(cpts, var=None, pos='')

Annotate specified list of component names cpts with voltage. pos specifies where to position the labels.

augment_node_map(node_map={})

Create a mapping dict for all nodes.

branch_list

Determine list of names of branch elements, e.g., [‘C1’, ‘V1’, ‘R1’, ‘R2’b].

conductance(Np, Nm=None)

Return conductance (inverse resistance) between nodes Np and Nm with independent sources killed. The result is in the AC (omega) domain. See also resistance, reactance, susceptance.

control_sources

Return dictionary of voltage sources required to specify control current for CCVS and CCCS components.

copy()

Create a copy of the netlist

dependent_sources

Return dictionary of dependent sources.

describe()

Print a message describing how circuit is solved.

draw(filename=None, **kwargs)

Draw schematic of netlist.

filename specifies the name of the file to produce. If None, the schematic is displayed on the screen.

Note, if using Jupyter, then need to first issue command %matplotlib inline

kwargs include:

label_ids: True to show component ids label_values: True to display component values draw_nodes: True to show all nodes, False to show no nodes,

‘primary’ to show primary nodes, ‘connections’ to show nodes that connect more than two components, ‘all’ to show all nodes
label_nodes: True to label all nodes, False to label no nodes,
‘primary’ to label primary nodes, ‘alpha’ to label nodes starting with a letter, ‘pins’ to label nodes that are pins on a chip, ‘all’ to label all nodes

style: ‘american’, ‘british’, or ‘european’ scale: schematic scale factor, default 1.0 node_spacing: spacing between component nodes, default 2.0 cpt_size: size of a component, default 1.5 dpi: dots per inch for png files help_lines: distance between lines in grid, default 0.0 (disabled) debug: True to display debug information

elements
equipotential_nodes

Determine nodes connected by wires that are of the same potential. This returns a dictionary keyed by the unique node names with values being lists of nodes of the same potential.

has_ac

Return True if any independent source has an AC component.

has_dc

Return True if any independent source has a DC component.

has_s

Return True if any independent source has an s-domain component.

has_transient

Return True if any independent source has a transient component.

impedance(Np, Nm=None)

Return driving-point impedance between nodes Np and Nm with independent sources killed and initial conditions ignored. Since the result is causal, the frequency domain impedance can be found by substituting j * omega for s.

independent_source_groups(transform=False)

Return dictionary of source groups. Each group is a list of sourcenames that can be analysed at the same time. Noise sources have separate groups since they are assumed to be uncorrelated.

If transform is True, the source values are decomposed into the different transform domains to determine which domains are required. In this case, a source can appear in multiple groups. For example, if a voltage source V1 has a value 10 + 5 * cos(omega * t), V1 will be added to the dc and ac groups.

independent_sources

Return dictionary of independent sources (this does not include implicit sources due to initial conditions).

initialize(cct, time)

Set the initial values for this netlist based on the values computed for netlist cct at specified time.

is_ac

Return True if all independent sources are AC and not an initial value problem.

is_causal

Return True if all independent sources are causal and not an initial value problem (unless all the initial values are zero).

is_dc

Return True if all independent sources are DC and not an initial value problem. The initial value problem may collapse to a DC problem but we cannot prove this yet.

is_ivp

Return True for an initial value problem. This is True if any component that allows initial conditions has them explicitly defined.

is_time_domain

Return True if can analyse in time domain.

isc(Np, Nm=None)

Return short-circuit t-domain current between nodes Np and Nm.

kill(*args)

Return a new circuit with the specified sources killed; i.e., make the voltage sources short-circuits and the current sources open-circuits. To kill initial conditions, specify ICs’. If no sources are specified, all independent sources (including initial conditions) are killed.

kill_except(*args)

Return a new circuit with all but the specified sources killed; i.e., make the voltage sources short-circuits and the current sources open-circuits. If no sources are specified, all independent sources (including initial conditions) are killed.

kill_zero()

Return a new circuit with the independent zero voltage sources and zero current sources killed.

match(pattern)

Return list of components names matching regular expression pattern.

missing_ic

Return components that allow initial conditions but do not have them explicitly defined.

netlist()

Return the current netlist.

node_list

Determine list of sorted unique node names, e.g., [‘0’, ‘1’, ‘2’].

node_map

Create dictionary mapping node names to the unique equipotential node names.

noise_model()

“Create noise model where resistors are converted into a series combination of an ideal resistor and a noise voltage source.

noisy(*args)

Return a new circuit with the specified resistors in series with noise voltage sources

noisy_except(*args)

Return a new circuit with all but the specified resistors in series with noise voltage sources

norton(Np, Nm=None)

Return s-domain Norton model between nodes Np and Nm.

If Np is a component name, create model using the component nodes.

oneport(Np, Nm=None)

Return oneport object between nodes Np and Nm. This might be a Thevenin network, a Norton network, or a single component.

If Np is a component name, create model using the component nodes.

pdb()

Enter the python debugger.

pre_initial_model()

Generate circuit model for determining the pre-initial conditions.

r_model()

“Create resistive equivalent model using companion circuits. This is experimental!

reactance(Np, Nm=None)

Return reactance between nodes Np and Nm with independent sources killed. The result is in the AC (omega) domain. See also conductance, resistance, susceptance.

reactances

Return dictionary of reactances.

remove(name)

Remove specified element or elements specified in list.

renumber(node_map={})

Renumber nodes using specified node_map. If node_map not specified then a mapping is created.

resistance(Np, Nm=None)

Return resistance between nodes Np and Nm with independent sources killed. The result is in the AC (omega) domain. See also conductance, reactance, susceptance.

s_model(var=sExpr(s))

“Create s-domain model.

save(filename)

Save netlist to file.

sch

Generate schematic of subnetlist.

select(kind)

Return new netlist with transform domain kind selected for specified sources in sourcenames.

sim

Generate simulation object.

sources

Return dictionary of all sources (this does not include implicit sources due to initial conditions).

ss

Generate state-space representation.

ss_model()

“Create state-space model by replacing inductors with current sources and capacitors with voltage sources.

state_space_model()

“Create state-space model by replacing inductors with current sources and capacitors with voltage sources.

subs(subs_dict)

Substitute values using dictionary of subsitutions.

super_nodes

Super nodes are nodes linked by voltage sources.

susceptance(Np, Nm=None)

Return susceptance (inverse reactance) between nodes Np and Nm with independent sources killed. The result is in the AC (omega) domain. See also conductance, reactance, resistance.

symbols

Return dictionary of symbols defined in the circuit.

thevenin(Np, Nm=None)

Return s-domain Thevenin oneport model between nodes Np and Nm.

If Np is a component name, create model using the component nodes.

transfer(N1p, N1m, N2p, N2m)

Create s-domain voltage transfer function V2(s) / V1(s) where: V1 is V[N1p] - V[N1m] V2 is V[N2p] - V[N2m]

Note, independent sources are killed and initial conditions are ignored. Since the result is causal, the frequency response can be found by substituting j * omega for s.

twoport(N1p, N1m, N2p, N2m, model='B')

Create s-domain twoport model for two-port defined by nodes N1p, N1m, N2p, and N2m, where: I1 is the current flowing into N1p and out of N1m I2 is the current flowing into N2p and out of N2m V1 is V[N1p] - V[N1m] V2 is V[N2p] - V[N2m]

voc(Np, Nm=None)

Return open-circuit t-domain voltage between nodes Np and Nm.

zeroic

Return True if the initial conditions for all components are zero.

class lcapy.netlist.NetlistNamespace(namespace, netlist)

Bases: object

This class allows elements, nodes, or other namespaces in a heirachical namespace to be accessed by name, via __getattr__.

For example,

>>> a = Circuit('''
... b.L1 1 2'''
>>> a.b.L1.v

draw(filename=None, **kwargs)

Draw schematic of subnetlist.

filename specifies the name of the file to produce. If None, the schematic is displayed on the screen.

Note, if using Jupyter, then need to first issue command %matplotlib inline

kwargs include:

label_ids: True to show component ids label_values: True to display component values draw_nodes:

True to show all nodes, False or ‘none’ to show no nodes, ‘primary’ to show primary nodes, ‘connections’ to show nodes that connect more than two components, ‘all’ to show all nodes
label_nodes:
True to label all nodes, False or ‘none’ to label no nodes, ‘primary’ to label primary nodes, ‘alpha’ to label nodes starting with a letter, ‘pins’ to label nodes that are pins on a chip, ‘all’ to label all nodes

style: ‘american’, ‘british’, or ‘european’ scale: schematic scale factor, default 1.0 node_spacing: spacing between component nodes, default 2.0 cpt_size: size of a component, default 1.5 dpi: dots per inch for png files help_lines: distance between lines in grid, default 0.0 (disabled) debug: True to display debug information

netlist()

Return the current netlist for this namespace.

sch

Generate schematic for this namespace.

class lcapy.netlist.Node(cct, name)
V

Node voltage with respect to ground.

admittance

Driving-point admittance between node and ground.

append(cpt)
impedance

Driving-point impedance between node and ground.

norton(node=0)

Create Norton oneport object with respect to specified node (default ground).

oneport(node=0)

Create oneport object with respect to specified node (default ground).

thevenin(node=0)

Create Thevenin oneport object with respect to specified node (default ground).

v

Node time-domain voltage with respect to ground.

class lcapy.netlist.SubNetlist(netlist, kind)

This is a representation of a netlist for a particular transformation domain, such as ac, dc, transient, or noise.

get_I(name)

Current through component

get_Vd(Np, Nm=None)

Voltage drop between nodes

get_i(name)

Time-domain current through component

get_vd(Np, Nm=None)

Time-domain voltage drop between nodes

class lcapy.netlist.Transformdomains

Bases: dict

### Netfile¶

class lcapy.netfile.NetfileMixin

Bases: object

add(string)

Add a component to the netlist. The general form is: ‘Name Np Nm args’ where Np is the positive node and Nm is the negative node.

A positive current is defined to flow from the positive node to the negative node.

netfile_add(filename)

Add the nets from file with specified filename

### MNA¶

This module implements modified nodal analysis (MNA).

class lcapy.mna.Branchdict
class lcapy.mna.MNAMixin

Bases: object

This class performs modified nodal analysis (MNA) on a netlist of components. There are several variants:

1. DC analysis if all the independent sources are DC. The .V and .I methods return DC expressions with the dc assumption set.

2. AC analysis if all the independent sources are AC. The .V and .I methods return phasors.

3. Initial value Laplace analysis if an L or C has an explicit initial value. The .V and .I methods return s-domain expressions with no assumption sets; thus the time-domain results are only valid for t >= 0.

4. General Laplace analysis. If all the sources are causal and all the initial conditions are zero (explicitly or implicitly) then the time-domain results are causal.

1. Noise analysis.

It is assumed that the use of this class uses superposition to solve problems with mixed independent sources, such as DC and AC.

A

Return A matrix for MNA

Idict

Return dictionary of transform domain branch currents indexed by component name

Vdict

Return dictionary of transform domain node voltages indexed by node name

X

Return X vector (of unknowns) for MNA

ZV

Return Z vector for MNA

equations(inverse=False)

System of equations used to find the unknowns.

If inverse is True, evaluate the Matrix inverse.

class lcapy.mna.Nodedict

### Statespace¶

This module performs state-space analysis.

class lcapy.statespace.StateSpace(cct, node_voltages=True, branch_currents=False)

Bases: object

This converts a circuit to state-space representation.

It can take a long time for a symbolic circuit with many reactive components.

G

System transfer functions.

H

X(s) / U(s)

Lambda

Diagonal matrix of eigenvalues.

M

Modal matrix (eigenvectors of A).

P

Characteristic polynomial (aka system polynomial).

lambda(s) = |s * I - A|

Phi

s-domain state transition matrix.

U

Laplace transform of input vector.

X

Laplace transform of state-variable vector.

Y

Laplace transform of output vector.

characteristic_polynomial()

Characteristic polynomial (aka system polynomial).

lambda(s) = |s * I - A|

eigenvalues

List of eigenvalues, the roots of the characteristic polynomial (equivalent to the poles of Phi(s)).

eigenvalues_dict

Dictionary of eigenvalues, the roots of the characteristic polynomial (equivalent to the poles of Phi(s)). The dictionary values are the multiplicity of the eigenvalues.

For a list of eigenvalues use eigenvalues.

eigenvectors

List of tuples (eigenvalue, multiplicity of eigenvalue, basis of the eigenspace) of A.

g

System impulse responses.

h
output_equations()

System of output equations:

y = C x + D u

where y is the output vector, x is the state vector and u is the input vector.

phi

State transition matrix.

state_equations()

System of first-order differential state equations:

dotx = A x + B u

where x is the state vector and u is the input vector.

### Loopanalysis¶

This module performs loop analysis. It is primarily for showing the equations rather than evaluating them.

class lcapy.loopanalysis.LoopAnalysis(cct)

Bases: object

analyse()
loops()

### Nodalanalysis¶

This module performs nodal analysis. It is primarily for showing the equations rather than for evaluating them.

class lcapy.nodalanalysis.NodalAnalysis(cct)

Bases: object

This is an experimental class for nodal analysis. The API is likely to change.

>>> from lcapy import Circuit, NodalAnalysis
>>> cct = Circuit('''
... V1 1 0 {u(t)}; down
... R1 1 2; right=2
... L1 2 3; down=2
... W1 0 3; right
... W 1 5; up
... W 2 6; up
... C1 5 6; right=2
...''')


To perform nodal analysis in the Laplace domain:

>>> na = NodalAnalysis(cct.laplace)


To display the system of equations (in matrix form) that needs to be solved:

>>> na.equations().pprint()


To display the equations found by applying KCL at each node:

>>> na.nodal_equations().pprint()

equations()

Return the equations in matrix form.

nodal_equations()

Return the equations found by applying KCL at each node. This is a directory of equations keyed by the node name.

nodes()

### Oneport¶

This module supports simple linear one-port networks based on the following ideal components:

V independent voltage source I independent current source R resistor C capacitor L inductor

These components are converted to s-domain models and so capacitor and inductor components can be specified with initial voltage and currents, respectively, to model transient responses.

One-ports can either be connected in series (+) or parallel (|) to create a new one-port.

class lcapy.oneport.V(Vval)

Bases: lcapy.oneport.VoltageSource

Arbitrary voltage source

class lcapy.oneport.I(Ival)

Bases: lcapy.oneport.CurrentSource

Arbitrary current source

class lcapy.oneport.v(vval)

Bases: lcapy.oneport.VoltageSource

Arbitrary t-domain voltage source

class lcapy.oneport.i(ival)

Bases: lcapy.oneport.CurrentSource

Arbitrary t-domain current source

class lcapy.oneport.R(Rval)

Bases: lcapy.oneport.OnePort

Resistor

resistor = True
class lcapy.oneport.L(Lval, i0=None)

Bases: lcapy.oneport.OnePort

Inductor

Inductance Lval, initial current i0

inductor = True
class lcapy.oneport.C(Cval, v0=None)

Bases: lcapy.oneport.OnePort

Capacitor

Capacitance Cval, initial voltage v0

capacitor = True
class lcapy.oneport.G(Gval)

Bases: lcapy.oneport.OnePort

Conductance

resistor = True
class lcapy.oneport.Y(Yval)

Bases: lcapy.oneport.OnePort

class lcapy.oneport.Z(Zval)

Bases: lcapy.oneport.OnePort

General impedance.

class lcapy.oneport.Vdc(v)

Bases: lcapy.oneport.VoltageSource

DC voltage source (note a DC voltage source of voltage V has an s domain voltage of V / s).

netkeyword = 'dc'
voc
class lcapy.oneport.Vstep(v)

Bases: lcapy.oneport.VoltageSource

Step voltage source (s domain voltage of v / s).

netkeyword = 'step'
class lcapy.oneport.Idc(i)

Bases: lcapy.oneport.CurrentSource

DC current source (note a DC current source of current i has an s domain current of i / s).

isc
netkeyword = 'dc'
class lcapy.oneport.Istep(i)

Bases: lcapy.oneport.CurrentSource

Step current source (s domain current of i / s).

netkeyword = 'step'
class lcapy.oneport.Vac(V, phi=None, omega=None)

Bases: lcapy.oneport.VoltageSource

AC voltage source.

netkeyword = 'ac'
voc
class lcapy.oneport.sV(Vval)

Bases: lcapy.oneport.VoltageSource

Arbitrary s-domain voltage source

netkeyword = 's'
class lcapy.oneport.sI(Ival)

Bases: lcapy.oneport.CurrentSource

Arbitrary s-domain current source

netkeyword = 's'
class lcapy.oneport.Iac(I, phi=0, omega=None)

Bases: lcapy.oneport.CurrentSource

AC current source.

isc
netkeyword = 'ac'
class lcapy.oneport.Vnoise(V, nid=None)

Bases: lcapy.oneport.VoltageSource

Noise voltage source.

is_noisy = True
netkeyword = 'noise'
class lcapy.oneport.Inoise(I, nid=None)

Bases: lcapy.oneport.CurrentSource

Noise current source.

is_noisy = True
netkeyword = 'noise'
class lcapy.oneport.Par(*args)

Bases: lcapy.oneport.ParSer

Parallel class

admittance
height
impedance
width
class lcapy.oneport.Ser(*args)

Bases: lcapy.oneport.ParSer

Series class

Admittance
height
impedance
width
class lcapy.oneport.Xtal(C0, R1, L1, C1)

Bases: lcapy.oneport.OnePort

Crystal

This is modelled as a series R, L, C circuit in parallel with C0 (a Butterworth van Dyke model). Note, harmonic resonances are not modelled.

expand()
class lcapy.oneport.FerriteBead(Rs, Rp, Cp, Lp)

Bases: lcapy.oneport.OnePort

This is modelled as a series resistor (Rs) connected to a parallel R, L, C network (Rp, Lp, Cp).

expand()
class lcapy.oneport.CPE(K, alpha=0.5)

Bases: lcapy.oneport.OnePort

Constant phase element

This has an impedance 1 / (s**alpha * K). When alpha == 0, the CPE is equivalent to a resistor of resistance 1 / K. When alpha == 1, the CPE is equivalent to a capacitor of capacitance K.

When alpha == 0.5 (default), the CPE is a Warburg element.

The phase of the impedance is -pi * alpha / 2.

Note, when alpha is non-integral, the impedance cannot be represented as a rational function and so there are no poles or zeros. So don’t be suprised if Lcapy throws an occasional wobbly.

lcapy.oneport.series(*args)

Create a series combination of a number of components. Args that are None are ignored. If there is only one non-None component, return that component.

lcapy.oneport.parallel(*args)

Create a parallel combination of a number of components. Args that are None are ignored. If there is only one non-None component, return that component.

lcapy.oneport.ladder(*args, start_series=True)

Create a ladder oneport network with alternating series and shunt components. If an arg is None, the component is ignored.

ladder(R(1), C(2), R(3)) is equivalent to R(1) + (C(1) | R(3))

ladder(None, R(1), C(2), R(3)) is equivalent to R(1) | (C(1) + R(3))

### Expr¶

This module provides the Expr class. This attempts to create a consistent interface to SymPy’s expressions.

class lcapy.expr.Expr(arg, **assumptions)

Decorator class for sympy classes derived from sympy.Expr

D

Return denominator of rational function. The denominator is chosen so that it is a polynomial.

Ddegree

Return the degree (order) of the denominator of a rational function. This will throw an exception if the expression is not a rational function.

Note zero has a degree of -inf.

K

Return gain.

N

Return numerator of rational function. The denominator is chosen so that it is a polynomial.

Ndegree

Return the degree (order) of the numerator of a rational function. This will throw an exception if the expression is not a rational function.

Note zero has a degree of -inf.

ZPK()

Convert to zero-pole-gain (ZPK) form (factored form). For example,

5 * (s + 1)**2 / ((s - 2 * j) * (s + 2 * j))

Note, both the numerator and denominator are expressed as products of monic factors, i.e., (s + 1 / 3) rather than (3 * s + 1).

abs

Return magnitude

angle

Return phase angle

approximate_fractional_power(order=2)

This is an experimental method to approximate s**a, where a is fractional, with a rational function using a Pade approximant.

as_N_D(monic_denominator=False)

Responses due to a sum of delayed transient responses cannot be factored into ZPK form with a constant delay. For example, sometimes SymPy gives:

⎛ s⋅τ ⎞ -s⋅τ ⎝V₁⋅ℯ - V₂⎠⋅ℯ
I = ────────────────────
s⋅(L⋅s + R)

This method tries to extract the numerator and denominator where the denominator is a polynomial.

N, D = I.as_N_D()

-s⋅τ

N = V₁ - V₂⋅ℯ D = s⋅(L⋅s + R)

as_continued_fraction()

Convert expression into acontinued fraction.

as_continued_fraction_inverse()
as_monic_terms()

Rewrite terms so that each denominator is monic.

This does not expand the expression first; use .expand().

as_nonmonic_terms()

Rewrite terms so that each denominator is not monic.

This does not expand the expression first; use .expand().

as_sum()

Responses due to a sum of delayed transient responses cannot be factored into ZPK form with a constant delay. For example, sometimes SymPy gives:

⎛ s⋅τ ⎞ -s⋅τ ⎝V₁⋅ℯ - V₂⎠⋅ℯ
I = ────────────────────
s⋅(L⋅s + R)

While this cannot be factored into ZPK form, it can be expressed as a sum of ZPK forms or as a partial fraction expansion. However, SymPy does not play ball if trying to express as a sum of terms:

I.as_ordered_terms()

⎡⎛ s⋅τ ⎞ -s⋅τ⎤ ⎢⎝V₁⋅ℯ - V₂⎠⋅ℯ ⎥ ⎢────────────────────⎥ ⎣ s⋅(L⋅s + R) ⎦

Instead, it appears necessary to split into N / D where D is a polynomial. Then N can be split.

canonical(factor_const=False)

Convert rational function to canonical form (aka polynomial form); this is like general form but with a unity highest power of denominator. For example,

(5 * s**2 + 5 * s + 5) / (s**2 + 4)

If factor_const is True, factor constants from numerator, for example,

5 * (s**2 + s + 1) / (s**2 + 4)

This is also called gain-polynomial form.

cartesian

Return in Cartesian format

causal
coeffs(norm=False)

Return list of coeffs assuming the expr is a polynomial in s. The highest powers come first. This will fail for a rational function. Instead use expr.N.coeffs or expr.D.coeffs for numerator or denominator respectively.

If norm is True, normalise coefficients to highest power is 1.

conjugate

Return complex conjugate.

continued_fraction_coeffs()
continued_fraction_inverse_coeffs()
copy()

Copy the expression.

dB

Return magnitude in dB.

debug()

Print the SymPy epxression and the assumptions for all symbols in the expression.

degree

Return the degree (order) of the rational function.

This the maximum of the numerator and denominator degrees. Note zero has a degree of -inf.

denominator

Return denominator of rational function. The denominator is chosen so that it is a polynomial.

diff(arg=None)
differentiate(arg=None)
divide_top_and_bottom(factor)

Divide numerator and denominator by common factor.

domain_label
evalf(n=15, *args, **kwargs)

Convert constants in an expression to floats, evaluated to n decimal places. If the expression is a constant, return the floating point result.

See sympy.evalf for more details.

evaluate(arg=None)

Evaluate expression at arg. arg may be a scalar, or a vector. The result is of type float or complex.

There can be only one or fewer undefined variables in the expression. This is replaced by arg and then evaluated to obtain a result.

expandcanonical()

Expand in terms for different powers with each term expressed in canonical form. For example,

s / (s**2 + 4) + 5 / (s**2 + 4)

factor_const()
factored()

Convert to factored form. For example,

5 * (s + 1)**2 / ((s - 2 * j) * (s + 2 * j))

This is an alias for ZPK. See also canonical, general, standard, partfrac, and timeconst.

floatrat()

This converts floating point numbers to rational numbers in an expression. See also ratfloat.

For example, 0.2 * t - > t / 5

func

Return the top-level function in the Sympy Expression.

For example, this returns Mul for the expression 3 * s. See also .args(), to return the args, in this case (3, s)

general()

Convert rational function to general form. For example,

(5 * s**2 + 10 * s + 5) / (s**2 + 4)

has(*patterns)

Test whether any subexpressions matches any of the patterns. For example, V.has(exp(t)) V.has(t)

has_symbol(sym)

Test if have symbol contained. For example, V.has_symbol(‘a’) V.has_symbol(t)

imag

Return imaginary part.

infer_assumptions()
integrate(arg=None, **kwargs)
is_ac
is_causal
is_complex
is_conditional

Return True if expression has a condition, such as t >= 0.

is_constant
is_dc
is_number
is_rational_function

Return True if expression is a rational function.

is_strictly_proper

Return True if the degree of the dominator is greater than the degree of the numerator. This will throw an exception if the expression is not a rational function.

label
limit(var, value, dir='+')

Determine limit of expression(var) at var = value. If dir == ‘+’ search from right else if dir == ‘-‘ search from left.

magnitude

Return magnitude

merge_assumptions(**assumptions)
mixedfrac()

This is an alias for standard and may be deprecated.

multiply_top_and_bottom(factor)

Multiply numerator and denominator by common factor.

normcoeffs()

Return list of coeffs (normalised so the highest power is 1) assuming the expr is a polynomial in s. The highest powers come first. This will fail for a rational function. Instead use expr.N.normcoeffs or expr.D.normcoeffs for numerator or denominator respectively.

numerator

Return numerator of rational function. The denominator is chosen so that it is a polynomial.

one_sided = False
parallel(x)

Parallel combination

partfrac(combine_conjugates=False, damping=None)

Convert rational function into partial fraction form. For example,

5 + (5 - 15 * j / 4) / (s + 2 * j) + (5 + 15 * j / 4) / (s - 2 * j)

If combine_conjugates is True then the pair of partial fractions for complex conjugate poles are combined.

phase

phase_degrees

Return phase in degrees.

polar

Return in polar format

poles(aslist=False, damping=None)

Return poles of expression as a dictionary Note this may not find them all.

prune_HOT(degree)

Prune higher order terms if expression is a polynomial so that resultant approximate expression has the desired degree.

ratfloat()

This converts rational numbers in an expression to floats. See also floatrat.

For example, t / 5 -> 0.2 * t

rationalize_denominator()

Rationalize denominator by multiplying numerator and denominator by complex conjugate of denominator.

real

Return real part.

real_imag

Rewrite as x + j * y

recippartfrac(combine_conjugates=False, damping=None)

Convert rational function into partial fraction form using reciprocal of variable.

For example, if H = 5 * (s**2 + 1) / (s**2 + 5*s + 4) then H.recippartfrac() gives 5/4 - 10/(3*(1 + 1/s)) + 85/(48*(1/4 + 1/s))

If combine_conjugates is True then the pair of partial fractions for complex conjugate poles are combined.

replace(query, value, map=False, simultaneous=True, exact=None)
roots(aslist=False)

Return roots of expression as a dictionary Note this may not find them all.

sign

Return sign

simplify()

Simplify expression.

simplify_factors()

Simplify factors in expression individually.

simplify_terms()

Simplify terms in expression individually.

solve(*symbols, **flags)
standard()

Convert rational function into mixed fraction form. For example,

(5 * s - 5) / (s**2 + 4) + 5

This is the sum of strictly proper rational function and a polynomial.

subs(*args, **kwargs)

Substitute variables in expression, see sympy.subs for usage.

symbols

Return dictionary of symbols in the expression keyed by name.

term_const()
timeconst()

Convert rational function into time constant form. For example,

5 * (s**2 + 2 * s + 1) / (4 * (s**2 / 4 + 1))

timeconst_terms()

Convert each term of expression into time constant form.

transform(arg, **assumptions)

Transform into a different domain.

If arg is f, s, t, omega, jomega perform domain transformation, otherwise perform substitution.

Note (5 * s)(omega) will fail since 5 * s is assumed not to be causal and so Fourier transform is unknown. However, Zs(5 * s)(omega) will work since Zs is assumed to be causal.

val

Return floating point value of expression if it can be evaluated, otherwise the expression.

var = None
zeros(aslist=False)

Return zeroes of expression as a dictionary Note this may not find them all.

class lcapy.expr.ExprContainer

Bases: object

evaluate()

Evaluate each element to convert to floating point.

simplify()

Simplify each element.

symbols

Return dictionary of symbols in the expression keyed by name.

class lcapy.expr.ExprDict

Bases: lcapy.expr.ExprPrint, lcapy.expr.ExprContainer, lcapy.expr.ExprMisc, collections.OrderedDict

Decorator class for dictionary created by sympy.

evaluate()

Evaluate each element to convert to floating point. The keys are also converted if possible to handle dictionaries of poles/zeros.

simplify()

Simplify each element but not the keys.

subs(*args, **kwargs)

Substitute variables in expression, see sympy.subs for usage.

class lcapy.expr.ExprList(iterable, evalf=False)

Decorator class for list created by sympy.

subs(*args, **kwargs)

Substitute variables in expression, see sympy.subs for usage.

class lcapy.expr.ExprMisc

Bases: object

pdb()

Enter the python debugger.

class lcapy.expr.ExprPrint

Bases: object

latex(**kwargs)

Make latex string.

latex_math(**kwargs)

Make latex math-mode string.

latexans(name, **kwargs)

Print latex string with LHS name.

pprint(**kwargs)

Pretty print

pprintans(name, **kwargs)

Pretty print string with LHS name.

pretty(**kwargs)

Make pretty string.

prettyans(name, **kwargs)

Make pretty string with LHS name.

class lcapy.expr.ExprTuple

Bases: lcapy.expr.ExprPrint, tuple, lcapy.expr.ExprContainer, lcapy.expr.ExprMisc

Decorator class for tuple created by sympy.

subs(*args, **kwargs)

Substitute variables in expression, see sympy.subs for usage.

lcapy.expr.expr(arg, **assumptions)

Create Lcapy expression from arg.

If arg is a string:
If a t symbol is found in the string a tExpr object is created. If a s symbol is found in the string a sExpr object is created. If a f symbol is found in the string an fExpr object is created. If an omega symbol is found in the string an omegaExpr object is created.

For example, v = expr(‘3 * exp(-t / tau) * u(t)’)

V = expr(‘5 * s’, causal=True)

lcapy.expr.symbol(name, **assumptions)

Create an Lcapy symbol.

By default, symbols are assumed to be positive unless real is defined or positive is defined as False.

lcapy.expr.symbols(names, **assumptions)

Create Lcapy symbols from whitespace or comma delimiter string of symbol names. See also symbol.

### Sexpr¶

This module provides the sExpr class to represent s-domain (Laplace domain) expressions.

class lcapy.sexpr.Hs(val, **assumptions)

Bases: lcapy.sexpr.sExpr

s-domain ratio

quantity = 's-ratio'
units = ''
class lcapy.sexpr.Is(val, **assumptions)

Bases: lcapy.sexpr.sExpr

s-domain current (units A s / radian).

cpt()
quantity = 's-Current'
superkind = 'Current'
units = 'A/Hz'
class lcapy.sexpr.Vs(val, **assumptions)

Bases: lcapy.sexpr.sExpr

s-domain voltage (units V s / radian).

cpt()
quantity = 's-Voltage'
superkind = 'Voltage'
units = 'V/Hz'
class lcapy.sexpr.Ys(val, causal=True, **assumptions)

Bases: lcapy.sexpr.sExpr

cpt()
network(form='default')

Synthesise a network with an equivalent impedance. form includes: cauerI, cauerII, fosterI, fosterII.

Note some methods generate networks with negative value components.

quantity = 'Admittance'
units = 'siemens'
class lcapy.sexpr.Zs(val, causal=True, **assumptions)

Bases: lcapy.sexpr.sExpr

s-domain impedance value.

cpt()
network(form='default')

Synthesise a network with an equivalent impedance. form includes: cauerI, cauerII, fosterI, fosterII.

Note some methods generate networks with negative value components.

quantity = 'Impedance'
units = 'ohms'
lcapy.sexpr.zp2tf(zeros, poles, K=1, var=None)

Create a transfer function from lists of zeros and poles, and from a constant gain.

lcapy.sexpr.tf(numer, denom=1, var=None)

Create a transfer function from lists of the coefficient for the numerator and denominator.

### Cexpr¶

class lcapy.cexpr.Vconst(val, **assumptions)

Bases: lcapy.cexpr.cExpr

cpt()
superkind = 'Voltage'
time(**assumptions)
class lcapy.cexpr.Iconst(val, **assumptions)

Bases: lcapy.cexpr.cExpr

cpt()
superkind = 'Current'
time(**assumptions)

### Texpr¶

This module provides the tExpr class to represent time domain expressions.

class lcapy.texpr.Ht(val, **assumptions)

Bases: lcapy.texpr.tExpr

impulse response

quantity = 'Impulse response'
units = '1/s'
class lcapy.texpr.It(val, **assumptions)

Bases: lcapy.texpr.tExpr

t-domain current (units A).

cpt()
quantity = 'Current'
superkind = 'Current'
units = 'A'
class lcapy.texpr.Vt(val, **assumptions)

Bases: lcapy.texpr.tExpr

t-domain voltage (units V).

cpt()
quantity = 'Voltage'
superkind = 'Voltage'
units = 'V'
class lcapy.texpr.Yt(val, **assumptions)

Bases: lcapy.texpr.tExpr

units = 'siemens/s'
class lcapy.texpr.Zt(val, **assumptions)

Bases: lcapy.texpr.tExpr

t-domain ‘impedance’ value.

units = 'ohms/s'

### Fexpr¶

This module provides the fExpr class to represent f-domain (Fourier domain) expressions.

class lcapy.fexpr.Hf(val, **assumptions)

f-domain transfer function response.

quantity = 'Transfer function'
units = ''
class lcapy.fexpr.If(val, **assumptions)

f-domain current (units A/Hz).

quantity = 'Current spectrum'
superkind = 'Current'
units = 'A/Hz'
class lcapy.fexpr.Vf(val, **assumptions)

f-domain voltage (units V/Hz).

quantity = 'Voltage spectrum'
superkind = 'Voltage'
units = 'V/Hz'
class lcapy.fexpr.Yf(val, **assumptions)

quantity = 'Admittance'
units = 'siemens'
class lcapy.fexpr.Zf(val, **assumptions)

f-domain impedance

quantity = 'Impedance'
units = 'ohms'
class lcapy.fexpr.fExpr(val, **assumptions)

Fourier domain expression or symbol.

IFT(**assumptions)

Convert to t-domain. This is an alias for inverse_fourier.

domain_name = 'Frequency'
domain_units = 'Hz'
inverse_fourier(evaluate=True, **assumptions)

Attempt inverse Fourier transform.

laplace(**assumptions)

Determine one-side Laplace transform with 0- as the lower limit.

plot(fvector=None, **kwargs)

Plot frequency response at values specified by fvector. If fvector is a tuple, this sets the frequency limits.

kwargs include: axes - the plot axes to use otherwise a new figure is created xlabel - the x-axis label ylabel - the y-axis label ylabel2 - the second y-axis label if needed, say for mag and phase xscale - the x-axis scaling, say for plotting as ms yscale - the y-axis scaling, say for plotting mV plot_type - ‘dB_phase’, ‘mag-phase’, ‘real-imag’, ‘mag’, ‘phase’, ‘real’, or ‘imag’ in addition to those supported by the matplotlib plot command.

The plot axes are returned.

There are many plotting options, see lcapy.plot and matplotlib.pyplot.plot.

For example:
V.plot(fvector, log_frequency=True) V.real.plot(fvector, color=’black’) V.phase.plot(fvector, color=’black’, linestyle=’–’)

By default complex data is plotted as separate plots of magnitude (dB) and phase.

time(**assumptions)
transform(arg, **assumptions)

Transform into a different domain.

var = f
lcapy.fexpr.fexpr(arg, **assumptions)

Create fExpr object. If arg is fsym return f

### Nexpr¶

This module provides the nExpr class to represent discrete-time expressions.

class lcapy.nexpr.Hn(val, **assumptions)

Bases: lcapy.nexpr.nExpr

impulse response

quantity = 'Impulse response'
units = ''
class lcapy.nexpr.In(val, **assumptions)

Bases: lcapy.nexpr.nExpr

t-domain current (units A).

quantity = 'Current'
units = 'A'
class lcapy.nexpr.Vn(val, **assumptions)

Bases: lcapy.nexpr.nExpr

t-domain voltage (units V).

quantity = 'Voltage'
units = 'V'
class lcapy.nexpr.Yn(val, **assumptions)

Bases: lcapy.nexpr.nExpr

units = 'siemens/s'
class lcapy.nexpr.Zn(val, **assumptions)

Bases: lcapy.nexpr.nExpr

t-domain ‘impedance’ value.

units = 'ohms/s'

### Kexpr¶

This module provides the kExpr class to represent k-domain (discrete Fourier domain) expressions.

class lcapy.kexpr.Hk(val, **assumptions)

f-domain transfer function response.

quantity = 'Transfer function'
units = ''
class lcapy.kexpr.Ik(val, **assumptions)

f-domain current (units A/Hz).

quantity = 'Current spectrum'
units = 'A/Hz'
class lcapy.kexpr.Vk(val, **assumptions)

f-domain voltage (units V/Hz).

quantity = 'Voltage spectrum'
units = 'V/Hz'
class lcapy.kexpr.Yk(val, **assumptions)

quantity = 'Admittance'
units = 'siemens'
class lcapy.kexpr.Zk(val, **assumptions)

f-domain impedance

quantity = 'Impedance'
units = 'ohms'
class lcapy.kexpr.kExpr(val, **assumptions)

Bases: lcapy.seqexpr.seqExpr

Discrete Fourier domain expression or symbol.

IDFT(N=None, evaluate=True)
ZT(**assumptions)
domain_name = 'Frequency'
domain_units = 'Hz'
plot(kvector=None, **kwargs)

Plot frequency response at values specified by kvector. If kvector is a tuple, this sets the frequency limits.

kwargs include: axes - the plot axes to use otherwise a new figure is created xlabel - the x-axis label ylabel - the y-axis label ylabel2 - the second y-axis label if needed, say for mag and phase xscale - the x-axis scaling, say for plotting as ms yscale - the y-axis scaling, say for plotting mV plot_type - ‘dB_phase’, ‘mag-phase’, ‘real-imag’, ‘mag’, ‘phase’, ‘real’, or ‘imag’ in addition to those supported by the matplotlib plot command.

The plot axes are returned.

There are many plotting options, see lcapy.plot and matplotlib.pyplot.plot.

For example:
V.plot(kvector, log_frequency=True) V.real.plot(kvector, color=’black’) V.phase.plot(kvector, color=’black’, linestyle=’–’)

By default complex data is plotted as separate plots of magnitude (dB) and phase.

var = k
lcapy.kexpr.kexpr(arg, **assumptions)

Create kExpr object. If arg is ksym return k

### Zexpr¶

This module provides the zExpr class to represent z-domain expressions.

class lcapy.zexpr.Hz(val, **assumptions)

Bases: lcapy.zexpr.zExpr

z-domain ratio

quantity = 'z-ratio'
units = ''
class lcapy.zexpr.Iz(val, **assumptions)

Bases: lcapy.zexpr.zExpr

z-domain current (units A s / radian).

quantity = 'z-Current'
units = 'A/Hz'
class lcapy.zexpr.Vz(val, **assumptions)

Bases: lcapy.zexpr.zExpr

z-domain voltage (units V s / radian).

quantity = 'z-Voltage'
units = 'V/Hz'
class lcapy.zexpr.Yz(val, causal=True, **assumptions)

Bases: lcapy.zexpr.zExpr

quantity = 'Admittance'
units = 'siemens'
class lcapy.zexpr.Zz(val, causal=True, **assumptions)

Bases: lcapy.zexpr.zExpr

z-domain impedance value.

quantity = 'Impedance'
units = 'ohms'

### Sequence¶

This module handles sequences.

class lcapy.sequence.Sequence(seq, n=None, evaluate=False, var=None)
DTFT(**assumptions)

Convert to Fourier domain using discrete time Fourier transform.

ZT(**assumptions)
as_impulses(var=None)

Convert to discrete-time signal in the form of a weighted sum of delayed impulses. For example, {1, 2, 3} -> ui[n] + 2 * ui[n - 1] + 3 * ui[n - 2]

convolve(h, mode='full')

Convolve with h.

discrete_time_fourier_transform(**assumptions)

Convert to Fourier domain using discrete time Fourier transform.

extent()

Determine extent of the sequence.

For example, Sequence([1, 1]).extent() = 2
Sequence([1, 0, 1]).extent() = 3 Sequence([0, 1, 0, 1]).extent() = 3
latex()
lfilter(b=[], a=[1])

implement digital filter specified by a transfer function. The transfer function is described by a vector b of coefficients for the numerator and a a vector of coefficients for the denominator.

For a FIR filter a = [1].

plot(n=None, **kwargs)

Plot the sequence. If n is not specified, it defaults to the range (-20, 20). n can be a vector of specified instants, a tuple specifing the range, or a constant specifying the maximum value with the minimum value set to 0.

kwargs include: axes - the plot axes to use otherwise a new figure is created xlabel - the x-axis label ylabel - the y-axis label xscale - the x-axis scaling, say for plotting as ms yscale - the y-axis scaling, say for plotting mV in addition to those supported by the matplotlib plot command.

The plot axes are returned.

pretty(**kwargs)
prune()

Remove zeros from ends of sequence.

{0, 0, 1, 2, 3, 0} -> {1, 2, 3}

vals
zeropad(M)

Add M zeros to end of sequence:

For example, with M = 3

{1, 2, 3} -> {1, 2, 3, 0, 0, 0}

### Omegaexpr¶

This module provides the omegaExpr class to represent omega-domain (angular frequency Fourier domain) expressions.

class lcapy.omegaexpr.Homega(val, **assumptions)

omega-domain transfer function response.

quantity = 'Transfer function'
units = ''
class lcapy.omegaexpr.Iomega(val, **assumptions)

quantity = 'Current spectrum'
superkind = 'Current'
units = 'A/rad/s'
class lcapy.omegaexpr.Vomega(val, **assumptions)

quantity = 'Voltage spectrum'
superkind = 'Voltage'
units = 'V/rad/s'
class lcapy.omegaexpr.Yomega(val, **assumptions)

cpt()
quantity = 'Admittance'
units = 'siemens'
class lcapy.omegaexpr.Zomega(val, **assumptions)

omega-domain impedance.

cpt()
quantity = 'Impedance'
units = 'ohms'
class lcapy.omegaexpr.omegaExpr(val, **assumptions)

Fourier domain expression or symbol (angular frequency).

domain_name = 'Angular frequency'
domain_units = 'rad/s'
inverse_fourier()

Attempt inverse Fourier transform.

plot(wvector=None, **kwargs)

Plot angular frequency response at values specified by wvector.

There are many plotting options, see matplotlib.pyplot.plot.

For example:
V.plot(fvector, log_frequency=True) V.real.plot(fvector, color=’black’) V.phase.plot(fvector, color=’black’, linestyle=’–’)

By default complex data is plotted as separate plots of magnitude (dB) and phase.

time()

Alias for inverse_fourier.

transform(arg, **assumptions)

Transform into a different domain.

var = omega
lcapy.omegaexpr.omegaexpr(arg, **assumptions)

Create omegaExpr object. If arg is omegasym return omega

### Noiseexpr¶

class lcapy.noiseexpr.noiseExpr(val, **assumptions)

Frequency domain (one-sided) noise spectrum expression (amplitude spectral density).

This characterises a zero-mean Gaussian noise process.

When performing arithmetic on two noiseExpr expressions it is assumed that they are uncorrelated unless they have the same nid (noise indentifier). If the nid is not specified, a new one is created.

Uncorrelated noise expressions are added in quadrature (on a power basis). Thus (Vnoisy(3) + Vnoisy(4)).expr = 5 since 5 = sqrt(3**2 + 4**2)

Vnoisy(3) != Vnoisy(3) since they are different noise realisations albeit with the same properties. However, Vnoisy(3).expr == Vnoisy(3).expr. Similarly, Vnoisy(3, nid=’n1’) == Vnoisy(3, nid=’n1’) since they have the same noise identifier and thus have the same realisation.

Caution: The sum of two noise expressions generates a noise expression with a new nid. This can lead to unexpected results since noise expressions with different nids are assumed to be uncorrelated. For example, consider: a = Vnoisy(3); b = Vnoisy(4) a + b - b gives sqrt(41) and a + b - a gives sqrt(34).

This case is correctly handled by the Super class since each noise component is stored and considered separately.

(Voltage(a) + Voltage(b) - Voltage(b)).n gives 3 as expected.

autocorrelation()
is_positive = True
is_real = True
laplace()
nid
one_sided = True
plot(fvector=None, **kwargs)

Plot frequency response at values specified by fvector.

There are many plotting options, see matplotlib.pyplot.plot.

For example:
V.plot(fvector, log_frequency=True) V.real.plot(fvector, color=’black’) V.phase.plot(fvector, color=’black’, linestyle=’–’)

By default complex data is plotted as separate plots of magnitude (dB) and phase.

rms()

Calculate rms value.

sample(t)

Return a sample function (realisation) of the noise process evaluated at time values specified by vector t.

subs(*args, **kwargs)
time()

### Phasor¶

This module provides the Phasor class to represent phasors for AC analysis.

A phasor represents the amplitude and phase for a single sinusoid. By default the angular frequency is omega_0 but it can be any number or symbol.

class lcapy.phasor.Vphasor(val, **assumptions)

Bases: lcapy.phasor.Phasor

t-domain voltage (units V) parameterized as a phasor of a single angular frequency, omega0.

cpt()
quantity = 'Voltage'
superkind = 'Voltage'
units = 'V'
class lcapy.phasor.Iphasor(val, **assumptions)

Bases: lcapy.phasor.Phasor

t-domain current (units V) parameterized as a phasor of a single angular frequency, omega0.

cpt()
quantity = 'Current'
superkind = 'Current'
units = 'A'

### Matrix¶

This module implements a wrapper for the SymPy Matrix class.

class lcapy.matrix.Matrix

Bases: sympy.matrices.dense.MutableDenseMatrix

canonical()
det()
inv()
latex(**kwargs)
norm()
pprint()
simplify()
symbols
lcapy.matrix.matrix(mat)

Create Lcapy Matrix from a SymPy Matrix.

If a t symbol is found in an element a tMatrix object is created. If a s symbol is found in an element an sMatrix object is created.

lcapy.matrix.msympify(expr)

### Smatrix¶

This module implements the sMatrix class for a matrix of Laplace-domain expressions.

class lcapy.smatrix.sMatrix
ZPK()
canonical()
general()
inverse_laplace(**assumptions)
mixedfrac()
partfrac()
class sExpr(val, **assumptions)

s-domain expression or symbol.

ILT(**assumptions)

Convert to t-domain. This is an alias for inverse_laplace.

angular_frequency_response(wvector=None)

Convert to angular frequency domain and evaluate response if angular frequency vector specified.

backward_euler_transform()

Approximate s = ln(z)

by s = (1 / dt) * (1 - z**-1)

bilinear_transform()

Approximate s = ln(z)

by s = (2 / dt) * (1 - z**-1) / (1 + z**-1)

This is also called Tustin’s method and is equivalent to the trapezoidal method.

delay(T)

Apply delay of T seconds by multiplying by exp(-s T).

differential_equation(input='x', output='y')

Create differential equation from transfer function.

For example, >>> H = (s + 3) / (s**2 + 4) >>> H.differential_equation()

d d
3.y(t) + –(y(t)) = 4.x(t) + —(x(t))
dt 2
dt
evaluate(svector=None)
final_value()

Determine value at t = oo.

forward_euler_transform()

Approximate s = ln(z)

by s = (1 / dt) * (1 - z**-1) / z**-1

fourier(**assumptions)

Convert to Fourier domain.

frequency_response(fvector=None)

Convert to frequency domain and evaluate response if frequency vector specified.

impulse_response(tvector=None)

Evaluate transient (impulse) response.

inverse_laplace(**assumptions)

Attempt inverse Laplace transform.

If causal=True the response is zero for t < 0 and the result is multiplied by Heaviside(t) If ac=True or dc=True the result is extrapolated for t < 0. Otherwise the result is only known for t >= 0.

jomega

Return expression with s = j omega.

laplace(**assumptions)

Convert to s-domain.

parameterize(zeta=True)

Parameterize first and second-order expressions.

For example, pexpr, defs = expr.parameterize()

If parameterization is successful, defs is a dictionary of the paramters. The original expression can be obtained with pexpr.subs(defs)

For first order systems, parameterize as:

K * (s + beta) / (s + alpha)

K / (s + alpha)

K (s + beta)

where appropriate.

If zeta is True, parameterize second-order expression in standard form using damping factor and natural frequency representation, i.e.

N(s) / (s**2 + 2 * zeta * omega_0 * s + omega_0**2)

otherwise parameterize as

N(s) / (s**2 + 2 * sigma_1 * s + omega_1**2 + sigma_1**2)

phasor(**assumptions)
plot(t=None, **kwargs)

Plot pole-zero map.

post_initial_value()

Determine post-initial value at t = 0+.

response(x, t)

Evaluate response to input signal x at times t.

step_response(tvector=None)

Evaluate step response.

tdifferentiate()

Differentiate in t-domain (multiply by s).

time(**assumptions)

Convert to time domain.

tintegrate()

Integrate in t-domain (divide by s).

transform(arg, **assumptions)

Transform into a different domain.

transient_response(tvector=None)

Evaluate transient (impulse) response.

var = s
timeconst()

### Tmatrix¶

This module implements the tMatrix class for a matrix of time-domain expressions.

class lcapy.tmatrix.tMatrix
laplace()
class tExpr(val, **assumptions)

t-domain expression or symbol.

FT(**assumptions)

Convert to f-domain. This is an alias for fourier.

LT(**assumptions)

Convert to s-domain. This is an alias for laplace.

convolve(impulseresponse, commutate=False, **assumptions)

Convolve self with impulse response.

domain_name = 'Time'
domain_units = 's'
final_value()

Determine value at t = oo.

force_causal()

Remove the piecewise condition from the expression and multiply by Heaviside function. See also remove_condition.

fourier(evaluate=True, **assumptions)

Attempt Fourier transform.

infer_assumptions()
initial_value()

laplace(evaluate=True, **assumptions)

Determine one-sided Laplace transform with 0- as the lower limit.

phasor(**assumptions)
plot(t=None, **kwargs)

Plot the time waveform. If t is not specified, it defaults to the range (-0.2, 2). t can be a vector of specified instants, a tuple specifing the range, or a constant specifying the maximum value with the minimum value set to 0.

kwargs include: axes - the plot axes to use otherwise a new figure is created xlabel - the x-axis label ylabel - the y-axis label xscale - the x-axis scaling, say for plotting as ms yscale - the y-axis scaling, say for plotting mV in addition to those supported by the matplotlib plot command.

The plot axes are returned.

post_initial_value()

pre_initial_value()

remove_condition()

sample(t)

Return a discrete-time signal evaluated at time values specified by vector t.

var = t

### Network¶

class lcapy.network.Network

Bases: object

This is the base class for network objects.

all_symbols

Return dictionary of symbols defined in the network and global symbols.

analysis
capacitor = False
cct

Convert a Network object into a Circuit object.

circuit()

Convert a Network object into a Circuit object.

current_source = False
describe()

Print a message describing how network is solved.

draw(filename=None, form='horizontal', **kwargs)

Draw schematic of network.

filename specifies the name of the file to produce. If None, the schematic is displayed on the screen.

Note, if using Jupyter, then need to first issue command %matplotlib inline

form is either ‘horizontal’, ‘vertical’, or ‘ladder’.

kwargs include:

label_ids: True to show component ids label_values: True to display component values draw_nodes: True to show all nodes, False to show no nodes,

‘primary’ to show primary nodes, ‘connections’ to show nodes that connect more than two components, ‘all’ to show all nodes
label_nodes: True to label all nodes, False to label no nodes,
‘primary’ to label primary nodes, ‘alpha’ to label nodes starting with a letter, ‘pins’ to label nodes that are pins on a chip, ‘all’ to label all nodes

style: ‘american’, ‘british’, or ‘european’ scale: schematic scale factor, default 1.0 node_spacing: spacing between component nodes, default 2.0 cpt_size: size of a component, default 1.5 dpi: dots per inch for png files help_lines: distance between lines in grid, default 0.0 (disabled) debug: True to display debug information

has_ac
has_dc
has_transient
hasic = None
inductor = False
initial_value_problem
is_ac
is_causal
is_dc
is_ivp
kinds

Return list of transform domain kinds.

latex(**kwargs)
netkeyword = ''
netlist(form='horizontal')

Create a netlist.

form can be ‘horizontal’, ‘vertical’, or ‘ladder’.

netname = ''
pdb()

Enter the python debugger.

pretty(**kwargs)
resistor = False
sch(form)

Convert a Network object into a Schematic object.

simplify()
symbols

Return dictionary of symbols defined in the network.

transform(form='causerI')

Transform the network into an alternative form. The transformation is performed using network synthesis of the network’s impedance (note, this ignores the sources). form includes: cauerI, cauerII, fosterI, fosterII.

Note some methods generate networks with negative value components.

voltage_source = False
zeroic = True

### Voltage¶

This module provides the Voltage class. This represents voltages as a superposition in different transform domains.

For example, the following expression is a superposition of a DC component, an AC component, and a transient component:

V1 = Voltage(‘1 + 2 * cos(2 * pi * 3 * t) + 3 * u(t)’)

V1(t) returns the time domain expression V1(s) returns the Laplace domain expression V1(omega) returns the Fourier domain expression with angular frequency V1(f) returns the Fourier domain expression with linear frequency

V1.dc returns the DC component V1.ac returns a dictionary of the AC components, keyed by the frequency V1.transient returns the time-domain transient component

V1.is_dc returns True if a pure DC signal V1.is_ac returns True if a pure AC signal V1.is_transient returns True if a pure transient signal V1.has_dc returns True if has a DC signal V1.has_ac returns True if has an AC signal V1.has_transient returns True if has a transient signal

lcapy.voltage.Vname(name, kind, cache=False)
class lcapy.voltage.Voltage(*args, **kwargs)
cpt()
lcapy.voltage.Vtype(kind)

### Current¶

This module provides the Current class. This represents currents as a superposition in different transform domains.

For example, the following expression is a superposition of a DC component, an AC component, and a transient component:

I1 = Current(‘1 + 2 * cos(2 * pi * 3 * t) + 3 * u(t)’)

I1(t) returns the time domain expression I1(s) returns the Laplace domain expression I1(omega) returns the Fourier domain expression with angular frequency I1(f) returns the Fourier domain expression with linear frequency

I1.dc returns the DC component I1.ac returns a dictionary of the AC components, keyed by the frequency I1.transient returns the time-domain transient component

I1.is_dc returns True if a pure DC signal I1.is_ac returns True if a pure AC signal I1.is_transient returns True if a pure transient signal I1.has_dc returns True if has a DC signal I1.has_ac returns True if has an AC signal I1.has_transient returns True if has a transient signal

class lcapy.current.Current(*args, **kwargs)
cpt()
lcapy.current.Iname(name, kind, cache=False)
lcapy.current.Itype(kind)

### Super¶

This module provides the Super class. It is the base class for Current and Voltage. It represents voltages and currents as a superposition in different transform domains.

class lcapy.super.Super(*args, **kwargs)

This class represents a superposition of different signal types, DC, AC, transient, and noise.

The time-domain representation is returned with the time method, V.time(), or with the notation V(t). This does not include the noise component.

The Laplace representation is returned with the laplace method, V.laplace() or with the notation V(s). This does not include the noise component.

Noise components with different noise identifiers are stored separately, keyed by the noise identifier. They are ignored by the laplace() and time() methods.

The total noise can be accessed with the .n attribute. This sums each of the noise components in quadrature since they are independent.

For example, consider V = Voltage(‘cos(3 * t) + exp(-4 * t) + 5’)

str(V(t)) gives ‘cos(3*t) + 5 + exp(-4*t)’

str(V(s)) gives ‘s/(9*(s**2/9 + 1)) + 1/(4*(s/4 + 1)) + 5/s’

V.dc gives 5

V.ac gives {3: 1}

V.s gives 1/(s + 4)

ac

Return the AC components.

ac_keys()

Return list of keys for all ac components.

add(value)

Add a value into the superposition.

canonical()
dc

Return the DC component.

decompose()

Decompose into a new representation in the transform domains.

final_value()

Determine value at t = oo.

fourier(**assumptions)

Convert to Fourier domain.

frequency_response(fvector=None)

Convert to frequency domain and evaluate response if frequency vector specified.

has(subexpr)

Test whether the sub-expression is contained. For example, V.has(exp(t)) V.has(t)

has_ac

True if there is an AC component.

has_dc

True if there is a DC component.

has_n

True if there is a noise component.

has_s

True if have transient component defined in the s-domain.

has_symbol(sym)

Test if have symbol. For example, V.has_symbol(‘a’) V.has_symbol(t)

has_t

True if have transient component defined in the time-domain.

has_transient

True if have transient component.

initial_value()

is_ac

True if only has AC components.

is_causal
is_dc

True if only has a DC component.

is_n

True if only has noise components.

is_s_transient

True if only has s-domain transient component.

is_superposition
is_t_transient

True if only has t-domain transient component.

is_transient

True if only has transient component(s). Note, should not have both t and s components.

laplace(**assumptions)

Convert to s-domain.

latex(**kwargs)

Latex

n
netval(kind)
noise

Return the total noise.

noise_keys()

Return list of keys for all noise components.

oneport()

Create oneport component.

post_initial_value()

pprint()

Pretty print

pre_initial_value()

s

Return the s-domain representation of the transient component. This is not the full s-domain representation as returned by the laplace method V.laplace() or V(s).

This attribute may be deprecated due to possible confusion.

select(kind)

Select a component of the signal representation by kind where: ‘super’ : the entire superposition ‘time’ : the time domain representation (equivalent to self.time()) ‘laplace’ : the laplace domain representation (equivalent to self.laplace()) ‘ivp’ : the s-domain representation (equivalent to self.laplace()) ‘dc’ : the DC component ‘ac’ : the AC component with angular frequency omega0 omega : the AC component with angular frequency omega ‘s’ : the transient component in the s-domain ‘n’ : the noise component ‘t’ : the time-domain transient component (this may or may not

include the DC and AC components).
simplify()
subs(*args, **kwargs)
symbols

Return dictionary of symbols in the expression keyed by name.

time(**assumptions)

Convert to time domain.

transform(arg, **assumptions)

Transform into a different domain.

transient

Return the transient component.

transient_response(tvector=None)

Evaluate transient (impulse) response.

w

Return the AC component with angular frequency omega0. This should be deprecated.

This module provides the Admittance class. This is a generalized impedance (s-domain) and converts to other representations.

class lcapy.admittance.Admittance(val, kind=None, causal=True, positive=False, **assumptions)

Y(omega) = G(omega) + j * B(omega)

where G is the conductance and B is the susceptance.

Admittance is the reciprocal of impedance,

Z(omega) = 1 / Y(omega)

Y
Yw
Z
Zw
cpt()

network(form='default')

Synthesise a network with an equivalent admittance. form includes: cauerI, cauerII, fosterI, fosterII.

Note some methods generate networks with negative value components.

### Impedance¶

This module provides the Impedance class. This is a generalized impedance (s-domain) and converts to other representations.

class lcapy.impedance.Impedance(val, kind=None, causal=True, positive=False, **assumptions)

Generic impedance class.

Z(omega) = R(omega) + j * X(omega)

where R is the resistance and X is the reactance.

Impedance is the reciprocal of admittance,

Y(omega) = 1 / Z(omega)

Y
Yw
Z
Zw
cpt()

network(form='default')

Synthesise a network with an equivalent impedance. form includes: cauerI, cauerII, fosterI, fosterII.

Note some methods generate networks with negative value components.

### Immittance¶

This module provides the Immittance class, the base class for Admittance and Impedance and the rest of the menagerie.

class lcapy.immitance.Immitance(val, kind=None, causal=True, positive=False, **assumptions)

Bases: lcapy.sexpr.sExpr

B

Susceptance.

G

Conductance.

R

Resistance.

X

Reactance.

abs

Absolute part of Z(omega).

imag

Imaginary part of Z(omega).

new(kind)
oneport()

Create oneport component.

phase

phase_degrees

Phase of Z(omega) (degrees).

real

Real part of Z(omega).

selectexpr(kind=None)
class lcapy.immitance.ImmitanceMixin

Bases: object

B

Susceptance.

G

Conductance.

Note Y = G + j * B = 1 / Z = 1 / (R + j * X) and so G = R / (R**2 + X**2).

Thus for DC, when X = 0, then G = 1 / R and is infinite for R = 0. However, if Z is purely imaginary, i.e, R = 0 then G = 0, not infinity as might be expected.

R

Resistance.

X

Reactance.

Y

Ys

Yw

Z

Impedance.

Zs

Generalized impedance Z(s).

Zw

Impedance Z(omega).

conductance

Conductance.

reactance

Reactance.

resistance

Resistance.

susceptance

Susceptance.

### Functions¶

This module provides functions.

class lcapy.functions.Add

Bases: sympy.core.add.Add

default_assumptions = {}
class lcapy.functions.Eq

Bases: sympy.core.relational.Equality

default_assumptions = {}
class lcapy.functions.Function(arg)

Bases: object

class lcapy.functions.Log10(arg)
class lcapy.functions.MatAdd

Bases: sympy.matrices.expressions.matadd.MatAdd

default_assumptions = {'algebraic': False, 'commutative': False, 'complex': False, 'composite': False, 'even': False, 'extended_negative': False, 'extended_nonnegative': False, 'extended_nonpositive': False, 'extended_nonzero': False, 'extended_positive': False, 'extended_real': False, 'imaginary': False, 'integer': False, 'irrational': False, 'negative': False, 'noninteger': False, 'nonnegative': False, 'nonpositive': False, 'nonzero': False, 'odd': False, 'positive': False, 'prime': False, 'rational': False, 'real': False, 'transcendental': False, 'zero': False}
is_algebraic = False
is_commutative = False
is_complex = False
is_composite = False
is_even = False
is_extended_negative = False
is_extended_nonnegative = False
is_extended_nonpositive = False
is_extended_nonzero = False
is_extended_positive = False
is_extended_real = False
is_imaginary = False
is_integer = False
is_irrational = False
is_negative = False
is_noninteger = False
is_nonnegative = False
is_nonpositive = False
is_nonzero = False
is_odd = False
is_positive = False
is_prime = False
is_rational = False
is_real = False
is_transcendental = False
is_zero = False
class lcapy.functions.MatMul

Bases: sympy.matrices.expressions.matmul.MatMul

default_assumptions = {'algebraic': False, 'commutative': False, 'complex': False, 'composite': False, 'even': False, 'extended_negative': False, 'extended_nonnegative': False, 'extended_nonpositive': False, 'extended_nonzero': False, 'extended_positive': False, 'extended_real': False, 'imaginary': False, 'integer': False, 'irrational': False, 'negative': False, 'noninteger': False, 'nonnegative': False, 'nonpositive': False, 'nonzero': False, 'odd': False, 'positive': False, 'prime': False, 'rational': False, 'real': False, 'transcendental': False, 'zero': False}
is_algebraic = False
is_commutative = False
is_complex = False
is_composite = False
is_even = False
is_extended_negative = False
is_extended_nonnegative = False
is_extended_nonpositive = False
is_extended_nonzero = False
is_extended_positive = False
is_extended_real = False
is_imaginary = False
is_integer = False
is_irrational = False
is_negative = False
is_noninteger = False
is_nonnegative = False
is_nonpositive = False
is_nonzero = False
is_odd = False
is_positive = False
is_prime = False
is_rational = False
is_real = False
is_transcendental = False
is_zero = False
class lcapy.functions.Mul

Bases: sympy.core.mul.Mul

default_assumptions = {}
class lcapy.functions.UnitImpulse

Bases: sympy.core.function.Function

default_assumptions = {'algebraic': True, 'commutative': True, 'complex': True, 'extended_real': True, 'finite': True, 'hermitian': True, 'imaginary': False, 'infinite': False, 'integer': True, 'irrational': False, 'noninteger': False, 'rational': True, 'real': True, 'transcendental': False}
classmethod eval(nval)

Evaluates the discrete unit impulse function.

is_algebraic = True
is_commutative = True
is_complex = True
is_extended_real = True
is_finite = True
is_hermitian = True
is_imaginary = False
is_infinite = False
is_integer = True
is_irrational = False
is_noninteger = False
is_rational = True
is_real = True
is_transcendental = False
class lcapy.functions.UnitStep

Bases: sympy.core.function.Function

default_assumptions = {'algebraic': True, 'commutative': True, 'complex': True, 'extended_real': True, 'finite': True, 'hermitian': True, 'imaginary': False, 'infinite': False, 'integer': True, 'irrational': False, 'noninteger': False, 'rational': True, 'real': True, 'transcendental': False}
classmethod eval(nval)

Evaluates the discrete unit step function.

is_algebraic = True
is_commutative = True
is_complex = True
is_extended_real = True
is_finite = True
is_hermitian = True
is_imaginary = False
is_infinite = False
is_integer = True
is_irrational = False
is_noninteger = False
is_rational = True
is_real = True
is_transcendental = False

### Symbols¶

This module defines special symbols f, s, t, and omega.

### Mnacpts¶

This module defines the components for modified nodal analysis. The components are defined at the bottom of this file.

class lcapy.mnacpts.C(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
C
V0

Initial voltage (for capacitors only).

reactive = True
class lcapy.mnacpts.CCCS(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
need_control_current = True
class lcapy.mnacpts.CCVS(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
need_branch_current = True
need_control_current = True
class lcapy.mnacpts.CPE(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
reactive = True
class lcapy.mnacpts.Cable(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
class lcapy.mnacpts.Cpt(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
I

Current through component. The current is defined to be into the positive node for passive devices and out of the positive node for sources.

I0

Initial current (for inductors only).

Isc

Short-circuit current for component in isolation, i.e, current in wire connected across component.

V

Voltage drop across component.

V0

Initial voltage (for capacitors only).

Voc

Open-circuit voltage for component in isolation.

admittance

Self admittance of component. For the driving-point admittance measured across the component use .dpY or .oneport().Y

branch_index
dependent_source = False
directive = False
dpIsc

Driving-point short-circuit current, i.e, current in wire connected across component connected in-circuit.

dpVoc

Driving-point open-circuit voltage across component in-circuit.

dpY

Driving-point admittance measured across component in-circuit. For the admittance of the component in isolation use .Y

dpYs

Driving-point generalized admittance (s-domain) measured across component in-circuit. For the admittance of the component in isolation use .Ys

dpZ

Driving-point impedance measured across component in-circuit. For the impedance of the component in isolation use .Z

dpZs

Driving-point generalized impedance (s-domain) measured across component in-circuit. For the impedance of the component in isolation use .Zs

dpisc

Driving-point short-circuit time-domain current i.e, current in wire connected across component in-circuit.

dpvoc

Driving-point open-circuit time-domain voltage across component in circuit.

dummy_node()
flip_branch_current = False
has_s

Return True if source has s-domain component.

has_transient

Return True if source has a transient component.

hasic

Return True if initial conditions are specified.

i

Time-domain current through component. The current is defined to be into the positive node for passive devices and out of the positive node for sources.

impedance

Self impedance of component. For the driving-point impedance measured across the component use .dpZ or .oneport().Z

independent_source = False
is_ac

Return True if source is ac.

is_capacitor

Return True if component is a capacitor.

is_causal

Return True if causal component or if source produces a causal signal.

is_current_source

Return True if component is a current source (dependent or independent)

is_dc

Return True if source is dc.

is_inductor

Return True if component is an inductor.

is_noisy

Return True if source is noisy.

is_resistor

Return True if component is a resistor.

is_source

Return True if component is a source (dependent or independent)

is_voltage_source

Return True if component is a voltage source (dependent or independent)

isc

Short-circuit time-domain current for component in isolation, i.e, current in wire connected across component.

need_branch_current = False
need_control_current = False
need_extra_branch_current = False
node_indexes
norton()

Create Norton oneport object.

oneport()

Create oneport object.

reactive = False
thevenin()

Create Thevenin oneport object.

v

Time-domain voltage drop across component.

voc

Open-circuit time-domain voltage for component in isolation.

zeroic

Return True if initial conditions are zero (or unspecified).

class lcapy.mnacpts.DependentSource(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
dependent_source = True
class lcapy.mnacpts.Dummy(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
ac = False
causal = True
dc = False
hasic = None
noisy = False
zeroic = True
class lcapy.mnacpts.FB(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)

class lcapy.mnacpts.GY(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)

Gyrator

need_branch_current = True
need_extra_branch_current = True
class lcapy.mnacpts.I(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
class lcapy.mnacpts.IndependentSource(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
independent_source = True
class lcapy.mnacpts.Invalid(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
cpt
class lcapy.mnacpts.K(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
class lcapy.mnacpts.L(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
I0

Initial current (for capacitors only).

L
need_branch_current = True
reactive = True
class lcapy.mnacpts.Logic(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
class lcapy.mnacpts.Misc(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
class lcapy.mnacpts.NonLinear(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
class lcapy.mnacpts.O(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)

Open circuit

I
i
class lcapy.mnacpts.P(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)

Port

class lcapy.mnacpts.R(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
class lcapy.mnacpts.RC(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
class lcapy.mnacpts.RLC(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
class lcapy.mnacpts.RV(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
class lcapy.mnacpts.SPpm(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
need_branch_current = True
class lcapy.mnacpts.SPpmm(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
need_branch_current = True
class lcapy.mnacpts.SPpp(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
need_branch_current = True
class lcapy.mnacpts.SPppm(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
need_branch_current = True
class lcapy.mnacpts.SPppp(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
need_branch_current = True
class lcapy.mnacpts.TF(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)

Transformer

need_branch_current = True
class lcapy.mnacpts.TFtap(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)

Tapped transformer

class lcapy.mnacpts.TL(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)

Transmission line

class lcapy.mnacpts.TP(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)

Two port

class lcapy.mnacpts.TR(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)

Transfer function. This is equivalent to a VCVS with the input and output referenced to node 0.

need_branch_current = True
class lcapy.mnacpts.TimeVarying(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
class lcapy.mnacpts.V(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
flip_branch_current = True
need_branch_current = True
class lcapy.mnacpts.VCCS(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
class lcapy.mnacpts.VCVS(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
need_branch_current = True
class lcapy.mnacpts.W(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)

Wire

I
i
class lcapy.mnacpts.XT(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)

Crystal

reactive = True
class lcapy.mnacpts.XX(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)
directive = True
class lcapy.mnacpts.Y(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)

reactive = True
class lcapy.mnacpts.Z(cct, namespace, defname, name, cpt_type, cpt_id, string, opts_string, nodes, keyword, *args)

Impedance

reactive = True
lcapy.mnacpts.cls

alias of lcapy.mnacpts.Z

lcapy.mnacpts.defcpt(name, base, docstring)
lcapy.mnacpts.make(classname, parent, name, cpt_type, cpt_id, string, opts_string, nodes, *args)

### Laplace¶

This module provides support for Laplace transforms. It acts as a wrapper for SymPy’s Laplace transform. It calculates the unilateral Laplace transform using:

F(s) = lim_{t_0

ightarrow 0} int_{-t_0}^{infty} f(t) e^{-s t} dt

In comparison, SymPy uses:

F(s) = int_{0}^{infty} f(t) e^{-s t} dt

The latter gives 0.5 for the Laplace transform of DiracDelta(t) whereas the former version gives 1. Note, SymPy is inconsistent in that it gives DiracDelta(t) for the inverse Laplace transform of 1.

Another difference with this implementation is that it will transform undefined functions such as v(t) to V(s).

These functions are for internal use by Lcapy.

lcapy.laplace.LT(expr, t, s, **assumptions)

Compute unilateral Laplace transform of expr with lower limit 0-.

Undefined functions such as v(t) are converted to V(s).

lcapy.laplace.ILT(expr, s, t, **assumptions)

Calculate inverse Laplace transform of X(s) and return x(t).

The unilateral Laplace transform cannot determine x(t) for t < 0 unless given additional information in the way of assumptions.

The assumptions are: dc – x(t) = constant so X(s) must have the form constant / s causal – x(t) = 0 for t < 0. ac – x(t) = A cos(a * t) + B * sin(b * t)

### Fourier¶

This module provides support for Fourier transforms. It acts as a wrapper for SymPy’s Fourier transform. It calculates the bilateral Fourier transform using:

S(f) = int_{-infty}^{infty} s(t) e^{-j * 2 * pi * t} dt

It also allows functions that strictly do not have a Fourier transform by using Dirac deltas. For example, a, cos(a * t), sin(a * t), exp(j * a * t).

lcapy.fourier.FT(expr, t, f, **assumptions)

Compute bilateral Fourier transform of expr.

Undefined functions such as v(t) are converted to V(f)

This also handles some expressions that do not really have a Fourier transform, such as a, cos(a * t), sin(a * t), exp(I * a * t).

lcapy.fourier.IFT(expr, f, t, **assumptions)

Compute bilateral inverse Fourier transform of expr.

Undefined functions such as V(f) are converted to v(t)

This also handles some expressions that do not really have an inverse Fourier transform, such as a, cos(a * f), sin(a * f), exp(I * a * f).

### Ztransform¶

This module provides support for z transforms.

lcapy.ztransform.ZT(expr, n, z, **assumptions)

Compute unilateral Z-Transform transform of expr with lower limit 0.

Undefined functions such as v[n] are converted to V(z).

lcapy.ztransform.IZT(expr, z, n, **assumptions)

Calculate inverse z-Transform of X(s) and return x[n].

The unilateral Z-Transform transform cannot determine x[n] for n < 0 unless given additional information in the way of assumptions.

The assumptions are: dc – x[n] = constant causal – x[n] = 0 for n < 0. ac – x[n] = A cos(a * n) + B * sin(b * n)

### Transform¶

This module performs transformations between domains.

lcapy.transform.call(expr, arg, **assumptions)
lcapy.transform.transform(expr, arg, **assumptions)

If arg is f, s, t, omega, jomega perform domain transformation, otherwise perform substitution.

Note (5 * s)(omega) will fail since 5 * s is assumed not to be causal and so Fourier transform is unknown. However, Zs(5 * s)(omega) will work since Zs is assumed to be causal.

### Plot¶

This module performs plotting using matplotlib.

lcapy.plot.make_axes(figsize=None, axes=None, **kwargs)
lcapy.plot.plot_angular_frequency(obj, omega, **kwargs)
lcapy.plot.plot_frequency(obj, f, **kwargs)
lcapy.plot.plot_phasor(obj, **kwargs)
lcapy.plot.plot_pole_zero(obj, **kwargs)
lcapy.plot.plot_sequence(obj, n, **kwargs)
lcapy.plot.plot_time(obj, t, **kwargs)

### Acdc¶

class lcapy.acdc.ACChecker(expr, var)

Bases: object

class lcapy.acdc.CausalChecker(expr, var)

Bases: object

class lcapy.acdc.DCChecker(expr, var)

Bases: object

lcapy.acdc.is_ac(expr, var)
lcapy.acdc.is_causal(expr, var)
lcapy.acdc.is_dc(expr, var)

### Ratfun¶

This module provides support for rational functions.

class lcapy.ratfun.Pole(expr, n, damping=None)

Bases: object

conjugate
class lcapy.ratfun.Ratfun(expr, var)

Bases: object

D
Ddegree

Return the degree (order) of the denominator of a rational function. Note zero has a degree of -inf.

N
Ndegree

Return the degree (order) of the numerator of a rational function. Note zero has a degree of -inf.

ZPK()

Convert to zero-pole-gain (ZPK) form.

as_QMD()

Decompose expression into Q, M, D, delay, undef where

expression = (Q + M / D) * exp(-delay * var) * undef

as_QRD(combine_conjugates=False, damping=None)

Decompose expression into Q, R, D, delay, undef where

expression = (Q + sum_n R_n / D_n) * exp(-delay * var) * undef

as_const_undef_rest()

Split expr as (const, undef, rest) where expr = const * undef * rest

as_ratfun_delay()

Split expr as (N, D, delay) where expr = (N / D) * exp(var * delay)

Note, delay only represents a delay when var is s.

as_ratfun_delay_undef()

Split expr as (N, D, delay, undef) where expr = (N / D) * exp(var * delay) * undef and where N is a polynomial in var, D is a polynomial in var, and undef is the product of undefined functions, e.g., V(s).

Note, delay only represents a delay when var is s.

canonical(factor_const=True)

Convert rational function to canonical form; this is like general form but with a unity highest power of denominator. For example,

(5 * s**2 + 5 * s + 5) / (s**2 + 4)

If factor_const is True, factor constants from numerator, for example,

5 * (s**2 + s + 1) / (s**2 + 4)

coeffs()
degree

Return the degree (order) of the rational function.

This the maximum of the numerator and denominator degrees. Note zero has a degree of -inf.

denominator

Return denominator of rational function

expandcanonical()

Expand in terms for different powers with each term expressed in canonical form.

general()

Convert rational function to general form.

is_strictly_proper

Return True if the degree of the dominator is greater than the degree of the numerator.

numerator

Return numerator of rational function

numerator_denominator

Return numerator and denominator of rational function

partfrac(combine_conjugates=False, damping=None, split=True)

Convert rational function into partial fraction form.

If combine_conjugates is True then the pair of partial fractions for complex conjugate poles are combined.

poles(damping=None)

Return poles of expression as a dictionary of Pole objects. Note this may not find all the poles.

residue(pole, poles)
residues(combine_conjugates=False, damping=None)

Return residues of partial fraction expansion.

This is not much use without the corresponding poles. It is better to use as_QRD.

roots()

Return roots of expression as a dictionary Note this may not find them all.

standard(split=True)

Convert rational function into mixed fraction form.

This is the sum of strictly proper rational function and a polynomial.

timeconst()

Convert rational function to time constant form with unity lowest power of denominator.

zeros()

Return zeroes of expression as a dictionary Note this may not find them all.

lcapy.ratfun.as_numer_denom(expr, var)
lcapy.ratfun.as_numer_denom_poly(expr, var)
lcapy.ratfun.as_ratfun_delay(expr, var)
lcapy.ratfun.as_ratfun_delay_undef(expr, var)

## Schematics¶

### Schematic¶

This module performs schematic drawing using circuitikz from a netlist.

>>> from lcapy import Schematic
>>> sch = Schematic()
>>> sch.draw()


class lcapy.schematic.Schematic(filename=None, allow_anon=False, **kwargs)
add(string)

Add a component to the netlist. The general form is: ‘Name Np Nm args’ where Np is the positive node and Nm is the negative node.

A positive current is defined to flow from the positive node to the negative node.

draw(filename=None, **kwargs)

filename specifies the name of the file to produce. If None, the schematic is displayed on the screen.

Note, if using Jupyter, then need to first issue command %matplotlib inline

kwargs include:

label_ids: True to show component ids label_values: True to display component values draw_nodes: True to show all nodes,

False or ‘none’ to show no nodes, ‘primary’ to show primary nodes, ‘connections’ to show nodes that connect more than two components, ‘all’ to show all nodes
label_nodes: True to label all nodes,
False or ‘none’ to label no nodes, ‘primary’ to label primary nodes, ‘alpha’ to label nodes starting with a letter, ‘pins’ to label nodes that are pins on a chip, ‘all’ to label all nodes, ‘none’ to label no nodes

style: ‘american’, ‘british’, or ‘european’ scale: schematic scale factor, default 1.0 node_spacing: spacing between component nodes, default 2.0 cpt_size: size of a component, default 1.5 dpi: dots per inch for png files help_lines: distance between lines in grid, default 0.0 (disabled) debug: True to display debug information

make_graphs(debug=None)
netfile_add(filename)

Add the nets from file with specified filename

netlist()

Return the current netlist

tikz_draw(filename, **kwargs)

### Schemcpts¶

This module defines and draws the schematic components using circuitikz. The components are defined at the bottom of this file.

class lcapy.schemcpts.A(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Annotation.

draw(**kwargs)
xplace(graphs)
yplace(graphs)
class lcapy.schemcpts.BJT(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
node_pinnames = ('e', 'b', 'c')
npins = {'b': ('lx', 0, 0.8), 'c': ('lx', 1, 0), 'e': ('lx', 1, 1.6)}
ppins = {'b': ('lx', 0, 0.8), 'c': ('lx', 1, 1.6), 'e': ('lx', 1, 0)}
class lcapy.schemcpts.Bipole(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
can_invert = True
can_mirror = True
can_scale = True
draw(**kwargs)
node_pinnames = ('1', '2')
pins = {'1': ('lx', -0.5, 0), '2': ('rx', 0.5, 0)}
class lcapy.schemcpts.Box(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
pins = {'e': ('r', 0.5, 0), 'ene': ('r', 0.5, 0.25), 'ese': ('r', 0.5, -0.25), 'n': ('t', 0, 0.5), 'ne': ('t', 0.5, 0.5), 'nne': ('t', 0.25, 0.5), 'nnw': ('t', -0.25, 0.5), 'nw': ('t', -0.5, 0.5), 's': ('b', 0, -0.5), 'se': ('b', 0.5, -0.5), 'sse': ('b', 0.25, -0.5), 'ssw': ('b', -0.25, -0.5), 'sw': ('b', -0.5, -0.5), 'w': ('l', -0.5, 0), 'wnw': ('l', -0.5, 0.25), 'wsw': ('l', -0.5, -0.25)}
shape = 'rectangle'
class lcapy.schemcpts.Box12(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
pins = {'e': ('r', 0.5, 0), 'ene': ('r', 0.5, 0.25), 'ese': ('r', 0.5, -0.25), 'n': ('t', 0, 0.5), 'nne': ('t', 0.25, 0.5), 'nnw': ('t', -0.25, 0.5), 's': ('b', 0, -0.5), 'sse': ('b', 0.25, -0.5), 'ssw': ('b', -0.25, -0.5), 'w': ('l', -0.5, 0), 'wnw': ('l', -0.5, 0.25), 'wsw': ('l', -0.5, -0.25)}
shape = 'rectangle'
class lcapy.schemcpts.Box2(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Square box, A rectangle is created by defining aspect.

pins = {'e': ('r', 0.5, 0), 'w': ('l', -0.5, 0)}
shape = 'rectangle'
class lcapy.schemcpts.Box4(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
pins = {'e': ('r', 0.5, 0), 'n': ('t', 0, 0.5), 's': ('b', 0, -0.5), 'w': ('l', -0.5, 0)}
shape = 'rectangle'
class lcapy.schemcpts.CCS(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Current controlled source

required_node_names
class lcapy.schemcpts.CPE(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Constant phase element

draw(**kwargs)
class lcapy.schemcpts.Cable(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
a = 0.3
default_aspect = 4
draw(**kwargs)
pins = {'b': ('c', 0, -0.5), 'ignd': ('l', -0.5, -0.5), 'in': ('l', -0.5, 0), 'in+': ('l', -0.5, 0.3), 'in-': ('l', -0.5, -0.3), 'ognd': ('r', 0.475, -0.5), 'out': ('r', 0.5, 0), 'out+': ('r', 0.5, 0.3), 'out-': ('r', 0.5, -0.3), 't': ('c', 0, 0.5)}
class lcapy.schemcpts.Chip(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

General purpose chip

default_width = 2.0
do_transpose = True
draw(**kwargs)
path
class lcapy.schemcpts.Circle(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
shape = 'circle'
class lcapy.schemcpts.Circle2(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Circle

pins = {'e': ('r', 0.5, 0), 'w': ('l', -0.5, 0)}
shape = 'circle'
class lcapy.schemcpts.Circle4(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
pins = {'e': ('r', 0.5, 0), 'n': ('t', 0, 0.5), 's': ('b', 0, -0.5), 'w': ('l', -0.5, 0)}
shape = 'circle'
class lcapy.schemcpts.Cpt(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Bases: object

R(angle_offset=0)

Return rotation matrix

angle

Return rotation angle

annotate(pos, label, args_str='', bold=False)
args_list
args_str
aspect
auxiliary = {}
boolattr(opt)
can_invert = False
can_mirror = False
can_rotate = True
can_scale = False
can_stretch = True
check()

Check schematic options and return True if component is to be drawn

coords
current_keys = ('i', 'i_', 'i^', 'i_>', 'i_<', 'i^>', 'i^<', 'i>_', 'i<_', 'i>^', 'i<^', 'i>', 'i<', 'ir')
current_str
default_aspect = 1.0
default_pins = None
default_width = 1.0
directive = False
do_transpose = False
down
draw(**kwargs)
draw_label(pos, keys=('l', 'l^', 'l_'), default=True, **kwargs)
draw_node(n, **kwargs)
draw_node_label(node, label_nodes)
draw_node_labels(**kwargs)
draw_nodes(**kwargs)
draw_nodes_opt
draw_path(points, style='', join='--', closed=False)
draw_pinlabel(node)
draw_pinname(node)
draw_pins()
drawn_nodes

Nodes that are drawn

fakepin(pinname)

Return True if pinname is a fake pin

find_ref_node_names()

Determine which nodes are referenced for this component.

fixed
fliplr
flipud
flow_keys = ('f', 'f_', 'f^', 'f_>', 'f_<', 'f^>', 'f^<', 'f>_', 'f<_', 'f>^', 'f<^', 'f>', 'f<')
flow_str
free
h

Normalised height

horizontal
ignore
implicit_keys = ('implicit', 'ground', 'sground', 'rground', 'cground', 'nground', 'pground', 'vss', 'vdd', 'vee', 'vcc', 'input', 'output', 'bidir', 'pad', 'antenna', 'rxantenna', 'txantenna')
inner_label_keys = ('t',)
inner_label_str
invert
invisible
kind
label(keys=('l', 'l^', 'l_'), default=True, **kwargs)
label_keys = ('l', 'l_', 'l^')
label_make(label_pos='', **kwargs)
label_nodes_opt
label_str
label_str_list
left
midpoint(node1, node2)
mirror
mirrorinputs
misc_keys = ('left', 'right', 'up', 'down', 'rotate', 'size', 'mirror', 'invert', 'scale', 'invisible', 'variable', 'fixed', 'aspect', 'pins', 'image', 'offset', 'pinlabels', 'pinnames', 'pinnodes', 'pindefs', 'outside', 'pinmap', 'kind', 'wire', 'ignore', 'style', 'nowires', 'nolabels', 'steps', 'free', 'fliplr', 'flipud', 'nodots', 'draw_nodes', 'label_nodes', 'nodraw', 'mirrorinputs')
node(pinname)

Return node by pinname

node_pinnames = ()
nodes

Nodes used to draw the current element.

nodots
nodraw
nolabels
nowires
offset
opts_str(choices)

Format voltage, current, or label string as a key-value pair

opts_str_list(choices)

Format voltage, current, or label string as a key-value pair and return list of strings

parse_pindefs()
pinpos(pinname)

Return pinpos by pinname

pins = {}
place(graphs, vals)
required_node_names

Subset of node_names. This filters out nodes that are not drawn. For example, the ground node of an Eopamp is not drawn.

required_pins
right
s

Sanitised name

scale
scales
setup()
size

Component size between its nodes

steps
stretch
style
tcoords

Transformed coordinates for each of the nodes

tf(centre, offset, angle_offset=0.0, scale=None)

Transform coordinate

up
variable
vertical
voltage_keys = ('v', 'v_', 'v^', 'v_>', 'v_<', 'v^>', 'v^<', 'v<', 'v>')
voltage_str
w

Normalised width

wire
xplace(graphs)
xvals
yplace(graphs)
yvals
class lcapy.schemcpts.Eamp(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Amplifier.

can_scale = True
default_width = 1.0
do_transpose = False
draw(**kwargs)
node_pinnames = ('out', '', 'in', '')
pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}
pins = {'in': ('lx', -1.25, 0.0), 'out': ('rx', 1.25, 0.0), 'r+': ('l', -0.85, 0.25), 'r-': ('l', -0.85, -0.25), 'ref': ('b', 0.45, -0.245), 'vdd': ('t', 0, 0.5), 'vdd2': ('t', -0.45, 0.755), 'vss': ('b', 0, -0.5), 'vss2': ('b', -0.45, -0.755)}
class lcapy.schemcpts.Efdopamp(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

This is for a fully differential opamp created with the E netlist type. See also Ufdopamp for a fully differential opamp created with the U netlist type.

can_mirror = True
can_scale = True
default_width = 1.0
do_transpose = False
draw(**kwargs)
node_pinnames = ('out+', 'out-', 'in+', 'in-')
npins = {'in+': ('l', -1.25, -0.5), 'in-': ('l', -1.25, 0.5), 'out+': ('r', 0.85, 0.5), 'out-': ('r', 0.85, -0.5), 'r+': ('l', -0.85, -0.25), 'r-': ('l', -0.85, 0.25), 'vdd': ('t', -0.25, 0.645), 'vocm': ('l', -0.85, 0), 'vss': ('b', -0.25, -0.645)}
pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}
pins
ppins = {'in+': ('l', -1.25, 0.5), 'in-': ('l', -1.25, -0.5), 'out+': ('r', 0.85, -0.5), 'out-': ('r', 0.85, 0.5), 'r+': ('l', -0.85, 0.25), 'r-': ('l', -0.85, -0.25), 'vdd': ('t', -0.25, 0.645), 'vocm': ('l', -0.85, 0), 'vss': ('b', -0.25, -0.645)}
class lcapy.schemcpts.Ellipse(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
pins = {'e': ('r', 0.5, 0), 'ene': ('r', 0.4619, 0.1913), 'ese': ('r', 0.4619, -0.1913), 'n': ('t', 0, 0.5), 'ne': ('r', 0.3536, 0.35365), 'nne': ('t', 0.1913, 0.4619), 'nnw': ('t', -0.1913, 0.4619), 'nw': ('t', -0.3536, 0.3536), 's': ('b', 0, -0.5), 'se': ('r', 0.3536, -0.3536), 'sse': ('b', 0.1913, -0.4619), 'ssw': ('b', -0.1913, -0.4619), 'sw': ('b', -0.3536, -0.3536), 'w': ('l', -0.5, 0), 'wnw': ('l', -0.4619, 0.1913), 'wsw': ('l', -0.4619, -0.1913)}
shape = 'ellipse'
class lcapy.schemcpts.Eopamp(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

This is for an opamp created with the E netlist type as used for simulation.

can_mirror = True
can_scale = True
default_width = 1.0
do_transpose = False
draw(**kwargs)
node_pinnames = ('out', '', 'in+', 'in-')
npins = {'in+': ('lx', -1.25, -0.5), 'in-': ('lx', -1.25, 0.5), 'out': ('rx', 1.25, 0.0), 'r+': ('l', -0.85, -0.25), 'r-': ('l', -0.85, 0.25), 'ref': ('b', 0.45, -0.245), 'vdd': ('t', 0, 0.5), 'vdd2': ('t', -0.45, 0.755), 'vss': ('b', 0, -0.5), 'vss2': ('b', -0.45, -0.755)}
pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}
pins
ppins = {'in+': ('lx', -1.25, 0.5), 'in-': ('lx', -1.25, -0.5), 'out': ('rx', 1.25, 0.0), 'r+': ('l', -0.85, 0.25), 'r-': ('l', -0.85, -0.25), 'ref': ('b', 0.45, -0.245), 'vdd': ('t', 0, 0.5), 'vdd2': ('t', -0.45, 0.755), 'vss': ('b', 0, -0.5), 'vss2': ('b', -0.45, -0.755)}
class lcapy.schemcpts.FB(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

draw(**kwargs)
class lcapy.schemcpts.FixedCpt(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
can_stretch = False
centre
tf(centre, offset, angle_offset=0.0, scale=None)

Transform coordinate.

class lcapy.schemcpts.Flipflop(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
default_width = 1.0
class lcapy.schemcpts.Gyrator(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
draw(**kwargs)
node_pinnames = ('out+', 'out-', 'in+', 'in-')
pins = {'in+': ('lx', 0, 1), 'in-': ('lx', 0, 0), 'out+': ('rx', 1, 1), 'out-': ('rx', 1, 0)}
class lcapy.schemcpts.JFET(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
node_pinnames = ('d', 'g', 's')
npins = {'d': ('lx', 1, 1.5), 'g': ('lx', 0, 0.46), 's': ('lx', 1, 0)}
ppins = {'d': ('lx', 1, 0), 'g': ('lx', 0, 1.04), 's': ('lx', 1, 1.5)}
class lcapy.schemcpts.K(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Mutual coupling

coords
nodes
scales
class lcapy.schemcpts.MOSFET(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
node_pinnames = ('d', 'g', 's')
npins = {'d': ('lx', 0.85, 1.64), 'g': ('lx', -0.25, 0.82), 's': ('lx', 0.85, 0)}
ppins = {'d': ('lx', 0.85, 0), 'g': ('lx', -0.25, 0.82), 's': ('lx', 0.85, 1.64)}
class lcapy.schemcpts.MT(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Motor

draw(**kwargs)
class lcapy.schemcpts.MX(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Mixer

can_scale = True
draw(**kwargs)
node_pinnames = ('in1', 'in2', 'out')
pins = {'in1': ('lx', 0.25, 0.25), 'in2': ('lx', -0.25, 0.25), 'out': ('rx', 0, 0)}
class lcapy.schemcpts.Mux(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Multiplexer

path
class lcapy.schemcpts.Potentiometer(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Potentiometer Np, Nm, No

can_stretch = False
node_pinnames = ('1', '2', 'wiper')
pins = {'1': ('rx', 0, 0), '2': ('rx', 1, 0), 'wiper': ('lx', 0.5, 0.3)}
class lcapy.schemcpts.SP(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Summing point

can_mirror = True
can_scale = True
draw(**kwargs)
node_pinnames = ('in1', 'in2', 'out', 'in3')
npins = {'in1': ('lx', -0.25, 0), 'in2': ('tx', 0, 0.25), 'in3': ('bx', 0, -0.25), 'out': ('rx', 0.25, 0)}
pins
ppins = {'in1': ('lx', -0.25, 0), 'in2': ('bx', 0, -0.25), 'in3': ('tx', 0, 0.25), 'out': ('rx', 0.25, 0)}
class lcapy.schemcpts.SP3(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Summing point

node_pinnames = ('in1', 'in2', 'out')
npins = {'in1': ('lx', -0.25, 0), 'in2': ('tx', 0, 0.25), 'out': ('rx', 0.25, 0)}
pins
ppins = {'in1': ('lx', -0.25, 0), 'in2': ('bx', 0, -0.25), 'out': ('rx', 0.25, 0)}
class lcapy.schemcpts.SPDT(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

SPDT switch

can_invert = True
can_mirror = True
draw(**kwargs)
node_pinnames = ('1', '2', 'common')
pins = {'1': ('lx', 0, 0.169), '2': ('rx', 0.632, 0.338), 'common': ('lx', 0.632, 0)}
class lcapy.schemcpts.SPpm(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Summing point

labels = '+-'
class lcapy.schemcpts.SPpmm(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Summing point

labels = '+--'
class lcapy.schemcpts.SPpp(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Summing point

labels = '++'
class lcapy.schemcpts.SPppm(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Summing point

labels = '++-'
class lcapy.schemcpts.SPppp(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Summing point

labels = '+++'
class lcapy.schemcpts.Shape(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

General purpose shape

auxiliary = {'bl': ('l', -0.5, -0.5), 'br': ('r', 0.5, -0.5), 'mid': ('c', 0.0, 0.0), 'tl': ('l', -0.5, 0.5), 'top': ('t', 0, 0.5), 'tr': ('r', 0.5, 0.5)}
can_invert = True
can_mirror = True
default_aspect = 1.0
draw(**kwargs)
height
parse_pindefs()
parse_pinlabels()
parse_pinnames()
parse_pinnodes()
pinlabels = {}
pinpos_rotate(pinpos, angle)

Rotate pinpos by multiple of 90 degrees. pinpos is either ‘l’, ‘t’, ‘r’, ‘b’.

process_pinlabels()
process_pinnames()
process_pinnodes()
setup()
width
class lcapy.schemcpts.StretchyCpt(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
can_stretch = True
tf(centre, offset, angle_offset=0.0, scale=None)

Transform coordinate.

xtf(centre, offset, angle_offset=0.0)

Transform coordinate.

class lcapy.schemcpts.TF1(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Transformer

default_aspect = 0.8
draw(link=True, **kwargs)
misc = {'label': (0, 0.48), 'link': (0, 0.15), 'pdot': (-0.30000000000000004, 0.34), 'sdot': (0.30000000000000004, 0.34)}
node_pinnames = ('s+', 's-', 'p+', 'p-')
pins = {'p+': ('lx', 0, 1), 'p-': ('lx', 0, 0), 's+': ('rx', 0.8, 1), 's-': ('rx', 0.8, 0)}
w = 0.8
class lcapy.schemcpts.TFtap(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Transformer

draw(**kwargs)
drawn_nodes
node_pinnames = ('s+', 's-', 'p+', 'p-', 'ptap', 'stap')
pins = {'p+': ('lx', 0, 1), 'p-': ('lx', 0, 0), 'ptap': ('lx', 0, 0.5), 's+': ('rx', 0.8, 1), 's-': ('rx', 0.8, 0), 'stap': ('rx', 0.8, 0.5)}
w = 0.8
class lcapy.schemcpts.TL(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Transmission line

can_scale = True
draw(**kwargs)
drawn_nodes
node_pinnames = ('out1', 'out2', 'in1', 'in2')
pins = {'in1': ('lx', 0, 0.5), 'in2': ('lx', 0, 0), 'out1': ('rx', 1, 0.5), 'out2': ('rx', 1, 0)}
w = 1
class lcapy.schemcpts.TR(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Transfer function

default_aspect = 1.5
default_width = 1.5
node_pinnames = ('w', 'e')
class lcapy.schemcpts.Transformer(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
draw(**kwargs)
class lcapy.schemcpts.Transistor(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
can_mirror = True
can_scale = True
draw(**kwargs)
pins
class lcapy.schemcpts.Triangle(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Equilateral triangle, The triangle shape can be altered by defining aspect.

auxiliary = {'bl': ('l', -0.5, -0.2887), 'br': ('r', 0.5, -0.2887), 'mid': ('c', 0.0, 0.0), 'tl': ('l', -0.5, 0.5774), 'top': ('t', 0, 0.5774), 'tr': ('r', 0.5, 0.5774)}
draw(**kwargs)
pins = {'e': ('r', 0.5, -0.2887), 'ene': ('r', 0.375, -0.075), 'ese': ('b', 0.375, -0.2887), 'n': ('t', 0.0, 0.5774), 'ne': ('r', 0.25, 0.14435), 'nne': ('r', 0.125, 0.355), 'nnw': ('l', -0.125, 0.355), 'nw': ('l', -0.25, 0.14435), 's': ('b', 0.0, -0.2887), 'se': ('b', 0.25, -0.2887), 'sse': ('b', 0.125, -0.2887), 'ssw': ('b', -0.125, -0.2887), 'sw': ('b', -0.25, -0.2887), 'w': ('l', -0.5, -0.2887), 'wnw': ('l', -0.375, -0.075), 'wsw': ('b', -0.375, -0.2887)}
shape = 'triangle'
class lcapy.schemcpts.TwoPort(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Two-port

default_aspect = 1
default_width = 2
node_pinnames = ('ene', 'ese', 'wnw', 'wsw')
pins = {'e': ('r', 0.5, 0), 'ene': ('r', 0.5, 0.375), 'ese': ('r', 0.5, -0.375), 'n': ('t', 0, 0.5), 'nne': ('t', 0.25, 0.5), 'nnw': ('t', -0.25, 0.5), 's': ('b', 0, -0.5), 'sse': ('b', 0.25, -0.5), 'ssw': ('b', -0.25, -0.5), 'w': ('l', -0.5, 0), 'wnw': ('l', -0.5, 0.375), 'wsw': ('l', -0.5, -0.375)}
shape = 'rectangle'
class lcapy.schemcpts.Uadc(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

path
pinlabels = {'avdd': 'AVDD', 'avss': 'AVSS', 'clk': '>', 'data': 'DATA', 'dvdd': 'DVDD', 'dvss': 'DVSS', 'fs': 'FS', 'vdd': 'VDD', 'vref+': 'VREF+', 'vref-': 'VREF-', 'vss': 'VSS'}
pins = {'avdd': ('t', -0.1, 0.5), 'avss': ('b', -0.1, -0.5), 'clk': ('r', 0.5, -0.25), 'data': ('r', 0.5, 0), 'dvdd': ('t', 0.3, 0.5), 'dvss': ('b', 0.3, -0.5), 'fs': ('r', 0.5, 0.25), 'in': ('l', -0.5, 0), 'in+': ('l', -0.4375, 0.125), 'in-': ('l', -0.4375, -0.125), 'vdd': ('t', 0.1, 0.5), 'vref+': ('l', -0.375, 0.25), 'vref-': ('l', -0.375, -0.25), 'vss': ('b', 0.1, -0.5)}
class lcapy.schemcpts.Ubuffer(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Buffer with power supplies

default_width = 1.0
path
pinlabels = {'en': 'E', 'vdd': 'VDD', 'vss': 'VSS'}
pins = {'en': ('b', -0.25, -0.375), 'in': ('l', -0.5, 0), 'out': ('r', 0.5, 0), 'vdd': ('t', 0, 0.25), 'vdd1': ('t', -0.25, 0.375), 'vdd2': ('t', 0.25, 0.125), 'vss': ('b', 0, -0.25)}
class lcapy.schemcpts.Uchip1313(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Chip of size 1 3 1 3

pins = {'b1': ('b', -0.25, -0.5), 'b3': ('b', 0.25, -0.5), 'in': ('l', -0.5, 0), 'out': ('r', 0.5, 0), 't1': ('t', -0.25, 0.5), 't3': ('t', 0.25, 0.5), 'vdd': ('t', 0, 0.5), 'vss': ('b', 0, -0.5)}
class lcapy.schemcpts.Uchip2121(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Chip of size 2 1 2 1

pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}
pins = {'l1': ('l', -0.5, 0.25), 'l2': ('l', -0.5, -0.25), 'r1': ('r', 0.5, 0.25), 'r2': ('r', 0.5, -0.25), 'vdd': ('t', 0, 0.5), 'vss': ('b', 0, -0.5)}
class lcapy.schemcpts.Uchip2222(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Chip of size 2 2 2 2

pins = {'b1': ('b', -0.25, -0.5), 'b2': ('b', 0.25, -0.5), 'l1': ('l', -0.5, 0.25), 'l2': ('l', -0.5, -0.25), 'r1': ('r', 0.5, 0.25), 'r2': ('r', 0.5, -0.25), 't1': ('t', -0.25, 0.5), 't2': ('t', 0.25, 0.5)}
class lcapy.schemcpts.Uchip3131(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Chip of size 3 1 3 1

path
pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}
pins = {'l1': ('l', -0.5, 0.25), 'l2': ('l', -0.5, 0), 'l3': ('l', -0.5, -0.25), 'r1': ('r', 0.5, 0.25), 'r2': ('r', 0.5, 0), 'r3': ('r', 0.5, -0.25), 'vdd': ('t', 0.0, 0.5), 'vss': ('b', 0.0, -0.5)}
class lcapy.schemcpts.Uchip3333(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Chip of size 3 3 3 3

path
pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}
pins = {'b1': ('b', -0.25, -0.5), 'b3': ('b', 0.25, -0.5), 'l1': ('l', -0.5, 0.25), 'l2': ('l', -0.5, 0), 'l3': ('l', -0.5, -0.25), 'r1': ('r', 0.5, 0.25), 'r2': ('r', 0.5, 0), 'r3': ('r', 0.5, -0.25), 't1': ('t', -0.25, 0.5), 't3': ('t', 0.25, 0.5), 'vdd': ('t', 0.0, 0.5), 'vss': ('b', 0.0, -0.5)}
class lcapy.schemcpts.Uchip4141(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Chip of size 4 1 4 1

pins = {'l1': ('l', -0.5, 0.375), 'l2': ('l', -0.5, 0.125), 'l3': ('l', -0.5, -0.125), 'l4': ('l', -0.5, -0.375), 'r1': ('r', 0.5, 0.375), 'r2': ('r', 0.5, 0.125), 'r3': ('r', 0.5, -0.125), 'r4': ('r', 0.5, -0.375), 'vdd': ('t', 0.0, 0.5), 'vss': ('b', 0.0, -0.5)}
class lcapy.schemcpts.Uchip4444(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Chip of size 4 4 4 4

pins = {'b1': ('b', -0.375, -0.5), 'b2': ('b', -0.125, -0.5), 'b3': ('b', 0.125, -0.5), 'b4': ('b', 0.375, -0.5), 'l1': ('l', -0.5, 0.375), 'l2': ('l', -0.5, 0.125), 'l3': ('l', -0.5, -0.125), 'l4': ('l', -0.5, -0.375), 'r1': ('r', 0.5, 0.375), 'r2': ('r', 0.5, 0.125), 'r3': ('r', 0.5, -0.125), 'r4': ('r', 0.5, -0.375), 't1': ('t', -0.375, 0.5), 't2': ('t', -0.125, 0.5), 't3': ('t', 0.125, 0.5), 't4': ('t', 0.375, 0.5)}
class lcapy.schemcpts.Uchip8181(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Chip of size 8 1 8 1

pins = {'l1': ('l', -0.5, 0.4375), 'l2': ('l', -0.5, 0.3125), 'l3': ('l', -0.5, 0.1875), 'l4': ('l', -0.5, 0.0625), 'l5': ('l', -0.5, -0.0625), 'l6': ('l', -0.5, -0.1875), 'l7': ('l', -0.5, -0.3125), 'l8': ('l', -0.5, -0.4375), 'r1': ('r', 0.5, 0.4375), 'r2': ('r', 0.5, 0.3125), 'r3': ('r', 0.5, 0.1875), 'r4': ('r', 0.5, 0.0625), 'r5': ('r', 0.5, -0.0625), 'r6': ('r', 0.5, -0.1875), 'r7': ('r', 0.5, -0.3125), 'r8': ('r', 0.5, -0.4375), 'vdd': ('t', 0.0, 0.5), 'vss': ('b', 0.0, -0.5)}
class lcapy.schemcpts.Uchip8888(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Chip of size 8 8 8 8

pins = {'b1': ('b', -0.4375, -0.5), 'b2': ('b', -0.3125, -0.5), 'b3': ('b', -0.1875, -0.5), 'b4': ('b', -0.0625, -0.5), 'b5': ('b', 0.0625, -0.5), 'b6': ('b', 0.1875, -0.5), 'b7': ('b', 0.3125, -0.5), 'b8': ('b', -0.4375, -0.5), 'l1': ('l', -0.5, 0.4375), 'l2': ('l', -0.5, 0.3125), 'l3': ('l', -0.5, 0.1875), 'l4': ('l', -0.5, 0.0625), 'l5': ('l', -0.5, -0.0625), 'l6': ('l', -0.5, -0.1875), 'l7': ('l', -0.5, -0.3125), 'l8': ('l', -0.5, -0.4375), 'r1': ('r', 0.5, 0.4375), 'r2': ('r', 0.5, 0.3125), 'r3': ('r', 0.5, 0.1875), 'r4': ('r', 0.5, 0.0625), 'r5': ('r', 0.5, -0.0625), 'r6': ('r', 0.5, -0.1875), 'r7': ('r', 0.5, -0.3125), 'r8': ('r', 0.5, -0.4375), 't1': ('t', -0.4375, 0.5), 't2': ('t', -0.3125, 0.5), 't3': ('t', -0.1875, 0.5), 't4': ('t', -0.0625, 0.5), 't5': ('t', 0.0625, 0.5), 't6': ('t', 0.1875, 0.5), 't7': ('t', 0.3125, 0.5), 't8': ('t', -0.4375, 0.5)}
class lcapy.schemcpts.Udac(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

DAC

path
pinlabels = {'avdd': 'AVDD', 'avss': 'AVSS', 'clk': '>', 'data': 'DATA', 'dvdd': 'DVDD', 'dvss': 'DVSS', 'fs': 'FS', 'vdd': 'VDD', 'vref+': 'VREF+', 'vref-': 'VREF-', 'vss': 'VSS'}
pins = {'avdd': ('t', 0.1, 0.5), 'avss': ('b', 0.1, -0.5), 'clk': ('l', -0.5, -0.25), 'data': ('l', -0.5, 0), 'dvdd': ('t', -0.3, 0.5), 'dvss': ('b', -0.3, -0.5), 'fs': ('l', -0.5, 0.25), 'out': ('r', 0.5, 0), 'out+': ('r', 0.4375, 0.125), 'out-': ('r', 0.4375, -0.125), 'vdd': ('t', -0.1, 0.5), 'vref+': ('r', 0.375, 0.25), 'vref-': ('r', 0.375, -0.25), 'vss': ('b', -0.1, -0.5)}
class lcapy.schemcpts.Udff(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

D flip-flop

default_pins = '{d, clk, q}'
pinlabels = {'/q': '$\\overline{\\mathrm{Q}}$', 'clk': '>', 'd': 'D', 'q': 'Q', 'vdd': 'VDD', 'vss': 'VSS'}
pins = {'/q': ('r', 0.5, -0.25), 'clk': ('l', -0.5, 0), 'd': ('l', -0.5, 0.25), 'q': ('r', 0.5, 0.25), 'vdd': ('t', 0.0, 0.5), 'vss': ('b', 0.0, -0.5)}
class lcapy.schemcpts.Udiffamp(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Amplifier. This may be deprecated. It is not automatically annotated with + and - symbols for inputs. This can be achieved using opamp with nolabels.

default_width = 1.0
path
pinlabels = {'in+': '$+$', 'in-': '$-$', 'vdd': 'VDD', 'vss': 'VSS'}
pins = {'in+': ('l', -0.5, 0.25), 'in-': ('l', -0.5, -0.25), 'out': ('r', 0.5, 0), 'vdd': ('t', 0, 0.25), 'vss': ('b', 0, -0.25)}
class lcapy.schemcpts.Ufdopamp(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

This is for a fully differential opamp created with the U netlist type. It has no wires. See also FDOpamp for a fully differential opamp created with the E netlist type.

auxiliary = {'bl': ('l', -0.5, -0.5), 'br': ('r', 0.5, -0.5), 'lin+': ('c', -0.375, 0.2), 'lin-': ('c', -0.375, -0.2), 'lout+': ('c', 0, -0.17), 'lout-': ('c', 0, 0.17), 'mid': ('c', 0.0, 0.0), 'tl': ('l', -0.5, 0.5), 'top': ('t', 0, 0.5), 'tr': ('r', 0.5, 0.5)}
can_mirror = True
draw(**kwargs)
npins = {'in+': ('l', -0.5, -0.2), 'in-': ('l', -0.5, 0.2), 'out+': ('r', 0.1, 0.2), 'out-': ('r', 0.1, -0.2), 'vdd': ('t', -0.1, 0.3), 'vocm': ('l', -0.5, 0), 'vss': ('b', -0.1, -0.3)}
path
pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}
pins
ppins = {'in+': ('l', -0.5, 0.2), 'in-': ('l', -0.5, -0.2), 'out+': ('r', 0.1, -0.2), 'out-': ('r', 0.1, 0.2), 'vdd': ('t', -0.1, 0.3), 'vocm': ('l', -0.5, 0), 'vss': ('b', -0.1, -0.3)}
class lcapy.schemcpts.Uinamp(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Instrumentation amplifier created with U netlist type.

auxiliary = {'bl': ('l', -0.5, -0.5), 'br': ('r', 0.5, -0.5), 'lin+': ('c', -0.375, 0.3), 'lin-': ('c', -0.375, -0.3), 'mid': ('c', 0.0, 0.0), 'tl': ('l', -0.5, 0.5), 'top': ('t', 0, 0.5), 'tr': ('r', 0.5, 0.5)}
can_mirror = True
npins = {'in+': ('l', -0.5, -0.3), 'in-': ('l', -0.5, 0.3), 'out': ('r', 0.5, 0.0), 'r+': ('l', -0.5, -0.2), 'r-': ('l', -0.5, 0.2), 'ref': ('b', 0.225, -0.135), 'vdd': ('t', 0, 0.25), 'vdd2': ('t', -0.225, 0.365), 'vss': ('b', 0, -0.25), 'vss2': ('b', -0.225, -0.365)}
ppins = {'in+': ('l', -0.5, 0.3), 'in-': ('l', -0.5, -0.3), 'out': ('r', 0.5, 0.0), 'r+': ('l', -0.5, 0.2), 'r-': ('l', -0.5, -0.2), 'ref': ('b', 0.225, -0.135), 'vdd': ('t', 0, 0.25), 'vdd2': ('t', -0.225, 0.365), 'vss': ('b', 0, -0.25), 'vss2': ('b', -0.225, -0.365)}
class lcapy.schemcpts.Uinverter(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Inverter with power supplies

default_width = 1.0
draw(**kwargs)
path
pinlabels = {'en': 'E', 'vdd': 'VDD', 'vss': 'VSS'}
pins = {'en': ('b', -0.25, -0.37), 'in': ('l', -0.5, 0), 'out': ('r', 0.5, 0), 'vdd': ('t', 0, 0.22), 'vss': ('b', 0, -0.22)}
class lcapy.schemcpts.Uisoamp(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Isolated amplifier created with U netlist type.

auxiliary = {'bl': ('l', -0.5, -0.5), 'br': ('r', 0.5, -0.5), 'lin+': ('c', -0.4, 0.2), 'lin-': ('c', -0.4, -0.2), 'lout+': ('c', 0.1, 0.12), 'lout-': ('c', 0.1, -0.12), 'mid': ('c', 0.0, 0.0), 'tl': ('l', -0.5, 0.5), 'top': ('t', 0, 0.5), 'tr': ('r', 0.5, 0.5)}
path
pins = {'in': ('l', -0.5, 0.0), 'in+': ('l', -0.5, 0.2), 'in-': ('l', -0.5, -0.2), 'out': ('r', 0.5, 0), 'out+': ('r', 0.2, 0.15), 'out-': ('r', 0.2, -0.15), 'vdd1': ('t', -0.3, 0.4), 'vdd2': ('t', 0.0, 0.25), 'vss1': ('b', -0.3, -0.4), 'vss2': ('b', 0.0, -0.25)}
class lcapy.schemcpts.Ujkff(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

JK flip-flop

default_pins = '{j, k, clk, q}'
pinlabels = {'/q': '$\\overline{\\mathrm{Q}}$', 'clk': '>', 'j': 'J', 'k': 'K', 'q': 'Q', 'vdd': 'VDD', 'vss': 'VSS'}
pins = {'/q': ('r', 0.5, -0.25), 'clk': ('l', -0.5, 0), 'j': ('l', -0.5, 0.25), 'k': ('l', -0.5, -0.25), 'q': ('r', 0.5, 0.25), 'vdd': ('t', 0.0, 0.5), 'vss': ('b', 0.0, -0.5)}
class lcapy.schemcpts.Umux21(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Multiplexer 2 to 1

pins = {'b': ('b', 0, -0.375), 'l1': ('l', -0.25, 0.25), 'l2': ('l', -0.25, -0.25), 'r': ('r', 0.25, 0.0), 't': ('t', 0, 0.375)}
class lcapy.schemcpts.Umux41(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Multiplexer 4 to 1

pins = {'b1': ('b', -0.125, -0.4375), 'b2': ('b', 0.125, -0.3125), 'l1': ('l', -0.25, 0.375), 'l2': ('l', -0.25, 0.125), 'l3': ('l', -0.25, -0.125), 'l4': ('l', -0.25, -0.375), 'r': ('r', 0.25, 0), 't1': ('t', -0.125, 0.4375), 't2': ('t', 0.125, 0.3125)}
class lcapy.schemcpts.Umux42(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Multiplexer 4 to 2

pins = {'b1': ('b', -0.125, -0.4375), 'b2': ('b', 0.125, -0.3125), 'l1': ('l', -0.25, 0.375), 'l2': ('l', -0.25, 0.125), 'l3': ('l', -0.25, -0.125), 'l4': ('l', -0.25, -0.375), 'r1': ('r', 0.25, 0.125), 'r2': ('r', 0.25, -0.125), 't1': ('t', -0.125, 0.4375), 't2': ('t', 0.125, 0.3125)}
class lcapy.schemcpts.Uopamp(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

This is for an opamp created with the U netlist type. It has no wires. See also Opamp for an opamp created with the E netlist type.

auxiliary = {'bl': ('l', -0.5, -0.5), 'br': ('r', 0.5, -0.5), 'lin+': ('c', -0.375, 0.25), 'lin-': ('c', -0.375, -0.25), 'mid': ('c', 0.0, 0.0), 'tl': ('l', -0.5, 0.5), 'top': ('t', 0, 0.5), 'tr': ('r', 0.5, 0.5)}
can_mirror = True
draw(**kwargs)
npins = {'in+': ('l', -0.5, -0.25), 'in-': ('l', -0.5, 0.25), 'out': ('r', 0.5, 0.0), 'r+': ('l', -0.5, -0.125), 'r-': ('l', -0.5, 0.125), 'ref': ('b', 0.225, -0.135), 'vdd': ('t', 0, 0.25), 'vdd2': ('t', -0.225, 0.365), 'vss': ('b', 0, -0.25), 'vss2': ('b', -0.225, -0.365)}
path
pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}
pins
ppins = {'in+': ('l', -0.5, 0.25), 'in-': ('l', -0.5, -0.25), 'out': ('r', 0.5, 0.0), 'r+': ('l', -0.5, 0.125), 'r-': ('l', -0.5, -0.125), 'ref': ('b', 0.225, -0.135), 'vdd': ('t', 0, 0.25), 'vdd2': ('t', -0.225, 0.365), 'vss': ('b', 0, -0.25), 'vss2': ('b', -0.225, -0.365)}
class lcapy.schemcpts.Uregulator(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Voltage regulator

default_aspect = 1.3333333333333333
pinlabels = {'en': 'E', 'gnd': 'GND'}
pins = {'en': ('b', -0.25, -0.5), 'gnd': ('b', 0, -0.5), 'in': ('l', -0.5, 0), 'out': ('r', 0.5, 0)}
class lcapy.schemcpts.Urslatch(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

RS latch

default_pins = '{r, s, q}'
pinlabels = {'/q': '$\\overline{\\mathrm{Q}}$', 'q': 'Q', 'r': 'R', 's': 'S', 'vdd': 'VDD', 'vss': 'VSS'}
pins = {'/q': ('r', 0.5, -0.25), 'q': ('r', 0.5, 0.25), 'r': ('l', -0.5, 0.25), 's': ('l', -0.5, -0.25), 'vdd': ('t', 0.0, 0.5), 'vss': ('b', 0.0, -0.5)}
class lcapy.schemcpts.VCS(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)

Voltage controlled source

required_node_names
class lcapy.schemcpts.Wire(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
draw(**kwargs)
draw_implicit(**kwargs)

Draw implicit wires, i.e., connections to ground, etc.

setup()
class lcapy.schemcpts.XX(sch, namespace, defname, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)
directive = True
draw(**kwargs)
lcapy.schemcpts.defcpt(name, base, docstring, cpt=None)
lcapy.schemcpts.make(classname, parent, name, cpt_type, cpt_id, string, opts_string, node_names, *args)

### Schemgraph¶

This module provides classes for schematic layout.

class lcapy.schemgraph.Cnodes(nodes)

Bases: dict

Common nodes

Make nodes n1 and n2 share common node

class lcapy.schemgraph.Gedge(cpt, from_gnode, to_gnode, size, stretch=False)

Bases: object

Edge between common nodes

name
class lcapy.schemgraph.Gnode(name)

Bases: object

Drawing node

add_fedge(edge)
add_redge(edge)
fmt_name
pos
class lcapy.schemgraph.Graph(name, nodes, debug=False)

Bases: dict

Drawing graph

add(cpt, n1, n2, size, stretch)

Add cpt between nodes n1 and n2 to the graph

add_edges(cpt, gnode1, gnode2, size, stretch)
add_node(n)
add_start_nodes()

Nodes without forward edges are connected to the end node. Nodes without reverse edges are connected to the start node.

all_nodes
analyse(stage=None)

Analyse graph assigning gnode positions.

stage 0 — add start/end gnodes stage 1 — prune redundant edges stage 2 — assign gnode positions on longest path stage 3 — assign gnode positions with fixed positions to known gnodes stage 4 — assign all gnode positions

assign_fixed(unknown)

Assign node positions to nodes with fixed edge lengths to nodes with known positions. Iterate until no more changes. This stage is not needed but provides a minor optimisation.

assign_fixed1(gnode)
assign_longest(path, unknown)
assign_stretchy(unknown)

Use a worklist algorithm to assign nodes with unknown positions that are connected via stretchable edges to the known nodes.

assign_stretchy1(gnode, unknown)
check_positions()
dot(filename=None, stage=None)

Generate directed graph using graphviz notation

Make nodes n1 and n2 share common node

longest_path(from_gnode, to_gnode, forward=True)

Find longest path through DAG from from_gnode to to_gnode or to a gnode with a known position.

makepath(from_gnode)
nodes
path_to_closest_known(from_gnode, forward=True)

Find path through DAG to the closest node with a known pos.

prune()

Remove redundant paths from graph. If there are two parallel stretchy edges, the longest is chosen.

class lcapy.schemgraph.GraphPath

Bases: list

This is a list of edges defining a path through a graph.

dist
from_dist(match_node)
from_gnode
gnodes

Return list of nodes along path including end nodes.

on(match_node)
stretches
to_dist(match_node)
to_gnode
lcapy.schemgraph.unique(alist)

### Schemmisc¶

This module provides miscellaneous support for schematic drawing.

class lcapy.schemmisc.Pos(x, y=0)

Bases: object

xy
class lcapy.schemmisc.Steps(string, pos1, pos2)

Bases: object

## General¶

### Config¶

This module contains configuration information.

### Grammar¶

This module defines a grammar for SPICE-like netlists.

### Parser¶

This module performs parsing of SPICE-like netlists. It uses a custom parser rather than lex/yacc to give better error messages.

class lcapy.parser.Param(name, base, comment)

Bases: object

is_valid(string)
class lcapy.parser.Parser(cpts, grammar, allow_anon=False)

Bases: object

parse(string, namespace='', parent=None)

Parse string and create object

class lcapy.parser.Rule(cpt_type, classname, params, comment, pos)

Bases: object

process(paramdict, string, fields, name, namespace)
syntax_error(error, string)
lcapy.parser.split(s, delimiters)

Split string by specified delimiters but not if a delimiter is within curly brackets {} or “”.

### Printing¶

This module provides printing support.

lcapy.printing.pretty(expr, **settings)

Pretty print an expression.

lcapy.printing.pprint(expr, **kwargs)

Pretty print an expression.

If have non-interactive shell a latex string is returned.

lcapy.printing.latex(expr, fold_frac_powers=False, fold_func_brackets=False, fold_short_frac=None, inv_trig_style='abbreviated', itex=False, ln_notation=False, long_frac_ratio=None, mat_delim='[', mat_str=None, mode='plain', mul_symbol=None, order=None, symbol_names=None)
lcapy.printing.print_str(expr)

Convert expression into a string.

### Latex¶

class lcapy.latex.Latex(string)

Bases: object

mathrm()

Place words in sub- or super-scripts inside a mathrm. For example V_{rms} -> V_{mathrm{rms}}

lcapy.latex.latex_double_sub(s)
lcapy.latex.latex_format_label(s)
lcapy.latex.latex_format_node_label(s)
lcapy.latex.latex_mathrm(s)
lcapy.latex.latex_str(string)

### Context¶

This module provides the Context class that maintains the context for a Circuit.

class lcapy.context.Context

Bases: object

### State¶

This module provides the State class that maintains the global state.

class lcapy.state.State

Bases: object

new_context()
restore_context()
switch_context(context)

### System¶

This module wraps system dependent programs for pdf generation, etc.

lcapy.system.checkexe(command)
lcapy.system.circuitikz_version()
lcapy.system.convert_pdf_png(pdf_filename, png_filename, dpi=300)
lcapy.system.convert_pdf_png_convert(pdf_filename, png_filename, dpi=300)
lcapy.system.convert_pdf_png_ghostscript(pdf_filename, png_filename, dpi=300)
lcapy.system.convert_pdf_png_pdftoppm(pdf_filename, png_filename, dpi=300)
lcapy.system.convert_pdf_svg(pdf_filename, svg_filename)
lcapy.system.hasexe(program)
lcapy.system.latex_cleanup(tex_filename, wanted_filename='')
lcapy.system.run(command, stderr=-3, stdout=-3, shell=False)
lcapy.system.run_dot(dotfilename, filename)
lcapy.system.run_latex(tex_filename)
lcapy.system.tmpfilename(suffix='')
lcapy.system.which(program)

### Utils¶

lcapy.utils.as_N_D(expr, var, monic_denominator=False)
lcapy.utils.as_sum(expr, var)
lcapy.utils.as_sum_terms(expr, var)
lcapy.utils.factor_const(expr, var)
lcapy.utils.merge_common(lists)
lcapy.utils.scale_shift(expr, t)
lcapy.utils.term_const`(expr, var)