Create plots

../_images/colorCode.svg

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")
../_images/myPassiveNetwork.svg

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 each axis object is a list with trace objects that will be plotted the axis. Trace xdata, ydata, lables, colors, markers, etc, are all attributes of a trace 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")
../_images/f_mag.svg

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")
../_images/f_dBm.svg

Phase

24# Phase
25f_phs = sl.plotSweep("f_phs", "Phase plot", laplaceResult, 0.01, 100, 500, 
26                     sweepScale="M", yUnits="V", funcType="phase")
../_images/f_phs.svg

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")
../_images/f_del.svg

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")
../_images/p_mag.svg

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")
../_images/p_dBm.svg

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")
../_images/delta_t.svg

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")
../_images/mu_t.svg

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")
../_images/v_time.svg

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")
../_images/pp_time.svg

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$")
../_images/onoise_f.svg

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")
../_images/all_onoise_f.svg

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$")
../_images/inoise_f.svg

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", 
../_images/Cb_fs.svg

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")
../_images/p_plot.svg

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")
../_images/z_plot.svg

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)
../_images/pz_plot.svg

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)
../_images/ppzz_plot.svg

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")
../_images/f_dBmStepped.svg

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

../_images/pzStepped.svg

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")
../_images/Cb_fs_L.svg

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()
../_images/all_onoise.svg

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")
../_images/powers_x.svg ../_images/colorCode.svg