Modules¶
Lcapy is a Python library for symbolic linear circuit and signal analysis.
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 detailed documentation see http://lcapy.readthedocs.io/en/latest
Copyright 2014–2022 Michael Hayes, UCECE
- 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()
Copyright 2014–2023 Michael Hayes, UCECE
- class lcapy.circuit.Circuit(filename=None, netlist=None, allow_anon=False, context=None)¶
Bases:
Netlist
,NetfileMixin
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. This is equivalent to >>> cct.C1.V(t).
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 the Netlist class. It could be rolled into the Circuit class.
Copyright 2014–2023 Michael Hayes, UCECE
- class lcapy.netlist.Netlist(filename=None, context=None, allow_anon=False)¶
Bases:
NetlistOpsMixin
,NetlistMixin
,NetlistSimplifyMixin
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.
- property Idict¶
Return dictionary of branch currents for each transform domain
- property Vdict¶
Return dictionary of node voltages for each transform domain
- ac()¶
Return netlist for ac components of independent sources for angular frequency omega.
See also: dc, transient, laplace.
- annotate(cpts, *args, **kwargs)¶
Annotate a particular component (or list of components) with specified schematic attributes and return new netlist.
For example: cct.annotate(‘R1’, color=’blue’) cct.annotate(‘R1’, ‘color=blue, dashed’) cct.annotate((‘U1’, ‘U2’), fill=’blue’)
See also highlight.
- annotate_current(cpts, domainvar=None, flow=False, pos='')¶
- annotate_currents(cpts=None, domainvar=None, flow=False, eng_format=True, evalf=True, num_digits=3, show_units=True, pos='')¶
Annotate specified list of component names cpts with current (or flow).
domainvar specifies the domain to calculate the voltages for (e.g., t for time-domain, s for Laplace-domain)
flow (default False) if True annotates current as a flow
eng_format (default True) if True use engineering format if the current is a number, e.g., 100,mV instead of 0.1,V
evalf (default True) if True prints floating point numbers as decimals otherwise they are shown as rationals
show_units (default True) if True applies the units (e.g., V for volts)
pos specifies where to position the labels (see docs)
- annotate_node_voltages(nodes=None, domainvar=None, label_voltages=False, eng_format=True, evalf=True, num_digits=3, show_units=True, anchor='south west')¶
Create a new netlist with the node voltages annotated. This is useful for drawing a schematic with the node voltages shown. For example,
cct.annotate_node_voltages((1, 2, 3)).draw()
nodes is a list of the nodes to annotate or None for all.
domainvar specifies the domain to calculate the voltages for (e.g., t for time-domain, s for Laplace-domain)
label_voltages (default False) if True prefixes the annotation with V1= for node 1, etc.
eng_format (default True) if True use engineering format if the voltage is a number, e.g., 100,mV instead of 0.1,V
evalf (default True) if True prints floating point numbers as decimals otherwise they are shown as rationals
num_digits (default 3) specfies the number of digits to print for floating point numbers
show_units (default True) if True applies the units (e.g., V for volts)
anchor (default ‘south west’) specifies the position of the voltage label
- annotate_voltage(cpts, domainvar=None, pos='')¶
- annotate_voltages(cpts=None, domainvar=None, eng_format=True, evalf=True, num_digits=3, show_units=True, pos='')¶
Annotate specified list of component names cpts with voltage.
domainvar specifies the domain to calculate the voltages for (e.g., t for time-domain, s for Laplace-domain)
pos specifies where to position the labels, see docs
eng_format (default True) if True use engineering format if the voltage is a number, e.g., 100,mV instead of 0.1,V
evalf (default True) if True prints floating point numbers as decimals otherwise they are shown as rationals
show_units (default True) if True applies the units (e.g., V for volts)
pos specifies where to position the labels (see docs)
- apply_test_current_source(Np, Nm=None)¶
This copies the netlist, kills all the sources, and applies a Dirac delta test current source across the specified nodes. If the netlist is not connected to ground, the negative specified node is connected to ground. The new netlist is returned.
- apply_test_voltage_source(Np, Nm=None)¶
This copies the netlist, kills all the sources, and applies a Dirac delta test voltage source across the specified nodes. If the netlist is not connected to ground, the negative specified node is connected to ground. The new netlist is returned.
- convert_IVP(t=0)¶
Remove switches from netlist and convert to an initial value problem. t is used to determine the state of the switches.
- property cpts¶
Return list of component names.
- dc()¶
Return netlist for dc components of independent sources.
See also: ac, transient, laplace.
- describe()¶
Print a message describing how circuit is solved.
- description()¶
Return a message describing how circuit is solved.
- expand()¶
Expand the netlist, replacing complicated components with simpler components.
- get_I(name, nowarn=False)¶
Current through component (time-domain)
- get_Vd(Np, Nm=None, **kwargs)¶
Voltage drop between nodes (time-domain)
- get_i(name)¶
Time-domain current through component
- get_vd(Np, Nm=None)¶
Time-domain voltage drop between nodes
- highlight(cpts, color='blue')¶
Highlight a particular component (or list of components) with specified color and return new netlist.
See also annotate.
- initialize(cct, T=None)¶
Set the initial values for this netlist based on the values computed for netlist cct at specified time T.
Alternatively, set the initial values using a dictionary of values keyed by the component name.
- property kinds¶
Return list of transform domain kinds required to analyse the netlist.
- laplace()¶
Return netlist for Laplace representations of independent source values.
See also: dc, ac, transient.
- loop_analysis()¶
Perform loop analysis for this netlist. This is cached.
This is currently an alias for mesh_analysis() and so only works for circuits with a planar topology.
- mesh_analysis()¶
Perform mesh analysis for this netlist. This is cached.
This is only applicable for circuits with a planar topology.
- nodal_analysis()¶
Perform nodal analysis for this netlist. This is cached.
- noise_model(T='T')¶
“Create noise model where resistors are converted into a series combination of an ideal resistor and a noise voltage source.
- noisy(*args, T='T')¶
Return a new circuit with the specified resistors in series with noise voltage sources
- noisy_except(*args, T='T')¶
Return a new circuit with all but the specified resistors in series with noise voltage sources
- open_circuit(cpt)¶
Apply open-circuit in series with component. Returns name of open circuit component.
- property params¶
Return list of symbols used as arguments in the netlist.
- remove(name)¶
Remove specified element by name or elements specified in list.
- renumber(node_map=None)¶
Renumber nodes using specified node_map. If node_map not specified then a mapping is created.
- replace(oldname, newname)¶
Replace component.
For example, b = a.replace(‘C’, ‘W’) c = a.replace(‘C1’, ‘C1 1 2’)
- replace_switches(t=0, switchnames=None)¶
Replace specified switches with open-circuit or short-circuit for time at or after t. If switchnames is not specified, all switches are replaced.
- replace_switches_before(t=0, switchnames=None)¶
Replace specified switches with open-circuit or short-circuit for time just before t. If switchnames is not specified, all switches are replaced.
- save(filename)¶
Save netlist to file.
- select(kind)¶
Return new netlist with transform domain kind selected for specified sources in sourcenames.
- short_circuit(cpt)¶
Apply short-circuit across component. Returns name of voltage source component used as the short.
- property sim¶
Generate simulation object.
- property ss¶
Generate state-space representation. See also state_space()
- property sub¶
Return dictionary of subnetlists keyed by transform domain kind. Note, the subnetlists are not created until a specific one is selected.
- property subcircuits¶
Return dictionary of subnetlists keyed by transform domain kind. Note, the subnetlists are not created until a specific one is selected. The subcircuit keys are : ‘ivp’ for an initial value problem solved using Laplace methods, ‘s’ for transient analysis using Laplace methods, ‘dc’ for DC analysis, ‘time’ for time-domain analysis when there are no reactive components, ‘n*’ for noise-analysis (there is a subcircuit for each independent noise source), and omega (where omega is a number of expression specifying the angular frequency) for phasor analysis.
- property super_nodes¶
Super nodes are nodes linked by voltage sources.
- switching_times(tmax=1000000000000.0)¶
Return sorted list of the times that switches activate prior to tmax.
- property symbols¶
Return dictionary of symbols defined in the netlist.
- transient()¶
Return netlist for transient components of independent sources. Note, unlike the similar laplace method, dc and ac components are ignored.
See also: dc, ac, laplace.
- property undefined_symbols¶
Netfile¶
This module provides the NetfileMixin class. This is used for Netlist and Schematic to parse a netlist file.
Copyright 2020–2023 Michael Hayes, UCECE
- class lcapy.netfile.NetfileMixin¶
Bases:
object
This parses netlist files for Netlist and Schematic.
- add(string)¶
Add a component to the netlist. The general form is: ‘Name Np Nm args’ where Name is the component name, 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.
This returns the added component.
- last_added()¶
Return name of last added component.
- netfile_add(pathname)¶
Add the nets from file with specified pathname
MNA¶
This module implements modified nodal analysis (MNA).
Copyright 2014–2023 Michael Hayes, UCECE
- class lcapy.mna.Branchdict¶
Bases:
ExprDict
- class lcapy.mna.MNA(cct, solver_method)¶
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.
Noise analysis.
Note, it is assumed that the user of this class uses superposition to solve problems with mixed independent sources, such as DC and AC.
- property A¶
Return A matrix for MNA
- property B¶
Return B matrix for MNA
- property C¶
Return C matrix for MNA
- property D¶
Return D matrix for MNA
- property E¶
Return E vector for MNA
- property G¶
Return G matrix for MNA
- property I¶
Return I vector for MNA
- property Idict¶
Return dictionary of transform domain branch currents indexed by component name
- property Vdict¶
Return dictionary of transform domain node voltages indexed by node name
- property X¶
Return X vector (of unknowns) for MNA
- property Z¶
Return Z vector for MNA
- equations(inverse=False)¶
System of equations used to find the unknowns.
If inverse is True, evaluate the matrix inverse.
This is for compatibility and is deprecated. Use matrix_equations instead.
- matrix_equations(form='default', invert=False)¶
System of equations used to find the unknowns.
- Forms can be:
A y = b b = A y Ainv b = y y = Ainv b
If invert is True, evaluate the matrix inverse.
- class lcapy.mna.Nodedict¶
Bases:
ExprDict
Statespace¶
This module defines the StateSpace class for representing a linear continuous time-invariant system as a state-space model.
Copyright 2021–2023 Michael Hayes, UCECE
- class lcapy.statespace.StateSpace(A, B, C, D, u=None, y=None, x=None, x0=None)¶
Bases:
StateSpaceBase
Continuous-time linear time-invariant state space model.
- property G¶
System transfer functions. For a SISO system, use G[0].
- property H¶
X(s) / U(s)
- property Lambda¶
Diagonal matrix of eigenvalues.
- property M¶
Modal matrix (eigenvectors of A).
- property P¶
Characteristic polynomial (aka system polynomial).
lambda(s) = |s * I - A|
- property Phi¶
s-domain state transition matrix.
- property U¶
Laplace transform of input vector.
- property Wc¶
Controllability gramian matrix.
- property Wo¶
Observability gramian matrix.
- property Wr¶
Reachability gramian matrix.
- property X¶
Laplace transform of state-variable vector.
- property Y¶
Laplace transform of output vector.
- characteristic_polynomial()¶
Characteristic polynomial (aka system polynomial).
lambda(s) = |s * I - A|
- property controllability_gramian¶
Controllability gramian matrix.
- discretize(method='bilinear', alpha=0.5)¶
Convert to a discrete-time state space approximation.
The default method is ‘bilinear’. Other methods are ‘forward_euler’, ‘backward_euler’, and ‘gbf’. The latter has a parameter alpha.
- property dotx¶
Time derivative of state variable vector.
- classmethod from_circuit(cct, node_voltages=None, branch_currents=None)¶
- property g¶
System impulse responses.
- generalized_bilinear_transform(alpha=0.5)¶
- property h¶
ILT{X(s) / U(s)}
- property observability_gramian¶
Observability gramian matrix.
- output_equations()¶
System of output equations:
y(t) = C x(t) + D u(t)
where y is the output vector, x is the state vector and u is the input vector.
- property phi¶
State transition matrix.
- property reachability_gramian¶
Reachability gramian matrix. This is equivalent to the controllability gramian matrix for a linear time independent system.
- state_equations()¶
System of first-order differential state equations:
dotx(t) = A x(t) + B u(t)
where x is the state vector and u is the input vector.
- property u¶
Input vector.
- property x¶
State variable vector.
- property x0¶
State variable initial value vector.
- property y¶
Output vector.
Loopanalysis¶
This module performs loop analysis. It is primarily for showing the equations rather than evaluating them.
Copyright 2019–2023 Michael Hayes, UCECE
- class lcapy.loopanalysis.LoopAnalysis(cct)¶
Bases:
object
This performs for loop analysis. Currently, it uses mesh analysis and so is only applicable to circuits with a planar topology.
The API is likely to change since different invocations find different current loops.
>>> from lcapy import Circuit, LoopAnalysis >>> 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 loop analysis in the time domain:
>>> la = LoopAnalysis(cct)
To display the equations found by applying KVL around each mesh:
>>> la.mesh_equations().pprint()
To display the system of equations (in matrix form) that needs to be solved:
>>> la.matrix_equations().pprint()
- property A¶
Return A matrix where A y = b.
- property b¶
Return b vector where A y = b.
- classmethod from_circuit(cct)¶
- loops()¶
Return list of loops. Note, the loops can vary for different invocations of the LoopAnalysis class.
- loops_by_cpt_name()¶
Return list of loops specified by cpt name.
- matrix_equations(form='default', invert=False)¶
Return the equations in matrix form.
- Forms can be:
‘default’ ‘A y = b’ ‘b = A y’ ‘Ainv b = y’ ‘y = Ainv b’
If invert is True, evaluate the matrix inverse.
- mesh_currents()¶
- mesh_equations()¶
Return mesh equations as a dict keyed by the mesh current.
- mesh_equations_list()¶
Return mesh equations as a list.
- property num_loops¶
- solve_laplace()¶
Determine the unknown voltages using Laplace transforms and return as a dict
- property unknowns¶
Return tuple of the unknown voltages
- property y¶
Return y vector where A y = b.
Nodalanalysis¶
This module performs nodal analysis. It is primarily for showing the equations rather than for evaluating them.
Copyright 2019–2022 Michael Hayes, UCECE
- class lcapy.nodalanalysis.NodalAnalysis(cct, node_prefix='')¶
Bases:
object
This is for nodal analysis.
>>> 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 equations found by applying KCL at each node:
>>> na.nodal_equations().pprint()
To display the system of equations (in matrix form) that needs to be solved:
>>> na.matrix_equations().pprint()
- property A¶
Return A matrix where A y = b.
- property b¶
Return b vector where A y = b.
- equations_dict()¶
Return dictionary of equations keyed by node name.
- classmethod from_circuit(cct, node_prefix='')¶
- matrix_equations(form='default', invert=False)¶
Return the equations in matrix form.
- Forms can be:
‘default’ ‘A y = b’ ‘b = A y’ ‘Ainv b = y’ ‘y = Ainv b’
If invert is True, evaluate the matrix inverse.
- nodal_equations()¶
Return the equations found by applying KCL at each node. This is a directory of equations keyed by the node name.
- property nodes¶
- solve_laplace()¶
Determine the unknown voltages using Laplace transforms and return as a dict
- property unknowns¶
Return tuple of the unknown voltages
- property y¶
Return y vector where A y = b.
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.
Copyright 2014–2022 Michael Hayes, UCECE
- class lcapy.oneport.C(Cval='C', v0=None, **kwargs)¶
Bases:
OnePort
Capacitor
Capacitance Cval, initial voltage v0
- current_equation(v, kind='t')¶
Return expression for current through component given applied voltage.
- is_capacitor = True¶
- voltage_equation(i, kind='t')¶
Return expression for voltage across component given applied current.
- class lcapy.oneport.CPE(K, alpha=0.5, **kwargs)¶
Bases:
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.
- class lcapy.oneport.FerriteBead(Rs, Rp, Cp, Lp, **kwargs)¶
Bases:
OnePort
Ferrite bead (lossy inductor)
This is modelled as a series resistor (Rs) connected to a parallel R, L, C network (Rp, Lp, Cp).
- expand()¶
- class lcapy.oneport.G(Gval='G', **kwargs)¶
Bases:
OnePort
Conductor
- current_equation(v, kind='t')¶
Return expression for current through component given applied voltage.
- is_conductor = True¶
- is_noiseless = False¶
- voltage_equation(i, kind='t')¶
Return expression for voltage across component given applied current.
- class lcapy.oneport.I(Ival='Is', **kwargs)¶
Bases:
CurrentSourceBase
Arbitrary current source
- class lcapy.oneport.Iac(Ival, phi=0, omega=None, **kwargs)¶
Bases:
CurrentSourceBase
AC current source.
- property isc¶
Short-circuit time-domain current.
- netkeyword = 'ac'¶
- class lcapy.oneport.Idc(Ival, **kwargs)¶
Bases:
CurrentSourceBase
DC current source (note a DC current source of current i has an s domain current of i / s).
- property isc¶
Short-circuit time-domain current.
- netkeyword = 'dc'¶
- class lcapy.oneport.Inoise(Ival, nid=None, **kwargs)¶
Bases:
CurrentSourceBase
Noise current source.
- is_noisy = True¶
- netkeyword = 'noise'¶
- class lcapy.oneport.Istep(Ival, **kwargs)¶
Bases:
CurrentSourceBase
Step current source (s domain current of i / s).
- netkeyword = 'step'¶
- class lcapy.oneport.L(Lval='L', i0=None, **kwargs)¶
Bases:
OnePort
Inductor
Inductance Lval, initial current i0
- current_equation(v, kind='t')¶
Return expression for current through component given applied voltage.
- is_inductor = True¶
- voltage_equation(i, kind='t')¶
Return expression for voltage across component given applied current.
- class lcapy.oneport.Par(*args)¶
Bases:
ParSer
Parallel class
- property Isc¶
Short-circuit current.
- property admittance¶
- property has_parallel_V¶
- property height¶
Convert a string or number to a floating point number, if possible.
- property impedance¶
- is_parallel = True¶
- property width¶
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ‘+’ or ‘-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int(‘0b100’, base=0) 4
- class lcapy.oneport.R(Rval='R', **kwargs)¶
Bases:
OnePort
Resistor
- current_equation(v, kind='t')¶
Return expression for current through component given applied voltage.
- is_noiseless = False¶
- is_resistor = True¶
- voltage_equation(i, kind='t')¶
Return expression for voltage across component given applied current.
- class lcapy.oneport.Ser(*args)¶
Bases:
ParSer
Series class
- property Voc¶
Open-circuit voltage.
- property admittance¶
- property has_series_I¶
- property height¶
Convert a string or number to a floating point number, if possible.
- property impedance¶
- is_series = True¶
- property width¶
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ‘+’ or ‘-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int(‘0b100’, base=0) 4
- class lcapy.oneport.V(Vval='V', **kwargs)¶
Bases:
VoltageSourceBase
Arbitrary voltage source
- class lcapy.oneport.Vac(V, phi=None, omega=None, **kwargs)¶
Bases:
VoltageSourceBase
AC voltage source.
- netkeyword = 'ac'¶
- property voc¶
Open-circuit time-domain voltage.
- class lcapy.oneport.Vdc(Vval, **kwargs)¶
Bases:
VoltageSourceBase
DC voltage source (note a DC voltage source of voltage V has an s domain voltage of V / s).
- netkeyword = 'dc'¶
- property voc¶
Open-circuit time-domain voltage.
- class lcapy.oneport.Vnoise(V, nid=None, **kwargs)¶
Bases:
VoltageSourceBase
Noise voltage source.
- is_noisy = True¶
- netkeyword = 'noise'¶
- class lcapy.oneport.Vstep(v, **kwargs)¶
Bases:
VoltageSourceBase
Step voltage source (s domain voltage of v / s).
- netkeyword = 'step'¶
- class lcapy.oneport.Xtal(C0, R1, L1, C1, **kwargs)¶
Bases:
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.Y(Yval='Y', **kwargs)¶
Bases:
OnePort
General admittance.
- current_equation(v, kind='t')¶
Return expression for current through component given applied voltage.
- voltage_equation(i, kind='t')¶
Return expression for voltage across component given applied current.
- class lcapy.oneport.Z(Zval='Z', **kwargs)¶
Bases:
OnePort
General impedance.
- current_equation(v, kind='t')¶
Return expression for current through component given applied voltage.
- voltage_equation(i, kind='t')¶
Return expression for voltage across component given applied current.
- class lcapy.oneport.i(Ival, **kwargs)¶
Bases:
CurrentSourceBase
Arbitrary t-domain current source
- lcapy.oneport.ladder(*args, **kwargs)¶
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))
- 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.
- class lcapy.oneport.sI(Ival, **kwargs)¶
Bases:
CurrentSourceBase
Arbitrary s-domain current source
- netkeyword = 's'¶
- class lcapy.oneport.sV(Vval, **kwargs)¶
Bases:
VoltageSourceBase
Arbitrary s-domain voltage source
- netkeyword = 's'¶
- 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.
- class lcapy.oneport.v(vval, **kwargs)¶
Bases:
VoltageSourceBase
Arbitrary t-domain voltage source
Expr¶
This module provides the Expr class. This attempts to create a consistent interface to SymPy’s expressions.
Copyright 2014–2023 Michael Hayes, UCECE
- class lcapy.expr.UnevaluatedExpr(arg, **kwargs)¶
Bases:
Expr
Expression that is not evaluated unless released.
Examples¶
>>> from sympy import UnevaluatedExpr >>> from sympy.abc import x >>> x*(1/x) 1 >>> x*UnevaluatedExpr(1/x) x*1/x
- default_assumptions = {}¶
- doit(**hints)¶
Evaluate objects that are not evaluated by default like limits, integrals, sums and products. All objects of this kind will be evaluated recursively, unless some species were excluded via ‘hints’ or unless the ‘deep’ hint was set to ‘False’.
>>> from sympy import Integral >>> from sympy.abc import x
>>> 2*Integral(x, x) 2*Integral(x, x)
>>> (2*Integral(x, x)).doit() x**2
>>> (2*Integral(x, x)).doit(deep=False) 2*Integral(x, x)
- lcapy.expr.deg(arg, **assumptions)¶
Set units to degrees. See also degrees() that converts radians to degrees.
- lcapy.expr.equation(lhs, rhs, inputsym='x', outputsym='y', **assumptions)¶
Create an Lcapy equation.
This is an Lcapy expression of the form Eq(lhs, rhs). For example, e = equation(‘Y(s)’, ‘X(s) * 2 * s’)
The left hand side(lhs) and right hand side subexpressions can be obtained with the lhs and rhs attributes.
- lcapy.expr.expr(arg, var=None, override=False, units=None, **assumptions)¶
Create Lcapy expression from arg.
If arg is an Expr it is returned, unless assumptions is specified.
- If arg is a string:
If a t symbol is found in the string a TimeDomainExpression object is created. If a s symbol is found in the string a LaplaceDomainExpression object is created. If a f symbol is found in the string an FourierDomainExpression object is created. If an omega symbol is found in the string an AngularFourierDomainExpression object is created.
For example, v = expr(‘3 * exp(-t / tau) * u(t)’)
V = expr(‘5 * s’, causal=True)
If override is True, then create new symbol(s) even if previously defined by SymPy.
- lcapy.expr.rad(arg, **assumptions)¶
Set units to radians. See also radians() that converts degrees to radians.
- lcapy.expr.symbol(name, **assumptions)¶
Create Lcapy symbols from whitespace or comma delimited string of symbol names.
By default, symbols are assumed to be positive and real.
symbols(‘a b’, real=True) creates real symbols
symbols(‘a b’, complex=True) creates complex symbols
symbols(‘a b’, integer=True, positive=True) creates positive integer symbols
See also symbols.
- lcapy.expr.symbols(names, **assumptions)¶
Create Lcapy symbols from whitespace or comma delimited string of symbol names. See also symbol.
Sexpr¶
This module provides the LaplaceDomainExpression class to represent s-domain (Laplace domain) expressions.
Copyright 2014–2023 Michael Hayes, UCECE
- class lcapy.sexpr.LaplaceDomainExpression(val, **assumptions)¶
Bases:
LaplaceDomain
,Expr
s-domain expression or symbol.
- ILT(zero_initial_conditions=None, **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.
By default initial conditions are assumed to be zero. This can be controlled by zero_initial_conditions.
- angular_fourier(**assumptions)¶
Convert to angular Fourier domain.
- angular_frequency_response(**assumptions)¶
Convert to angular frequency response domain. Note, this is similar to the angular Fourier domain but not always.
- as_expr()¶
- backward_euler_transform()¶
Approximate s = ln(z) / dt
by s = (1 / dt) * (1 - z**-1). This is also known as the backward difference method.
See also discretize with regards to scaling of the result.
- bilinear_transform()¶
Approximate s = ln(z) / dt
by s = (2 / dt) * (1 - z**-1) / (1 + z**-1)
This is also called Tustin’s method and is equivalent to the trapezoidal method.
See also discretize with regards to scaling of the result.
- bode_plot(fvector=None, unwrap=True, var=None, strict=False, **kwargs)¶
Plot frequency response for a frequency-domain phasor as a Bode plot (but without the straight line approximations).
If var is None or f, fvector specifies the (linear) frequencies (in hertz) otherwise if var is omega, fvector specifies the angular frequencies (in radians).
If fvector is a tuple (f1, f2), it sets the frequency
limits. Since a logarithmic frequency scale is used, f1 must be greater than 0.
unwrap controls phase unwrapping (default True).
This method makes the assumption that the expression is causal. Note, the Bode plot does not exist for marginally stable and unstable systems since jw is outside the region of convergence.
- delay(T)¶
Apply delay of T seconds by multiplying by exp(-s T).
- differential_equation(inputsym='x', outputsym='y', normalize_a0=True)¶
Create differential equation from transfer function.
For example, >>> H = (s + 3) / (s**2 + 4) >>> H.differential_equation()
d d
- y(t) + –(y(t)) = 4.x(t) + —(x(t))
- dt 2
dt
- discrete_frequency(method='bilinear', **assumptions)¶
- discrete_time(method='bilinear', **assumptions)¶
- discretize(method=None, alpha=0.5, scale=None)¶
Convert to a discrete-time approximation in the z-domain:
\(H(z) pprox K H_c(s)\)
where \(K\) is a scale factor.
Note, the default scaling is different for admittance, impedance, transfer function, or undefined expressions compared to voltage and current expressions.
The scaling is chosen so that the discrete-time voltage and current expressions have plots similar to the continuous-time forms. For example, with the impulse-invariance method for a continuous-time voltage signal \(v_c(t)\):
\(v[n] = v_c(n \Delta t)\)
However, for a transfer-function with a continuous-time impulse response \(h_c(t)\), then
\(h[n] = \Delta t h_c(n \Delta t)\).
This corrects the scaling when approximating a continuous-time convolution by a discrete-time convolution.
The default method is ‘bilinear’. Other methods are: ‘impulse-invariance’ ‘bilinear’, ‘tustin’, ‘trapezoidal’ ‘generalized-bilinear’, ‘gbf’ controlled by the parameter alpha, ‘euler’, ‘forward-diff’, ‘forward-euler’ ‘backward-diff’, ‘backward-euler’ ‘simpson’, ‘matched-Z’, ‘zero-pole-matching’
- dlti_filter(method='bilinear', alpha=0.5)¶
Create DLTI filter using bilinear transform.
- evaluate(svector=None)¶
Evaluate expression at arg. arg may be a scalar or a vector. The result is of type float or complex.
If arg is iterable, a NumPy array is returned.
There can be only one or fewer undefined variables in the expression. This is replaced by arg and then evaluated to obtain a result.
- final_value()¶
Determine value at t = oo.
- forward_euler_transform()¶
Approximate s = ln(z) / dt
by s = (1 / dt) * (1 - z**-1) / z**-1. This is also known as the forward difference method.
See also discretize with regards to scaling of the result.
- fourier(**assumptions)¶
Convert to Fourier domain.
- frequency_response(**assumptions)¶
Convert to frequency response domain. Note, this is similar to the Fourier domain but not always.
- frequency_response_evaluate(fvector=None, var=None, **assumptions)¶
- classmethod from_numer_denom(numer, denom)¶
Create a transfer function from lists of the coefficient for the numerator and denominator.
See also from_zeros_poles_gain, from_poles_residues.
- classmethod from_poles_residues(poles, residues)¶
Create a transfer function from lists of poles and residues.
See also from_zeros_poles_gain, from_numer_denom.
- classmethod from_zeros_poles_gain(zeros, poles, K=1)¶
Create a transfer function from lists of zeros and poles, and from a constant gain.
See also from_poles_residues, from_numer_denom.
- generalized_bilinear_transform(alpha=0.5)¶
Approximate s = ln(z) / dt
by s = (1 / dt) * (1 - z**-1) / (alpha + (1 - alpha) * z**-1))
When alpha = 0 this is equivalent to the forward Euler (forward difference) method.
When alpha = 0.5 this is equivalent to the bilinear transform, aka, Tustin’s method or the trapezoidal method.
When alpha = 1 this is equivalent to the backward Euler (backward difference) method.
See also discretize with regards to scaling of the result.
- impulse_invariance_transform()¶
This samples the impulse response and then calculates the Z-transform. It does not work if the impulse response has Dirac deltas, say for a transfer function that is a pure delay or is not-strictly proper.
The discrete-time and continuous-time impulse responses are identical at the sampling instants n * dt.
The data needs to be sampled many times the bandwidth to avoid aliasing.
See also bilinear_transform and matched_ztransform.
See also discretize with regards to scaling of the result.
- impulse_response(tvector=None)¶
Evaluate transient (impulse) response.
- inverse_laplace(zero_initial_conditions=None, **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.
By default initial conditions are assumed to be zero. This can be controlled by zero_initial_conditions.
- property jomega¶
Return expression with s = j omega.
- laplace(**assumptions)¶
Convert to s-domain.
- lti_filter(normalize_a0=True)¶
Create continuous-time linear time-invariant filter from continuous-time transfer function.
- matched_ztransform()¶
Match poles and zeros of H(s) to approximate H(z).
If there are no zeros, this is equivalent to impulse_invariance.
See also bilinear_transform and impulse_invariance_transform.
See also discretize with regards to scaling of the result.
- nichols_plot(fvector=None, var=None, **kwargs)¶
Plot frequency response for a frequency-domain phasor as a Nichols plot (dB versus phase). fvector specifies the frequencies. If it is a tuple (f1, f2), it sets the frequency limits.
npoints set the number of plotted points.
This method makes the assumption that the expression is causal.
- norm_angular_fourier(**assumptions)¶
Convert to normalized angular Fourier domain.
- norm_fourier(**assumptions)¶
Convert to normalized Fourier domain.
- nyquist_plot(fvector=None, var=None, **kwargs)¶
Plot frequency response for a frequency-domain phasor as a Nyquist plot (imaginary part versus real part). fvector specifies the frequencies. If it is a tuple (f1, f2), it sets the frequency limits.
npoints set the number of plotted points.
The unit circle is shown by default. This can be disabled with unitcircle=False.
This method makes the assumption that the expression is causal.
- phasor(**assumptions)¶
Convert to phasor domain.
- phasor_ratio(**assumptions)¶
Convert to phasor ratio domain.
- plot(**kwargs)¶
Plot pole-zero map.
kwargs include: axes - the plot axes to use otherwise a new figure is created xlabel - the x-axis label (default Re(s)) ylabel - the y-axis label (default Im(s)) xscale - the x-axis scaling yscale - the y-axis scaling pole_color – the color of the pole markers zero_color – the color of the zero markers in addition to those supported by the matplotlib plot command.
The plot axes are returned.
- pole_zero_plot(**kwargs)¶
Plot pole-zero map.
- post_initial_value()¶
Determine post-initial value at t = 0+.
- response(xvector, tvector, method='bilinear', alpha=0.5)¶
Evaluate response to input signal xvector at times specified by tvector. This returns a NumPy array.
The default method is ‘bilinear’. Other methods are: ‘impulse-invariance’ ‘bilinear’, ‘tustin’, ‘trapezoidal’ ‘generalized-bilinear’, ‘gbf’ controlled by the parameter alpha ‘euler’, ‘forward-diff’, ‘forward-euler’ ‘backward-diff’, ‘backward-euler’.
See also discretize with regards to scaling of the result.
- simpson_transform()¶
Approximate s = ln(z) / dt
by s = (3 / dt) * (z**2 - 1) / (z**2 + 4 * z + 1). This is more accurate than the other methods but doubles the system order and can produce unstable poles.
See also discretize with regards to scaling of the result.
- property ss¶
Return state-space representation using controllable canonical form. For other forms, use state_space().
- state_space(form='CCF')¶
Create state-space representation from transfer function. Note, state-space representations are not unique and are determined by the form argument. Currently this can be ‘CCF’ for the controllable canonical form, ‘OCF’ for the observable canonical form, or ‘DCF’ for the diagonal canonical form.
- step_response(tvector=None)¶
Evaluate step response.
- tdifferentiate()¶
Differentiate in t-domain (multiply by s).
- time(**assumptions)¶
Convert to time domain.
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.
- tintegrate()¶
Integrate in t-domain (divide by s).
- transient_response(tvector=None)¶
Evaluate transient (impulse) response.
- var = s¶
- zdomain(**assumptions)¶
- lcapy.sexpr.pr2tf(poles, residues, var=None)¶
Create a transfer function from lists of poles and residues.
- lcapy.sexpr.sexpr(arg, **assumptions)¶
Create LaplaceDomainExpression object. If arg is ssym return s
- lcapy.sexpr.tf(numer, denom=1, var=None)¶
Create a transfer function from lists of the coefficient for the numerator and denominator.
- lcapy.sexpr.zp2tf(zeros, poles, K=1, var=None)¶
Create a transfer function from lists (or dictionaries) of zeros and poles, and from a constant gain.
Cexpr¶
This module provides the ConstantDomainExpression class to represent constant expressions.
Note there are two types: 1. ConstantTimeDomainExpression for signals 2. ConstantFrequencyResponseDomainExpression for transfer functions and immitances.
Note, impedance(3)(s) gives 3 but voltage(3)(s) gives 3 / s. Similarly, voltage(3)(t) gives 3 but impedance(3)(t) gives 3 * delta)(t)
Copyright 2014–2023 Michael Hayes, UCECE
- class lcapy.cexpr.ConstantDomainExpression(val, **assumptions)¶
Bases:
ConstantDomain
,ConstantExpr
Constant real expression or symbol.
If symbols in the expression are known to be negative, use ConstantDomainExpression(expr, positive=False)
- class lcapy.cexpr.ConstantFrequencyResponseDomainExpression(val, **assumptions)¶
Bases:
ConstantFrequencyResponseDomain
,ConstantExpr
This represents constant impedance, admittance, and transfer functions.
Note, impedance(3)(s) gives 3 but voltage(3)(s) gives 3 / s.
- laplace(**assumptions)¶
Convert to Laplace domain representation.
- phasor(omega=None, **assumptions)¶
- time(**assumptions)¶
Convert to time domain.
- class lcapy.cexpr.ConstantTimeDomainExpression(val, **assumptions)¶
Bases:
ConstantTimeDomain
,ConstantExpr
This represents constant voltage, current, voltage-squared, and current-squared signals.
Note, impedance(3)(s) gives 3 but voltage(3)(s) gives 3 / s.
- phasor_ratio(omega=None, **assumptions)¶
- lcapy.cexpr.cexpr(arg, frequency=False, **assumptions)¶
Create Lcapy constant expression from arg.
By default, arg is assumed to be positive. If symbols in the arg are known to be negative, use cexpr(arg, positive=False).
Texpr¶
This module provides the TimeDomainExpression class to represent time domain expressions.
Copyright 2014–2023 Michael Hayes, UCECE
- class lcapy.texpr.TimeDomainExpression(val, **assumptions)¶
Bases:
TimeDomain
,Expr
t-domain expression or symbol.
- FT(var=None, evaluate=True, **assumptions)¶
Attempt Fourier transform.
X(f) = int_{-infty} ^ {infty} x(t) exp(-j 2pi f t) dt.
- LT(evaluate=True, zero_initial_conditions=None, **assumptions)¶
Determine one-sided Laplace transform with 0- as the lower limit.
By default initial conditions are assumed to be zero. This can be controlled by zero_initial_conditions.
This is an alias for laplace.
- property abs¶
Return absolute value.
- angular_fourier(evaluate=True, **assumptions)¶
Attempt angular Fourier transform.
- angular_frequency_response(**assumptions)¶
Convert to angular frequency response domain. Note, this is similar to the angular Fourier domain but not always.
- as_expr()¶
- differential_equation(inputsym='x', outputsym='y')¶
Create differential equation from impulse response.
- discrete_frequency(**assumptions)¶
- discrete_time(**assumptions)¶
- discretize(method=None, alpha=0.5)¶
Convert to a discrete-time approximation:
\(x(n) pprox K x(t)\)
where \(K\) is a scale factor.
The default method depends on the expression quantity. If the quantity is undefined, voltage, current, `voltagesquared, currentsquared, or power, the default method is impulse-invariance and there is no scaling. This uses:
: math: x[n] = x(n Delta t)
For other quantities, the default method is bilinear’, and the result is scaled by the sampling interval (`Delta t) as is common for the discrete-time impulse response of digital filters:
: math: h[n] = Delta t h_c(n Delta t)
The methods are: ‘impulse-invariance’ ‘bilinear’, ‘tustin’, ‘trapezoidal’ ‘generalized-bilinear’, ‘gbf’ controlled by the parameter alpha ‘euler’, ‘forward-diff’, ‘forward-euler’ ‘backward-diff’, ‘backward-euler’ ‘simpson’, ‘matched-Z’, ‘zero-pole-matching’. All the methods except impulse-invariance are applied in the Laplace domain so the result is unknown for n < 0 unless the expression is causal.
- dlti_filter(method='bilinear')¶
Create DLTI filter using bilinear transform.
- property energy¶
Return signal energy.
- 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(var=None, evaluate=True, **assumptions)¶
Attempt Fourier transform. This is an alias for FT.
- frequency_response(**assumptions)¶
Convert to frequency response domain. Note, this is similar to the Fourier domain but not always.
- infer_assumptions()¶
- initial_value()¶
Determine value at t = 0. See also pre_initial_value and post_initial_value
- laplace(evaluate=True, zero_initial_conditions=None, **assumptions)¶
Determine one-sided Laplace transform with 0- as the lower limit.
By default initial conditions are assumed to be zero. This can be controlled by zero_initial_conditions.
This is an alias for LT.
- norm_angular_fourier(evaluate=True, **assumptions)¶
Attempt normalized angular Fourier transform.
- norm_fourier(evaluate=True, **assumptions)¶
Attempt normalized Fourier transform.
- phasor(**assumptions)¶
Convert to phasor domain.
- 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 plot_deltas - plot Dirac deltas as arrows in addition to those supported by the matplotlib plot command.
The plot axes are returned.
- post_initial_value()¶
Determine value at t = 0+. See also pre_initial_value and initial_value
- pre_initial_value()¶
Determine value at t = 0-. See also initial_value and post_initial_value
- response(xvector, tvector, method='bilinear')¶
Evaluate response to input signal xvector at times tvector. This returns a NumPy array.
- sample(tvector)¶
Return a discrete-time signal evaluated at time values specified by tvector. This returns a NumPy array.
- time(**assumptions)¶
- var = t¶
- zdomain(**assumptions)¶
- lcapy.texpr.texpr(arg, **assumptions)¶
Create TimeDomainExpression object. If arg is tsym return t
Fexpr¶
This module provides the FourierDomainExpression class to represent f-domain (Fourier domain) expressions.
Copyright 2014–2023 Michael Hayes, UCECE
- class lcapy.fexpr.FourierDomainExpression(val, **assumptions)¶
Bases:
FourierDomain
,Expr
Fourier domain expression or symbol.
- IDTFT(evaluate=True, **assumptions)¶
Convert to discrete-time domain using inverse discrete-time Fourier transform.
- IFT(evaluate=True, **assumptions)¶
Convert to time domain. This is an alias for inverse_fourier.
- angular_fourier(**assumptions)¶
Convert to angular Fourier domain.
- angular_frequency_response(**assumptions)¶
Convert to angular frequency response domain.
- as_expr()¶
- bode_plot(fvector=None, unwrap=True, **kwargs)¶
Plot frequency response for a frequency-domain phasor as a Bode plot (but without the straight line approximations). fvector specifies the frequencies. If it is a tuple (f1, f2), it sets the frequency limits. Since a logarithmic frequency scale is used, f1 must be greater than 0.
unwrap controls phase unwrapping (default True).
For more info, see plot.
- property energy¶
Return signal energy.
- frequency_response(**assumptions)¶
Convert to frequency response domain.
- inverse_fourier(evaluate=True, **assumptions)¶
Attempt inverse Fourier transform.
- laplace(**assumptions)¶
Determine one-sided Laplace transform with 0- as the lower limit.
- nichols_plot(fvector=None, log_frequency=True, **kwargs)¶
Plot frequency response as a Nichols plot (dB part versus phase). fvector specifies the frequencies. If it is a tuple (f1, f2), it sets the frequency limits as (f1, f2).
npoints set the number of plotted points.
- norm_angular_fourier(**assumptions)¶
Convert to normalized angular Fourier domain.
- norm_fourier(**assumptions)¶
Convert to normalized Fourier domain.
- nyquist_plot(fvector=None, log_frequency=True, **kwargs)¶
Plot frequency response as a Nyquist plot (imaginary part versus real part). fvector specifies the frequencies. If it is a tuple (f1, f2), it sets the frequency limits as (f1, f2).
npoints set the number of plotted points.
The unit circle is shown by default. This can be disabled with unitcircle=False.
- phasor(**assumptions)¶
Convert to phasor domain.
- plot(fvector=None, plot_type=None, **kwargs)¶
Plot frequency response at values specified by fvector.
If fvector is a tuple, this sets the frequency limits.
plot_type - ‘dB-phase’, ‘dB-phase-degrees’, ‘mag-phase’, ‘mag-phase-degrees’, ‘real-imag’, ‘mag’, ‘phase’, ‘phase-degrees’, ‘real’, or ‘imag’.
The default plot_type for complex data is dB-phase.
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 norm - use normalized frequency dbmin - the smallest value to plot in dB (default -120) plot_deltas - plot Dirac deltas as arrows in addition to those supported by the matplotlib plot command.
The plot axes are returned. This is a tuple for magnitude/phase or real/imaginary plots.
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)¶
- var = f¶
- lcapy.fexpr.fexpr(arg, **assumptions)¶
Create FourierDomainExpression object. If arg is fsym return f
Nexpr¶
This module provides the DiscreteTimeDomainExpression class to represent discrete-time expressions.
Copyright 2020–2023 Michael Hayes, UCECE
- lcapy.nexpr.nexpr(arg, **assumptions)¶
Create nExpr object. If arg is nsym return n
Kexpr¶
- This module provides the DiscreteFourierDomainExpression class to
represent k-domain (discrete Fourier domain) expressions.
Copyright 2020–2021 Michael Hayes, UCECE
- lcapy.kexpr.kexpr(arg, **assumptions)¶
Create kExpr object. If arg is ksym return k
Zexpr¶
This module provides the ZDomainExpression class to represent z-domain expressions.
Copyright 2020–2022 Michael Hayes, UCECE
- lcapy.zexpr.zexpr(arg, **assumptions)¶
Create ZDomainExpression object. If arg is zsym return z
Sequence¶
This module handles sequences.
Copyright 2020–2023 Michael Hayes, UCECE
- class lcapy.sequence.Sequence(seq, ni=None, origin=None, evaluate=False, var=None, start_trunc=False, end_trunc=False)¶
Bases:
ExprList
,SeqDomain
- DTFT(var=None, **assumptions)¶
Convert to Fourier domain using discrete time Fourier transform.
- as_array()¶
Numerically evaluate and store as NumPy array.
- 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.
- copy()¶
Return a shallow copy of the list.
- delay(m=0)¶
Return a new sequence delayed by an integer number of samples m. If m is negative, the sequence is advanced.
- discrete_time_fourier_transform(var=None, **assumptions)¶
Convert to Fourier domain using discrete time Fourier transform.
- evaluate(ni=None)¶
Evaluate expression at sequence indices specified by arg. arg may be a scalar or a vector. The result is of type float or complex. Zeroes are returned for indices outside the sequence extent.
If arg is iterable, a NumPy array is returned.
- property expr¶
Convert sequence to an Lcapy expression.
- property 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
- is_sequence = True¶
- lfilter(b=None, a=None)¶
Implement digital filter specified by a transfer function. The transfer function is described by a vector b of coefficients for the numerator and an a vector of coefficients for the denominator.
If you would like the response with initial conditions see DTfilter.response().
For a FIR filter a = [1].
- property origin¶
Return the element index for n == 0. This may raise a ValueError if the origin is not in the sequence.
- plot(ni=None, **kwargs)¶
Plot the sequence. If ni is not specified, it defaults to the sequence indices. ni can be a vector of specified sequence indices, 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)¶
Make pretty string.
- prune()¶
Remove zeros from ends of sequence.
{0, 0, 1, 2, 3, 0} -> {1, 2, 3}
- quantity = 'undefined'¶
- property vals¶
Return the SymPy values as a list.
- var = None¶
- zeroextend()¶
Extend sequence by adding zeros so that the origin is included. This is used for printing.
- zeropad(M)¶
Add M zeros to end of sequence:
For example, with M = 3
{1, 2, 3} -> {1, 2, 3, 0, 0, 0}
- lcapy.sequence.parse_seq_str(s)¶
Omegaexpr¶
This module provides the AngularFourierDomainExpression class to represent omega-domain (angular frequency Fourier domain) expressions.
Copyright 2014–2022 Michael Hayes, UCECE
- lcapy.omegaexpr.omegaexpr(arg, **assumptions)¶
Create AngularFourierDomainExpression object. If arg is omegasym return omega
Noiseexpr¶
This module provides the NoiseExpression class to represent noise expressions.
Copyright 2020–2022 Michael Hayes, UCECE
- class lcapy.noiseexpr.NoiseExpression(val, **assumptions)¶
Bases:
Expr
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 (NoiseExpression(3) + NoiseExpression(4)).expr = 5 since 5 = sqrt(3**2 + 4**2)
NoiseExpression(3) != NoiseExpression(3) since they are different noise realisations albeit with the same properties. However, NoiseExpression(3).expr == NoiseExpression(3).expr. Similarly, NoiseExpression(3, nid=’n1’) == NoiseExpression(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 = NoiseExpression(3); b = NoiseExpression(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.
- asd()¶
- autocorrelation()¶
- fourier()¶
- is_positive = True¶
- is_real = True¶
- laplace()¶
- property nid¶
- 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.
- psd()¶
- rms()¶
Calculate rms value.
- sample(t, seed=None)¶
Return a sample function (realisation) of the noise process evaluated at time values specified by vector t. If t is an integer, this returns t samples.
- subs(*args, **kwargs)¶
Substitute symbols in expression.
args is either: - two arguments, e.g. foo.subs(old, new) - one iterable argument, e.g. foo.subs(iterable). The iterable may be
- o an iterable container with (old, new) pairs. In this case the
replacements are processed in the order given with successive patterns possibly affecting replacements already made.
o a dict or set whose key/value items correspond to old/new pairs.
The domain of the result can be coerced using domain argument.
- time()¶
Phasor¶
- This module provides the PhasorDomain and PhasorRatioDomain classes
to represent phasors and ratios of 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.
Phasors straddle the time and frequency domains and hence the confusing phasor classes.
A phasor is described by an amplitude and phase. There is also an implicit frequency. The amplitude and phase are usually functions of frequency. A phasor is useful to describe an AC voltage or current signal.
Lcapy considers V(jw) or I(jw) a generic phasor but V(3j) or I(3j) a specific phasor. Similarly, X(jw) is a generic phasor ratio and X(3j) is a specific phasor ratio, where X denotes an immittance or transfer function.
A ratio of two phasors (of the same frequency) is not a phasor. The ratio of two generic phasors is a frequency domain quantity. The frequency dependence is explicit. A phasor ratio is useful to describe an immittance or transfer function. These are frequency domain concepts. A phasor ratio can be inferred from the Laplace domain by substituting jomega (or jw) for s, where omega is the angular frequency of the phasor.
Copyright 2014–2023 Michael Hayes, UCECE
- class lcapy.phasor.PhasorDomainExpression(val, **assumptions)¶
Bases:
PhasorDomain
,PhasorExpression
This is a phasor domain base class for voltages and currents.
- angular_fourier(**assumptions)¶
Angular Fourier transform.
- as_expr()¶
- fourier(**assumptions)¶
Fourier transform.
- classmethod from_constant(expr, omega=None, **assumptions)¶
- classmethod from_time(expr, omega=None, **assumptions)¶
- laplace(**assumptions)¶
Convert to Laplace domain representation.
- plot(**kwargs)¶
Plot polar diagram.
- time(**assumptions)¶
Convert to time domain representation.
- class lcapy.phasor.PhasorRatioDomainExpression(val, **assumptions)¶
Bases:
PhasorRatioDomain
,PhasorExpression
This represents the ratio of two-phasors; for example an impedance, an admittance, or a transfer function.
- angular_fourier(**assumptions)¶
Angular Fourier transform.
- as_expr()¶
- bode_plot(fvector=None, unwrap=True, **kwargs)¶
Plot frequency response for a frequency-domain phasor as a Bode plot (but without the straight line approximations). fvector specifies the frequencies. If it is a tuple (m1, m2), it sets the frequency limits as (10**m1, 10**m2).
unwrap controls phase unwrapping (default True).
- property domain_label¶
str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to ‘strict’.
- property domain_units¶
Expression representing multiplication operation for algebraic field.
Deprecated since version 1.7: Using arguments that aren’t subclasses of
Expr
in core operators (Mul
,Add
, andPow
) is deprecated. See non-expr-args-deprecated for details.Every argument of
Mul()
must beExpr
. Infix operator*
on most scalar objects in SymPy calls this class.Another use of
Mul()
is to represent the structure of abstract multiplication so that its arguments can be substituted to return different class. Refer to examples section for this.Mul()
evaluates the argument unlessevaluate=False
is passed. The evaluation logic includes:- Flattening
Mul(x, Mul(y, z))
->Mul(x, y, z)
- Identity removing
Mul(x, 1, y)
->Mul(x, y)
- Exponent collecting by
.as_base_exp()
Mul(x, x**2)
->Pow(x, 3)
- Exponent collecting by
- Term sorting
Mul(y, x, 2)
->Mul(2, x, y)
Since multiplication can be vector space operation, arguments may have the different
sympy.core.kind.Kind()
. Kind of the resulting object is automatically inferred.Examples¶
>>> from sympy import Mul >>> from sympy.abc import x, y >>> Mul(x, 1) x >>> Mul(x, x) x**2
If
evaluate=False
is passed, result is not evaluated.>>> Mul(1, 2, evaluate=False) 1*2 >>> Mul(x, x, evaluate=False) x*x
Mul()
also represents the general structure of multiplication operation.>>> from sympy import MatrixSymbol >>> A = MatrixSymbol('A', 2,2) >>> expr = Mul(x,y).subs({y:A}) >>> expr x*A >>> type(expr) <class 'sympy.matrices.expressions.matmul.MatMul'>
See Also¶
MatMul
- fourier(**assumptions)¶
Fourier transform.
- classmethod from_laplace(expr, **assumptions)¶
- is_phasor_ratio_domain = True¶
- is_transform_domain = True¶
- laplace(**assumptions)¶
Convert to Laplace domain representation.
- plot(fvector=None, **kwargs)¶
Plot frequency response.
If the dependent variable is omega, fvector specifies the angular frequencies. If it is a tuple, it sets the angular frequency limits.
If the dependent variable is f, fvector specifies the linear frequencies. If it is a tuple, it sets the linear frequency limits.
- time(**assumptions)¶
Convert to time domain representation.
- lcapy.phasor.phasor(arg, omega=None, **assumptions)¶
Create phasor.
If arg has the form A * cos(w * t + phi) the phasor A * exp(j * phi) of angular frequency w is returned.
If arg has the form A * sin(w * t + phi) the phasor A * exp(j * (phi - pi / 2)) of angular frequency w is returned.
If arg is a constant C, the phasor C is created with omega as the angular frequency (this defaults to ‘omega’ if not specified).
- lcapy.phasor.phasor_ratio(arg, omega=None, **assumptions)¶
Create phasor ratio.
If arg is a constant C, the phasor ratio C is created with omega as the angular frequency (this defaults to ‘omega’ if not specified).
Matrix¶
This module implements the Lcapy Matrix class.
Copyright 2019–2023 Michael Hayes, UCECE
- class lcapy.matrix.Matrix(*args, **kwargs)¶
Bases:
MutableDenseMatrix
- canonical()¶
- property conj¶
Complex conjugate; for compatilibility with Expr conj is an attribute.
- det()¶
Computes the determinant of a matrix if
M
is a concrete matrix object otherwise return an expressionsDeterminant(M)
ifM
is aMatrixSymbol
or other expression.Parameters¶
- methodstring, optional
Specifies the algorithm used for computing the matrix determinant.
If the matrix is at most 3x3, a hard-coded formula is used and the specified method is ignored. Otherwise, it defaults to
'bareiss'
.Also, if the matrix is an upper or a lower triangular matrix, determinant is computed by simple multiplication of diagonal elements, and the specified method is ignored.
If it is set to
'domain-ge'
, then Gaussian elimination method will be used via using DomainMatrix.If it is set to
'bareiss'
, Bareiss’ fraction-free algorithm will be used.If it is set to
'berkowitz'
, Berkowitz’ algorithm will be used.Otherwise, if it is set to
'lu'
, LU decomposition will be used.Note
For backward compatibility, legacy keys like “bareis” and “det_lu” can still be used to indicate the corresponding methods. And the keys are also case-insensitive for now. However, it is suggested to use the precise keys for specifying the method.
- iszerofuncFunctionType or None, optional
If it is set to
None
, it will be defaulted to_iszero
if the method is set to'bareiss'
, and_is_zero_after_expand_mul
if the method is set to'lu'
.It can also accept any user-specified zero testing function, if it is formatted as a function which accepts a single symbolic argument and returns
True
if it is tested as zero andFalse
if it tested as non-zero, and alsoNone
if it is undecidable.
Returns¶
- detBasic
Result of determinant.
Raises¶
- ValueError
If unrecognized keys are given for
method
oriszerofunc
.- NonSquareMatrixError
If attempted to calculate determinant from a non-square matrix.
Examples¶
>>> from sympy import Matrix, eye, det >>> I3 = eye(3) >>> det(I3) 1 >>> M = Matrix([[1, 2], [3, 4]]) >>> det(M) -2 >>> det(M) == M.det() True >>> M.det(method="domain-ge") -2
- discretize(method=None, alpha=0.5, drop_dt=False)¶
- evaluate(arg=None)¶
Evaluate matrix at arg. arg may be a scalar. The result is a NumPy float or complex array.
There can be only one or fewer undefined variables in the expression. This is replaced by arg and then evaluated to obtain a result.
- property expr¶
- inv(method='default')¶
Return the inverse of a matrix using the method indicated. Default for dense matrices is is Gauss elimination, default for sparse matrices is LDL.
Parameters¶
method : (‘GE’, ‘LU’, ‘ADJ’, ‘CH’, ‘LDL’)
- iszerofuncfunction, optional
Zero-testing function to use.
- try_block_diagbool, optional
If True then will try to form block diagonal matrices using the method get_diag_blocks(), invert these individually, and then reconstruct the full inverse matrix.
Examples¶
>>> from sympy import SparseMatrix, Matrix >>> A = SparseMatrix([ ... [ 2, -1, 0], ... [-1, 2, -1], ... [ 0, 0, 2]]) >>> A.inv('CH') Matrix([ [2/3, 1/3, 1/6], [1/3, 2/3, 1/3], [ 0, 0, 1/2]]) >>> A.inv(method='LDL') # use of 'method=' is optional Matrix([ [2/3, 1/3, 1/6], [1/3, 2/3, 1/3], [ 0, 0, 1/2]]) >>> A * _ Matrix([ [1, 0, 0], [0, 1, 0], [0, 0, 1]]) >>> A = Matrix(A) >>> A.inv('CH') Matrix([ [2/3, 1/3, 1/6], [1/3, 2/3, 1/3], [ 0, 0, 1/2]]) >>> A.inv('ADJ') == A.inv('GE') == A.inv('LU') == A.inv('CH') == A.inv('LDL') == A.inv('QR') True
Notes¶
According to the
method
keyword, it calls the appropriate method:GE …. inverse_GE(); default for dense matrices LU …. inverse_LU() ADJ … inverse_ADJ() CH … inverse_CH() LDL … inverse_LDL(); default for sparse matrices QR … inverse_QR()
Note, the GE and LU methods may require the matrix to be simplified before it is inverted in order to properly detect zeros during pivoting. In difficult cases a custom zero detection function can be provided by setting the
iszerofunc
argument to a function that should return True if its argument is zero. The ADJ routine computes the determinant and uses that to detect singular matrices in addition to testing for zeros on the diagonal.See Also¶
inverse_ADJ inverse_GE inverse_LU inverse_CH inverse_LDL
Raises¶
- ValueError
If the determinant of the matrix is zero.
- property is_complex¶
- latex(**kwargs)¶
- next_timestep()¶
- norm()¶
Return the Norm of a Matrix or Vector.
In the simplest case this is the geometric size of the vector Other norms can be specified by the ord parameter
ord
norm for matrices
norm for vectors
None
Frobenius norm
2-norm
‘fro’
Frobenius norm
does not exist
inf
maximum row sum
max(abs(x))
-inf
–
min(abs(x))
1
maximum column sum
as below
-1
–
as below
2
2-norm (largest sing. value)
as below
-2
smallest singular value
as below
other
does not exist
sum(abs(x)**ord)**(1./ord)
Examples¶
>>> from sympy import Matrix, Symbol, trigsimp, cos, sin, oo >>> x = Symbol('x', real=True) >>> v = Matrix([cos(x), sin(x)]) >>> trigsimp( v.norm() ) 1 >>> v.norm(10) (sin(x)**10 + cos(x)**10)**(1/10) >>> A = Matrix([[1, 1], [1, 1]]) >>> A.norm(1) # maximum sum of absolute values of A is 2 2 >>> A.norm(2) # Spectral norm (max of |Ax|/|x| under 2-vector-norm) 2 >>> A.norm(-2) # Inverse spectral norm (smallest singular value) 0 >>> A.norm() # Frobenius Norm 2 >>> A.norm(oo) # Infinity Norm 2 >>> Matrix([1, -2]).norm(oo) 2 >>> Matrix([-1, 2]).norm(-oo) 1
See Also¶
normalized
- property numpy¶
Return NumPy array; not a NumPy matrix.
- pdb()¶
Enter the python debugger.
- pprint()¶
- replace(query, value, map=False, simultaneous=True, exact=None)¶
Replaces Function F in Matrix entries with Function G.
Examples¶
>>> from sympy import symbols, Function, Matrix >>> F, G = symbols('F, G', cls=Function) >>> M = Matrix(2, 2, lambda i, j: F(i+j)) ; M Matrix([ [F(0), F(1)], [F(1), F(2)]]) >>> N = M.replace(F,G) >>> N Matrix([ [G(0), G(1)], [G(1), G(2)]])
- rewrite(*args, **hints)¶
- simplify()¶
Applies simplify to the elements of a matrix in place.
This is a shortcut for M.applyfunc(lambda x: simplify(x, ratio, measure))
See Also¶
sympy.simplify.simplify.simplify
- subs(*args, **kwargs)¶
Substitute variables in expression, see sympy.subs for usage.
- property symbols¶
- property sympy¶
- 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.matrix_inverse(M, method='default')¶
- lcapy.matrix.matrix_solve(M, b, method='default')¶
- lcapy.matrix.msympify(expr)¶
Smatrix¶
This module implements the LaplaceDomainMatrix class for a matrix of Laplace-domain expressions.
Copyright 2019–2023 Michael Hayes, UCECE
- class lcapy.smatrix.LaplaceDomainAdmittanceMatrix(*args, **kwargs)¶
Bases:
LaplaceDomainMatrix
- class LaplaceDomainAdmittance(val, **assumptions)¶
Bases:
AdmittanceMixin
,LaplaceDomainExpression
Angular frequency-domain admittance (units S).
- class lcapy.smatrix.LaplaceDomainCurrentMatrix(*args, **kwargs)¶
Bases:
LaplaceDomainMatrix
- class LaplaceDomainCurrent(val, **assumptions)¶
Bases:
CurrentMixin
,LaplaceDomainExpression
Angular frequency-domain current (units A/Hz).
- class lcapy.smatrix.LaplaceDomainImpedanceMatrix(*args, **kwargs)¶
Bases:
LaplaceDomainMatrix
- class LaplaceDomainImpedance(val, **assumptions)¶
Bases:
ImpedanceMixin
,LaplaceDomainExpression
Angular frequency-domain impedance (units ohm).
- class lcapy.smatrix.LaplaceDomainMatrix(*args, **kwargs)¶
Bases:
Matrix
- ILT(**assumptions)¶
- class LaplaceDomainExpression(val, **assumptions)¶
Bases:
LaplaceDomain
,Expr
s-domain expression or symbol.
- ILT(zero_initial_conditions=None, **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.
By default initial conditions are assumed to be zero. This can be controlled by zero_initial_conditions.
- angular_fourier(**assumptions)¶
Convert to angular Fourier domain.
- angular_frequency_response(**assumptions)¶
Convert to angular frequency response domain. Note, this is similar to the angular Fourier domain but not always.
- as_expr()¶
- backward_euler_transform()¶
Approximate s = ln(z) / dt
by s = (1 / dt) * (1 - z**-1). This is also known as the backward difference method.
See also discretize with regards to scaling of the result.
- bilinear_transform()¶
Approximate s = ln(z) / dt
by s = (2 / dt) * (1 - z**-1) / (1 + z**-1)
This is also called Tustin’s method and is equivalent to the trapezoidal method.
See also discretize with regards to scaling of the result.
- bode_plot(fvector=None, unwrap=True, var=None, strict=False, **kwargs)¶
Plot frequency response for a frequency-domain phasor as a Bode plot (but without the straight line approximations).
If var is None or f, fvector specifies the (linear) frequencies (in hertz) otherwise if var is omega, fvector specifies the angular frequencies (in radians).
If fvector is a tuple (f1, f2), it sets the frequency
limits. Since a logarithmic frequency scale is used, f1 must be greater than 0.
unwrap controls phase unwrapping (default True).
This method makes the assumption that the expression is causal. Note, the Bode plot does not exist for marginally stable and unstable systems since jw is outside the region of convergence.
- delay(T)¶
Apply delay of T seconds by multiplying by exp(-s T).
- differential_equation(inputsym='x', outputsym='y', normalize_a0=True)¶
Create differential equation from transfer function.
For example, >>> H = (s + 3) / (s**2 + 4) >>> H.differential_equation()
d d
- y(t) + –(y(t)) = 4.x(t) + —(x(t))
- dt 2
dt
- discrete_frequency(method='bilinear', **assumptions)¶
- discrete_time(method='bilinear', **assumptions)¶
- discretize(method=None, alpha=0.5, scale=None)¶
Convert to a discrete-time approximation in the z-domain:
\(H(z) pprox K H_c(s)\)
where \(K\) is a scale factor.
Note, the default scaling is different for admittance, impedance, transfer function, or undefined expressions compared to voltage and current expressions.
The scaling is chosen so that the discrete-time voltage and current expressions have plots similar to the continuous-time forms. For example, with the impulse-invariance method for a continuous-time voltage signal \(v_c(t)\):
\(v[n] = v_c(n \Delta t)\)
However, for a transfer-function with a continuous-time impulse response \(h_c(t)\), then
\(h[n] = \Delta t h_c(n \Delta t)\).
This corrects the scaling when approximating a continuous-time convolution by a discrete-time convolution.
The default method is ‘bilinear’. Other methods are: ‘impulse-invariance’ ‘bilinear’, ‘tustin’, ‘trapezoidal’ ‘generalized-bilinear’, ‘gbf’ controlled by the parameter alpha, ‘euler’, ‘forward-diff’, ‘forward-euler’ ‘backward-diff’, ‘backward-euler’ ‘simpson’, ‘matched-Z’, ‘zero-pole-matching’
- dlti_filter(method='bilinear', alpha=0.5)¶
Create DLTI filter using bilinear transform.
- evaluate(svector=None)¶
Evaluate expression at arg. arg may be a scalar or a vector. The result is of type float or complex.
If arg is iterable, a NumPy array is returned.
There can be only one or fewer undefined variables in the expression. This is replaced by arg and then evaluated to obtain a result.
- final_value()¶
Determine value at t = oo.
- forward_euler_transform()¶
Approximate s = ln(z) / dt
by s = (1 / dt) * (1 - z**-1) / z**-1. This is also known as the forward difference method.
See also discretize with regards to scaling of the result.
- fourier(**assumptions)¶
Convert to Fourier domain.
- frequency_response(**assumptions)¶
Convert to frequency response domain. Note, this is similar to the Fourier domain but not always.
- frequency_response_evaluate(fvector=None, var=None, **assumptions)¶
- classmethod from_numer_denom(numer, denom)¶
Create a transfer function from lists of the coefficient for the numerator and denominator.
See also from_zeros_poles_gain, from_poles_residues.
- classmethod from_poles_residues(poles, residues)¶
Create a transfer function from lists of poles and residues.
See also from_zeros_poles_gain, from_numer_denom.
- classmethod from_zeros_poles_gain(zeros, poles, K=1)¶
Create a transfer function from lists of zeros and poles, and from a constant gain.
See also from_poles_residues, from_numer_denom.
- generalized_bilinear_transform(alpha=0.5)¶
Approximate s = ln(z) / dt
by s = (1 / dt) * (1 - z**-1) / (alpha + (1 - alpha) * z**-1))
When alpha = 0 this is equivalent to the forward Euler (forward difference) method.
When alpha = 0.5 this is equivalent to the bilinear transform, aka, Tustin’s method or the trapezoidal method.
When alpha = 1 this is equivalent to the backward Euler (backward difference) method.
See also discretize with regards to scaling of the result.
- impulse_invariance_transform()¶
This samples the impulse response and then calculates the Z-transform. It does not work if the impulse response has Dirac deltas, say for a transfer function that is a pure delay or is not-strictly proper.
The discrete-time and continuous-time impulse responses are identical at the sampling instants n * dt.
The data needs to be sampled many times the bandwidth to avoid aliasing.
See also bilinear_transform and matched_ztransform.
See also discretize with regards to scaling of the result.
- impulse_response(tvector=None)¶
Evaluate transient (impulse) response.
- inverse_laplace(zero_initial_conditions=None, **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.
By default initial conditions are assumed to be zero. This can be controlled by zero_initial_conditions.
- property jomega¶
Return expression with s = j omega.
- laplace(**assumptions)¶
Convert to s-domain.
- lti_filter(normalize_a0=True)¶
Create continuous-time linear time-invariant filter from continuous-time transfer function.
- matched_ztransform()¶
Match poles and zeros of H(s) to approximate H(z).
If there are no zeros, this is equivalent to impulse_invariance.
See also bilinear_transform and impulse_invariance_transform.
See also discretize with regards to scaling of the result.
- nichols_plot(fvector=None, var=None, **kwargs)¶
Plot frequency response for a frequency-domain phasor as a Nichols plot (dB versus phase). fvector specifies the frequencies. If it is a tuple (f1, f2), it sets the frequency limits.
npoints set the number of plotted points.
This method makes the assumption that the expression is causal.
- norm_angular_fourier(**assumptions)¶
Convert to normalized angular Fourier domain.
- norm_fourier(**assumptions)¶
Convert to normalized Fourier domain.
- nyquist_plot(fvector=None, var=None, **kwargs)¶
Plot frequency response for a frequency-domain phasor as a Nyquist plot (imaginary part versus real part). fvector specifies the frequencies. If it is a tuple (f1, f2), it sets the frequency limits.
npoints set the number of plotted points.
The unit circle is shown by default. This can be disabled with unitcircle=False.
This method makes the assumption that the expression is causal.
- phasor(**assumptions)¶
Convert to phasor domain.
- phasor_ratio(**assumptions)¶
Convert to phasor ratio domain.
- plot(**kwargs)¶
Plot pole-zero map.
kwargs include: axes - the plot axes to use otherwise a new figure is created xlabel - the x-axis label (default Re(s)) ylabel - the y-axis label (default Im(s)) xscale - the x-axis scaling yscale - the y-axis scaling pole_color – the color of the pole markers zero_color – the color of the zero markers in addition to those supported by the matplotlib plot command.
The plot axes are returned.
- pole_zero_plot(**kwargs)¶
Plot pole-zero map.
- post_initial_value()¶
Determine post-initial value at t = 0+.
- response(xvector, tvector, method='bilinear', alpha=0.5)¶
Evaluate response to input signal xvector at times specified by tvector. This returns a NumPy array.
The default method is ‘bilinear’. Other methods are: ‘impulse-invariance’ ‘bilinear’, ‘tustin’, ‘trapezoidal’ ‘generalized-bilinear’, ‘gbf’ controlled by the parameter alpha ‘euler’, ‘forward-diff’, ‘forward-euler’ ‘backward-diff’, ‘backward-euler’.
See also discretize with regards to scaling of the result.
- simpson_transform()¶
Approximate s = ln(z) / dt
by s = (3 / dt) * (z**2 - 1) / (z**2 + 4 * z + 1). This is more accurate than the other methods but doubles the system order and can produce unstable poles.
See also discretize with regards to scaling of the result.
- property ss¶
Return state-space representation using controllable canonical form. For other forms, use state_space().
- state_space(form='CCF')¶
Create state-space representation from transfer function. Note, state-space representations are not unique and are determined by the form argument. Currently this can be ‘CCF’ for the controllable canonical form, ‘OCF’ for the observable canonical form, or ‘DCF’ for the diagonal canonical form.
- step_response(tvector=None)¶
Evaluate step response.
- tdifferentiate()¶
Differentiate in t-domain (multiply by s).
- time(**assumptions)¶
Convert to time domain.
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.
- tintegrate()¶
Integrate in t-domain (divide by s).
- transient_response(tvector=None)¶
Evaluate transient (impulse) response.
- var = s¶
- zdomain(**assumptions)¶
- class lcapy.smatrix.LaplaceDomainVoltageMatrix(*args, **kwargs)¶
Bases:
LaplaceDomainMatrix
- class LaplaceDomainVoltage(val, **assumptions)¶
Bases:
VoltageMixin
,LaplaceDomainExpression
Angular frequency-domain voltage (units V/Hz).
Tmatrix¶
This module implements the TimeDomainMatrix class for a matrix of time-domain expressions.
Copyright 2019–2021 Michael Hayes, UCECE
- class lcapy.tmatrix.TimeDomainMatrix(*args, **kwargs)¶
Bases:
Matrix
- LT()¶
- class TimeDomainExpression(val, **assumptions)¶
Bases:
TimeDomain
,Expr
t-domain expression or symbol.
- FT(var=None, evaluate=True, **assumptions)¶
Attempt Fourier transform.
X(f) = int_{-infty} ^ {infty} x(t) exp(-j 2pi f t) dt.
- LT(evaluate=True, zero_initial_conditions=None, **assumptions)¶
Determine one-sided Laplace transform with 0- as the lower limit.
By default initial conditions are assumed to be zero. This can be controlled by zero_initial_conditions.
This is an alias for laplace.
- property abs¶
Return absolute value.
- angular_fourier(evaluate=True, **assumptions)¶
Attempt angular Fourier transform.
- angular_frequency_response(**assumptions)¶
Convert to angular frequency response domain. Note, this is similar to the angular Fourier domain but not always.
- as_expr()¶
- differential_equation(inputsym='x', outputsym='y')¶
Create differential equation from impulse response.
- discrete_frequency(**assumptions)¶
- discrete_time(**assumptions)¶
- discretize(method=None, alpha=0.5)¶
Convert to a discrete-time approximation:
\(x(n) pprox K x(t)\)
where \(K\) is a scale factor.
The default method depends on the expression quantity. If the quantity is undefined, voltage, current, `voltagesquared, currentsquared, or power, the default method is impulse-invariance and there is no scaling. This uses:
: math: x[n] = x(n Delta t)
For other quantities, the default method is bilinear’, and the result is scaled by the sampling interval (`Delta t) as is common for the discrete-time impulse response of digital filters:
: math: h[n] = Delta t h_c(n Delta t)
The methods are: ‘impulse-invariance’ ‘bilinear’, ‘tustin’, ‘trapezoidal’ ‘generalized-bilinear’, ‘gbf’ controlled by the parameter alpha ‘euler’, ‘forward-diff’, ‘forward-euler’ ‘backward-diff’, ‘backward-euler’ ‘simpson’, ‘matched-Z’, ‘zero-pole-matching’. All the methods except impulse-invariance are applied in the Laplace domain so the result is unknown for n < 0 unless the expression is causal.
- dlti_filter(method='bilinear')¶
Create DLTI filter using bilinear transform.
- property energy¶
Return signal energy.
- 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(var=None, evaluate=True, **assumptions)¶
Attempt Fourier transform. This is an alias for FT.
- frequency_response(**assumptions)¶
Convert to frequency response domain. Note, this is similar to the Fourier domain but not always.
- infer_assumptions()¶
- initial_value()¶
Determine value at t = 0. See also pre_initial_value and post_initial_value
- laplace(evaluate=True, zero_initial_conditions=None, **assumptions)¶
Determine one-sided Laplace transform with 0- as the lower limit.
By default initial conditions are assumed to be zero. This can be controlled by zero_initial_conditions.
This is an alias for LT.
- norm_angular_fourier(evaluate=True, **assumptions)¶
Attempt normalized angular Fourier transform.
- norm_fourier(evaluate=True, **assumptions)¶
Attempt normalized Fourier transform.
- phasor(**assumptions)¶
Convert to phasor domain.
- 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 plot_deltas - plot Dirac deltas as arrows in addition to those supported by the matplotlib plot command.
The plot axes are returned.
- post_initial_value()¶
Determine value at t = 0+. See also pre_initial_value and initial_value
- pre_initial_value()¶
Determine value at t = 0-. See also initial_value and post_initial_value
- response(xvector, tvector, method='bilinear')¶
Evaluate response to input signal xvector at times tvector. This returns a NumPy array.
- sample(tvector)¶
Return a discrete-time signal evaluated at time values specified by tvector. This returns a NumPy array.
- time(**assumptions)¶
- var = t¶
- zdomain(**assumptions)¶
Network¶
Copyright 2014–2022 Michael Hayes, UCECE
- class lcapy.network.Network¶
Bases:
object
This is the base class for network objects.
- property analysis¶
- property cct¶
Convert a Network object into a Circuit object.
- circuit()¶
Convert a Network object into a Circuit object.
- cpt_type = ''¶
- describe()¶
Print a message describing how network is solved.
- draw(filename=None, layout='horizontal', form=None, evalf=False, **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
layout is either ‘horizontal’, ‘vertical’, or ‘ladder’.
evalf can be False or an integer specifying the number of decimal places used to evaluate floats.
- 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
- property has_ac¶
- property has_dc¶
- has_ic = None¶
- property has_transient¶
- property initial_value_problem¶
- property is_IVP¶
- property is_ac¶
- is_capacitor = False¶
- property is_causal¶
- is_conductor = False¶
- is_current_source = False¶
- property is_dc¶
- is_inductor = False¶
- is_noiseless = True¶
- is_parallel = False¶
- is_resistor = False¶
- is_series = False¶
- is_voltage_source = False¶
- property kinds¶
Return list of transform domain kinds.
- kwargs = {}¶
- latex(**kwargs)¶
- netkeyword = ''¶
- netlist(layout='horizontal', evalf=None)¶
Create a netlist.
layout can be ‘horizontal’, ‘vertical’, or ‘ladder’.
evalf can be False or an integer specifying the number of decimal places used to evaluate floats.
- noisy(T='T')¶
Create noisy network model by replacing resistances with a series combination of a resistance and a noise voltage source.
- property params¶
Return list of symbols used as arguments in the network.
- pdb()¶
Enter the python debugger.
- pprint()¶
- pretty(**kwargs)¶
- sch(layout='horizontal', evalf=False)¶
Convert a Network object into a Schematic object.
- simplify()¶
- subs(subs_dict)¶
Substitute values using dictionary of substitutions.
For example, b = a.subs({‘R1’: 1e3, ‘R2’: 9e3})
- property symbols¶
Return dictionary of symbols defined in the network.
- transform(form='cauerI')¶
Transform the network impedance 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.
- zeroic = True¶
Voltage¶
This module provides voltage support.
Copyright 2020–2023 Michael Hayes, UCECE
- lcapy.voltage.Vname(name, kind, cache=False)¶
- lcapy.voltage.Vtype(kind)¶
- lcapy.voltage.noisevoltage(arg, **assumptions)¶
Create a new noise voltage with specified amplitude spectral density.
- lcapy.voltage.phasorvoltage(arg, omega=None, **assumptions)¶
- lcapy.voltage.voltage(arg, **assumptions)¶
Current¶
This module provides current support.
Copyright 2020–2023 Michael Hayes, UCECE
- lcapy.current.Iname(name, kind, cache=False)¶
- lcapy.current.Itype(kind)¶
- lcapy.current.current(arg, **assumptions)¶
- lcapy.current.noisecurrent(arg, **assumptions)¶
Create a new noise current with specified amplitude spectral density.
- lcapy.current.phasorcurrent(arg, omega=None, **assumptions)¶
Super¶
This module provides the SuperpositionDomainExpression class. It is the base class for Current and Voltage. It represents voltages and currents as a superposition in different transform domains.
Copyright 2019–2023 Michael Hayes, UCECE
- class lcapy.super.Superposition(*args, **kwargs)¶
Bases:
SuperpositionDomain
,ExprDict
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)
- property abs¶
Return the magnitude if phasor.
- property ac¶
Return the AC components.
- ac_keys()¶
Return list of keys for all ac components.
- add(value)¶
Add a value into the superposition.
- angular_fourier(**assumptions)¶
Convert to angular Fourier domain.
- asd()¶
- canonical()¶
- property dc¶
Return the DC component.
- decompose()¶
Decompose into a new representation in the transform domains.
- decompose_to_domain(expr, kind)¶
- final_value()¶
Determine value at t = oo.
- force_time()¶
- 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)
- property has_ac¶
True if there is an AC component.
- property has_dc¶
True if there is a DC component.
- property has_noisy¶
True if there is a noise component.
- property has_s_transient¶
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)
- property has_t_transient¶
True if have transient component defined in the time-domain.
- property has_transient¶
True if have transient component.
- initial_value()¶
Determine value at t = 0. See also pre_initial_value and post_initial_value
- property is_ac¶
True if only has AC components.
- property is_causal¶
- property is_dc¶
True if only has a DC component.
- property is_noisy¶
True if only has noise components.
- property is_phasor_domain¶
True if has single AC component.
- property is_s_transient¶
True if only has s-domain transient component.
- property is_superposition¶
- property is_t_transient¶
True if only has t-domain transient component.
- property 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
- limit(var, value, dir='+')¶
Determine limit of expression(var) at var = value. If dir == ‘+’ search from right else if dir == ‘-’ search from left.
- property magnitude¶
Return the magnitude if phasor.
- property n¶
- netval(kind)¶
- property noise¶
Return the total noise.
- noise_keys()¶
Return list of keys for all noise components.
- property omega¶
Return angular frequency if phasor.
- oneport()¶
Create oneport component.
- property phase¶
Return the phase if phasor.
- phasor(**kwargs)¶
Return phasor if have a single AC component otherwise raise error.
- post_initial_value()¶
Determine value at t = 0+. See also pre_initial_value and initial_value
- pprint()¶
Pretty print
- pre_initial_value()¶
Determine value at t = 0-. See also initial_value and post_initial_value
- psd()¶
- rms()¶
- property 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 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()¶
Simplify each element but not the keys.
- subs(*args, **kwargs)¶
Substitute symbols for each expression in dict.
args is either: - two arguments, e.g. foo.subs(old, new) - one iterable argument, e.g. foo.subs(iterable). The iterable may be
- o an iterable container with (old, new) pairs. In this case the
replacements are processed in the order given with successive patterns possibly affecting replacements already made.
o a dict or set whose key/value items correspond to old/new pairs.
The domain of the result can be coerced using domain argument.
- property 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.
- property transient¶
Return the transient component.
- transient_response(tvector=None)¶
Evaluate transient (impulse) response.
- property units¶
Return the units of the expression. However, since this is a superposition, units are not defined. Instead, it is necessary to transform to a specific domain. For example, using V(s).
Admittance¶
This module provides admittance support.
Copyright 2019–2022 Michael Hayes, UCECE
- lcapy.admittance.admittance(arg, causal=True, **assumptions)¶
Create an admittance class for the specified admittance.
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)
Impedance¶
This module provides impedance support.
Copyright 2019–2022 Michael Hayes, UCECE
- lcapy.impedance.impedance(arg, causal=True, **assumptions)¶
Create an impedance class for the specified impedance.
Z(omega) = R(omega) + j * X(omega)
where G is the conductance and B is the susceptance.
Impedance is the reciprocal of admittance:
Z(omega) = 1 / Y(omega)
Functions¶
This module wraps SymPy functions and provides a few others. The underlying SymPy function is obtained with the sympy attribute.
Copyright 2014–2022 Michael Hayes, UCECE
Symbols¶
This module defines special symbols f, s, t, and omega.
Copyright 2014–2021 Michael Hayes, UCECE
Mnacpts¶
This module defines the components for modified nodal analysis. The components are defined at the bottom of this file.
Copyright 2015–2023 Michael Hayes, UCECE
Laplace¶
This module provides support for Laplace transforms. It acts as a quantity 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.
Copyright 2016–2023 Michael Hayes, UCECE
- lcapy.laplace.LT(expr, t, s, evaluate=True, **kwargs)¶
Compute unilateral Laplace transform of expr with lower limit 0-.
- lcapy.laplace.laplace_transform(expr, t, s, evaluate=True, **kwargs)¶
Compute unilateral Laplace transform of expr with lower limit 0-.
Fourier¶
This module provides support for Fourier transforms. 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).
Copyright 2016–2023 Michael Hayes, UCECE
- lcapy.fourier.FT(expr, t, f, **kwargs)¶
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).
Ztransform¶
This module provides support for z transforms.
Copyright 2020–2023 Michael Hayes, UCECE
- lcapy.ztransform.ZT(expr, n, z, evaluate=True, **kwargs)¶
Compute unilateral Z-Transform transform of expr with lower limit 0.
Undefined functions such as v[n] are converted to V(z).
Transform¶
This module performs transformations between domains.
Copyright 2018–2022 Michael Hayes, UCECE
- lcapy.transform.call(expr, arg, **assumptions)¶
- lcapy.transform.select(expr, kind)¶
- lcapy.transform.transform(expr, arg, **assumptions)¶
If arg is a domain variable perform domain transformation, otherwise perform substitution.
Note (1 / s)(omega) will fail since 1 / s is assumed not to be causal and so the Fourier transform is unknown. However, impedance(1 / s)(omega) will work since an impedance is assumed to be causal. Alternatively, use (1 / s)(omega, causal=True).
Transforming from s->jomega is fast since it just requires a substitution of s with jomega.
Transforming from s->omega, s->Omega, s->f, or s->F can be slow since this requires a inverse Laplace transform followed by a Fourier transform. However, if the expression is causal and the expression is lossy when s is replaced by jw, the result can be found by substituting jw or 2 * 2 * pi * f for s. This does not apply for an expression such as Z = 1 / (s * C).
Plot¶
This module performs plotting using matplotlib.
Copyright 2014–2022 Michael Hayes, UCECE
- lcapy.plot.make_axes(figsize=None, axes=None, **kwargs)¶
- lcapy.plot.parse_range(frange, zero=0.1, positive=False)¶
- lcapy.plot.plot_angular_bode(obj, f, **kwargs)¶
This is a helper function for a Bode plot. It is better to use the bode_plot() method of an AngularFourierDomainExpression.
- lcapy.plot.plot_angular_frequency(obj, omega, plot_type=None, **kwargs)¶
This is a helper function for a frequency response plot. It is better to use the plot() method of an AngularFourierDomainExpression.
- lcapy.plot.plot_bode(obj, f, **kwargs)¶
This is a helper function for a Bode plot. It is better to use the bode_plot() method of a FourierDomainExpression.
- lcapy.plot.plot_deltas(ax, t, deltas, var, plot_type='real', color='k')¶
- lcapy.plot.plot_frequency(obj, f, plot_type=None, **kwargs)¶
This is a helper function for a frequency response plot. It is better to use the plot() method of a FourierDomainExpression.
- lcapy.plot.plot_nichols(obj, f, norm=False, **kwargs)¶
This is a helper function for a Nichols plot. It is better to use the nichols_plot() method of a LaplaceDomainExpression.
- lcapy.plot.plot_nyquist(obj, f, norm=False, **kwargs)¶
This is a helper function for a Nyquist plot. It is better to use the nyquist_plot() method of a LaplaceDomainExpression.
- lcapy.plot.plot_phasor(obj, **kwargs)¶
This is a helper function for a phasor plot. It is better to use the plot() method of a PhasorDomainExpression.
- lcapy.plot.plot_pole_zero(obj, **kwargs)¶
This is a helper function for a pole zero plot. It is better to use the plot() method of a LaplaceDomainExpression.
- lcapy.plot.plot_sequence(obj, ni, plot_type=None, polar=False, **kwargs)¶
This is a helper function for a stem (lollipop) plot. It is better to use the plot() method of a DiscreteTimeDomainExpression.
- lcapy.plot.plot_sequence_polar(obj, ni=(-10, 10), **kwargs)¶
- lcapy.plot.plot_time(obj, t, plot_type=None, **kwargs)¶
This is a helper function for a time plot. It is better to use the plot() method of a TimeDomainExpression.
- lcapy.plot.plotit(ax, obj, f, V, plot_type=None, deltas=None, log_magnitude=False, log_frequency=False, norm=False, dbmin=-120, unwrap=False, **kwargs)¶
Acdc¶
This module provides the CausalChecker, ACChecker, and DCChecker classes as used by the is_causal, is_ac, and is_dc functions.
Copyright 2020–2023 Michael Hayes, UCECE
- class lcapy.acdc.ACChecker(expr, var)¶
Bases:
object
This looks for real ac signals; it does not work for complex ac signals.
- 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.
Copyright 2016–2022 Michael Hayes, UCECE
- class lcapy.ratfun.Ratfun(expr, var)¶
Bases:
object
- property Apoly¶
- property Bpoly¶
- property Ddegree¶
Return the degree (order) of the denominator of a rational function. Note zero has a degree of -inf.
- property Ndegree¶
Return the degree (order) of the numerator of a rational function. Note zero has a degree of -inf.
- ZPK(combine_conjugates=False)¶
Convert to zero-pole-gain (ZPK) form.
See also canonical, general, standard, timeconst, and partfrac
- as_B_A_delay_undef()¶
- as_QMA()¶
Decompose expression into Q, M, A, delay, undef where
expression = (Q + M / A) * exp(-delay * var) * undef
- as_QRF(combine_conjugates=False, damping=None, method=None)¶
Decompose expression into Q, R, F, delay, undef where
expression = (Q + sum_n r_n / f_n) * exp(-delay * var) * undef
- as_QRF_old(combine_conjugates=False, damping=None)¶
Decompose expression into Q, R, F, delay, undef where
expression = (Q + sum_n r_n / f_n) * exp(-delay * var) * undef
- as_QRPO(damping=None, method=None)¶
Decompose expression into Q, R, P, O, delay, undef where
expression = (Q + sum_n r_n / (var - p_n)**o_n) * exp(-delay * var) * undef
method can be ‘sub’ (substitution method, the default) or ‘ec’ (equating cofficients method).
- as_ZPK()¶
Decompose expression into zeros, poles, gain, undef where
expression = K * (prod_n (var - z_n) / (prod_n (var - p_n)) * undef
- 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)
See also general, partfrac, standard, timeconst, and ZPK
- coeffs()¶
- property 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.
- expandcanonical()¶
Expand in terms for different powers with each term expressed in canonical form.
- general()¶
Convert rational function to general form.
See also canonical, partfrac, standard, timeconst, and ZPK
- property is_strictly_proper¶
Return True if the degree of the dominator is greater than the degree of the numerator.
- partfrac(combine_conjugates=False, damping=None, method=None)¶
Convert rational function into partial fraction form.
If combine_conjugates is True then the pair of partial fractions for complex conjugate poles are combined.
See also canonical, standard, general, timeconst, and ZPK
- poles(damping=None)¶
Return poles of expression as a list of Pole objects. Note this may not find all the poles.
Poles at infinity are not returned. There will be p - q poles at infinity for a rational function with a numerator of degree p and a denominator of degree q.
- residue(pole, poles)¶
Determine residue for given pole.
- 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_QRF.
- roots()¶
Return roots of expression as a dictionary Note this may not find them all.
- standard()¶
Convert rational function into mixed fraction form.
This is the sum of strictly proper rational function and a polynomial.
See also canonical, general, partfrac, timeconst, and ZPK
- timeconst()¶
Convert rational function to time constant form with unity lowest power of denominator.
See also canonical, general, partfrac, standard, and ZPK
- zeros()¶
Return zeroes of expression as a dictionary Note this may not find them all.
Zeros at infinity are not returned. There will be q - p zeros at infinity for a rational function with a numerator of degree p and a denominator of degree q.
- lcapy.ratfun.as_B_A_delay_undef(expr, var)¶
- lcapy.ratfun.as_numer_denom(expr, var)¶
- lcapy.ratfun.polyroots(poly, var)¶
Return roots of polynomial poly for variable var.
- lcapy.ratfun.roots(expr, var)¶
Return roots of expression expr for variable var.
Schematics¶
Schematic¶
This module performs schematic drawing using circuitikz from a netlist:
>>> from lcapy import Schematic
>>> sch = Schematic('''
... P1 1 0.1; down
... R1 3 1; right
... L1 2 3; right
... C1 3 0; down
... P2 2 0.2; down
... W 0 0.1; right
... W 0.2 0.2; right''')
>>> sch.draw()
Copyright 2014–2023 Michael Hayes, UCECE
- class lcapy.schematic.Schematic(filename=None, allow_anon=False, **kwargs)¶
Bases:
NetfileMixin
- 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 ‘annotate_values’: True to display component values as separate label ‘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 (nodes without an underscore), ‘alpha’ to label nodes starting with a letter, ‘pins’ to label nodes that are pins on a chip, ‘all’ to label all nodes,
‘anchor’: where to position node label (default south east) ‘include’: name of file to include before begin{document} ‘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, default 300 ‘help_lines’: distance between lines in grid, default 0 (disabled) ‘debug’: non-zero to display debug information
- make_graphs(debug=0, **kwargs)¶
- netfile_add(filename)¶
Add the nets from file with specified filename
- netlist()¶
Return the current netlist
- pdb()¶
Enter the python debugger.
- 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.
Copyright 2015–2023 Michael Hayes, UCECE
- class lcapy.schemcpts.A(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Unipole
Annotation.
- tikz_cpt = ''¶
- class lcapy.schemcpts.ANT(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Unipole
Antenna
- can_invert = True¶
- can_mirror = True¶
- kinds = {'rx': 'rxantenna', 'tx': 'txantenna'}¶
- tikz_cpt = 'antenna'¶
- class lcapy.schemcpts.BAT(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Battery
- kinds = {'cell1': 'battery1'}¶
- tikz_cpt = 'battery'¶
- class lcapy.schemcpts.BJT(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Transistor
- aliases = {'base': 'b', 'collector': 'c', 'emitter': 'e'}¶
- inpins = {'b': ('lx', 0.55, 0.5), 'c': ('lx', 0, 0), 'e': ('lx', 0, 1)}¶
- ippins = {'b': ('lx', 0.55, 0.5), 'c': ('lx', 0, 1), 'e': ('lx', 0, 0)}¶
- kinds = {'Lnigbt': 'Lnigbt', 'Lnigbt-bodydiode': 'Lnigbt-bodydiode', 'Lpigbt': 'Lpigbt', 'Lpigbt-bodydiode': 'Lpigbt-bodydiode', 'bodydiode': '-bodydiode', 'nigbt': 'nigbt', 'nigbt-bodydiode': 'nigbt-bodydiode', 'npn': 'npn', 'pigbt': 'pigbt', 'pigbt-bodydiode': 'pigbt-bodydiode', 'pnp': 'pnp'}¶
- node_pinnames = ('e', 'b', 'c')¶
- npins = {'b': ('lx', 0, 0.5), 'c': ('lx', 0.55, 0), 'e': ('lx', 0.55, 1)}¶
- ppins = {'b': ('lx', 0, 0.5), 'c': ('lx', 0.55, 1), 'e': ('lx', 0.55, 0)}¶
- class lcapy.schemcpts.BL(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Block
- kinds = {'acdc': 'sacdc', 'adc': 'adc', 'allpass': 'allpass', 'amp': 'amp', 'bandpass': 'bandpass', 'bandstop': 'bandstop', 'dac': 'dac', 'dcac': 'sdcac', 'dcdc': 'sdcdc', 'detector': 'detector', 'dsp': 'dsp', 'fft': 'fft', 'highpass': 'highpass', 'highpass2': 'highpass2', 'lowpass': 'lowpass', 'lowpass2': 'lowpass2', 'phaseshifter': 'phaseshifter', 'piattenuator': 'piattenuator', 'tattenuator': 'tattenuator', 'twoport': 'twoport', 'twoportsplit': 'twoportsplit', 'vamp': 'vamp', 'vco': 'vco', 'vphaseshifter': 'vphaseshifter', 'vpiattenuator': 'vpiattenuator', 'vtattenuator': 'vtattenuator'}¶
- tikz_cpt = 'twoport'¶
- class lcapy.schemcpts.Bipole(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
StretchyCpt
- aliases = {'n': '-', 'p': '+'}¶
- can_invert = True¶
- can_mirror = True¶
- can_scale = True¶
- draw(**kwargs)¶
- label_make(label_pos='', **kwargs)¶
- node_pinnames = ('+', '-')¶
- pins = {'+': ('lx', -0.5, 0), '-': ('rx', 0.5, 0)}¶
- class lcapy.schemcpts.Box(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Shape
- 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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Shape
- 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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Shape
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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Shape
- 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.C(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Capacitor
- kinds = {'curved': 'cC', 'electrolytic': 'eC', 'ferroelectric': 'ferrocap', 'polar': 'cC', 'sensor': 'sC', 'tunable': 'vC, tunable end arrow={Bar}', 'variable': 'vC'}¶
- tikz_cpt = 'C'¶
- class lcapy.schemcpts.CCS(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Current controlled source
- node_pinnames = ('+', '-', '', '')¶
- class lcapy.schemcpts.CPE(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Constant phase element
- draw(**kwargs)¶
- class lcapy.schemcpts.Cable(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Shape
- a = 0.3¶
- auxiliary = {'bl': ('l', -0.5, -0.5), 'br': ('r', 0.5, -0.5), 'in': ('l', -0.5, 0), 'in+': ('l', -0.5, 0.3), 'in-': ('l', -0.5, -0.3), 'mid': ('c', 0.0, 0.0), 'out': ('r', 0.5, 0), 'out+': ('r', 0.5, 0.3), 'out-': ('r', 0.5, -0.3), 'tl': ('l', -0.5, 0.5), 'top': ('t', 0, 0.5), 'tr': ('r', 0.5, 0.5)}¶
- default_aspect = 4¶
- draw(**kwargs)¶
- pins = {'b': ('c', 0, -0.5), 'ignd': ('l', -0.5, -0.5), 'ognd': ('r', 0.46, -0.5), 't': ('c', 0, 0.5)}¶
- class lcapy.schemcpts.Chip(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Shape
General purpose chip
- default_width = 2.0¶
- do_transpose = True¶
- draw(**kwargs)¶
- property path¶
- class lcapy.schemcpts.Circle(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Ellipse
- shape = 'circle'¶
- class lcapy.schemcpts.Circle2(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Shape
Circle
- pins = {'e': ('r', 0.5, 0), 'w': ('l', -0.5, 0)}¶
- shape = 'circle'¶
- class lcapy.schemcpts.Circle4(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Shape
- 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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
object
- R(angle_offset=0)¶
Return rotation matrix
- aliases = {}¶
- anchor_opt(thing, default=None)¶
- property angle¶
Return rotation angle
- annotate(pos, label, dargs=None, bold=False)¶
- annotation_keys = ('a', 'a_', 'a^')¶
- property annotation_str¶
- args_str(**kwargs)¶
- property aspect¶
- autoground(autoground)¶
- 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
- check_nodes()¶
- connection_keys = ('input', 'output', 'bidir', 'pad')¶
- property coords¶
- current_keys = ('i', 'i_', 'i^', 'i_>', 'i_<', 'i^>', 'i^<', 'i>_', 'i<_', 'i>^', 'i<^', 'i>', 'i<', 'ir')¶
- property current_str¶
- default_aspect = 1.0¶
- default_pins = ()¶
- default_width = 1.0¶
- directive = False¶
- do_transpose = False¶
- property down¶
- draw(**kwargs)¶
- draw_connection(n, kind)¶
Draw connection and label.
- draw_cpt(pos1, pos2, cpt='', args='', dargs='')¶
Create a string to draw a circuitikz component cpt between positions pos1 and pos2. args is a list or string of the component options; dargs is a list or string of the draw options.
The general form of the generated string is:
draw[dargs] (pos1) to [cpt, args] (pos2);
- draw_cptnode(pos, cpt='', args='', dargs='', label='')¶
Create a string to draw a tikz node containing a circuitikz component cpt at position pos. args is a list or string of the node options; dargs is a list or string of the draw options. label is an optional label.
The general form of the generated string is:
draw[dargs] (pos) node[cpt, args] {label};
- draw_implicit(n, kind, draw_nodes)¶
Draw implicit connection and label.
- draw_implicit_norotate(n, kind, draw_nodes)¶
Draw implicit connection and label with no rotation.
- draw_implicit_rotate(n, kind, draw_nodes)¶
Draw implicit connection and label with rotation.
- draw_label(pos, keys=None, default=True, **kwargs)¶
Draw label for component that does not have a circuitikz label.
- draw_node(n, draw_nodes, dargs)¶
Draw a node symbol. This also draws the node label for implicit and connection nodes.
- draw_node_label(node, label_nodes, anchor, dargs=None)¶
- draw_node_labels(**kwargs)¶
- draw_nodes(**kwargs)¶
- property draw_nodes_opt¶
- draw_path(points, style='', join='--', closed=False, dargs=None)¶
- draw_pinlabel(node)¶
- draw_pinname(node)¶
- draw_pins()¶
- draw_stepped_wire(pos1, steps, dargs=None, startarrow='', endarrow='', style='')¶
- draw_wire(pos1, pos2, dargs=None, startarrow='', endarrow='', style='')¶
Create a string to draw a circuitikz wire between positions pos1 and pos2. dargs is a list or string of the draw options.
The general form of the generated string is:
draw[-, dargs] (pos1) to (pos2);
- property 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.
- property fixed¶
- property fliplr¶
- property flipud¶
- flow_keys = ('f', 'f_', 'f^', 'f_>', 'f_<', 'f^>', 'f^<', 'f>_', 'f<_', 'f>^', 'f<^', 'f>', 'f<')¶
- property flow_str¶
- property free¶
- ground_keys = ('ground', 'sground', 'rground', 'cground', 'nground', 'pground', '0V')¶
- property h¶
Normalized height
- property horizontal¶
- property ignore¶
- implicit_key(opts)¶
- implicit_keys = ('implicit', 'ground', 'sground', 'rground', 'cground', 'nground', 'pground', '0V', 'vcc', 'vdd', 'vee', 'vss')¶
- inner_label_keys = ('t',)¶
- property inner_label_str¶
- property invert¶
- property invisible¶
- property kind¶
- kinds = {}¶
- label(keys=None, default=True, **kwargs)¶
- label_keys = ('l', 'l_', 'l^')¶
- property label_nodes_opt¶
- label_opt_keys = ('label_values', 'label_ids', 'annotate_values')¶
- property label_str¶
- property label_str_list¶
- label_tweak(label, xscale, yscale, angle)¶
- property left¶
- midpoint(node1, node2)¶
- property mirror¶
- property 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', 'nosim', 'nowires', 'nolabels', 'steps', 'free', 'fliplr', 'flipud', 'nodots', 'draw_nodes', 'label_nodes', 'nodraw', 'mirrorinputs', 'autoground', 'xoffset', 'yoffset', 'anchor', 'def', 'nodes')¶
- node(pinname)¶
Return node by pinname
- node_opts()¶
- node_pinnames = ()¶
- node_special_keys = ('label', 'l', 'anchor')¶
- property nodes¶
Nodes used to draw the element.
- property nodots¶
- property nodraw¶
- property nolabels¶
- property nowires¶
- property 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_nodes()¶
- parse_pindefs()¶
- pinpos(pinname)¶
Return pinpos by pinname
- pins = {}¶
- place = True¶
- process_attribute_nodes()¶
Process nodes specified as attributes. For example, R1 1 2; .n.vss
- process_implicit_nodes()¶
Parse implicit nodes.
- process_nodes(nodes, draw_pin=False, add_pinname=False)¶
- required_auxiliary = ('mid',)¶
- property 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.
- property required_pins¶
- property right¶
- property s¶
Sanitised name
- property scale¶
- property scales¶
- setup()¶
- shape_scale = 1.0¶
- property size¶
Component size between its nodes
- special_keys = ('v', 'v_', 'v^', 'v_>', 'v_<', 'v^>', 'v^<', 'v<', 'v>', 'i', 'i_', 'i^', 'i_>', 'i_<', 'i^>', 'i^<', 'i>_', 'i<_', 'i>^', 'i<^', 'i>', 'i<', 'ir', 'f', 'f_', 'f^', 'f_>', 'f_<', 'f^>', 'f^<', 'f>_', 'f<_', 'f>^', 'f<^', 'f>', 'f<', 'l', 'l_', 'l^', 't', 'a', 'a_', 'a^', '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', 'nosim', 'nowires', 'nolabels', 'steps', 'free', 'fliplr', 'flipud', 'nodots', 'draw_nodes', 'label_nodes', 'nodraw', 'mirrorinputs', 'autoground', 'xoffset', 'yoffset', 'anchor', 'def', 'nodes', 'implicit', 'ground', 'sground', 'rground', 'cground', 'nground', 'pground', '0V', 'vcc', 'vdd', 'vee', 'vss', 'label_values', 'label_ids', 'annotate_values', 'input', 'output', 'bidir', 'pad')¶
- property steps¶
- property stretch¶
- property style¶
- styles = {}¶
- supply_keys = ('vcc', 'vdd', 'vee', 'vss')¶
- supply_negative_keys = ('vee', 'vss')¶
- supply_positive_keys = ('vcc', 'vdd')¶
- property tcoords¶
Transformed coordinates for each of the nodes
- tf(centre, offset, angle_offset=0.0, scale=None)¶
Transform coordinate.
- property up¶
- property variable¶
- property vertical¶
- voltage_keys = ('v', 'v_', 'v^', 'v_>', 'v_<', 'v^>', 'v^<', 'v<', 'v>')¶
- property voltage_str¶
- property w¶
Normalized width
- property wire¶
- property xoffset¶
- property xvals¶
- property yoffset¶
- property yvals¶
- class lcapy.schemcpts.D(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Diode
- kinds = {'bidirectional': 'biD', 'laser': 'lasD', 'led': 'leD', 'photo': 'pD', 'schottky': 'sD', 'tunnel': 'tD', 'tvs': 'tvsDo', 'varcap': 'VC', 'zener': 'zD', 'zzener': 'zzD'}¶
- styles = {'empty': '', 'full': '*', 'stroke': '-'}¶
- tikz_cpt = 'D'¶
- class lcapy.schemcpts.Eamp(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
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-', 'ocm')¶
- npins = {'in+': ('l', -1.25, -0.5), 'in-': ('l', -1.25, 0.5), 'ocm': ('l', -0.85, 0), '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), 'vss': ('b', -0.25, -0.645)}¶
- pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}¶
- property pins¶
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object’s
(key, value) pairs
- dict(iterable) -> new dictionary initialized as if via:
d = {} for k, v in iterable:
d[k] = v
- dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
- ppins = {'in+': ('l', -1.25, 0.5), 'in-': ('l', -1.25, -0.5), 'ocm': ('l', -0.85, 0), '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), 'vss': ('b', -0.25, -0.645)}¶
- class lcapy.schemcpts.Einamp(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Eopamp
Instrumentation amplifier created with E netlist type. See also Uinamp for an instrumentation amplifier created with the 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¶
- can_scale = True¶
- default_width = 1.0¶
- do_transpose = False¶
- node_pinnames = ('out', 'ref', 'in+', 'in-', 'r+', 'r-')¶
- class lcapy.schemcpts.Ellipse(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Shape
- 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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
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'}¶
- property pins¶
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object’s
(key, value) pairs
- dict(iterable) -> new dictionary initialized as if via:
d = {} for k, v in iterable:
d[k] = v
- dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
- 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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Ferrite bead
- draw(**kwargs)¶
- class lcapy.schemcpts.FixedCpt(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Cpt
- can_stretch = False¶
- property centre¶
- tf(centre, offset, angle_offset=0.0, scale=None)¶
Transform coordinate.
- class lcapy.schemcpts.Flipflop(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
- default_width = 1.0¶
- class lcapy.schemcpts.Gate2(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
- can_invert = False¶
- can_mirror = False¶
- can_scale = True¶
- draw(**kwargs)¶
- pins = {'in1': ('l', -0.6, 0.15), 'in2': ('l', -0.6, -0.15), 'out': ('r', 0.55, 0)}¶
- class lcapy.schemcpts.Gyrator(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
FixedCpt
- 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.I(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Current source
- kinds = {'ac': 'sI', 'dc': 'I', 'noise': 'nI', 'square': 'sqI', 'step': 'I', 'triangle': 'tI'}¶
- tikz_cpt = 'I'¶
- class lcapy.schemcpts.JFET(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Transistor
- aliases = {'drain': 'd', 'gate': 'g', 'source': 's'}¶
- inpins = {'d': ('lx', 0, 1), 'g': ('lx', 0.55, 0.355), 's': ('lx', 0, 0)}¶
- ippins = {'d': ('lx', 0, 0), 'g': ('lx', 0.55, 0.645), 's': ('lx', 0, 1)}¶
- node_pinnames = ('d', 'g', 's')¶
- npins = {'d': ('lx', 0.55, 1), 'g': ('lx', 0, 0.355), 's': ('lx', 0.55, 0)}¶
- ppins = {'d': ('lx', 0.55, 0), 'g': ('lx', 0, 0.645), 's': ('lx', 0.55, 1)}¶
- class lcapy.schemcpts.K(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
TF1
Mutual coupling
- property coords¶
- property nodes¶
Nodes used to draw the element.
- property scales¶
- class lcapy.schemcpts.L(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Inductor
- kinds = {'choke': 'cute choke', 'sensor': 'sL', 'tunable': 'vL, tunable end arrow={Bar}', 'twolineschoke': 'cute choke, twolineschoke', 'variable': 'vL'}¶
- tikz_cpt = 'L'¶
- class lcapy.schemcpts.MOSFET(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Transistor
- aliases = {'drain': 'd', 'gate': 'g', 'source': 's'}¶
- inpins = {'d': ('lx', 0, 1), 'g': ('lx', 0.55, 0.5), 's': ('lx', 0, 0)}¶
- inpins2 = {'d': ('lx', 0, 1), 'g': ('lx', 0.55, 0.355), 's': ('lx', 0, 0)}¶
- ippins = {'d': ('lx', 0, 0), 'g': ('lx', 0.55, 0.5), 's': ('lx', 0, 1)}¶
- ippins2 = {'d': ('lx', 0, 0), 'g': ('lx', 0.55, 0.645), 's': ('lx', 0, 1)}¶
- kinds = {'hemt': 'hemt', 'nfet': 'nfet', 'nfet-bodydiode': 'nfet-bodydiode', 'nfetd': 'nfetd', 'nfetd-bodydiode': 'nfetd-bodydiode', 'nigfetd': 'nigfetd', 'nigfetd-bodydiode': 'nigfetd-bodydiode', 'nigfete': 'nfigete', 'nigfete-bodydiode': 'nfigete-bodydiode', 'nigfetebulk': 'nigfetebulk', 'nmos': 'nmos', 'nmosd': 'nmosd', 'pfet': 'pfet', 'pfet-bodydiode': 'pfet-bodydiode', 'pfetd': 'pfetd', 'pfetd-bodydiode': 'pfetd-bodydiode', 'pigfetd': 'pigfetd', 'pigfetd-bodydiode': 'pigfetd-bodydiode', 'pigfete': 'pigfete', 'pigfete-bodydiode': 'pigfete-bodydiode', 'pigfetebulk': 'pigfetebulk', 'pmos': 'pmos', 'pmosd': 'pmosd'}¶
- node_pinnames = ('d', 'g', 's')¶
- npins = {'d': ('lx', 0.55, 1), 'g': ('lx', 0, 0.5), 's': ('lx', 0.55, 0)}¶
- npins2 = {'d': ('lx', 0.55, 1), 'g': ('lx', 0, 0.355), 's': ('lx', 0.55, 0)}¶
- ppins = {'d': ('lx', 0.55, 0), 'g': ('lx', 0, 0.5), 's': ('lx', 0.55, 1)}¶
- ppins2 = {'d': ('lx', 0.55, 0), 'g': ('lx', 0, 0.645), 's': ('lx', 0.55, 1)}¶
- class lcapy.schemcpts.MT(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Motor
- draw(**kwargs)¶
- class lcapy.schemcpts.MX(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
FixedCpt
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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Multiplexer
- property path¶
- class lcapy.schemcpts.Potentiometer(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Potentiometer Np, Nm, No
- aliases = {'+': 'p', '-': 'n'}¶
- can_stretch = False¶
- node_pinnames = ('p', 'n', 'wiper')¶
- pins = {'n': ('rx', 1, 0), 'p': ('rx', 0, 0), 'wiper': ('lx', 0.5, 0.3)}¶
- class lcapy.schemcpts.R(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Resistor
- kinds = {'tunable': 'vR, tunable end arrow = {Bar}', 'variable': 'vR'}¶
- tikz_cpt = 'R'¶
- class lcapy.schemcpts.REL(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Reluctance
- kinds = {'tunable': 'vR, tunable end arrow = {Bar}', 'variable': 'vR'}¶
- tikz_cpt = 'R'¶
- class lcapy.schemcpts.SP(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
FixedCpt
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)}¶
- property pins¶
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object’s
(key, value) pairs
- dict(iterable) -> new dictionary initialized as if via:
d = {} for k, v in iterable:
d[k] = v
- dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
- 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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
SP
Summing point
- node_pinnames = ('in1', 'in2', 'out')¶
- npins = {'in1': ('lx', -0.25, 0), 'in2': ('tx', 0, 0.25), 'out': ('rx', 0.25, 0)}¶
- property pins¶
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object’s
(key, value) pairs
- dict(iterable) -> new dictionary initialized as if via:
d = {} for k, v in iterable:
d[k] = v
- dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
- ppins = {'in1': ('lx', -0.25, 0), 'in2': ('bx', 0, -0.25), 'out': ('rx', 0.25, 0)}¶
- class lcapy.schemcpts.SPDT(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
FixedCpt
SPDT switch
- aliases = {'+': 'p', '-': 'n'}¶
- can_invert = True¶
- can_mirror = True¶
- draw(**kwargs)¶
- node_pinnames = ('p', 'n', 'common')¶
- npins = {'common': ('lx', 0, 0), 'n': ('rx', 0, 0.338), 'p': ('lx', 0.632, 0.169)}¶
- property pins¶
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object’s
(key, value) pairs
- dict(iterable) -> new dictionary initialized as if via:
d = {} for k, v in iterable:
d[k] = v
- dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
- ppins = {'common': ('lx', 0.632, 0), 'n': ('rx', 0.632, 0.338), 'p': ('lx', 0, 0.169)}¶
- class lcapy.schemcpts.SPpm(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
SP3
Summing point
- labels = '+-'¶
- class lcapy.schemcpts.SPpmm(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
SP
Summing point
- labels = '+--'¶
- class lcapy.schemcpts.SPpp(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
SP3
Summing point
- labels = '++'¶
- class lcapy.schemcpts.SPppm(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
SP
Summing point
- labels = '++-'¶
- class lcapy.schemcpts.SPppp(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
SP
Summing point
- labels = '+++'¶
- class lcapy.schemcpts.Shape(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
FixedCpt
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)¶
- property 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_implicit_nodes()¶
Parse implicit nodes.
- process_pinlabels()¶
- process_pinnames()¶
- process_pinnodes()¶
- setup()¶
- property width¶
- class lcapy.schemcpts.StretchyCpt(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Cpt
- can_stretch = True¶
- xtf(centre, offset, angle_offset=0.0)¶
Transform x coordinate.
- class lcapy.schemcpts.TF1(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
FixedCpt
Transformer
- can_scale = True¶
- 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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
TF1
Transformer
- draw(**kwargs)¶
- property drawn_nodes¶
Nodes that are drawn
- 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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
StretchyCpt
Transmission line
- aliases = {'in+': 'in1', 'in-': 'in2', 'out+': 'out1', 'out-': 'out2'}¶
- can_scale = True¶
- draw(**kwargs)¶
- property drawn_nodes¶
Nodes that are drawn
- 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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Box2
Transfer function
- default_aspect = 1.5¶
- default_width = 1.5¶
- node_pinnames = ('w', 'e')¶
- class lcapy.schemcpts.Transformer(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
TF1
- draw(**kwargs)¶
- class lcapy.schemcpts.Transistor(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
FixedCpt
- can_invert = True¶
- can_mirror = True¶
- can_scale = True¶
- draw(**kwargs)¶
- property pins¶
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object’s
(key, value) pairs
- dict(iterable) -> new dictionary initialized as if via:
d = {} for k, v in iterable:
d[k] = v
- dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
- class lcapy.schemcpts.Triangle(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Shape
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)}¶
- required_auxiliary = ('top', 'bl', 'br', 'mid')¶
- shape = 'triangle'¶
- class lcapy.schemcpts.Triode(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
FixedCpt
- aliases = {'anode': 'a', 'cathode': 'k', 'grid': 'g'}¶
- draw(**kwargs)¶
- node_pinnames = ('a', 'g', 'k')¶
- pins = {'a': ('l', 0.75, 0), 'g': ('l', 0.25, 0.5), 'k': ('l', -0.25, 0)}¶
- class lcapy.schemcpts.TwoPort(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Shape
Two-port
- auxiliary = {'bl': ('l', -0.5, -0.5), 'br': ('r', 0.5, -0.5), 'ene': ('l', 0.5, 0.375), 'ese': ('l', 0.5, -0.375), 'mid': ('c', 0.0, 0.0), 'tl': ('l', -0.5, 0.5), 'top': ('t', 0, 0.5), 'tr': ('r', 0.5, 0.5), 'wnw': ('l', -0.5, 0.375), 'wsw': ('l', -0.5, -0.375)}¶
- default_aspect = 1¶
- default_width = 1¶
- draw(**kwargs)¶
- n = 0.75¶
- node_pinnames = ('out+', 'out-', 'in+', 'in-')¶
- p = 0.375¶
- pins = {'e': ('r', 0.5, 0), 'in+': ('lx', -0.75, 0.375), 'in-': ('lx', -0.75, -0.375), 'n': ('t', 0, 0.5), 'nne': ('t', 0.375, 0.5), 'nnw': ('t', -0.375, 0.5), 'out+': ('rx', 0.75, 0.375), 'out-': ('rx', 0.75, -0.375), 's': ('b', 0, -0.5), 'sse': ('b', 0.375, -0.5), 'ssw': ('b', -0.375, -0.5), 'w': ('l', -0.5, 0)}¶
- required_auxiliary = ('wnw', 'wsw', 'ene', 'ese', 'mid')¶
- shape = 'rectangle'¶
- shape_scale = 1.3333333333333333¶
- x = 0.5¶
- class lcapy.schemcpts.Uadc(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
ADC
- property 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.Uand(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Gate2
- kind = 'and'¶
- class lcapy.schemcpts.Ubuffer(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Buffer with power supplies
- default_width = 1.0¶
- property 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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Chip of size 1 3 1 3
- aliases = {'in': 'l1', 'out': 'r1', 'vdd': 't2', 'vss': 'b2'}¶
- pins = {'b1': ('b', -0.25, -0.5), 'b2': ('b', 0, -0.5), 'b3': ('b', 0.25, -0.5), 'l1': ('l', -0.5, 0), 'r1': ('r', 0.5, 0), 't1': ('t', -0.25, 0.5), 't2': ('t', 0, 0.5), 't3': ('t', 0.25, 0.5)}¶
- class lcapy.schemcpts.Uchip2121(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Chip of size 2 1 2 1
- aliases = {'vdd': 't1', 'vss': 'b1'}¶
- pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}¶
- pins = {'b1': ('b', 0, -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, 0.5)}¶
- class lcapy.schemcpts.Uchip2222(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Chip of size 3 1 3 1
- aliases = {'vdd': 't1', 'vss': 'b1'}¶
- property path¶
- pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}¶
- pins = {'b1': ('b', 0.0, -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.0, 0.5)}¶
- class lcapy.schemcpts.Uchip3333(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Chip of size 3 3 3 3
- aliases = {'vdd': 't2', 'vss': 'b2'}¶
- property path¶
- pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}¶
- pins = {'b1': ('b', -0.25, -0.5), 'b2': ('b', 0.0, -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), 't2': ('t', 0.0, 0.5), 't3': ('t', 0.25, 0.5)}¶
- class lcapy.schemcpts.Uchip4141(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Chip of size 4 1 4 1
- aliases = {'vdd': 't1', 'vss': 'b1'}¶
- pins = {'b1': ('b', 0.0, -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.0, 0.5)}¶
- class lcapy.schemcpts.Uchip4444(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
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.Uchip5555(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Chip of size 5 5 5 5
- pins = {'b1': ('b', -0.4, -0.5), 'b2': ('b', -0.2, -0.5), 'b3': ('b', 0.0, -0.5), 'b4': ('b', 0.2, -0.5), 'b5': ('b', 0.4, -0.5), 'l1': ('l', -0.5, 0.4), 'l2': ('l', -0.5, 0.2), 'l3': ('l', -0.5, 0.0), 'l4': ('l', -0.5, -0.2), 'l5': ('l', -0.5, -0.4), 'r1': ('r', 0.5, 0.4), 'r2': ('r', 0.5, 0.2), 'r3': ('r', 0.5, 0.0), 'r4': ('r', 0.5, -0.2), 'r5': ('r', 0.5, -0.4), 't1': ('t', -0.4, 0.5), 't2': ('t', -0.2, 0.5), 't3': ('t', 0, 0.5), 't4': ('t', 0.2, 0.5), 't5': ('t', 0.4, 0.5)}¶
- class lcapy.schemcpts.Uchip6666(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Chip of size 6 6 6 6
- pins = {'b1': ('b', -0.375, -0.5), 'b2': ('b', -0.225, -0.5), 'b3': ('b', -0.075, -0.5), 'b4': ('b', 0.075, -0.5), 'b5': ('b', 0.225, -0.5), 'b6': ('b', 0.375, -0.5), 'l1': ('l', -0.5, 0.375), 'l2': ('l', -0.5, 0.225), 'l3': ('l', -0.5, 0.075), 'l4': ('l', -0.5, -0.075), 'l5': ('l', -0.5, -0.225), 'l6': ('l', -0.5, -0.375), 'r1': ('r', 0.5, 0.375), 'r2': ('r', 0.5, 0.225), 'r3': ('r', 0.5, 0.075), 'r4': ('r', 0.5, -0.075), 'r5': ('r', 0.5, -0.225), 'r6': ('r', 0.5, -0.375), 't1': ('t', -0.375, 0.5), 't2': ('t', -0.225, 0.5), 't3': ('t', -0.075, 0.5), 't4': ('t', 0.075, 0.5), 't5': ('t', 0.225, 0.5), 't6': ('t', 0.357, 0.5)}¶
- class lcapy.schemcpts.Uchip7777(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Chip of size 7 7 7 7
- pins = {'b1': ('b', -0.375, -0.5), 'b2': ('b', -0.25, -0.5), 'b3': ('b', -0.125, -0.5), 'b4': ('b', 0.0, -0.5), 'b5': ('b', 0.125, -0.5), 'b6': ('b', 0.25, -0.5), 'b7': ('b', 0.375, -0.5), 'l1': ('l', -0.5, 0.375), 'l2': ('l', -0.5, 0.25), 'l3': ('l', -0.5, 0.125), 'l4': ('l', -0.5, 0.0), 'l5': ('l', -0.5, -0.125), 'l6': ('l', -0.5, -0.25), 'l7': ('l', -0.5, -0.375), 'r1': ('r', 0.5, 0.375), 'r2': ('r', 0.5, 0.25), 'r3': ('r', 0.5, 0.125), 'r4': ('r', 0.5, 0.0), 'r5': ('r', 0.5, -0.125), 'r6': ('r', 0.5, -0.25), 'r7': ('r', 0.5, -0.375), 't1': ('t', -0.375, 0.5), 't2': ('t', -0.25, 0.5), 't3': ('t', -0.125, 0.5), 't4': ('t', 0.0, 0.5), 't5': ('t', 0.125, 0.5), 't6': ('t', 0.25, 0.5), 't7': ('t', 0.375, 0.5)}¶
- class lcapy.schemcpts.Uchip8181(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Chip of size 8 1 8 1
- aliases = {'vdd': 't1', 'vss': 'b1'}¶
- pins = {'b1': ('b', 0.0, -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.0, 0.5)}¶
- class lcapy.schemcpts.Uchip8888(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
DAC
- property 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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Flipflop
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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Differential amplifier. It is not automatically annotated with + and - symbols for inputs. This can be achieved using pinlabels={in+, in-}.
- default_width = 1.0¶
- property 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.Udiffdriver(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Differential driver with power supplies
- default_width = 1.0¶
- draw(**kwargs)¶
- property path¶
- pinlabels = {'en': 'E', 'vdd': 'VDD', 'vss': 'VSS'}¶
- pins = {'en': ('b', -0.3, -0.4), 'in': ('l', -0.5, 0), 'out+': ('r', -0.02, 0.25), 'out-': ('r', 0.1, -0.25), 'vdd': ('t', 0, 0.22), 'vss': ('b', -0.15, -0.3)}¶
- class lcapy.schemcpts.Ufdopamp(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
This is for a fully differential opamp created with the U netlist type. It has no wires. See also Efdopamp 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), 'ocm': ('l', -0.5, 0), 'out+': ('r', 0.1, 0.2), 'out-': ('r', 0.1, -0.2), 'vdd': ('t', -0.1, 0.3), 'vss': ('b', -0.1, -0.3)}¶
- property path¶
- pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}¶
- property pins¶
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object’s
(key, value) pairs
- dict(iterable) -> new dictionary initialized as if via:
d = {} for k, v in iterable:
d[k] = v
- dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
- ppins = {'in+': ('l', -0.5, 0.2), 'in-': ('l', -0.5, -0.2), 'ocm': ('l', -0.5, 0), 'out+': ('r', 0.1, -0.2), 'out-': ('r', 0.1, 0.2), 'vdd': ('t', -0.1, 0.3), 'vss': ('b', -0.1, -0.3)}¶
- required_auxiliary = ('lin+', 'lin-', 'lout+', 'lout-', 'mid')¶
- class lcapy.schemcpts.Uinamp(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Uopamp
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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
Inverter with power supplies
- default_width = 1.0¶
- draw(**kwargs)¶
- property 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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Ufdopamp
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)}¶
- property 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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Flipflop
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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Mux
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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Mux
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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Mux
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.Unand(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Gate2
- kind = 'nand'¶
- class lcapy.schemcpts.Unipole(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Cpt
- aliases = {'p': '+'}¶
- draw(**kwargs)¶
- node_pinnames = ('+',)¶
- pins = {'+': ('lx', 0, 0)}¶
- place = False¶
- class lcapy.schemcpts.Unor(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Gate2
- kind = 'nor'¶
- class lcapy.schemcpts.Uopamp(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
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)}¶
- property path¶
- pinlabels = {'vdd': 'VDD', 'vss': 'VSS'}¶
- property pins¶
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object’s
(key, value) pairs
- dict(iterable) -> new dictionary initialized as if via:
d = {} for k, v in iterable:
d[k] = v
- dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
- 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)}¶
- required_auxiliary = ('lin+', 'lin-', 'mid')¶
- class lcapy.schemcpts.Uor(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Gate2
- kind = 'or'¶
- class lcapy.schemcpts.Uregulator(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Chip
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, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Flipflop
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.Uxnor(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Gate2
- kind = 'xnor'¶
- class lcapy.schemcpts.Uxor(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Gate2
- kind = 'xor'¶
- class lcapy.schemcpts.V(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Voltage source
- kinds = {'ac': 'sV', 'dc': 'V', 'noise': 'nV', 'square': 'sqV', 'step': 'V', 'triangle': 'tV'}¶
- tikz_cpt = 'V'¶
- class lcapy.schemcpts.VCS(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Voltage controlled source
- node_pinnames = ('+', '-', '', '')¶
- class lcapy.schemcpts.Wire(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
- draw(**kwargs)¶
- class lcapy.schemcpts.XX(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Cpt
- directive = True¶
- draw(**kwargs)¶
- process_opts_nodes()¶
- class lcapy.schemcpts.Y(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Admittance
- kinds = {'sensor': 'european resistive sensor', 'tunable': 'variable european resistor, tunable end arrow = {Bar}', 'variable': 'variable european resistor'}¶
- tikz_cpt = 'generic'¶
- class lcapy.schemcpts.Z(sch, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, keyword, *args)¶
Bases:
Bipole
Impedance
- kinds = {'sensor': 'european resistive sensor', 'tunable': 'variable european resistor, tunable end arrow = {Bar}', 'variable': 'variable european resistor'}¶
- tikz_cpt = 'generic'¶
- lcapy.schemcpts.anchor_choose(pinpos, outside=False)¶
- lcapy.schemcpts.anchor_map(anchor)¶
- lcapy.schemcpts.angle_choose(pinpos)¶
- lcapy.schemcpts.arrow_map(name)¶
- lcapy.schemcpts.check_boolean(value)¶
- lcapy.schemcpts.defcpt(name, base, docstring, cpt=None)¶
- lcapy.schemcpts.make(classname, parent, namespace, name, cpt_type, cpt_id, string, opts_string, node_names, *args)¶
Schemgraph¶
This module provides classes for schematic layout.
Copyright 2014–2021 Michael Hayes, UCECE
- class lcapy.schemgraph.Gedge(cpt, from_gnode, to_gnode, size, stretch=False)¶
Bases:
object
Edge between common nodes
- property name¶
- class lcapy.schemgraph.Gnode(name)¶
Bases:
object
Drawing node
- add_fedge(edge)¶
- add_redge(edge)¶
- property fmt_name¶
- property 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.
- property all_nodes¶
- 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, tweak_node_label=True)¶
Generate directed graph using graphviz notation
- link(n1, n2)¶