Create plots
SLiCAP output displayed on this manual page, is generated with the script: plots.py
, imported by Manual.py
.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3"""
4plots.py: SLiCAP scripts for the HTML help file
5"""
6import SLiCAP as sl
7from copy import deepcopy
8import numpy as np
9
10cir = sl.makeCircuit("kicad/myPassiveNetwork/myPassiveNetwork.kicad_sch")
SLiCAP provides a number of plot functions for pre-formatted plotting of instruction results. Plot types, axis types, trace colors, markers, labels and plot legends are automatically selected from the instruction settings.
Plot functions are collected in the SLiCAP module SLiCAPplots.py.
SLiCAP plots are hierarchically structured:
A figure object is the main object that can be plotted using its
.plot()
method.The figure’s
.axis
attribute is a list of lists with axis objects for each row, from left to right.The
.traces
attribute of eachaxis
object is a list with trace objects that will be plotted the axis. Trace xdata, ydata, lables, colors, markers, etc, are all attributes of atrace
object.
SLiCAP built-in figures are single-axis figures.
SLiCAP has three built-in plot functions:
SLiCAP plot functions use the Python module matplotlib. When using SLiCAP built-in plot functions, knowledge about matplotlib is not required.
Built-in plot types
plotSweep()
plotSweep() displays traces from expressions with one symbolic variable. It can be used for plotting time-domain responses, frequency-domain responses and swept parameter plots.
plotPZ()
plotPZ() displays X-Y scatter plots. These plots are configured for plotting the results of pole-zero analysis.
plot()
plot() generates X-Y line plots from a dictionary with traces. Such dictionaries can be generated from data from other applications, such as, LTspice, SImetrix, NGspice, or Cadence, or from .csv
files.
Plot settings
Plot settings are found in the [plot] section of the SLiCAP.ini
file in the project directory. These settings can be changed from within the Python environment.
>>> import SLiCAP as sl
>>> sl.ini.dump("plot")
PLOT
----
ini.gain_colors_gain = b
ini.gain_colors_loopgain = k
ini.gain_colors_asymptotic = r
ini.gain_colors_servo = m
ini.gain_colors_direct = g
ini.gain_colors_vi = c
ini.axis_height = 5
ini.axis_width = 7
ini.line_width = 2
ini.line_type = -
ini.plot_fontsize = 12
ini.marker_size = 7
ini.legend_loc = best
ini.default_colors = ['r', 'b', 'g', 'c', 'm', 'y', 'k']
ini.default_markers = ['']
ini.plot_file_type = svg
ini.svg_margin = 1
note
Pole-zero plots are square plots: the axis width is set to the axis height.
Creating and updating plots
The three built-in plot functions create a figure object. After creation, traces can be added to a plot and the figure objects needs to be updated. The method figure.plot()
recreates the plot.
Showing plots
All plot functions have a keyword argument show=False
by default. In this way they don’t pop up running a script blocking further execution of the script during pop-up.
Saving plots
All plot functions by default store a .pdf
graphics file and a graphics file of the type set by ini.plot_file_type
in the project image folder set by ini.img_path
:
>>> import SLiCAP as sl
>>> sl.ini.dump("paths")
ini.project_path = /home/USR/DATA/SLiCAP/SLiCAP_github/SLiCAP_python/docs/
ini.html_path = html/
ini.cir_path = cir/
ini.img_path = img/
ini.csv_path = csv/
ini.txt_path = txt/
ini.tex_path = tex/
ini.user_lib_path = lib/
ini.sphinx_path = sphinx/
ini.tex_snippets = tex/SLiCAPdata/
ini.html_snippets = sphinx/SLiCAPdata/
ini.rst_snippets = sphinx/SLiCAPdata/
ini.myst_snippets = sphinx/SLiCAPdata/
ini.md_snippets = sphinx/SLiCAPdata/
Important
Plots are always saved, independent of the value of the keyword argument show
.
Frequency-characteristics
12# Swept variable plots
13# Laplace analysis
14laplaceResult = sl.doLaplace(cir, pardefs="circuit", numeric=True)
Magnitude
16# Magnitude
17f_mag = sl.plotSweep("f_mag", "Magnitude plot", laplaceResult, 0.01, 100, 500,
18 sweepScale="M", yUnits="V")
dB Magnitude
20# dB Magnitude
21f_dBm = sl.plotSweep("f_dBm", "dB magnitude plot", laplaceResult, 0.01, 100,
22 500, sweepScale="M", yUnits="V", funcType="dBmag")
Phase
24# Phase
25f_phs = sl.plotSweep("f_phs", "Phase plot", laplaceResult, 0.01, 100, 500,
26 sweepScale="M", yUnits="V", funcType="phase")
Group delay
28# Group delay
29f_del = sl.plotSweep("f_del", "Group delay plot", laplaceResult, 0.01, 100,
30 500, sweepScale="M", yUnits="V", yScale="u",
31 funcType="delay")
Polar Magnitude-phase
33# Magnitude-polar
34p_mag = sl.plotSweep("p_mag", "Magnitude-phase plot", laplaceResult, 0.01, 100,
35 500, axisType="polar", sweepScale="M", yUnits="V")
Polar dB magnitude-phase
37# dB magnitude-polar
38p_dBm = sl.plotSweep("p_dBm", "dB magnitude-phase plot", laplaceResult, 0.01,
39 100, 500, axisType="polar", sweepScale="M", yUnits="V",
40 funcType="dBmag")
Time-domain plots
Unit impulse response
44# Impulse
45impulseResp = sl.doImpulse(cir, pardefs="circuit", numeric=True)
46delta_t = sl.plotSweep("delta_t", "Unit-impulse response", impulseResp,
47 0, 5, 500, sweepScale="u", yScale="M")
Unit Step response
49# Step
50stepResp = sl.doStep(cir, pardefs="circuit", numeric=True)
51mu_t = sl.plotSweep("mu_t", "Unit-step response", stepResp, 0, 5, 500,
52 sweepScale="u")
Time-domain response
54# Time
55timeResp = sl.doTime(cir, pardefs="circuit", numeric=True)
56v_time = sl.plotSweep("v_time", "Time-domain response", timeResp, 0, 5, 500,
57 sweepScale="u")
Periodic pulse response
Modify trace data and label
59# Periodic pulse
60stepResp.stepResp = sl.step2PeriodicPulse(stepResp.stepResp, 20e-9, 1e-6, 3)
61stepResp.label = "3 Pulses response"
62pp_time = sl.plotSweep("pp_time", "Periodic pulse response", stepResp, 0, 5,
63 1000, sweepScale="u")
Noise spectrum
Detector-referred noise
65# Noise spectrum
66noiseResult = sl.doNoise(cir, pardefs="circuit", numeric=True)
67onoise_f = sl.plotSweep("onoise_f", "Detector-referred noise spectrum",
68 noiseResult, 0.01, 100, 500, funcType="onoise",
69 sweepScale="M", yUnits="$V^2/Hz$")
Contributions to detector-referred noise
71all_onoise_f = sl.plotSweep("all_onoise_f", "Contributions to detector-referred noise",
72 noiseResult, 0.01, 100, 500, funcType="onoise",
73 sweepScale="M", yUnits="$V^2/Hz$",
74 noiseSources="all")
Source-referred noise
76inoise_f = sl.plotSweep("inoise_f", "Source-referred noise spectrum",
77 noiseResult, 0.01, 100, 500, funcType="inoise",
78 sweepScale="M", yUnits="$V^2/Hz$")
Swept parameter plots
In the circuit model used for this page the parameter \(C_b\) is defined as a function of the frequency \(f_s\).
This function can be plotted using a swept parameter plot.
79
80# Swept parameter plots
81# Create an instruction result object for plotting
82parResult = sl.doParams(cir)
83# Create the swept-parameter plot
84Cb_fs = sl.plotSweep("Cb_fs", "$C_b$ versus $f_s$", parResult, 1, 5, 100,
85 axisType="semilogy", funcType="param", sweepVar="f_s",
86 sweepScale="M", xUnits="Hz", yVar="C_b", yScale="n",
Pole-zero plots
Poles
90# Plot the poles
91polesResult = sl.doPoles(cir, pardefs="circuit", numeric=True)
92p_plot = sl.plotPZ("p_plot", "Poles", polesResult, xscale="M", yscale="M")
Zeros
94# Plot the zeros
95zerosResult = sl.doZeros(cir, pardefs="circuit", numeric=True)
96z_plot = sl.plotPZ("z_plot", "Zeros", zerosResult, xscale="M", yscale="M")
Observable and controllable poles and zeros
98# Only observable and controllable
99pzResult = sl.doPZ(cir, pardefs="circuit", numeric=True)
100pz_plot = sl.plotPZ("pz_plot", "Observable and controllable poles and zeros",
101 pzResult, xscale="M", yscale="M", xmin=-11, xmax=1,
102 ymin=-6, ymax=6)
Multiple results in one plot
104# Multiple results in one plot
105all_pz = sl.plotPZ("ppzz_plot", "All poles and zeros",
106 [polesResult, zerosResult], xscale="M", yscale="M",
107 xmin=-11, xmax=1, ymin=-6, ymax=6)
Parameter stepping
109# Parameter stepping
110# Define the step parameters
111step_dict = {"params": "f_s",
112 "method": "lin",
113 "start": "1M",
114 "stop": "5M",
115 "num": 5}
Stepped plotSweep()
117# dB Magnitude stepped
118laplaceStepped = sl.doLaplace(cir, pardefs="circuit", stepdict=step_dict,
119 numeric=True)
120f_dBmStepped = sl.plotSweep("f_dBmStepped", "dB magnitude plot", laplaceStepped,
121 0.01, 100, 500, sweepScale="M", yUnits="V",
122 funcType="dBmag")
Stepped plotPZ(): root locus plots
124# Root-locus plots
125pzStepped = sl.doPZ(cir, pardefs="circuit", stepdict=step_dict,
126 numeric=True)
127pz_stepped = sl.plotPZ("pzStepped", "Stepped PZ plot", pzStepped, xscale="M",
128 yscale="M", xmin=-11, xmax=1, ymin=-6, ymax=6)
A stepped pole-zero plot shows:
The start end en locations of poles as \(\times\) and \(+\), respectively
For each step value a dot at the pole location
The start end en locations of zeros as \(\circ\) and \(\square\), respectively
For each step value a dot at the zero location
Stepped parameter sweep
130# Stepped parameter sweep
131# Define the step parameters
132step_dict = {"params": "L",
133 "method": "lin",
134 "start": "1u",
135 "stop": "5u",
136 "num": 5}
137# Create an instruction result object for plotting with parameter stepping
138parResult = sl.doParams(cir, stepdict=step_dict)
139Cb_fs_L = sl.plotSweep("Cb_fs_L", "$C_b$ versus $f_s$", parResult, 1, 5, 100,
140 axisType="semilogy", funcType="param", sweepVar="f_s",
141 sweepScale="M", xUnits="Hz", yVar="C_b", yScale="n",
142 yUnits="F")
Work with traces
Extract traces from a figure
144# Extract traces from plots
145onoise_trace = onoise_f.traceDict
Add a dictionary with traces to an existing plot
The function traces2fig() adds traces to a figure.
147# Add onoise_trace to a copy of all_onoise_f
148# Create a deepcopy of the figure
149all_oonoise_f = deepcopy(all_onoise_f)
150# Change the file name so we don't overwrite the original
151all_oonoise_f.fileName = "all_onoise"
152# Add the onoise trace to the new figure
153sl.traces2fig(onoise_trace, all_oonoise_f)
154# Don't show it, just save the figure
155all_oonoise_f.show = False
156# Generate and save the figure
157all_oonoise_f.plot()
Create and plot a dictionary with traces
159# Create traces
160x = np.linspace(-1, 1, 100)
161
162y1 = sl.trace([x, x])
163y1.label = "$y=x$"
164
165y2 = sl.trace([x, x**2])
166y2.label = "$y=x^2$"
167
168y3 = sl.trace([x, x**3])
169y3.label = "$y=x^3$"
170
171y4 = sl.trace([x, x**4])
172y4.label = "$y=x^4$"
173
174trc_dict = {"y1": y1, "y2": y2, "y3": y3, "y4": y4}
175
176# Plot a dictionary with traces
177
178pwrs_x = sl.plot("powers_x", "Powers of $x$", "lin", trc_dict,
179 xName = "x", yName="y")