Create, Simulate, and Plot
This example will create a new workspace in your HOME directory called “create_simulate_plot_example”. In the workspace a new library and schematic are created and populate with an RC filter. Next, the circuit will be simulated and finally the response from the filter will be plotted inline in the ADS Python console.
# Copyright Keysight Technologies 2023 - 2023
import os
from pathlib import Path
import keysight.ads.de as de
from keysight.ads.de import db_uu as db
def create_workspace_and_design_then_simulate_and_plot() -> None:
home_dir = os.environ["HOME"]
workspace_path = os.path.join(home_dir, "create_simulate_plot_example")
# ensure to start from a closed workspace
if de.workspace_is_open():
de.close_workspace()
# create the workspace
workspace = de.create_workspace(workspace_path)
workspace.open()
create_design_then_simulate_and_plot(workspace)
def create_design_then_simulate_and_plot(workspace: de.Workspace) -> None:
from keysight.edatoolbox import util
target_output_dir = os.path.join(workspace.path, "output")
# create the simulation output directory
util.safe_makedirs(target_output_dir)
lib_dir = os.path.join(workspace.path, "low_pass_filter_lib")
de.create_new_library("low_pass_filter_lib", lib_dir)
workspace.add_library("low_pass_filter_lib", lib_dir, de.LibraryMode.NON_SHARED)
# create the schematic
design = db.create_schematic("low_pass_filter_lib:cell:schematic")
# add components to the schematic
design.add_instance(("ads_sources", "V_AC", "symbol"), (-2, 0), name="SRC1", angle=-90)
r = design.add_instance(("ads_rflib", "R", "symbol"), (0, 0), name="R1", angle=0)
r.parameters["R"].value = "3.0 kOhm"
c = design.add_instance(("ads_rflib", "C", "symbol"), (2, 0), name="C1", angle=-90)
c.parameters["C"].value = "1.0 uF"
design.add_instance(("ads_rflib", "GROUND", "symbol"), (-2, -1), angle=-90)
design.add_instance(("ads_rflib", "GROUND", "symbol"), (2, -1), angle=-90)
design.add_wire([(-2.0, 0.0), (0.0, 0.0)])
wire = design.add_wire([(1.0, 0.0), (2.0, 0.0)])
wire.add_wire_label("R1_v")
ac = design.add_instance(("ads_simulation", "AC", "symbol"), (-4, 1), name="AC1", angle=0)
ac.parameters["Start"].value = "1.0 Hz"
ac.parameters["Stop"].value = "1.0 MHz"
ac.parameters["Dec"].value = "5"
ac.parameters["Step"].value = ""
v = design.add_instance(("ads_datacmps", "VAR", "symbol"), (0, 2), name="VAR1", angle=-90)
assert v.is_var_instance
v.vars["X"] = "1.0"
v.vars["Y"] = "X/2.0"
design.save_design()
# data plot cannot be run in automation mode
if de.is_pde_app():
simulate_and_plot(design, target_output_dir)
# plot() not testable in automation mode
def simulate_and_plot(design: db.Design, output_dir: str) -> None:
import os
# use the dataset module to grab the output
import keysight.ads.dataset as dataset
from IPython.core import getipython
from keysight.edatoolbox import ads
ipython = getipython.get_ipython()
if ipython is None:
print("The remaining portion of the script must be run in an IPython environment. Exiting.")
return
# capture the netlist in a string
netlist = design.generate_netlist()
# access to the simulator object to run netlists
simulator = ads.CircuitSimulator()
# run the netlist, this will block output
simulator.run_netlist(netlist, output_dir=output_dir)
output_data = dataset.open(Path(os.path.join(output_dir, "cell.ds")))
# switch to a dataframe representation
# reset the index to normalize the data
dataf = output_data["AC1.AC"].to_dataframe().reset_index()
# plot using matplotlib/seaborn
import matplotlib.pyplot as plt
# plot using inline
ipython.run_line_magic("matplotlib", "inline") # type: ignore
# make sure we plot the magnitude
import numpy as np
def dB(x) -> float: # noqa: ANN001
return 10.0 * np.log10(abs(x))
_, ax = plt.subplots()
ax.set_xscale("log") # type: ignore
ax.set_title("Filter response") # type: ignore
plt.plot(dataf["freq"], dB(dataf["R1_v"]))
# alternatively show as dedicated window
# plt.show()